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