xref: /haiku/src/kits/package/RefreshRepositoryRequest.cpp (revision 7d7ed9bf4bdd7bc31e31143c402c4f96a324b30b)
1 /*
2  * Copyright 2011, 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 <Directory.h>
13 #include <Path.h>
14 
15 #include <package/ActivateRepositoryCacheJob.h>
16 #include <package/ChecksumAccessors.h>
17 #include <package/ValidateChecksumJob.h>
18 #include <package/FetchFileJob.h>
19 #include <package/JobQueue.h>
20 #include <package/RepositoryCache.h>
21 #include <package/RepositoryConfig.h>
22 #include <package/PackageRoster.h>
23 
24 
25 namespace BPackageKit {
26 
27 
28 using namespace BPrivate;
29 
30 
31 BRefreshRepositoryRequest::BRefreshRepositoryRequest(const BContext& context,
32 	const BRepositoryConfig& repoConfig)
33 	:
34 	inherited(context),
35 	fRepoConfig(repoConfig)
36 {
37 }
38 
39 
40 BRefreshRepositoryRequest::~BRefreshRepositoryRequest()
41 {
42 }
43 
44 
45 status_t
46 BRefreshRepositoryRequest::CreateInitialJobs()
47 {
48 	status_t result = InitCheck();
49 	if (result != B_OK)
50 		return B_NO_INIT;
51 
52 	if ((result = fRepoConfig.InitCheck()) != B_OK)
53 		return result;
54 
55 	// fetch the current checksum and compare with our cache's checksum,
56 	// if they differ, fetch the updated cache
57 	result = fContext.GetNewTempfile("repochecksum-", &fFetchedChecksumFile);
58 	if (result != B_OK)
59 		return result;
60 	BString repoChecksumURL
61 		= BString(fRepoConfig.URL()) << "/" << "repo.sha256";
62 	FetchFileJob* fetchChecksumJob = new (std::nothrow) FetchFileJob(
63 		fContext,
64 		BString("Fetching repository checksum from ") << fRepoConfig.URL(),
65 		repoChecksumURL, fFetchedChecksumFile);
66 	if (fetchChecksumJob == NULL)
67 		return B_NO_MEMORY;
68 	if ((result = QueueJob(fetchChecksumJob)) != B_OK) {
69 		delete fetchChecksumJob;
70 		return result;
71 	}
72 
73 	BRepositoryCache repoCache;
74 	BPackageRoster roster;
75 	roster.GetRepositoryCache(fRepoConfig.Name(), &repoCache);
76 
77 	ValidateChecksumJob* validateChecksumJob
78 		= new (std::nothrow) ValidateChecksumJob(fContext,
79 			BString("Validating checksum for ") << fRepoConfig.Name(),
80 			new (std::nothrow) ChecksumFileChecksumAccessor(
81 				fFetchedChecksumFile),
82 			new (std::nothrow) GeneralFileChecksumAccessor(repoCache.Entry(),
83 				true),
84 			false);
85 	if (validateChecksumJob == NULL)
86 		return B_NO_MEMORY;
87 	validateChecksumJob->AddDependency(fetchChecksumJob);
88 	if ((result = QueueJob(validateChecksumJob)) != B_OK) {
89 		delete validateChecksumJob;
90 		return result;
91 	}
92 	fValidateChecksumJob = validateChecksumJob;
93 
94 	return B_OK;
95 }
96 
97 
98 void
99 BRefreshRepositoryRequest::JobSucceeded(BJob* job)
100 {
101 	if (job == fValidateChecksumJob
102 		&& !fValidateChecksumJob->ChecksumsMatch()) {
103 		// the remote repo cache has a different checksum, we fetch it
104 		fValidateChecksumJob = NULL;
105 			// don't re-trigger fetching if anything goes wrong, fail instead
106 		_FetchRepositoryCache();
107 	}
108 }
109 
110 
111 status_t
112 BRefreshRepositoryRequest::_FetchRepositoryCache()
113 {
114 	// download repository cache and put it in either the common/user cache
115 	// path, depending on where the corresponding repo-config lives
116 
117 	// job fetching the cache
118 	BEntry tempRepoCache;
119 	status_t result = fContext.GetNewTempfile("repocache-", &tempRepoCache);
120 	if (result != B_OK)
121 		return result;
122 	BString repoCacheURL = BString(fRepoConfig.URL()) << "/" << "repo";
123 	FetchFileJob* fetchCacheJob = new (std::nothrow) FetchFileJob(fContext,
124 		BString("Fetching repository-cache from ") << fRepoConfig.URL(),
125 		repoCacheURL, tempRepoCache);
126 	if (fetchCacheJob == NULL)
127 		return B_NO_MEMORY;
128 	if ((result = QueueJob(fetchCacheJob)) != B_OK) {
129 		delete fetchCacheJob;
130 		return result;
131 	}
132 
133 	// job validating the cache's checksum
134 	ValidateChecksumJob* validateChecksumJob
135 		= new (std::nothrow) ValidateChecksumJob(fContext,
136 			BString("Validating checksum for ") << fRepoConfig.Name(),
137 			new (std::nothrow) ChecksumFileChecksumAccessor(
138 				fFetchedChecksumFile),
139 			new (std::nothrow) GeneralFileChecksumAccessor(tempRepoCache));
140 	if (validateChecksumJob == NULL)
141 		return B_NO_MEMORY;
142 	validateChecksumJob->AddDependency(fetchCacheJob);
143 	if ((result = QueueJob(validateChecksumJob)) != B_OK) {
144 		delete validateChecksumJob;
145 		return result;
146 	}
147 
148 	// job activating the cache
149 	BPath targetRepoCachePath;
150 	BPackageRoster roster;
151 	result = fRepoConfig.IsUserSpecific()
152 		? roster.GetUserRepositoryCachePath(&targetRepoCachePath, true)
153 		: roster.GetCommonRepositoryCachePath(&targetRepoCachePath, true);
154 	if (result != B_OK)
155 		return result;
156 	BDirectory targetDirectory(targetRepoCachePath.Path());
157 	ActivateRepositoryCacheJob* activateJob
158 		= new (std::nothrow) ActivateRepositoryCacheJob(fContext,
159 			BString("Activating repository cache for ") << fRepoConfig.Name(),
160 			tempRepoCache, fRepoConfig.Name(), targetDirectory);
161 	if (activateJob == NULL)
162 		return B_NO_MEMORY;
163 	activateJob->AddDependency(validateChecksumJob);
164 	if ((result = QueueJob(activateJob)) != B_OK) {
165 		delete activateJob;
166 		return result;
167 	}
168 
169 	return B_OK;
170 }
171 
172 
173 }	// namespace BPackageKit
174