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 31 using namespace BPackageKit; 32 using namespace BPackageKit::BManager::BPrivate; 33 34 35 LocalRepositoryUpdateProcess::LocalRepositoryUpdateProcess( 36 Model *model, bool force) 37 : 38 AbstractProcess(), 39 fModel(model), 40 fForce(force) 41 { 42 } 43 44 45 LocalRepositoryUpdateProcess::~LocalRepositoryUpdateProcess() 46 { 47 } 48 49 50 const char* 51 LocalRepositoryUpdateProcess::Name() const 52 { 53 return "LocalRepositoryUpdateProcess"; 54 } 55 56 57 const char* 58 LocalRepositoryUpdateProcess::Description() const 59 { 60 return B_TRANSLATE("Fetching remote repository data"); 61 } 62 63 64 status_t 65 LocalRepositoryUpdateProcess::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 100 bool 101 LocalRepositoryUpdateProcess::_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 130 status_t 131 LocalRepositoryUpdateProcess::_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 160 void 161 LocalRepositoryUpdateProcess::_NotifyError(const BString& error) const 162 { 163 _NotifyError(error, ""); 164 } 165 166 167 void 168 LocalRepositoryUpdateProcess::_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