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 roster.GetRepositoryCache(fRepoConfig.Name(), &repoCache); 78 79 ValidateChecksumJob* validateChecksumJob 80 = new (std::nothrow) ValidateChecksumJob(fContext, 81 BString("Validating checksum for ") << fRepoConfig.Name(), 82 new (std::nothrow) ChecksumFileChecksumAccessor( 83 fFetchedChecksumFile), 84 new (std::nothrow) GeneralFileChecksumAccessor(repoCache.Entry(), 85 true), 86 false); 87 if (validateChecksumJob == NULL) 88 return B_NO_MEMORY; 89 validateChecksumJob->AddDependency(fetchChecksumJob); 90 if ((result = QueueJob(validateChecksumJob)) != B_OK) { 91 delete validateChecksumJob; 92 return result; 93 } 94 fValidateChecksumJob = validateChecksumJob; 95 96 return B_OK; 97 } 98 99 100 void 101 BRefreshRepositoryRequest::JobSucceeded(BSupportKit::BJob* job) 102 { 103 if (job == fValidateChecksumJob 104 && !fValidateChecksumJob->ChecksumsMatch()) { 105 // the remote repo cache has a different checksum, we fetch it 106 fValidateChecksumJob = NULL; 107 // don't re-trigger fetching if anything goes wrong, fail instead 108 _FetchRepositoryCache(); 109 } 110 } 111 112 113 status_t 114 BRefreshRepositoryRequest::_FetchRepositoryCache() 115 { 116 // download repository cache and put it in either the common/user cache 117 // path, depending on where the corresponding repo-config lives 118 119 // job fetching the cache 120 BEntry tempRepoCache; 121 status_t result = fContext.GetNewTempfile("repocache-", &tempRepoCache); 122 if (result != B_OK) 123 return result; 124 BString repoCacheURL = BString(fRepoConfig.BaseURL()) << "/" << "repo"; 125 FetchFileJob* fetchCacheJob = new (std::nothrow) FetchFileJob(fContext, 126 BString("Fetching repository-cache from ") << fRepoConfig.BaseURL(), 127 repoCacheURL, tempRepoCache); 128 if (fetchCacheJob == NULL) 129 return B_NO_MEMORY; 130 if ((result = QueueJob(fetchCacheJob)) != B_OK) { 131 delete fetchCacheJob; 132 return result; 133 } 134 135 // job validating the cache's checksum 136 ValidateChecksumJob* validateChecksumJob 137 = new (std::nothrow) ValidateChecksumJob(fContext, 138 BString("Validating checksum for ") << fRepoConfig.Name(), 139 new (std::nothrow) ChecksumFileChecksumAccessor( 140 fFetchedChecksumFile), 141 new (std::nothrow) GeneralFileChecksumAccessor(tempRepoCache)); 142 if (validateChecksumJob == NULL) 143 return B_NO_MEMORY; 144 validateChecksumJob->AddDependency(fetchCacheJob); 145 if ((result = QueueJob(validateChecksumJob)) != B_OK) { 146 delete validateChecksumJob; 147 return result; 148 } 149 150 // job activating the cache 151 BPath targetRepoCachePath; 152 BPackageRoster roster; 153 result = fRepoConfig.IsUserSpecific() 154 ? roster.GetUserRepositoryCachePath(&targetRepoCachePath, true) 155 : roster.GetCommonRepositoryCachePath(&targetRepoCachePath, true); 156 if (result != B_OK) 157 return result; 158 BDirectory targetDirectory(targetRepoCachePath.Path()); 159 ActivateRepositoryCacheJob* activateJob 160 = new (std::nothrow) ActivateRepositoryCacheJob(fContext, 161 BString("Activating repository cache for ") << fRepoConfig.Name(), 162 tempRepoCache, fRepoConfig.Name(), targetDirectory); 163 if (activateJob == NULL) 164 return B_NO_MEMORY; 165 activateJob->AddDependency(validateChecksumJob); 166 if ((result = QueueJob(activateJob)) != B_OK) { 167 delete activateJob; 168 return result; 169 } 170 171 return B_OK; 172 } 173 174 175 } // namespace BPackageKit 176