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