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