xref: /haiku/src/kits/package/RefreshRepositoryRequest.cpp (revision 4b918abdb02a26a770d898594eaaccc6f1726e9b)
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