1 /*
2 * Copyright 2011-2015, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Oliver Tappe <zooey@hirschkaefer.de>
7 */
8
9
10 #include <package/RefreshRepositoryRequest.h>
11
12 #include <Catalog.h>
13 #include <Directory.h>
14 #include <Path.h>
15
16 #include <JobQueue.h>
17
18 #include <package/ActivateRepositoryCacheJob.h>
19 #include <package/ChecksumAccessors.h>
20 #include <package/ValidateChecksumJob.h>
21 #include <package/RepositoryCache.h>
22 #include <package/RepositoryConfig.h>
23 #include <package/PackageRoster.h>
24
25 #include "FetchFileJob.h"
26
27 #undef B_TRANSLATION_CONTEXT
28 #define B_TRANSLATION_CONTEXT "RefreshRepositoryRequest"
29
30
31 namespace BPackageKit {
32
33
34 using namespace BPrivate;
35
36
BRefreshRepositoryRequest(const BContext & context,const BRepositoryConfig & repoConfig)37 BRefreshRepositoryRequest::BRefreshRepositoryRequest(const BContext& context,
38 const BRepositoryConfig& repoConfig)
39 :
40 inherited(context),
41 fRepoConfig(repoConfig)
42 {
43 }
44
45
~BRefreshRepositoryRequest()46 BRefreshRepositoryRequest::~BRefreshRepositoryRequest()
47 {
48 }
49
50
51 status_t
CreateInitialJobs()52 BRefreshRepositoryRequest::CreateInitialJobs()
53 {
54 status_t result = InitCheck();
55 if (result != B_OK)
56 return B_NO_INIT;
57
58 if ((result = fRepoConfig.InitCheck()) != B_OK)
59 return result;
60
61 // fetch the current checksum and compare with our cache's checksum,
62 // if they differ, fetch the updated cache
63 result = fContext.GetNewTempfile("repochecksum-", &fFetchedChecksumFile);
64 if (result != B_OK)
65 return result;
66 BString repoChecksumURL
67 = BString(fRepoConfig.BaseURL()) << "/" << "repo.sha256";
68 BString title = B_TRANSLATE("Fetching repository checksum from %url");
69 title.ReplaceAll("%url", fRepoConfig.BaseURL());
70 FetchFileJob* fetchChecksumJob = new (std::nothrow) FetchFileJob(
71 fContext, title, repoChecksumURL, fFetchedChecksumFile);
72 if (fetchChecksumJob == NULL)
73 return B_NO_MEMORY;
74 if ((result = QueueJob(fetchChecksumJob)) != B_OK) {
75 delete fetchChecksumJob;
76 return result;
77 }
78
79 BRepositoryCache repoCache;
80 BPackageRoster roster;
81 // We purposely don't check this error, because this may be for a new repo,
82 // which doesn't have a cache file yet. The true passed to
83 // GeneralFileChecksumAccessor below will handle this case, and cause the
84 // repo data to be fetched and cached for the future in JobSucceeded below.
85 roster.GetRepositoryCache(fRepoConfig.Name(), &repoCache);
86
87 title = B_TRANSLATE("Validating checksum for %repositoryName");
88 title.ReplaceAll("%repositoryName", fRepoConfig.Name());
89 ValidateChecksumJob* validateChecksumJob
90 = new (std::nothrow) ValidateChecksumJob(fContext,
91 title,
92 new (std::nothrow) ChecksumFileChecksumAccessor(
93 fFetchedChecksumFile),
94 new (std::nothrow) GeneralFileChecksumAccessor(repoCache.Entry(),
95 true),
96 false);
97 if (validateChecksumJob == NULL)
98 return B_NO_MEMORY;
99 validateChecksumJob->AddDependency(fetchChecksumJob);
100 if ((result = QueueJob(validateChecksumJob)) != B_OK) {
101 delete validateChecksumJob;
102 return result;
103 }
104 fValidateChecksumJob = validateChecksumJob;
105
106 return B_OK;
107 }
108
109
110 void
JobSucceeded(BSupportKit::BJob * job)111 BRefreshRepositoryRequest::JobSucceeded(BSupportKit::BJob* job)
112 {
113 if (job == fValidateChecksumJob
114 && !fValidateChecksumJob->ChecksumsMatch()) {
115 // the remote repo cache has a different checksum, we fetch it
116 fValidateChecksumJob = NULL;
117 // don't re-trigger fetching if anything goes wrong, fail instead
118 _FetchRepositoryCache();
119 }
120 }
121
122
123 status_t
_FetchRepositoryCache()124 BRefreshRepositoryRequest::_FetchRepositoryCache()
125 {
126 // download repository cache and put it in either the common/user cache
127 // path, depending on where the corresponding repo-config lives
128
129 // job fetching the cache
130 BEntry tempRepoCache;
131 status_t result = fContext.GetNewTempfile("repocache-", &tempRepoCache);
132 if (result != B_OK)
133 return result;
134 BString repoCacheURL = BString(fRepoConfig.BaseURL()) << "/" << "repo";
135 BString title = B_TRANSLATE("Fetching repository-cache from %url");
136 title.ReplaceAll("%url", fRepoConfig.BaseURL());
137 FetchFileJob* fetchCacheJob = new (std::nothrow) FetchFileJob(fContext,
138 title, repoCacheURL, tempRepoCache);
139 if (fetchCacheJob == NULL)
140 return B_NO_MEMORY;
141 if ((result = QueueJob(fetchCacheJob)) != B_OK) {
142 delete fetchCacheJob;
143 return result;
144 }
145
146 // job validating the cache's checksum
147 title = B_TRANSLATE("Validating checksum for %repositoryName");
148 title.ReplaceAll("%repositoryName", fRepoConfig.Name());
149 ValidateChecksumJob* validateChecksumJob
150 = new (std::nothrow) ValidateChecksumJob(fContext,
151 title,
152 new (std::nothrow) ChecksumFileChecksumAccessor(
153 fFetchedChecksumFile),
154 new (std::nothrow) GeneralFileChecksumAccessor(tempRepoCache));
155 if (validateChecksumJob == NULL)
156 return B_NO_MEMORY;
157 validateChecksumJob->AddDependency(fetchCacheJob);
158 if ((result = QueueJob(validateChecksumJob)) != B_OK) {
159 delete validateChecksumJob;
160 return result;
161 }
162
163 // job activating the cache
164 BPath targetRepoCachePath;
165 BPackageRoster roster;
166 result = fRepoConfig.IsUserSpecific()
167 ? roster.GetUserRepositoryCachePath(&targetRepoCachePath, true)
168 : roster.GetCommonRepositoryCachePath(&targetRepoCachePath, true);
169 if (result != B_OK)
170 return result;
171 BDirectory targetDirectory(targetRepoCachePath.Path());
172 ActivateRepositoryCacheJob* activateJob
173 = new (std::nothrow) ActivateRepositoryCacheJob(fContext,
174 BString("Activating repository cache for ") << fRepoConfig.Name(),
175 tempRepoCache, fRepoConfig.Name(), targetDirectory);
176 if (activateJob == NULL)
177 return B_NO_MEMORY;
178 activateJob->AddDependency(validateChecksumJob);
179 if ((result = QueueJob(activateJob)) != B_OK) {
180 delete activateJob;
181 return result;
182 }
183
184 return B_OK;
185 }
186
187
188 } // namespace BPackageKit
189