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 25 namespace BPackageKit { 26 27 28 using namespace BPrivate; 29 30 31 BRefreshRepositoryRequest::BRefreshRepositoryRequest(const BContext& context, 32 const BRepositoryConfig& repoConfig) 33 : 34 inherited(context), 35 fRepoConfig(repoConfig) 36 { 37 } 38 39 40 BRefreshRepositoryRequest::~BRefreshRepositoryRequest() 41 { 42 } 43 44 45 status_t 46 BRefreshRepositoryRequest::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 98 void 99 BRefreshRepositoryRequest::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 111 status_t 112 BRefreshRepositoryRequest::_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