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