1/*
2 * Copyright 2018, 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 "AppUtils.h"
20#include "DecisionProvider.h"
21#include "JobStateListener.h"
22#include "Logger.h"
23#include "HaikuDepotConstants.h"
24
25
26#undef B_TRANSLATION_CONTEXT
27#define B_TRANSLATION_CONTEXT "LocalRepositoryUpdateProcess"
28
29
30using namespace BPackageKit;
31using namespace BPackageKit::BManager::BPrivate;
32
33
34LocalRepositoryUpdateProcess::LocalRepositoryUpdateProcess(
35	Model *model, bool force)
36	:
37	AbstractProcess(),
38	fModel(model),
39	fForce(force)
40{
41}
42
43
44LocalRepositoryUpdateProcess::~LocalRepositoryUpdateProcess()
45{
46}
47
48
49const char*
50LocalRepositoryUpdateProcess::Name() const
51{
52	return "LocalRepositoryUpdateProcess";
53}
54
55
56const char*
57LocalRepositoryUpdateProcess::Description() const
58{
59	return B_TRANSLATE("Fetching remote repository data");
60}
61
62
63status_t
64LocalRepositoryUpdateProcess::RunInternal()
65{
66	BPackageRoster roster;
67	BStringList repoNames;
68
69	if (Logger::IsInfoEnabled()) {
70		printf("[%s] will update local repositories\n", Name());
71	}
72
73	status_t result = roster.GetRepositoryNames(repoNames);
74
75	if (result == B_OK) {
76		DecisionProvider decisionProvider;
77		JobStateListener listener;
78		BContext context(decisionProvider, listener);
79		BRepositoryCache cache;
80
81		for (
82			int32 i = 0;
83			result == B_OK && i < repoNames.CountStrings() && !WasStopped();
84			++i) {
85			result = _RunForRepositoryName(repoNames.StringAt(i), context,
86				roster, &cache);
87		}
88	} else {
89		_NotifyError(strerror(result));
90		result = B_ERROR;
91	}
92
93	if (result == B_OK && Logger::IsInfoEnabled()) {
94		printf("[%s] did update %" B_PRIi32 " local repositories\n",
95			Name(), repoNames.CountStrings());
96	}
97
98	return result;
99}
100
101status_t
102LocalRepositoryUpdateProcess::_RunForRepositoryName(const BString& repoName,
103	BPackageKit::BContext& context, BPackageKit::BPackageRoster& roster,
104	BPackageKit::BRepositoryCache* cache)
105{
106	status_t result = B_ERROR;
107	BRepositoryConfig repoConfig;
108	result = roster.GetRepositoryConfig(repoName, &repoConfig);
109	if (result == B_OK) {
110		if (roster.GetRepositoryCache(repoName, cache) != B_OK || fForce) {
111			try {
112				BRefreshRepositoryRequest refreshRequest(context, repoConfig);
113				result = refreshRequest.Process();
114				result = B_OK;
115			} catch (BFatalErrorException ex) {
116				_NotifyError(ex.Message(), ex.Details());
117			} catch (BException ex) {
118				_NotifyError(ex.Message());
119			}
120		}
121	} else {
122		_NotifyError(strerror(result));
123	}
124
125	return result;
126}
127
128
129void
130LocalRepositoryUpdateProcess::_NotifyError(const BString& error) const
131{
132	_NotifyError(error, "");
133}
134
135
136void
137LocalRepositoryUpdateProcess::_NotifyError(const BString& error,
138	const BString& details) const
139{
140	printf("an error has arisen updating the local repositories : %s\n",
141		error.String());
142
143	BString alertText(B_TRANSLATE("An error occurred while refreshing the "
144		"repository: %error%"));
145	alertText.ReplaceFirst("%error%", error);
146
147	if (!details.IsEmpty()) {
148		alertText.Append(" (");
149		alertText.Append(details);
150		alertText.Append(")");
151	}
152
153	AppUtils::NotifySimpleError(
154		B_TRANSLATE("Repository update error"),
155		alertText);
156}