1/* 2 * Copyright 2018-2020, Andrew Lindesay <apl@lindesay.co.nz>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 7#include "LocalRepositoryUpdateProcess.h" 8 9#include <Catalog.h> 10#include <Roster.h> 11#include <String.h> 12#include <StringList.h> 13 14#include <package/Context.h> 15#include <package/manager/Exceptions.h> 16#include <package/PackageRoster.h> 17#include <package/RefreshRepositoryRequest.h> 18 19#include "App.h" 20#include "AppUtils.h" 21#include "DecisionProvider.h" 22#include "JobStateListener.h" 23#include "Logger.h" 24#include "HaikuDepotConstants.h" 25 26 27#undef B_TRANSLATION_CONTEXT 28#define B_TRANSLATION_CONTEXT "LocalRepositoryUpdateProcess" 29 30 31using namespace BPackageKit; 32using namespace BPackageKit::BManager::BPrivate; 33 34 35LocalRepositoryUpdateProcess::LocalRepositoryUpdateProcess( 36 Model *model, bool force) 37 : 38 AbstractProcess(), 39 fModel(model), 40 fForce(force) 41{ 42} 43 44 45LocalRepositoryUpdateProcess::~LocalRepositoryUpdateProcess() 46{ 47} 48 49 50const char* 51LocalRepositoryUpdateProcess::Name() const 52{ 53 return "LocalRepositoryUpdateProcess"; 54} 55 56 57const char* 58LocalRepositoryUpdateProcess::Description() const 59{ 60 return B_TRANSLATE("Fetching remote repository data"); 61} 62 63 64status_t 65LocalRepositoryUpdateProcess::RunInternal() 66{ 67 BPackageRoster roster; 68 BStringList repoNames; 69 HDINFO("[%s] will update local repositories' caches", Name()); 70 71 status_t result = roster.GetRepositoryNames(repoNames); 72 73 if (result == B_OK) { 74 DecisionProvider decisionProvider; 75 JobStateListener listener; 76 BContext context(decisionProvider, listener); 77 BRepositoryCache cache; 78 79 for ( 80 int32 i = 0; 81 result == B_OK && i < repoNames.CountStrings() && !WasStopped(); 82 ++i) { 83 result = _RunForRepositoryName(repoNames.StringAt(i), context, 84 roster, &cache); 85 } 86 } else { 87 _NotifyError(strerror(result)); 88 result = B_ERROR; 89 } 90 91 if (result == B_OK) { 92 HDINFO("[%s] did update %" B_PRIi32 " local repositories' caches", 93 Name(), repoNames.CountStrings()); 94 } 95 96 return result; 97} 98 99 100bool 101LocalRepositoryUpdateProcess::_ShouldRunForRepositoryName( 102 const BString& repoName, BPackageKit::BPackageRoster& roster, 103 BPackageKit::BRepositoryCache* cache) 104{ 105 if (fForce) { 106 HDINFO("[%s] am refreshing cache for repo [%s] as it was forced", 107 Name(), repoName.String()); 108 return true; 109 } 110 111 if (roster.GetRepositoryCache(repoName, cache) != B_OK) { 112 HDINFO("[%s] am updating cache for repo [%s] as there was no cache", 113 Name(), repoName.String()); 114 return true; 115 } 116 117 if (static_cast<App*>(be_app)->IsFirstRun()) { 118 HDINFO("[%s] am updating cache for repo [%s] as this is the first" 119 " time that the application has run", Name(), repoName.String()); 120 return true; 121 } 122 123 HDDEBUG("[%s] skipped update local repo [%s] cache", Name(), 124 repoName.String()); 125 126 return false; 127} 128 129 130status_t 131LocalRepositoryUpdateProcess::_RunForRepositoryName(const BString& repoName, 132 BPackageKit::BContext& context, BPackageKit::BPackageRoster& roster, 133 BPackageKit::BRepositoryCache* cache) 134{ 135 status_t result = B_ERROR; 136 BRepositoryConfig repoConfig; 137 result = roster.GetRepositoryConfig(repoName, &repoConfig); 138 if (result == B_OK) { 139 if (_ShouldRunForRepositoryName(repoName, roster, cache)) { 140 try { 141 BRefreshRepositoryRequest refreshRequest(context, repoConfig); 142 result = refreshRequest.Process(); 143 HDINFO("[%s] did update local repo [%s] cache", Name(), 144 repoName.String()); 145 result = B_OK; 146 } catch (BFatalErrorException& ex) { 147 _NotifyError(ex.Message(), ex.Details()); 148 } catch (BException& ex) { 149 _NotifyError(ex.Message()); 150 } 151 } 152 } else { 153 _NotifyError(strerror(result)); 154 } 155 156 return result; 157} 158 159 160void 161LocalRepositoryUpdateProcess::_NotifyError(const BString& error) const 162{ 163 _NotifyError(error, ""); 164} 165 166 167void 168LocalRepositoryUpdateProcess::_NotifyError(const BString& error, 169 const BString& details) const 170{ 171 HDINFO("an error has arisen updating the local repositories : %s", 172 error.String()); 173 174 BString alertText(B_TRANSLATE("An error occurred while refreshing the " 175 "repository: %error%")); 176 alertText.ReplaceFirst("%error%", error); 177 178 if (!details.IsEmpty()) { 179 alertText.Append(" ("); 180 alertText.Append(details); 181 alertText.Append(")"); 182 } 183 184 AppUtils::NotifySimpleError( 185 B_TRANSLATE("Repository update error"), 186 alertText); 187} 188