/
ssurepomanager.cpp
347 lines (275 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
/**
* @file ssurepomanager.cpp
* @copyright 2013 Jolla Ltd.
* @author Bernd Wachter <bwachter@lart.info>
* @date 2013
*/
#include <QStringList>
#include <QRegExp>
#include <QDirIterator>
12
#include "sandbox_p.h"
13
14
#include "ssudeviceinfo.h"
#include "ssurepomanager.h"
15
#include "ssucoreconfig.h"
16
#include "ssusettings.h"
17
#include "ssulog.h"
18
#include "ssuvariables.h"
19
#include "ssufeaturemanager.h"
20
21
22
23
24
25
26
27
#include "ssu.h"
#include "../constants.h"
SsuRepoManager::SsuRepoManager(): QObject() {
}
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void SsuRepoManager::add(QString repo, QString repoUrl){
SsuCoreConfig *ssuSettings = SsuCoreConfig::instance();
if (repoUrl == ""){
// just enable a repository which has URL in repos.ini
QStringList enabledRepos;
if (ssuSettings->contains("enabled-repos"))
enabledRepos = ssuSettings->value("enabled-repos").toStringList();
enabledRepos.append(repo);
enabledRepos.removeDuplicates();
ssuSettings->setValue("enabled-repos", enabledRepos);
} else
ssuSettings->setValue("repository-urls/" + repo, repoUrl);
ssuSettings->sync();
}
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
QString SsuRepoManager::caCertificatePath(QString domain){
SsuCoreConfig *settings = SsuCoreConfig::instance();
SsuSettings repoSettings(SSU_REPO_CONFIGURATION, QSettings::IniFormat);
if (domain.isEmpty())
domain = settings->domain();
QString ca = SsuVariables::variable(&repoSettings, domain + "-domain",
"_ca-certificate").toString();
if (!ca.isEmpty())
return ca;
// compat setting, can go away after some time
if (settings->contains("ca-certificate"))
return settings->value("ca-certificate").toString();
return "";
}
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
void SsuRepoManager::disable(QString repo){
SsuCoreConfig *ssuSettings = SsuCoreConfig::instance();
QStringList disabledRepos;
if (ssuSettings->contains("disabled-repos"))
disabledRepos = ssuSettings->value("disabled-repos").toStringList();
disabledRepos.append(repo);
disabledRepos.removeDuplicates();
ssuSettings->setValue("disabled-repos", disabledRepos);
ssuSettings->sync();
}
void SsuRepoManager::enable(QString repo){
SsuCoreConfig *ssuSettings = SsuCoreConfig::instance();
QStringList disabledRepos;
if (ssuSettings->contains("disabled-repos"))
disabledRepos = ssuSettings->value("disabled-repos").toStringList();
disabledRepos.removeAll(repo);
disabledRepos.removeDuplicates();
ssuSettings->setValue("disabled-repos", disabledRepos);
ssuSettings->sync();
}
void SsuRepoManager::remove(QString repo){
SsuCoreConfig *ssuSettings = SsuCoreConfig::instance();
if (ssuSettings->contains("repository-urls/" + repo))
ssuSettings->remove("repository-urls/" + repo);
if (ssuSettings->contains("enabled-repos")){
QStringList enabledRepos = ssuSettings->value("enabled-repos").toStringList();
if (enabledRepos.contains(repo)){
enabledRepos.removeAll(repo);
enabledRepos.removeDuplicates();
ssuSettings->setValue("enabled-repos", enabledRepos);
}
}
ssuSettings->sync();
}
110
111
112
113
114
115
QStringList SsuRepoManager::repos(bool rnd, int filter){
SsuDeviceInfo deviceInfo;
return repos(rnd, deviceInfo, filter);
}
116
// @todo the non-device specific repository resolving should move from deviceInfo to repomanager
117
118
119
120
QStringList SsuRepoManager::repos(bool rnd, SsuDeviceInfo &deviceInfo, int filter){
QStringList result;
result = deviceInfo.repos(rnd, filter);
121
122
123
SsuFeatureManager featureManager;
result.append(featureManager.repos(rnd, filter));
124
125
126
127
128
129
result.sort();
result.removeDuplicates();
return result;
}
130
131
132
133
134
135
136
137
void SsuRepoManager::update(){
// - delete all non-ssu managed repositories (missing ssu_ prefix)
// - create list of ssu-repositories for current adaptation
// - go through ssu_* repositories, delete all which are not in the list; write others
SsuDeviceInfo deviceInfo;
QStringList ssuFilters;
138
139
SsuCoreConfig *ssuSettings = SsuCoreConfig::instance();
int deviceMode = ssuSettings->value("deviceMode").toInt();
140
141
142
143
144
145
SsuLog *ssuLog = SsuLog::instance();
// if device is misconfigured, always assume release mode
bool rndMode = false;
146
if ((deviceMode & Ssu::DisableRepoManager) == Ssu::DisableRepoManager){
147
148
149
150
151
152
153
ssuLog->print(LOG_INFO, "Repo management requested, but not enabled (option 'deviceMode')");
return;
}
if ((deviceMode & Ssu::RndMode) == Ssu::RndMode)
rndMode = true;
154
// get list of device-specific repositories...
155
QStringList repositoryList = repos(rndMode);
156
157
158
159
// strict mode enabled -> delete all repositories not prefixed by ssu
// assume configuration error if there are no device repos, and don't delete
// anything, even in strict mode
160
if ((deviceMode & Ssu::LenientMode) != Ssu::LenientMode && !repositoryList.isEmpty()){
161
QDirIterator it(Sandbox::map(ZYPP_REPO_PATH), QDir::AllEntries|QDir::NoDot|QDir::NoDotDot);
162
163
164
165
166
167
168
169
170
171
172
while (it.hasNext()){
it.next();
if (it.fileName().left(4) != "ssu_"){
ssuLog->print(LOG_INFO, "Strict mode enabled, removing unmanaged repository " + it.fileName());
QFile(it.filePath()).remove();
}
}
}
// ... delete all ssu-managed repositories not valid for this device ...
ssuFilters.append("ssu_*");
173
QDirIterator it(Sandbox::map(ZYPP_REPO_PATH), ssuFilters);
174
175
176
177
178
179
while (it.hasNext()){
QString f = it.next();
QStringList parts = it.fileName().split("_");
// repo file structure is ssu_<reponame>_<rnd|release>.repo -> splits to 3 parts
if (parts.count() == 3){
180
if (!repositoryList.contains(parts.at(1)) ||
181
parts.at(2) != (rndMode ? "rnd.repo" : "release.repo" ))
182
183
184
185
186
187
QFile(it.filePath()).remove();
} else
QFile(it.filePath()).remove();
}
// ... and create all repositories required for this device
188
foreach (const QString &repo, repositoryList){
189
190
191
192
193
194
195
196
197
// repo should be used where a unique identifier for silly human brains, or
// zypper is required. repoName contains the shortened form for ssu use
QString repoName = repo;
QString debugSplit;
if (repo.endsWith("-debuginfo")){
debugSplit = "&debug";
repoName = repo.left(repo.size() - 10);
}
198
QString repoFilePath = QString("%1/ssu_%2_%3.repo")
199
.arg(Sandbox::map(ZYPP_REPO_PATH))
200
201
202
.arg(repo)
.arg(rndMode ? "rnd" : "release");
203
if (url(repoName, rndMode) == ""){
204
205
206
207
208
209
210
211
212
213
// TODO, repositories should only be disabled if they're not required
// for this machine. For required repositories error is better
QTextStream qerr(stderr);
qerr << "Repository " << repo << " does not contain valid URL, skipping and disabling." << endl;
disable(repo);
QFile(repoFilePath).remove();
continue;
}
QFile repoFile(repoFilePath);
214
215
216
217
218
219
220
221
222
223
224
225
226
if (repoFile.open(QIODevice::WriteOnly | QIODevice::Text)){
QTextStream out(&repoFile);
// TODO, add -rnd or -release if we want to support having rnd and
// release enabled at the same time
out << "[" << repo << "]" << endl
<< "name=" << repo << endl
<< "failovermethod=priority" << endl
<< "type=rpm-md" << endl
<< "gpgcheck=0" << endl
<< "enabled=1" << endl;
if (rndMode)
227
out << "baseurl=plugin:ssu?rnd&repo=" << repoName << debugSplit << endl;
228
else
229
out << "baseurl=plugin:ssu?repo=" << repoName << debugSplit << endl;
230
231
232
233
234
out.flush();
}
}
}
235
236
QStringList SsuRepoManager::repoVariables(QHash<QString, QString> *storageHash, bool rnd){
237
238
SsuVariables var;
SsuCoreConfig *settings = SsuCoreConfig::instance();
239
QStringList configSections;
240
SsuSettings repoSettings(SSU_REPO_CONFIGURATION, QSettings::IniFormat);
241
242
// fill in all arbitrary variables from ssu.ini
243
var.variableSection(settings, "repository-url-variables", storageHash);
244
245
// add/overwrite some of the variables with sane ones
246
247
248
if (rnd){
storageHash->insert("flavour",
repoSettings.value(
249
settings->flavour()+"-flavour/flavour-pattern").toString());
250
251
storageHash->insert("flavourPattern",
repoSettings.value(
252
settings->flavour()+"-flavour/flavour-pattern").toString());
253
storageHash->insert("flavourName", settings->flavour());
254
255
256
257
configSections << settings->flavour()+"-flavour" << "rnd" << "all";
// Make it possible to give any values with the flavour as well.
// These values can be overridden later with domain if needed.
258
var.variableSection(&repoSettings, settings->flavour()+"-flavour", storageHash);
259
260
261
262
} else {
configSections << "release" << "all";
}
263
storageHash->insert("release", settings->release(rnd));
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
if (!storageHash->contains("debugSplit"))
storageHash->insert("debugSplit", "packages");
if (!storageHash->contains("arch"))
storageHash->insert("arch", settings->value("arch").toString());
return configSections;
}
// RND repos have flavour (devel, testing, release), and release (latest, next)
// Release repos only have release (latest, next, version number)
QString SsuRepoManager::url(QString repoName, bool rndRepo,
QHash<QString, QString> repoParameters,
QHash<QString, QString> parametersOverride){
QString r;
QStringList configSections;
SsuVariables var;
SsuCoreConfig *settings = SsuCoreConfig::instance();
283
SsuSettings repoSettings(SSU_REPO_CONFIGURATION, QSettings::IniFormat);
284
SsuDeviceInfo deviceInfo;
285
286
287
288
289
290
291
// set debugSplit for incorrectly configured debuginfo repositories (debugSplit
// should already be passed by the url resolver); might be overriden later on,
// if required
if (repoName.endsWith("-debuginfo") && !repoParameters.contains("debugSplit"))
repoParameters.insert("debugSplit", "debug");
292
configSections = repoVariables(&repoParameters, rndRepo);
293
294
295
296
297
298
299
300
301
// Override device model (and therefore all the family, ... stuff)
if (parametersOverride.contains("model"))
deviceInfo.setDeviceModel(parametersOverride.value("model"));
repoParameters.insert("deviceFamily", deviceInfo.deviceFamily());
repoParameters.insert("deviceModel", deviceInfo.deviceModel());
302
repoName = deviceInfo.adaptationVariables(repoName, &repoParameters);
303
304
305
306
307
308
309
310
311
312
313
314
QString domain;
if (parametersOverride.contains("domain")){
domain = parametersOverride.value("domain");
domain.replace("-", ":");
} else
domain = settings->domain();
// variableSection does autodetection for the domain default section
var.variableSection(&repoSettings,
domain + "-domain", &repoParameters);
315
316
317
318
319
320
321
322
// override arbitrary variables, mostly useful for generating mic URLs
QHash<QString, QString>::const_iterator i = parametersOverride.constBegin();
while (i != parametersOverride.constEnd()){
repoParameters.insert(i.key(), i.value());
i++;
}
323
324
325
326
327
328
329
// search for URLs for repositories. Lookup order is:
// 1. overrides in ssu.ini
// 2. URLs from features
// 3. URLs from repos.ini
SsuFeatureManager featureManager;
330
331
if (settings->contains("repository-urls/" + repoName))
r = settings->value("repository-urls/" + repoName).toString();
332
333
else if (featureManager.url(repoName, rndRepo) != "")
r = featureManager.url(repoName, rndRepo);
334
335
else {
foreach (const QString §ion, configSections){
336
337
338
339
repoSettings.beginGroup(section);
if (repoSettings.contains(repoName)){
r = repoSettings.value(repoName).toString();
repoSettings.endGroup();
340
341
break;
}
342
repoSettings.endGroup();
343
344
345
346
347
}
}
return var.resolveString(r, &repoParameters);
}