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
25namespace BPackageKit {
26
27
28using namespace BPrivate;
29
30
31BRefreshRepositoryRequest::BRefreshRepositoryRequest(const BContext& context,
32	const BRepositoryConfig& repoConfig)
33	:
34	inherited(context),
35	fRepoConfig(repoConfig)
36{
37}
38
39
40BRefreshRepositoryRequest::~BRefreshRepositoryRequest()
41{
42}
43
44
45status_t
46BRefreshRepositoryRequest::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.BaseURL()) << "/" << "repo.sha256";
62	FetchFileJob* fetchChecksumJob = new (std::nothrow) FetchFileJob(
63		fContext,
64		BString("Fetching repository checksum from ") << fRepoConfig.BaseURL(),
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
98void
99BRefreshRepositoryRequest::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
111status_t
112BRefreshRepositoryRequest::_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.BaseURL()) << "/" << "repo";
123	FetchFileJob* fetchCacheJob = new (std::nothrow) FetchFileJob(fContext,
124		BString("Fetching repository-cache from ") << fRepoConfig.BaseURL(),
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