Skip to content

Commit 29858d0

Browse files
authored
Merge pull request #7807 from nextcloud/bugfix/migration
Bugfix migration from legacy clients.
2 parents c21d706 + 417f692 commit 29858d0

File tree

6 files changed

+128
-117
lines changed

6 files changed

+128
-117
lines changed

src/gui/accountmanager.cpp

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ constexpr auto unbrandedRelativeConfigLocationC = "/Nextcloud/nextcloud.cfg";
7878
constexpr auto unbrandedCfgFileNameC = "nextcloud.cfg";
7979

8080
// The maximum versions that this client can read
81-
constexpr auto maxAccountsVersion = 2;
82-
constexpr auto maxAccountVersion = 1;
81+
constexpr auto maxAccountsVersion = 13;
82+
constexpr auto maxAccountVersion = 13;
8383

8484
constexpr auto serverHasValidSubscriptionC = "serverHasValidSubscription";
8585
}
@@ -150,6 +150,9 @@ void AccountManager::backwardMigrationSettingsKeys(QStringList *deleteKeys, QStr
150150
const auto settings = ConfigFile::settingsWithGroup(QLatin1String(accountsC));
151151
const auto accountsVersion = settings->value(QLatin1String(versionC)).toInt();
152152

153+
qCInfo(lcAccountManager) << "Checking for accounts versions.";
154+
qCInfo(lcAccountManager) << "Config accounts version:" << accountsVersion;
155+
qCInfo(lcAccountManager) << "Max accounts Version is set to:" << maxAccountsVersion;
153156
if (accountsVersion <= maxAccountsVersion) {
154157
const auto settingsChildGroups = settings->childGroups();
155158
for (const auto &accountId : settingsChildGroups) {
@@ -158,6 +161,7 @@ void AccountManager::backwardMigrationSettingsKeys(QStringList *deleteKeys, QStr
158161

159162
if (accountVersion > maxAccountVersion) {
160163
ignoreKeys->append(settings->group());
164+
qCInfo(lcAccountManager) << "Ignoring account" << accountId << "because of version" << accountVersion;
161165
}
162166
settings->endGroup();
163167
}
@@ -236,41 +240,8 @@ bool AccountManager::restoreFromLegacySettings()
236240
}
237241
}
238242

239-
// Check the theme url to see if it is the same url that the oC config was for
240-
const auto overrideUrl = Theme::instance()->overrideServerUrl();
241-
const auto cleanOverrideUrl = overrideUrl.endsWith('/') ? overrideUrl.chopped(1) : overrideUrl;
242-
qCInfo(lcAccountManager) << "Migrate: overrideUrl" << cleanOverrideUrl;
243-
244-
if (!cleanOverrideUrl.isEmpty()) {
245-
oCSettings->beginGroup(QLatin1String(accountsC));
246-
const auto accountsChildGroups = oCSettings->childGroups();
247-
for (const auto &accountId : accountsChildGroups) {
248-
oCSettings->beginGroup(accountId);
249-
const auto oCUrl = oCSettings->value(QLatin1String(urlC)).toString();
250-
const auto cleanOCUrl = oCUrl.endsWith('/') ? oCUrl.chopped(1) : oCUrl;
251-
252-
// in case the urls are equal reset the settings object to read from
253-
// the ownCloud settings object
254-
qCInfo(lcAccountManager) << "Migrate oC config if " << cleanOCUrl << " == " << cleanOverrideUrl << ":"
255-
<< (cleanOCUrl == cleanOverrideUrl ? "Yes" : "No");
256-
if (cleanOCUrl == cleanOverrideUrl) {
257-
qCInfo(lcAccountManager) << "Copy settings" << oCSettings->allKeys().join(", ");
258-
oCSettings->endGroup(); // current accountID group
259-
oCSettings->endGroup(); // accounts group
260-
settings = std::move(oCSettings);
261-
break;
262-
}
263-
264-
oCSettings->endGroup();
265-
}
266-
267-
if (oCSettings) {
268-
oCSettings->endGroup();
269-
}
270-
} else {
271-
qCInfo(lcAccountManager) << "Copy settings" << oCSettings->allKeys().join(", ");
272-
settings = std::move(oCSettings);
273-
}
243+
qCInfo(lcAccountManager) << "Copy settings" << oCSettings->allKeys().join(", ");
244+
settings = std::move(oCSettings);
274245

275246
ConfigFile::setDiscoveredLegacyConfigPath(configFileInfo.canonicalPath());
276247
break;

src/gui/application.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ bool Application::configVersionMigration()
143143
const auto versionChanged = previousVersion != currentVersion;
144144
const auto downgrading = previousVersion > currentVersion;
145145

146+
if (versionChanged) {
147+
qCInfo(lcApplication) << "Version changed. Removing updater settings from config.";
148+
configFile.cleanUpdaterConfiguration();
149+
}
150+
146151
if (!versionChanged && !(!deleteKeys.isEmpty() || (!ignoreKeys.isEmpty() && versionChanged))) {
147152
return true;
148153
}
@@ -194,13 +199,16 @@ bool Application::configVersionMigration()
194199
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
195200
return false;
196201
}
202+
}
197203

