xref: /haiku/src/apps/haikudepot/server/LocalRepositoryUpdateProcess.cpp (revision fa5c8097c9eddf48e05e70cd0dc6b389532fcaa3)
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 
LocalRepositoryUpdateProcess(Model * model,bool force)35 LocalRepositoryUpdateProcess::LocalRepositoryUpdateProcess(
36 	Model *model, bool force)
37 	:
38 	AbstractProcess(),
39 	fModel(model),
40 	fForce(force)
41 {
42 }
43 
44 
~LocalRepositoryUpdateProcess()45 LocalRepositoryUpdateProcess::~LocalRepositoryUpdateProcess()
46 {
47 }
48 
49 
50 const char*
Name() const51 LocalRepositoryUpdateProcess::Name() const
52 {
53 	return "LocalRepositoryUpdateProcess";
54 }
55 
56 
57 const char*
Description() const58 LocalRepositoryUpdateProcess::Description() const
59 {
60 	return B_TRANSLATE("Fetching remote repository data");
61 }
62 
63 
64 status_t
RunInternal()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
_ShouldRunForRepositoryName(const BString & repoName,BPackageKit::BPackageRoster & roster,BPackageKit::BRepositoryCache * cache)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
_RunForRepositoryName(const BString & repoName,BPackageKit::BContext & context,BPackageKit::BPackageRoster & roster,BPackageKit::BRepositoryCache * cache)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
_NotifyError(const BString & error) const161 LocalRepositoryUpdateProcess::_NotifyError(const BString& error) const
162 {
163 	_NotifyError(error, "");
164 }
165 
166 
167 void
_NotifyError(const BString & error,const BString & details) const168 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