vfs: Remove newFilesAreVirtual - use root PinState instead
authorChristian Kamm <mail@ckamm.de>
Thu, 20 Dec 2018 10:24:41 +0000 (11:24 +0100)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:30 +0000 (10:58 +0100)
This unifies how to deal with pin states.

Also enable reading a folders direct pin state vs its effective pin
state.

13 files changed:
src/common/syncjournaldb.cpp
src/common/syncjournaldb.h
src/gui/accountsettings.cpp
src/gui/folder.cpp
src/gui/folder.h
src/gui/folderman.cpp
src/gui/owncloudsetupwizard.cpp
src/libsync/discovery.cpp
src/libsync/discovery.h
src/libsync/discoveryphase.cpp
src/libsync/syncoptions.h
test/testsyncjournaldb.cpp
test/testsyncvirtualfiles.cpp

index 7ccb38c7918bec9aa80f924badebd5a265a978d8..f008175f9ff9d065a04df593125d48f9dfde75c6 100644 (file)
@@ -2071,24 +2071,47 @@ void SyncJournalDb::markVirtualFileForDownloadRecursively(const QByteArray &path
     query.exec();
 }
 
-PinState SyncJournalDb::pinStateForPath(const QByteArray &path)
+Optional<PinState> SyncJournalDb::rawPinStateForPath(const QByteArray &path)
 {
     QMutexLocker lock(&_mutex);
     if (!checkConnect())
-        return PinState::Unspecified;
+        return {};
+
+    auto &query = _getRawPinStateQuery;
+    ASSERT(query.initOrReset(QByteArrayLiteral(
+            "SELECT pinState FROM flags WHERE path == ?1;"),
+        _db));
+    query.bindValue(1, path);
+    query.exec();
+
+    // no-entry means Inherited
+    if (!query.next())
+        return PinState::Inherited;
+
+    return static_cast<PinState>(query.intValue(0));
+}
+
+Optional<PinState> SyncJournalDb::effectivePinStateForPath(const QByteArray &path)
+{
+    QMutexLocker lock(&_mutex);
+    if (!checkConnect())
+        return {};
 
-    auto &query = _getPinStateQuery;
+    auto &query = _getEffectivePinStateQuery;
     ASSERT(query.initOrReset(QByteArrayLiteral(
             "SELECT pinState FROM flags WHERE"
-            " " IS_PREFIX_PATH_OR_EQUAL("path", "?1")
+            // explicitly allow "" to represent the root path
+            // (it'd be great if paths started with a / and "/" could be the root)
+            " (" IS_PREFIX_PATH_OR_EQUAL("path", "?1") " OR path == '')"
             " AND pinState is not null AND pinState != 0"
             " ORDER BY length(path) DESC;"),
         _db));
     query.bindValue(1, path);
     query.exec();
 
+    // If the root path has no setting, assume AlwaysLocal
     if (!query.next())
-        return PinState::Unspecified;
+        return PinState::AlwaysLocal;
 
     return static_cast<PinState>(query.intValue(0));
 }
index ddf5a1989a61594c4b612d879906c1dc74d37970..ca589b1d3d57fad4e5d3c95fe1b606bb30d6ba2b 100644 (file)
@@ -28,6 +28,7 @@
 #include "common/utility.h"
 #include "common/ownsql.h"
 #include "common/syncjournalfilerecord.h"
