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 70 if (Logger::IsInfoEnabled()) { 71 printf("[%s] will update local repositories' caches\n", Name()); 72 } 73 74 status_t result = roster.GetRepositoryNames(repoNames); 75 76 if (result == B_OK) { 77 DecisionProvider decisionProvider; 78 JobStateListener listener; 79 BContext context(decisionProvider, listener); 80 BRepositoryCache cache; 81 82 for ( 83 int32 i = 0; 84 result == B_OK && i < repoNames.CountStrings() && !WasStopped(); 85 ++i) { 86 result = _RunForRepositoryName(repoNames.StringAt(i), context, 87 roster, &cache); 88 } 89 } else { 90 _NotifyError(strerror(result)); 91 result = B_ERROR; 92 } 93 94 if (result == B_OK && Logger::IsInfoEnabled()) { 95 printf("[%s] did update %" B_PRIi32 " local repositories' caches\n", 96 Name(), repoNames.CountStrings()); 97 } 98 99 return result; 100 } 101 102 103 bool 104 LocalRepositoryUpdateProcess::_ShouldRunForRepositoryName( 105 const BString& repoName, BPackageKit::BPackageRoster& roster, 106 BPackageKit::BRepositoryCache* cache) 107 { 108 if (fForce) { 109 if (Logger::IsInfoEnabled()) { 110 printf("[%s] am refreshing cache for repo [%s] as it was forced\n", 111 Name(), repoName.String()); 112 } 113 return true; 114 } 115 116 if (roster.GetRepositoryCache(repoName, cache) != B_OK) { 117 if (Logger::IsInfoEnabled()) { 118 printf("[%s] am updating cache for repo [%s] as there was no" 119 " cache\n", Name(), repoName.String()); 120 } 121 return true; 122 } 123 124 if (static_cast<App*>(be_app)->IsFirstRun()) { 125 if (Logger::IsInfoEnabled()) { 126 printf("[%s] am updating cache for repo [%s] as this is the first" 127 " time that the application has run\n", Name(), 128 repoName.String()); 129 } 130 return true; 131 } 132 133 if (Logger::IsDebugEnabled()) { 134 printf("[%s] skipped update local repo [%s] cache\n", Name(), 135 repoName.String()); 136 } 137 138 return false; 139 } 140 141 142 status_t 143 LocalRepositoryUpdateProcess::_RunForRepositoryName(const BString& repoName, 144 BPackageKit::BContext& context, BPackageKit::BPackageRoster& roster, 145 BPackageKit::BRepositoryCache* cache) 146 { 147 status_t result = B_ERROR; 148 BRepositoryConfig repoConfig; 149 result = roster.GetRepositoryConfig(repoName, &repoConfig); 150 if (result == B_OK) { 151 if (_ShouldRunForRepositoryName(repoName, roster, cache)) { 152 try { 153 BRefreshRepositoryRequest refreshRequest(context, repoConfig); 154 result = refreshRequest.Process(); 155 if (Logger::IsInfoEnabled()) { 156 printf("[%s] did update local repo [%s] cache\n", Name(), 157 repoName.String()); 158 } 159 result = B_OK; 160 } catch (BFatalErrorException& ex) { 161 _NotifyError(ex.Message(), ex.Details()); 162 } catch (BException& ex) { 163 _NotifyError(ex.Message()); 164 } 165 } 166 } else { 167 _NotifyError(strerror(result)); 168 } 169 170 return result; 171 } 172 173 174 void 175 LocalRepositoryUpdateProcess::_NotifyError(const BString& error) const 176 { 177 _NotifyError(error, ""); 178 } 179 180 181 void 182 LocalRepositoryUpdateProcess::_NotifyError(const BString& error, 183 const BString& details) const 184 { 185 printf("an error has arisen updating the local repositories : %s\n", 186 error.String()); 187 188 BString alertText(B_TRANSLATE("An error occurred while refreshing the " 189 "repository: %error%")); 190 alertText.ReplaceFirst("%error%", error); 191 192 if (!details.IsEmpty()) { 193 alertText.Append(" ("); 194 alertText.Append(details); 195 alertText.Append(")"); 196 } 197 198 AppUtils::NotifySimpleError( 199 B_TRANSLATE("Repository update error"), 200 alertText); 201 } 202