xref: /haiku/src/apps/haikudepot/server/LocalRepositoryUpdateProcess.cpp (revision 16ad15142c48ee36cd6a807a24efc99c88d4310d)
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