+#include "common/result.h"
 
 namespace OCC {
 class SyncJournalFileRecord;
@@ -35,7 +36,7 @@ class SyncJournalFileRecord;
 /** Determines whether files should be available locally or not
  *
  * For new remote files the file's PinState is calculated by looking for
- * the closest parent folder that isn't Unspecified.
+ * the closest parent folder that isn't Inherited.
  *
  * TODO: It seems to make sense to also store per-file PinStates.
  * Maybe these could communicate intent, similar to ItemTypeVirtualFileDownload
@@ -43,7 +44,7 @@ class SyncJournalFileRecord;
  */
 enum class PinState {
     /// Inherit the PinState of the parent directory (default)
-    Unspecified = 0,
+    Inherited = 0,
     /// Download file and keep it updated.
     AlwaysLocal = 1,
     /// File shall be virtual locally.
@@ -261,15 +262,35 @@ public:
     void markVirtualFileForDownloadRecursively(const QByteArray &path);
 
     /**
-     * Gets the PinState for the path.
+     * Gets the PinState for the path without considering parents.
      *
-     * If the exact path has no entry or has an unspecified state,
-     * the state is inherited through the parent.
+     * If a path has no explicit PinState "Inherited" is returned.
+     *
+     * It's valid to use the root path "".
+     *
+     * Returns none on db error.
+     */
+    Optional<PinState> rawPinStateForPath(const QByteArray &path);
+
+    /**
+     * Gets the PinState for the path after inheriting from parents.
+     *
+     * If the exact path has no entry or has an Inherited state,
+     * the state of the closest parent path is returned.
+     *
+     * It's valid to use the root path "".
+     *
+     * Never returns PinState::Inherited. If the root is "Inherited"
+     * or there's an error, "AlwaysLocal" is returned.
+     *
+     * Returns none on db error.
      */
-    PinState pinStateForPath(const QByteArray &path);
+    Optional<PinState> effectivePinStateForPath(const QByteArray &path);
 
     /**
      * Sets a path's pin state.
+     *
+     * It's valid to use the root path "".
      */
     void setPinStateForPath(const QByteArray &path, PinState state);
 
@@ -337,7 +358,8 @@ private:
     SqlQuery _getConflictRecordQuery;
     SqlQuery _setConflictRecordQuery;
     SqlQuery _deleteConflictRecordQuery;
-    SqlQuery _getPinStateQuery;
+    SqlQuery _getRawPinStateQuery;
+    SqlQuery _getEffectivePinStateQuery;
     SqlQuery _setPinStateQuery;
 
     /* Storing etags to these folders, or their parent folders, is filtered out.
index a8cb24852ff92970c02dfededffa711ab5b3a7a2..b58351e06987546c2deb2bbe01ca7ee637fb6cb9 100644 (file)
@@ -538,8 +538,6 @@ void AccountSettings::slotFolderWizardAccepted()
 
     if (folderWizard->property("useVirtualFiles").toBool()) {
         definition.virtualFilesMode = bestAvailableVfsMode();
-        if (definition.virtualFilesMode != Vfs::Off)
-            definition.newFilesAreVirtual = true;
     }
 
     {
@@ -572,6 +570,9 @@ void AccountSettings::slotFolderWizardAccepted()
 
     Folder *f = folderMan->addFolder(_accountState, definition);
     if (f) {
+        if (definition.virtualFilesMode != Vfs::Off && folderWizard->property("useVirtualFiles").toBool())
+            f->setNewFilesAreVirtual(true);
+
         f->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, selectiveSyncBlackList);
 
         // The user already accepted the selective sync dialog. everything is in the white list
index ffdabb55e7da3dd5065f0b37d01380e2062fd072..e43745a3c30b03f5340360021fcaaa63fb3d251a 100644 (file)
@@ -649,13 +649,13 @@ void Folder::setSupportsVirtualFiles(bool enabled)
 
 bool Folder::newFilesAreVirtual() const
 {
-    return _definition.newFilesAreVirtual;
+    auto pinState = _journal.rawPinStateForPath("");
+    return pinState && *pinState == PinState::OnlineOnly;
 }
 
 void Folder::setNewFilesAreVirtual(bool enabled)
 {
-    _definition.newFilesAreVirtual = enabled;
-    saveToSettings();
+    _journal.setPinStateForPath("", enabled ? PinState::OnlineOnly : PinState::AlwaysLocal);
 }
 
 void Folder::saveToSettings() const
@@ -691,8 +691,12 @@ void Folder::saveToSettings() const
     settings->beginGroup(settingsGroup);
     // Note: Each of these groups might have a "version" tag, but that's
     //       currently unused.
+    settings->beginGroup(FolderMan::escapeAlias(_definition.alias));
     FolderDefinition::save(*settings, _definition);
 
+    // Technically redundant, just for older clients
+    settings->setValue(QLatin1String("usePlaceholders"), newFilesAreVirtual());
+
     settings->sync();
     qCInfo(lcFolder) << "Saved folder" << _definition.alias << "to settings, status" << settings->status();
 }
@@ -841,7 +845,6 @@ void Folder::setSyncOptions()
     opt._confirmExternalStorage = cfgFile.confirmExternalStorage();
     opt._moveFilesToTrash = cfgFile.moveToTrash();
     opt._vfs = _vfs;
-    opt._newFilesAreVirtual = _definition.newFilesAreVirtual;
 
     QByteArray chunkSizeEnv = qgetenv("OWNCLOUD_CHUNK_SIZE");
     if (!chunkSizeEnv.isEmpty()) {
@@ -1241,13 +1244,11 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, bool *cancel
 
 void FolderDefinition::save(QSettings &settings, const FolderDefinition &folder)
 {
-    settings.beginGroup(FolderMan::escapeAlias(folder.alias));
     settings.setValue(QLatin1String("localPath"), folder.localPath);
     settings.setValue(QLatin1String("journalPath"), folder.journalPath);
     settings.setValue(QLatin1String("targetPath"), folder.targetPath);
     settings.setValue(QLatin1String("paused"), folder.paused);
     settings.setValue(QLatin1String("ignoreHiddenFiles"), folder.ignoreHiddenFiles);
-    settings.setValue(QLatin1String("usePlaceholders"), folder.newFilesAreVirtual);
 
     settings.setValue(QStringLiteral("virtualFilesMode"), Vfs::modeToString(folder.virtualFilesMode));
 
@@ -1263,13 +1264,11 @@ void FolderDefinition::save(QSettings &settings, const FolderDefinition &folder)
         settings.setValue(QLatin1String("navigationPaneClsid"), folder.navigationPaneClsid);
     else
         settings.remove(QLatin1String("navigationPaneClsid"));
-    settings.endGroup();
 }
 
 bool FolderDefinition::load(QSettings &settings, const QString &alias,
     FolderDefinition *folder)
 {
-    settings.beginGroup(alias);
     folder->alias = FolderMan::unescapeAlias(alias);
     folder->localPath = settings.value(QLatin1String("localPath")).toString();
     folder->journalPath = settings.value(QLatin1String("journalPath")).toString();
@@ -1277,7 +1276,6 @@ bool FolderDefinition::load(QSettings &settings, const QString &alias,
     folder->paused = settings.value(QLatin1String("paused")).toBool();
     folder->ignoreHiddenFiles = settings.value(QLatin1String("ignoreHiddenFiles"), QVariant(true)).toBool();
     folder->navigationPaneClsid = settings.value(QLatin1String("navigationPaneClsid")).toUuid();
-    folder->newFilesAreVirtual = settings.value(QLatin1String("usePlaceholders")).toBool();
 
     folder->virtualFilesMode = Vfs::WithSuffix;
     QString vfsModeString = settings.value(QStringLiteral("virtualFilesMode")).toString();
@@ -1291,8 +1289,6 @@ bool FolderDefinition::load(QSettings &settings, const QString &alias,
         folder->upgradeVfsMode = true;
     }
 
-    settings.endGroup();
-
     // Old settings can contain paths with native separators. In the rest of the
     // code we assum /, so clean it up now.
     folder->localPath = prepareLocalPath(folder->localPath);
index 978fa6144d205a514e21904f6bab977ad146be9d..a1c891a9503b628a91e7411165acc3dfb84336e9 100644 (file)
@@ -63,18 +63,16 @@ public:
     bool ignoreHiddenFiles = false;
     /// Which virtual files setting the folder uses
     Vfs::Mode virtualFilesMode = Vfs::Off;
-    /// Whether new files are virtual
-    bool newFilesAreVirtual = false;
     /// The CLSID where this folder appears in registry for the Explorer navigation pane entry.
     QUuid navigationPaneClsid;
 
     /// Whether the vfs mode shall silently be updated if possible
     bool upgradeVfsMode = false;
 
-    /// Saves the folder definition, creating a new settings group.
+    /// Saves the folder definition into the current settings group.
     static void save(QSettings &settings, const FolderDefinition &folder);
 
-    /// Reads a folder definition from a settings group with the name 'alias'.
+    /// Reads a folder definition from the current settings group.
     static bool load(QSettings &settings, const QString &alias,
         FolderDefinition *folder);
 
@@ -265,7 +263,10 @@ public:
     bool supportsVirtualFiles() const;
     void setSupportsVirtualFiles(bool enabled);
 
-    /** whether new remote files shall become virtual locally */
+    /** whether new remote files shall become virtual locally
+     *
+     * This is the root folder pin state and can be overridden by explicit subfolder pin states.
+     */
     bool newFilesAreVirtual() const;
     void setNewFilesAreVirtual(bool enabled);
 
@@ -427,7 +428,7 @@ private:
     /// Reset when no follow-up is requested.
     int _consecutiveFollowUpSyncs;
 
-    SyncJournalDb _journal;
+    mutable SyncJournalDb _journal;
 
     QScopedPointer<SyncRunFileLog> _fileLog;
 
index b5fff9fa05a67d285102e17ce4a29fd07bff2135..49a3ab286819d07b566bacccdd696231ba2f03d1 100644 (file)
@@ -222,6 +222,7 @@ void FolderMan::setupFoldersHelper(QSettings &settings, AccountStatePtr account,
         settings.endGroup();
 
         FolderDefinition folderDefinition;
+        settings.beginGroup(folderAlias);
         if (FolderDefinition::load(settings, folderAlias, &folderDefinition)) {
             auto defaultJournalPath = folderDefinition.defaultJournalPath(account->account());
 
@@ -293,15 +294,23 @@ void FolderMan::setupFoldersHelper(QSettings &settings, AccountStatePtr account,
 
             Folder *f = addFolderInternal(std::move(folderDefinition), account.data(), std::move(vfs));
             if (f) {
+                // Migrate the old "usePlaceholders" setting to the root folder pin state
+                if (settings.value(QLatin1String(versionC), 1).toInt() == 1
+                    && settings.value(QLatin1String("usePlaceholders"), false).toBool()) {
+                    f->setNewFilesAreVirtual(true);
+                }
+
                 // Migration: Mark folders that shall be saved in a backwards-compatible way
                 if (backwardsCompatible)
                     f->setSaveBackwardsCompatible(true);
                 if (foldersWithPlaceholders)
                     f->setSaveInFoldersWithPlaceholders();
+
                 scheduleFolder(f);
                 emit folderSyncStateChange(f);
             }
         }
+        settings.endGroup();
     }
 }
 
index d402839d293608e4673a48e7b3fa716019242676..519fcaef0b2b2210029b9a71c39bce088d43f3b9 100644 (file)
@@ -637,14 +637,15 @@ void OwncloudSetupWizard::slotAssistantFinished(int result)
             folderDefinition.ignoreHiddenFiles = folderMan->ignoreHiddenFiles();
             if (_ocWizard->useVirtualFileSync()) {
                 folderDefinition.virtualFilesMode = bestAvailableVfsMode();
-                if (folderDefinition.virtualFilesMode != Vfs::Off)
-                    folderDefinition.newFilesAreVirtual = true;
             }
             if (folderMan->navigationPaneHelper().showInExplorerNavigationPane())
                 folderDefinition.navigationPaneClsid = QUuid::createUuid();
 
             auto f = folderMan->addFolder(account, folderDefinition);
             if (f) {
+                if (folderDefinition.virtualFilesMode != Vfs::Off && _ocWizard->useVirtualFileSync())
+                    f->setNewFilesAreVirtual(true);
+
                 f->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
                     _ocWizard->selectiveSyncBlacklist());
                 if (!_ocWizard->isConfirmBigFolderChecked()) {
index 13f013efc5f5d9c015a14a331bcb63eb7b09ad5c..435cbcdb2eb80c4d8560ce90340b78d08ee04ce8 100644 (file)
@@ -410,10 +410,14 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(
         }
         // Turn new remote files into virtual files if the option is enabled.
         auto &opts = _discoveryData->_syncOptions;
+        if (!directoryPinState()) {
+            dbError();
+            return;
+        }
         if (!localEntry.isValid()
             && item->_type == ItemTypeFile
             && opts._vfs->mode() != Vfs::Off
-            && directoryPinState() == PinState::OnlineOnly) {
+            && *directoryPinState() == PinState::OnlineOnly) {
             item->_type = ItemTypeVirtualFile;
             if (isVfsWithSuffix())
                 addVirtualFileSuffix(path._original);
@@ -1331,17 +1335,14 @@ bool ProcessDirectoryJob::runLocalQuery()
     return true;
 }
 
-PinState ProcessDirectoryJob::directoryPinState()
+Optional<PinState> ProcessDirectoryJob::directoryPinState()
 {
-    if (_pinStateCache)
-        return *_pinStateCache;
-
-    // Get the path's pinstate and anchor to the root option
-    _pinStateCache = _discoveryData->_statedb->pinStateForPath(_currentFolder._original.toUtf8());
-    if (*_pinStateCache == PinState::Unspecified)
-        _pinStateCache = _discoveryData->_syncOptions._newFilesAreVirtual ? PinState::OnlineOnly : PinState::AlwaysLocal;
-
-    return *_pinStateCache;
+    if (!_pinStateCache) {
+        _pinStateCache = _discoveryData->_statedb->effectivePinStateForPath(
+                _currentFolder._original.toUtf8());
+        // don't cache db errors, just retry next time
+    }
+    return _pinStateCache;
 }
 
 bool ProcessDirectoryJob::isVfsWithSuffix() const
index 0ec44b9408454ab7cf163661825295f77f364576..bfb6856a357276a9ee21706c5b7c54a2dbd9c447 100644 (file)
@@ -181,7 +181,7 @@ private:
     bool runLocalQuery();
 
     /** Retrieve and cache directory pin state */
-    PinState directoryPinState();
+    Optional<PinState> directoryPinState();
 
     QueryMode _queryServer;
     QueryMode _queryLocal;
index cc0a47ee82355656263ec173cf6381d8cf83b73a..e97af0e7e079862aa2a83a8d2bd95232297c6c4c 100644 (file)
@@ -100,7 +100,7 @@ void DiscoveryPhase::checkSelectiveSyncNewFolder(const QString &path, RemotePerm
     }
 
     auto limit = _syncOptions._newBigFolderSizeLimit;
-    if (limit < 0 || (_syncOptions._vfs->mode() != Vfs::Off && _syncOptions._newFilesAreVirtual)) {
+    if (limit < 0 || _syncOptions._vfs->mode() != Vfs::Off) {
         // no limit, everything is allowed;
         return callback(false);
     }
index f40954b044d02ae0c013bea66b1ac92c34a00df5..8de39a7892a2c8a0093bcdd20ff79022d091aad4 100644 (file)
@@ -44,9 +44,6 @@ struct SyncOptions
     /** Create a virtual file for new files instead of downloading. May not be null */
     QSharedPointer<Vfs> _vfs;
 
-    /** True if new files shall be virtual */
-    bool _newFilesAreVirtual = false;
-
     /** The initial un-adjusted chunk size in bytes for chunked uploads, both
      * for old and new chunking algorithm, which classifies the item to be chunked
      *
index cd42f0f4b94ce532a063b51db40edf20ebf25093..03c7a747515ae2a3ec42134313f6130385613bf5 100644 (file)
@@ -324,56 +324,76 @@ private slots:
     {
         auto make = [&](const QByteArray &path, PinState state) {
             _db.setPinStateForPath(path, state);
+            auto pinState = _db.rawPinStateForPath(path);
+            QVERIFY(pinState);
+            QCOMPARE(*pinState, state);
         };
-        auto get = [&](const QByteArray &path) {
-            return _db.pinStateForPath(path);
+        auto get = [&](const QByteArray &path) -> PinState {
+            auto state = _db.effectivePinStateForPath(path);
+            if (!state) {
+                QTest::qFail("couldn't read pin state", __FILE__, __LINE__);
+                return PinState::Inherited;
+            }
+            return *state;
         };
 
         // Make a thrice-nested setup
         make("local", PinState::AlwaysLocal);
         make("online", PinState::OnlineOnly);
-        make("unspec", PinState::Unspecified);
-        for (auto base : {"local/", "online/", "unspec/"}) {
-            make(QByteArray(base) + "unspec", PinState::Unspecified);
+        make("inherit", PinState::Inherited);
+        for (auto base : {"local/", "online/", "inherit/"}) {
+            make(QByteArray(base) + "inherit", PinState::Inherited);
             make(QByteArray(base) + "local", PinState::AlwaysLocal);
             make(QByteArray(base) + "online", PinState::OnlineOnly);
 
-            for (auto base2 : {"local/", "online/", "unspec/"}) {
-                make(QByteArray(base) + base2 + "/unspec", PinState::Unspecified);
+            for (auto base2 : {"local/", "online/", "inherit/"}) {
+                make(QByteArray(base) + base2 + "/inherit", PinState::Inherited);
                 make(QByteArray(base) + base2 + "/local", PinState::AlwaysLocal);
                 make(QByteArray(base) + base2 + "/online", PinState::OnlineOnly);
             }
         }
 
-        // Baseline direct checks
+        // Baseline direct checks (the fallback for unset root pinstate is AlwaysLocal)
         QCOMPARE(get("local"), PinState::AlwaysLocal);
         QCOMPARE(get("online"), PinState::OnlineOnly);
-        QCOMPARE(get("unspec"), PinState::Unspecified);
-        QCOMPARE(get("nonexistant"), PinState::Unspecified);
+        QCOMPARE(get("inherit"), PinState::AlwaysLocal);
+        QCOMPARE(get("nonexistant"), PinState::AlwaysLocal);
         QCOMPARE(get("online/local"), PinState::AlwaysLocal);
         QCOMPARE(get("local/online"), PinState::OnlineOnly);
-        QCOMPARE(get("unspec/local"), PinState::AlwaysLocal);
-        QCOMPARE(get("unspec/online"), PinState::OnlineOnly);
-        QCOMPARE(get("unspec/unspec"), PinState::Unspecified);
-        QCOMPARE(get("unspec/nonexistant"), PinState::Unspecified);
+        QCOMPARE(get("inherit/local"), PinState::AlwaysLocal);
+        QCOMPARE(get("inherit/online"), PinState::OnlineOnly);
+        QCOMPARE(get("inherit/inherit"), PinState::AlwaysLocal);
+        QCOMPARE(get("inherit/nonexistant"), PinState::AlwaysLocal);
 
         // Inheriting checks, level 1
-        QCOMPARE(get("local/unspec"), PinState::AlwaysLocal);
+        QCOMPARE(get("local/inherit"), PinState::AlwaysLocal);
         QCOMPARE(get("local/nonexistant"), PinState::AlwaysLocal);
-        QCOMPARE(get("online/unspec"), PinState::OnlineOnly);
+        QCOMPARE(get("online/inherit"), PinState::OnlineOnly);
         QCOMPARE(get("online/nonexistant"), PinState::OnlineOnly);
 
         // Inheriting checks, level 2
-        QCOMPARE(get("local/unspec/unspec"), PinState::AlwaysLocal);
-        QCOMPARE(get("local/local/unspec"), PinState::AlwaysLocal);
+        QCOMPARE(get("local/inherit/inherit"), PinState::AlwaysLocal);
+        QCOMPARE(get("local/local/inherit"), PinState::AlwaysLocal);
         QCOMPARE(get("local/local/nonexistant"), PinState::AlwaysLocal);
-        QCOMPARE(get("local/online/unspec"), PinState::OnlineOnly);
+        QCOMPARE(get("local/online/inherit"), PinState::OnlineOnly);
         QCOMPARE(get("local/online/nonexistant"), PinState::OnlineOnly);
-        QCOMPARE(get("online/unspec/unspec"), PinState::OnlineOnly);
-        QCOMPARE(get("online/local/unspec"), PinState::AlwaysLocal);
+        QCOMPARE(get("online/inherit/inherit"), PinState::OnlineOnly);
+        QCOMPARE(get("online/local/inherit"), PinState::AlwaysLocal);
         QCOMPARE(get("online/local/nonexistant"), PinState::AlwaysLocal);
-        QCOMPARE(get("online/online/unspec"), PinState::OnlineOnly);
+        QCOMPARE(get("online/online/inherit"), PinState::OnlineOnly);
         QCOMPARE(get("online/online/nonexistant"), PinState::OnlineOnly);
+
+        // Check changing the root pin state
+        make("", PinState::OnlineOnly);
+        QCOMPARE(get("local"), PinState::AlwaysLocal);
+        QCOMPARE(get("online"), PinState::OnlineOnly);
+        QCOMPARE(get("inherit"), PinState::OnlineOnly);
+        QCOMPARE(get("nonexistant"), PinState::OnlineOnly);
+        make("", PinState::AlwaysLocal);
+        QCOMPARE(get("local"), PinState::AlwaysLocal);
+        QCOMPARE(get("online"), PinState::OnlineOnly);
+        QCOMPARE(get("inherit"), PinState::AlwaysLocal);
+        QCOMPARE(get("nonexistant"), PinState::AlwaysLocal);
     }
 
 private:
index cc38527a92d67d5eda7f8127abe21cc995ee8b07..7c55eaaa02b3e181eb6617a57e6b2f6a529bfd22 100644 (file)
@@ -59,11 +59,11 @@ void markForDehydration(FakeFolder &folder, const QByteArray &path)
     journal.avoidReadFromDbOnNextSync(record._path);
 }
 
-SyncOptions vfsSyncOptions()
+SyncOptions vfsSyncOptions(FakeFolder &fakeFolder)
 {
     SyncOptions options;
     options._vfs.reset(createVfsFromPlugin(Vfs::WithSuffix).release());
-    options._newFilesAreVirtual = true;
+    fakeFolder.syncJournal().setPinStateForPath("", PinState::OnlineOnly);
     return options;
 }
 
@@ -85,7 +85,7 @@ private slots:
         QFETCH(bool, doLocalDiscovery);
 
         FakeFolder fakeFolder{ FileInfo() };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
 
@@ -206,7 +206,7 @@ private slots:
     void testVirtualFileConflict()
     {
         FakeFolder fakeFolder{ FileInfo() };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
 
@@ -277,7 +277,7 @@ private slots:
     void testWithNormalSync()
     {
         FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
 
@@ -313,7 +313,7 @@ private slots:
     void testVirtualFileDownload()
     {
         FakeFolder fakeFolder{ FileInfo() };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
 
@@ -381,7 +381,7 @@ private slots:
     void testVirtualFileDownloadResume()
     {
         FakeFolder fakeFolder{ FileInfo() };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
 
@@ -422,7 +422,7 @@ private slots:
     void testNewFilesNotVirtual()
     {
         FakeFolder fakeFolder{ FileInfo() };
-        SyncOptions syncOptions = vfsSyncOptions();
+        SyncOptions syncOptions = vfsSyncOptions(fakeFolder);
         fakeFolder.syncEngine().setSyncOptions(syncOptions);
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
 
@@ -431,8 +431,7 @@ private slots:
         QVERIFY(fakeFolder.syncOnce());
         QVERIFY(fakeFolder.currentLocalState().find("A/a1.nextcloud"));
 
-        syncOptions._newFilesAreVirtual = false;
-        fakeFolder.syncEngine().setSyncOptions(syncOptions);
+        fakeFolder.syncJournal().setPinStateForPath("", PinState::AlwaysLocal);
 
         // Create a new remote file, it'll not be virtual
         fakeFolder.remoteModifier().insert("A/a2");
@@ -444,7 +443,7 @@ private slots:
     void testDownloadRecursive()
     {
         FakeFolder fakeFolder{ FileInfo() };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
 
         // Create a virtual file for remote files
@@ -541,7 +540,7 @@ private slots:
     void testRenameToVirtual()
     {
         FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
 
@@ -579,7 +578,7 @@ private slots:
     void testRenameVirtual()
     {
         FakeFolder fakeFolder{ FileInfo() };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
 
@@ -621,7 +620,7 @@ private slots:
     void testSyncDehydration()
     {
         FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
 
         QVERIFY(fakeFolder.syncOnce());
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
@@ -698,7 +697,7 @@ private slots:
     void testWipeVirtualSuffixFiles()
     {
         FakeFolder fakeFolder{ FileInfo{} };
-        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
+        fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
 
         // Create a suffix-vfs baseline
 
@@ -743,8 +742,7 @@ private slots:
     void testNewVirtuals()
     {
         FakeFolder fakeFolder{ FileInfo() };
-        SyncOptions syncOptions = vfsSyncOptions();
-        syncOptions._newFilesAreVirtual = true;
+        SyncOptions syncOptions = vfsSyncOptions(fakeFolder);
         fakeFolder.syncEngine().setSyncOptions(syncOptions);
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
 
@@ -774,8 +772,7 @@ private slots:
         QVERIFY(fakeFolder.currentLocalState().find("unspec/file1.nextcloud"));
 
         // Test 2: root is AlwaysLocal
-        syncOptions._newFilesAreVirtual = false;
-        fakeFolder.syncEngine().setSyncOptions(syncOptions);
+        fakeFolder.syncJournal().setPinStateForPath("", PinState::AlwaysLocal);
 
         fakeFolder.remoteModifier().insert("file2");
         fakeFolder.remoteModifier().insert("online/file2");