204+
if (!deleteKeys.isEmpty()) {
198205
auto settings = ConfigFile::settingsWithGroup("foo");
199206
settings->endGroup();
200207

201208
// Wipe confusing keys from the future, ignore the others
202209
for (const auto &badKey : std::as_const(deleteKeys)) {
203210
settings->remove(badKey);
211+
qCInfo(lcApplication) << "Migration: removed" << badKey << "key from settings.";
204212
}
205213
}
206214

@@ -236,40 +244,40 @@ Application::Application(int &argc, char **argv)
236244
setWindowIcon(_theme->applicationIcon());
237245

238246
if (!ConfigFile().exists()) {
239-
// Migrate from version <= 2.4
240247
setApplicationName(_theme->appNameGUI());
241-
// We need to use the deprecated QDesktopServices::storageLocation because of its Qt4
242-
// behavior of adding "data" to the path
243-
QString oldDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/data/" + organizationName() + "/" + applicationName();
244-
if (oldDir.endsWith('/')) oldDir.chop(1); // macOS 10.11.x does not like trailing slash for rename/move.
248+
QString legacyDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/" + APPLICATION_CONFIG_NAME;
249+
250+
if (legacyDir.endsWith('/')) {
251+
legacyDir.chop(1); // macOS 10.11.x does not like trailing slash for rename/move.
252+
}
245253
setApplicationName(_theme->appName());
246-
if (QFileInfo(oldDir).isDir()) {
254+
if (QFileInfo(legacyDir).isDir()) {
247255
auto confDir = ConfigFile().configPath();
248256

249257
// macOS 10.11.x does not like trailing slash for rename/move.
250258
if (confDir.endsWith('/')) {
251259
confDir.chop(1);
252260
}
253261

254-
qCInfo(lcApplication) << "Migrating old config from" << oldDir << "to" << confDir;
262+
qCInfo(lcApplication) << "Migrating old config from" << legacyDir << "to" << confDir;
255263

256-
if (!QFile::rename(oldDir, confDir)) {
257-
qCWarning(lcApplication) << "Failed to move the old config directory to its new location (" << oldDir << "to" << confDir << ")";
264+
if (!QFile::rename(legacyDir, confDir)) {
265+
qCWarning(lcApplication) << "Failed to move the old config directory to its new location (" << legacyDir << "to" << confDir << ")";
258266

259267
// Try to move the files one by one
260268
if (QFileInfo(confDir).isDir() || QDir().mkdir(confDir)) {
261-
const QStringList filesList = QDir(oldDir).entryList(QDir::Files);
269+
const QStringList filesList = QDir(legacyDir).entryList(QDir::Files);
262270
qCInfo(lcApplication) << "Will move the individual files" << filesList;
263271
for (const auto &name : filesList) {
264-
if (!QFile::rename(oldDir + "/" + name, confDir + "/" + name)) {
272+
if (!QFile::rename(legacyDir + "/" + name, confDir + "/" + name)) {
265273
qCWarning(lcApplication) << "Fallback move of " << name << "also failed";
266274
}
267275
}
268276
}
269277
} else {
270278
#ifndef Q_OS_WIN
271279
// Create a symbolic link so a downgrade of the client would still find the config.
272-
QFile::link(confDir, oldDir);
280+
QFile::link(confDir, legacyDir);
273281
#endif
274282
}
275283
}

src/gui/folder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,9 @@ class FolderDefinition
8585
* (version remains readable by 2.5.1)
8686
* Version 3: introduction of new windows vfs mode in 2.6.0
8787
* Version 5: available in oC client 4.0.0 and 4.2.0
88+
* Version 13: available in oC client 5.2.0 and 5.3.1
8889
*/
89-
static int maxSettingsVersion() { return 5; }
90+
static int maxSettingsVersion() { return 13; }
9091

9192
/// Ensure / as separator and trailing /.
9293
static QString prepareLocalPath(const QString &path);

src/gui/folderman.cpp

Lines changed: 79 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
namespace {
4343
constexpr auto settingsAccountsC = "Accounts";
4444
constexpr auto settingsFoldersC = "Folders";
45+
constexpr auto settingsFoldersWithPlaceholdersC = "FoldersWithPlaceholders";
4546
constexpr auto settingsVersionC = "version";
4647
constexpr auto maxFoldersVersion = 1;
4748

@@ -388,16 +389,19 @@ void FolderMan::backwardMigrationSettingsKeys(QStringList *deleteKeys, QStringLi
388389
auto processSubgroup = [&](const QString &name) {
389390
settings->beginGroup(name);
390391
const auto foldersVersion = settings->value(QLatin1String(settingsVersionC), 1).toInt();
392+
qCInfo(lcFolderMan) << "FolderDefinition::maxSettingsVersion:" << FolderDefinition::maxSettingsVersion();
391393
if (foldersVersion <= maxFoldersVersion) {
392394
for (const auto &folderAlias : settings->childGroups()) {
393395
settings->beginGroup(folderAlias);
394396
const auto folderVersion = settings->value(QLatin1String(settingsVersionC), 1).toInt();
395397
if (folderVersion > FolderDefinition::maxSettingsVersion()) {
398+
qCInfo(lcFolderMan) << "Ignoring folder:" << folderAlias << "version:" << folderVersion;
396399
ignoreKeys->append(settings->group());
397400
}
398401
settings->endGroup();
399402
}
400403
} else {
404+
qCInfo(lcFolderMan) << "Ignoring group:" << name << "version:" << foldersVersion;
401405
deleteKeys->append(settings->group());
402406
}
403407
settings->endGroup();
@@ -523,89 +527,97 @@ void FolderMan::setupLegacyFolder(const QString &fileNamePath, AccountState *acc
523527
return;
524528
}
525529

526-
settings.beginGroup(settingsAccountsC);
527-
qCDebug(lcFolderMan) << "try to migrate accountId:" << accountState->account()->id();
528-
settings.beginGroup(accountState->account()->id());
529-
settings.beginGroup(settingsFoldersC);
530-
531-
if (settings.childGroups().isEmpty()) {
532-
qCDebug(lcFolderMan) << "there are no legacy folders for accountId:" << accountState->account()->id();
533-
return;
534-
}
535-
536-
const auto childGroups = settings.childGroups();
537-
for (const auto &alias : childGroups) {
538-
settings.beginGroup(alias);
539-
qCDebug(lcFolderMan) << "try to migrate folder alias:" << alias;
540-
541-
const auto path = settings.value(QLatin1String("localPath")).toString();
542-
const auto targetPath = settings.value(QLatin1String("targetPath")).toString();
543-
const auto journalPath = settings.value(QLatin1String("journalPath")).toString();
544-
const auto paused = settings.value(QLatin1String("paused"), false).toBool();
545-
const auto ignoreHiddenFiles = settings.value(QLatin1String("ignoreHiddenFiles"), false).toBool();
546-
547-
if (path.isEmpty()) {
548-
qCDebug(lcFolderMan) << "localPath is empty";
549-
settings.endGroup();
550-
continue;
551-
}
552-
553-
if (targetPath.isEmpty()) {
554-
qCDebug(lcFolderMan) << "targetPath is empty";
555-
settings.endGroup();
556-
continue;
530+
auto migrateFoldersGroup = [&](const QString &folderGroupName) {
531+
const auto childGroups = settings.childGroups();
532+
if (childGroups.isEmpty()) {
533+
qCDebug(lcFolderMan) << "There are no" << folderGroupName << "to migrate from account" << accountState->account()->id();
534+
return;
557535
}
536+
for (const auto &alias : childGroups) {
537+
settings.beginGroup(alias);
538+
qCDebug(lcFolderMan) << "try to migrate" << folderGroupName << "alias:" << alias;
539+
540+
const auto path = settings.value(QLatin1String("localPath")).toString();
541+
const auto targetPath = settings.value(QLatin1String("targetPath")).toString();
542+
const auto journalPath = settings.value(QLatin1String("journalPath")).toString();
543+
const auto paused = settings.value(QLatin1String("paused"), false).toBool();
544+
const auto ignoreHiddenFiles = settings.value(QLatin1String("ignoreHiddenFiles"), false).toBool();
545+
546+
if (path.isEmpty()) {
547+
qCDebug(lcFolderMan) << "localPath is empty";
548+
settings.endGroup();
549+
continue;
550+
}
558551

559-
if (journalPath.isEmpty()) {
560-
qCDebug(lcFolderMan) << "journalPath is empty";
561-
settings.endGroup();
562-
continue;
563-
}
552+
if (targetPath.isEmpty()) {
553+
qCDebug(lcFolderMan) << "targetPath is empty";
554+
settings.endGroup();
555+
continue;
556+
}
564557

565-
FolderDefinition folderDefinition;
566-
folderDefinition.alias = alias;
567-
folderDefinition.localPath = path;
568-
folderDefinition.targetPath = targetPath;
569-
folderDefinition.journalPath = journalPath;
570-
folderDefinition.paused = paused;
571-
folderDefinition.ignoreHiddenFiles = ignoreHiddenFiles;
572-
573-
if (const auto folder = addFolderInternal(folderDefinition, accountState, std::make_unique<VfsOff>())) {
574-
auto ok = true;
575-
auto legacyBlacklist = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
576-
&ok);
577-
if (!ok) {
578-
qCInfo(lcFolderMan) << "There was a problem retrieving the database selective sync for " << folder;
558+
if (journalPath.isEmpty()) {
559+
qCDebug(lcFolderMan) << "journalPath is empty";
560+
settings.endGroup();
561+
continue;
579562
}
580563

581-
legacyBlacklist << settings.value(QLatin1String("blackList")).toStringList();
582-
if (!legacyBlacklist.isEmpty()) {
583-
qCInfo(lcFolderMan) << "Legacy selective sync list found:" << legacyBlacklist;
584-
for (const auto &legacyFolder : legacyBlacklist) {
585-
folder->migrateBlackListPath(legacyFolder);
564+
qCDebug(lcFolderMan) << folderGroupName << "located at" << path;
565+
566+
FolderDefinition folderDefinition;
567+
folderDefinition.alias = alias;
568+
folderDefinition.localPath = path;
569+
folderDefinition.targetPath = targetPath;
570+
folderDefinition.journalPath = journalPath;
571+
folderDefinition.paused = paused;
572+
folderDefinition.ignoreHiddenFiles = ignoreHiddenFiles;
573+
574+
if (const auto folder = addFolderInternal(folderDefinition, accountState, std::make_unique<VfsOff>())) {
575+
auto ok = true;
576+
auto legacyBlacklist = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
577+
&ok);
578+
if (!ok) {
579+
qCInfo(lcFolderMan) << "There was a problem retrieving the database selective sync for " << folder;
580+
}
581+
582+
legacyBlacklist << settings.value(QLatin1String("blackList")).toStringList();
583+
if (!legacyBlacklist.isEmpty()) {
584+
qCInfo(lcFolderMan) << "Legacy selective sync list found:" << legacyBlacklist;
585+
for (const auto &legacyFolder : legacyBlacklist) {
586+
folder->migrateBlackListPath(legacyFolder);
587+
}
588+
settings.remove(QLatin1String("blackList"));
586589
}
587-
settings.remove(QLatin1String("blackList"));
588-
}
589590

590-
folder->saveToSettings();
591+
folder->saveToSettings();
591592

592-
qCInfo(lcFolderMan) << "Migrated!" << folder->path();
593-
settings.sync();
593+
qCInfo(lcFolderMan) << "Migrated!" << folder->path();
594+
settings.sync();
594595

595-
if (!folder) {
596-
continue;
597-
}
596+
if (!folder) {
597+
continue;
598+
}
598599

599-
scheduleFolder(folder);
600-
emit folderSyncStateChange(folder);
600+
scheduleFolder(folder);
601+
emit folderSyncStateChange(folder);
602+
}
603+
settings.endGroup(); // folder alias
601604
}
605+
};
602606

603-
settings.endGroup();
604-
}
607+
settings.beginGroup(settingsAccountsC);
608+
qCDebug(lcFolderMan) << "try to migrate accountId:" << accountState->account()->id();
609+
settings.beginGroup(accountState->account()->id());
605610

611+
settings.beginGroup(settingsFoldersWithPlaceholdersC);
612+
migrateFoldersGroup(settingsFoldersWithPlaceholdersC);
606613
settings.endGroup();
614+
615+
settings.beginGroup(settingsFoldersC);
616+
migrateFoldersGroup(settingsFoldersC);
607617
settings.endGroup();
608618

619+
settings.endGroup();
620+
settings.endGroup();
609621
return;
610622
}
611623

src/libsync/configfile.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,17 @@ QString ConfigFile::excludeFileFromSystem()
453453
return fi.absoluteFilePath();
454454
}
455455

456+
void OCC::ConfigFile::cleanUpdaterConfiguration()
457+
{
458+
QSettings settings(configFile(), QSettings::IniFormat);
459+
settings.beginGroup("Updater");
460+
settings.remove("autoUpdateAttempted");
461+
settings.remove("updateTargetVersion");
462+
settings.remove("updateTargetVersionString");
463+
settings.remove("updateAvailable");
464+
settings.sync();
465+
}
466+
456467
QString ConfigFile::backup(const QString &fileName) const
457468
{
458469
const QString baseFilePath = configPath() + fileName;
@@ -1260,6 +1271,12 @@ void ConfigFile::setupDefaultExcludeFilePaths(ExcludedFiles &excludedFiles)
12601271
const auto userList = cfg.excludeFile(ConfigFile::UserScope);
12611272
const auto legacyList = cfg.excludeFile(ConfigFile::LegacyScope);
12621273

1274+
if (Theme::instance()->isBranded() && QFile::exists(systemList) && QFile::copy(systemList, userList)) {
1275+
qCInfo(lcConfigFile) << "Overwriting user list" << userList << "with system list" << systemList;
1276+
excludedFiles.addExcludeFilePath(systemList);
1277+
return;
1278+
}
1279+
12631280
if (!QFile::exists(userList)) {
12641281
qCInfo(lcConfigFile) << "User defined ignore list does not exist:" << userList;
12651282

src/libsync/configfile.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class OWNCLOUDSYNC_EXPORT ConfigFile
4848
[[nodiscard]] QString excludeFile(Scope scope) const;
4949
static QString excludeFileFromSystem(); // doesn't access config dir
5050

51+
void cleanUpdaterConfiguration();
52+
5153
/**
5254
* Creates a backup of any given fileName in the config folder
5355
*

0 commit comments

Comments
 (0)