Skip to content

Commit 8d24cf8

Browse files
erikjvmodSpike
andauthored
Remove OC10SyncRoot (#12422)
* Remove OC10SyncRoot Also simplify the path validity checks. * Fix review comments - remove static from methods accessing the `FolderMan` instance - renamed method for clarity - improve entry point method documentation Also use `tr()` calls instead of `FolderMan::tr()` for member methods. * Improve doc for `findExistingFolderAndCheckValidity` --------- Co-authored-by: modSpike <lisa.reese@kiteworks.com>
1 parent 7be957f commit 8d24cf8

File tree

6 files changed

+166
-145
lines changed

6 files changed

+166
-145
lines changed

src/gui/folderman.cpp

Lines changed: 63 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ void FolderMan::saveFolder(Folder *folder)
761761
saveFolder(folder, settings);
762762
}
763763

764-
Folder *FolderMan::folderForPath(const QString &path, QString *relativePath)
764+
Folder *FolderMan::folderForPath(const QString &path, QString *relativePath) const
765765
{
766766
QString absolutePath = QDir::cleanPath(path) + QLatin1Char('/');
767767

@@ -912,29 +912,40 @@ static QString canonicalPath(const QString &path)
912912

913913
static QString checkPathForSyncRootMarkingRecursive(const QString &path, FolderMan::NewFolderType folderType, const QUuid &accountUuid)
914914
{
915+
// First do basic checks if this path is usable
916+
const QFileInfo selectedPathInfo(path);
917+
if (!selectedPathInfo.isDir()) {
918+
return FolderMan::tr("The selected path is not a folder.");
919+
}
920+
921+
if (numberOfSyncJournals(selectedPathInfo.filePath()) != 0) {
922+
return FolderMan::tr("The folder %1 is used in a folder sync connection.").arg(QDir::toNativeSeparators(selectedPathInfo.filePath()));
923+
}
924+
925+
// Check for sync root markings in this folder
915926
std::pair<QString, QUuid> existingTags = Utility::getDirectorySyncRootMarkings(path);
916927
if (!existingTags.first.isEmpty()) {
917928
if (existingTags.first != Theme::instance()->orgDomainName()) {
918929
// another application uses this as spaces root folder
919-
return FolderMan::tr("Folder '%1' is already in use by application %2!").arg(path, existingTags.first);
930+
return FolderMan::tr("Folder '%1' is already in use by application %2.").arg(path, existingTags.first);
920931
}
921932

922933
// Looks good, it's our app, let's check the account tag:
923934
switch (folderType) {
924935
case FolderMan::NewFolderType::SpacesFolder:
925936
if (existingTags.second == accountUuid) {
926-
// Nice, that's what we like, the sync root for our account in our app. No error.
937+
// Nice, that's what we like, the sync root for our account in our app. No error, and we don't need to check the parent folders.
927938
return {};
928939
}
929940
[[fallthrough]];
930-
case FolderMan::NewFolderType::OC10SyncRoot:
931-
[[fallthrough]];
932941
case FolderMan::NewFolderType::SpacesSyncRoot:
933942
// It's our application but we don't want to create a spaces folder, so it must be another space root
934943
return FolderMan::tr("Folder '%1' is already in use by another account.").arg(path);
935944
}
936945
}
937946

947+
// This folder is ok, but check the parent folders if they are used
948+
938949
QString parent = QFileInfo(path).path();
939950
if (parent == path) { // root dir, stop recursing
940951
return {};
@@ -943,51 +954,7 @@ static QString checkPathForSyncRootMarkingRecursive(const QString &path, FolderM
943954
return checkPathForSyncRootMarkingRecursive(parent, folderType, accountUuid);
944955
}
945956

946-
QString FolderMan::checkPathValidityRecursive(const QString &path, FolderMan::NewFolderType folderType, const QUuid &accountUuid)
947-
{
948-
if (path.isEmpty()) {
949-
return FolderMan::tr("No valid folder selected!");
950-
}
951-
952-
#ifdef Q_OS_WIN
953-
Utility::NtfsPermissionLookupRAII ntfs_perm;
954-
#endif
955-
956-
auto pathLengthCheck = Folder::checkPathLength(path);
957-
if (!pathLengthCheck) {
958-
return pathLengthCheck.error();
959-
}
960-
961-
const QFileInfo selectedPathInfo(path);
962-
if (!selectedPathInfo.exists()) {
963-
const QString parentPath = selectedPathInfo.path();
964-
if (parentPath != path) {
965-
return checkPathValidityRecursive(parentPath, folderType, accountUuid);
966-
}
967-
return FolderMan::tr("The selected path does not exist!");
968-
}
969-
970-
if (numberOfSyncJournals(selectedPathInfo.filePath()) != 0) {
971-
return FolderMan::tr("The folder %1 is used in a folder sync connection!").arg(QDir::toNativeSeparators(selectedPathInfo.filePath()));
972-
}
973-
974-
// At this point we know there is no syncdb in the parent hierarchy, check for spaces sync root.
975-
976-
if (!selectedPathInfo.isDir()) {
977-
return FolderMan::tr("The selected path is not a folder!");
978-
}
979-
980-
if (!selectedPathInfo.isWritable()) {
981-
return FolderMan::tr("You have no permission to write to the selected folder!");
982-
}
983-
984-
return checkPathForSyncRootMarkingRecursive(path, folderType, accountUuid);
985-
}
986-
987957
/*
988-
* OC10 folder:
989-
* - sync root not in syncdb folder
990-
* - sync root not in spaces root
991958
* with spaces:
992959
* - spaces sync root not in syncdb folder
993960
* - spaces sync root not in another spaces sync root
@@ -996,41 +963,71 @@ QString FolderMan::checkPathValidityRecursive(const QString &path, FolderMan::Ne
996963
* - space *can* be in sync root
997964
* - space not in spaces sync root of other account (check with account uuid)
998965
*/
999-
QString FolderMan::checkPathValidityForNewFolder(const QString &path, NewFolderType folderType, const QUuid &accountUuid) const
966+
QString FolderMan::checkPathValidity(const QString &path, NewFolderType folderType, const QUuid &accountUuid) const
1000967
{
1001-
// check if the local directory isn't used yet in another ownCloud sync
968+
// Do checks against existing folders. This catches cases where:
969+
// - the user deleted a folder from the filesystem, but there is still a folder sync connection in the configuration
970+
// - check if this folder contains other folders for spaces
971+
// If so, error out.
1002972
const auto cs = Utility::fsCaseSensitivity();
1003-
1004973
const QString userDir = QDir::cleanPath(canonicalPath(path)) + QLatin1Char('/');
1005974
for (auto f : folders()) {
1006975
const QString folderDir = QDir::cleanPath(canonicalPath(f->path())) + QLatin1Char('/');
1007-
1008976
if (QString::compare(folderDir, userDir, cs) == 0) {
1009-
return tr("There is already a sync from the server to this local folder. "
1010-
"Please pick another local folder!");
977+
return tr("There is already a sync from the server to this local folder.");
1011978
}
1012979
if (FileSystem::isChildPathOf(folderDir, userDir)) {
1013-
return tr("The local folder %1 already contains a folder used in a folder sync connection. "
1014-
"Please pick another local folder!")
980+
return tr("The local folder %1 already contains a folder used in a folder sync connection.")
1015981
.arg(QDir::toNativeSeparators(path));
1016982
}
1017983

1018984
if (FileSystem::isChildPathOf(userDir, folderDir)) {
1019-
return tr("The local folder %1 is already contained in a folder used in a folder sync connection. "
1020-
"Please pick another local folder!")
985+
return tr("The local folder %1 is already contained in a folder used in a folder sync connection.")
1021986
.arg(QDir::toNativeSeparators(path));
1022987
}
1023988
}
1024989

1025-
const auto result = checkPathValidityRecursive(path, folderType, accountUuid);
1026-
if (!result.isEmpty()) {
1027-
return tr("%1 Please pick another local folder!").arg(result);
990+
// Now run filesystem based checks
991+
return findExistingFolderAndCheckValidity(path, folderType, accountUuid);
992+
}
993+
994+
QString FolderMan::findExistingFolderAndCheckValidity(const QString &path, NewFolderType folderType, const QUuid &accountUuid)
995+
{
996+
if (path.isEmpty()) {
997+
return tr("No valid folder selected.");
1028998
}
1029-
return {};
999+
1000+
#ifdef Q_OS_WIN
1001+
Utility::NtfsPermissionLookupRAII ntfs_perm;
1002+
#endif
1003+
1004+
auto pathLengthCheck = Folder::checkPathLength(path);
1005+
if (!pathLengthCheck) {
1006+
return pathLengthCheck.error();
1007+
}
1008+
1009+
// If this is a new folder, recurse up to the first parent that exists, to see if we can use that to create a new folder
1010+
const QFileInfo selectedPathInfo(path);
1011+
if (!selectedPathInfo.exists()) {
1012+
const QString parentPath = selectedPathInfo.path();
1013+
if (parentPath != path) {
1014+
return findExistingFolderAndCheckValidity(parentPath, folderType, accountUuid);
1015+
}
1016+
return tr("The selected path does not exist.");
1017+
}
1018+
1019+
// At this point we have an existing folder, so check if we can create files/folders here.
1020+
// Note: we don't need to write to any parent, so we don't need to check writablility when traversing the parents.
1021+
if (!selectedPathInfo.isWritable()) {
1022+
return tr("You have no permission to write to the selected folder.");
1023+
}
1024+
1025+
// Now check if none of the parents is already used.
1026+
return checkPathForSyncRootMarkingRecursive(canonicalPath(path), folderType, accountUuid);
10301027
}
10311028

10321029
QString FolderMan::findGoodPathForNewSyncFolder(
1033-
const QString &basePath, const QString &newFolder, FolderMan::NewFolderType folderType, const QUuid &accountUuid)
1030+
const QString &basePath, const QString &newFolder, FolderMan::NewFolderType folderType, const QUuid &accountUuid) const
10341031
{
10351032
OC_ASSERT(!accountUuid.isNull() || folderType == FolderMan::NewFolderType::SpacesSyncRoot);
10361033

@@ -1041,7 +1038,7 @@ QString FolderMan::findGoodPathForNewSyncFolder(
10411038
// possibly find a valid sync folder inside it.
10421039
// Example: Someone syncs their home directory. Then ~/foobar is not
10431040
// going to be an acceptable sync folder path for any value of foobar.
1044-
if (FolderMan::instance()->folderForPath(QFileInfo(normalisedPath).canonicalPath())) {
1041+
if (folderForPath(QFileInfo(normalisedPath).canonicalPath())) {
10451042
// Any path with that parent is going to be unacceptable,
10461043
// so just keep it as-is.
10471044
return canonicalPath(normalisedPath);
@@ -1050,7 +1047,7 @@ QString FolderMan::findGoodPathForNewSyncFolder(
10501047
{
10511048
QString folder = normalisedPath;
10521049
for (int attempt = 2; attempt <= 100; ++attempt) {
1053-
if (!QFileInfo::exists(folder) && FolderMan::instance()->checkPathValidityForNewFolder(folder, folderType, accountUuid).isEmpty()) {
1050+
if (!QFileInfo::exists(folder) && checkPathValidity(folder, folderType, accountUuid).isEmpty()) {
10541051
return canonicalPath(folder);
10551052
}
10561053
folder = normalisedPath + QStringLiteral(" (%1)").arg(attempt);

src/gui/folderman.h

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ class OWNCLOUDGUI_EXPORT FolderMan : public QObject
8585
* Or in case of a space folder, that if the new folder is in a Space sync root, it is the sync root of the same account.
8686
*/
8787
enum class NewFolderType {
88-
OC10SyncRoot, // todo: #43
8988
SpacesSyncRoot,
9089
SpacesFolder,
9190
};
@@ -130,8 +129,22 @@ class OWNCLOUDGUI_EXPORT FolderMan : public QObject
130129

131130
static QString suggestSyncFolder(NewFolderType folderType, const QUuid &accountUuid);
132131

133-
134-
static QString checkPathValidityRecursive(const QString &path, FolderMan::NewFolderType folderType, const QUuid &accountUuid);
132+
/**
133+
* @brief Check a path for a new spaces sync root or spaces folder for validity.
134+
*
135+
* @param path The path to check
136+
* @param folderType The kind of folder that is to be created (Folder or Spaces sync root)
137+
* @param the account UUID for the which the folder is created
138+
* @return an error string if there is a problem, or an null string if the path is valid
139+
*
140+
* Checks:
141+
* - spaces sync root not in a syncdb folder (a space folder)
142+
* - spaces sync root not in another spaces sync root
143+
* - space folder not in a syncdb folder (another space folder)
144+
* - space folder *can* be in sync root, if:
145+
* - space folder not in a spaces sync root of other account (check with account uuid) or (possibly branded) client
146+
*/
147+
QString checkPathValidity(const QString &path, NewFolderType folderType, const QUuid &accountUuid) const;
135148

136149
static std::unique_ptr<FolderMan> createInstance();
137150

@@ -203,7 +216,7 @@ class OWNCLOUDGUI_EXPORT FolderMan : public QObject
203216
* Optionally, the path relative to the found folder is returned in
204217
* relativePath.
205218
*/
206-
Folder *folderForPath(const QString &path, QString *relativePath = nullptr);
219+
Folder *folderForPath(const QString &path, QString *relativePath = nullptr) const;
207220

208221
/**
209222
* Ensures that a given directory does not contain a sync journal file.
@@ -215,14 +228,6 @@ class OWNCLOUDGUI_EXPORT FolderMan : public QObject
215228

216229
SocketApi *socketApi();
217230

218-
/**
219-
* Check if @a path is a valid path for a new folder considering the already sync'ed items.
220-
* Make sure that this folder, or any subfolder is not sync'ed already.
221-
*
222-
* @returns an empty string if it is allowed, or an error if it is not allowed
223-
*/
224-
QString checkPathValidityForNewFolder(const QString &path, NewFolderType folderType, const QUuid &accountUuid) const;
225-
226231
/**
227232
* Attempts to find a non-existing, acceptable path for creating a new sync folder.
228233
*
@@ -232,7 +237,7 @@ class OWNCLOUDGUI_EXPORT FolderMan : public QObject
232237
* subfolder of ~ would be a good candidate. When that happens \a basePath
233238
* is returned.
234239
*/
235-
static QString findGoodPathForNewSyncFolder(const QString &basePath, const QString &newFolder, NewFolderType folderType, const QUuid &accountUuid);
240+
QString findGoodPathForNewSyncFolder(const QString &basePath, const QString &newFolder, NewFolderType folderType, const QUuid &accountUuid) const;
236241

237242
bool ignoreHiddenFiles() const;
238243
void setIgnoreHiddenFiles(bool ignore);
@@ -457,6 +462,16 @@ private Q_SLOTS:
457462
// pair this with _socketApi->slotUnregisterPath(folder);
458463
void registerFolderWithSocketApi(Folder *folder);
459464

465+
// Helper for `checkPathValidity`. It first checks if the folder `path` exists, and if not recusively checks its parent. When a folder
466+
// is found, it checks for sync root markers. See the documentation of `checkPathValidity` for when a path is valid. If the path
467+
// is valid, a null-string is returned. When a path is invalid, an error string is returned.
468+
//
469+
// For example: start with /x/y/z
470+
// First check is if z exists. If not, retry with /x/y.
471+
// Now if /x/y exists, check for markers wether this is used as a spaces folder, or a sync root for another account. If it is, return an error message. If
472+
// not, check /x. When a path is valid, the null string is returned.
473+
static QString findExistingFolderAndCheckValidity(const QString &path, NewFolderType folderType, const QUuid &accountUuid);
474+
460475
QString _folderConfigPath;
461476
bool _ignoreHiddenFiles = true;
462477

src/gui/folderwizard/folderwizard.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,12 @@ QString FolderWizardPrivate::formatWarnings(const QStringList &warnings, bool is
5959
return ret;
6060
}
6161

62-
// todo: #43
6362
QString FolderWizardPrivate::defaultSyncRoot() const
6463
{
6564
// this should never happen when we have set up the account using spaces - there is ALWAYS a default root when spaces are in play
6665
// and they are always in play so this check is bogus. todo: #43
6766
if (!_account->hasDefaultSyncRoot()) {
68-
const auto folderType = FolderMan::NewFolderType::SpacesSyncRoot; // todo: #43 : FolderMan::NewFolderType::OC10SyncRoot;
67+
const auto folderType = FolderMan::NewFolderType::SpacesSyncRoot;
6968
return FolderMan::suggestSyncFolder(folderType, _account->uuid());
7069
} else {
7170
return _account->defaultSyncRoot();
@@ -102,7 +101,7 @@ FolderWizardPrivate::FolderWizardPrivate(FolderWizard *q, Account *account)
102101

103102
QString FolderWizardPrivate::initialLocalPath() const
104103
{
105-
return FolderMan::findGoodPathForNewSyncFolder(
104+
return FolderMan::instance()->findGoodPathForNewSyncFolder(
106105
defaultSyncRoot(), _spacesPage->currentSpace()->displayName(), FolderMan::NewFolderType::SpacesSyncRoot, _account->uuid());
107106
}
108107

src/gui/folderwizard/folderwizardlocalpath.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ bool FolderWizardLocalPath::isComplete() const
6565
{
6666
auto folderType = FolderMan::NewFolderType::SpacesFolder;
6767
auto accountUuid = folderWizardPrivate()->uuid();
68-
QString errorStr = FolderMan::instance()->checkPathValidityForNewFolder(localPath(), folderType, accountUuid);
68+
QString errorStr = FolderMan::instance()->checkPathValidity(localPath(), folderType, accountUuid);
6969

7070
bool isOk = errorStr.isEmpty();
7171
QStringList warnStrings;

src/gui/newaccountwizard/advancedsettingspagecontroller.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ bool AdvancedSettingsPageController::validateSyncRoot(const QString &rootPath)
226226
return false;
227227
}
228228

229-
QString invalidPathErrorMessage = FolderMan::checkPathValidityRecursive(rootPath, FolderMan::NewFolderType::SpacesSyncRoot, {});
229+
QString invalidPathErrorMessage = FolderMan::instance()->checkPathValidity(rootPath, FolderMan::NewFolderType::SpacesSyncRoot, {});
230230
if (!invalidPathErrorMessage.isEmpty()) {
231231
_errorField->setText(errorMessageTemplate.arg(rootPath, invalidPathErrorMessage));
232232
return false;

0 commit comments

Comments
 (0)