Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kamm <mail@ckamm.de>2019-01-23 17:12:02 +0300
committerckamm <mail@ckamm.de>2019-02-11 15:35:14 +0300
commit010abe4c823af3dae7078854d1096f25b8b7225c (patch)
tree48852485d65dd29243f6e2a5fec69706b4294b76
parent8ea639e58f2d2599f3f966f9f65a4f29c025ca43 (diff)
Pin state updates
- unspecified and inherited are different - move enum to header in common/ - access through Vfs instead of directly in Journal
-rw-r--r--src/common/pinstate.h76
-rw-r--r--src/common/syncjournaldb.h19
-rw-r--r--src/common/vfs.cpp26
-rw-r--r--src/common/vfs.h51
-rw-r--r--src/gui/folder.cpp1
-rw-r--r--src/gui/folder.h1
-rw-r--r--src/gui/folderwatcher_win.cpp5
-rw-r--r--src/gui/socketapi.cpp12
-rw-r--r--src/libsync/discovery.cpp29
-rw-r--r--src/libsync/discovery.h38
-rw-r--r--src/libsync/syncengine.cpp4
-rw-r--r--src/libsync/vfs/suffix/vfs_suffix.cpp10
-rw-r--r--src/libsync/vfs/suffix/vfs_suffix.h4
-rw-r--r--test/syncenginetestutils.h30
-rw-r--r--test/testsyncvirtualfiles.cpp45
15 files changed, 254 insertions, 97 deletions
diff --git a/src/common/pinstate.h b/src/common/pinstate.h
new file mode 100644
index 000000000..5fb267168
--- /dev/null
+++ b/src/common/pinstate.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) by Christian Kamm <mail@ckamm.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef PINSTATE_H
+#define PINSTATE_H
+
+#include "ocsynclib.h"
+
+namespace OCC {
+
+/** Determines whether items should be available locally permanently or not
+ *
+ * The idea is that files and folders can be marked with the user intent
+ * on availability.
+ *
+ * The Inherited state is used for resetting a pin state to what its
+ * parent path would do.
+ *
+ * The pin state of a directory usually only matters for the initial pin and
+ * hydration state of new remote files. It's perfectly possible for a
+ * AlwaysLocal directory to have only OnlineOnly items. (though setting pin
+ * states is usually done recursively, so one'd need to set the folder to
+ * pinned and then each contained item to unpinned)
+ *
+ * Note: This enum intentionally mimics CF_PIN_STATE of Windows cfapi.
+ */
+enum class PinState {
+ /** The pin state is derived from the state of the parent folder.
+ *
+ * For example new remote files start out in this state, following
+ * the state of their parent folder.
+ *
+ * This state is used purely for resetting pin states to their derived
+ * value. The effective state for an item will never be "Inherited".
+ */
+ Inherited = 0,
+
+ /** The file shall be available and up to date locally.
+ *
+ * Also known as "pinned". Pinned dehydrated files shall be hydrated
+ * as soon as possible.
+ */
+ AlwaysLocal = 1,
+
+ /** File shall be a dehydrated placeholder, filled on demand.
+ *
+ * Also known as "unpinned". Unpinned hydrated files shall be dehydrated
+ * as soon as possible.
+ *
+ * If a unpinned file becomes hydrated its pin state changes to unspecified.
+ */
+ OnlineOnly = 2,
+
+ /** The user hasn't made a decision. The client or platform may hydrate or
+ * dehydrate as they see fit.
+ *
+ * New remote files in unspecified directories start unspecified, and
+ * dehydrated (which is an arbitrary decision).
+ */
+ Unspecified = 3,
+};
+
+}
+
+#endif
diff --git a/src/common/syncjournaldb.h b/src/common/syncjournaldb.h
index 5dd4aab5c..b69a6e1e4 100644
--- a/src/common/syncjournaldb.h
+++ b/src/common/syncjournaldb.h
@@ -29,28 +29,11 @@
#include "common/ownsql.h"
#include "common/syncjournalfilerecord.h"
#include "common/result.h"
+#include "common/pinstate.h"
namespace OCC {
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 Inherited.
- *
- * TODO: It seems to make sense to also store per-file PinStates.
- * Maybe these could communicate intent, similar to ItemTypeVirtualFileDownload
- * and ...FileDehydrate?
- */
-enum class PinState {
- /// Inherit the PinState of the parent directory (default)
- Inherited = 0,
- /// Download file and keep it updated.
- AlwaysLocal = 1,
- /// File shall be virtual locally.
- OnlineOnly = 2,
-};
-
/**
* @brief Class that handles the sync database
*
diff --git a/src/common/vfs.cpp b/src/common/vfs.cpp
index 4f3b6fadc..7e712a654 100644
--- a/src/common/vfs.cpp
+++ b/src/common/vfs.cpp
@@ -19,6 +19,7 @@
#include "vfs.h"
#include "plugin.h"
#include "version.h"
+#include "syncjournaldb.h"
#include <QPluginLoader>
#include <QLoggingCategory>
@@ -59,11 +60,34 @@ Optional<Vfs::Mode> Vfs::modeFromString(const QString &str)
return {};
}
-VfsOff::VfsOff(QObject *parent)
+VfsDefaults::VfsDefaults(QObject *parent)
: Vfs(parent)
{
}
+void VfsDefaults::start(const VfsSetupParams &params)
+{
+ _setupParams = params;
+}
+
+bool VfsDefaults::setPinState(const QString &folderPath, PinState state)
+{
+ auto path = folderPath.toUtf8();
+ _setupParams.journal->wipePinStateForPathAndBelow(path);
+ _setupParams.journal->setPinStateForPath(path, state);
+ return true;
+}
+
+Optional<PinState> VfsDefaults::getPinState(const QString &folderPath)
+{
+ return _setupParams.journal->effectivePinStateForPath(folderPath.toUtf8());
+}
+
+VfsOff::VfsOff(QObject *parent)
+ : VfsDefaults(parent)
+{
+}
+
VfsOff::~VfsOff() = default;
static QString modeToPluginName(Vfs::Mode mode)
diff --git a/src/common/vfs.h b/src/common/vfs.h
index 9db7edc9c..35e7b86ac 100644
--- a/src/common/vfs.h
+++ b/src/common/vfs.h
@@ -22,6 +22,7 @@
#include "ocsynclib.h"
#include "result.h"
#include "syncfilestatus.h"
+#include "pinstate.h"
typedef struct csync_file_stat_s csync_file_stat_t;
@@ -48,7 +49,7 @@ struct OCSYNC_EXPORT VfsSetupParams
*
* Note: The journal must live at least until the Vfs::stop() call.
*/
- SyncJournalDb *journal;
+ SyncJournalDb *journal = nullptr;
/// Strings potentially passed on to the platform
QString providerName;
@@ -101,14 +102,14 @@ public:
virtual QString fileSuffix() const = 0;
- /// Must be called at least once before start(). May make sense to merge with start().
- virtual void registerFolder(const VfsSetupParams &params) = 0;
-
/** Initializes interaction with the VFS provider.
*
* For example, the VFS provider might monitor files to be able to start a file
* hydration (download of a file's remote contents) when the user wants to open
* it.
+ *
+ * Usually some registration needs to be done with the backend. This function
+ * should take care of it if necessary.
*/
virtual void start(const VfsSetupParams &params) = 0;
@@ -160,6 +161,24 @@ public:
*/
virtual bool statTypeVirtualFile(csync_file_stat_t *stat, void *stat_data) = 0;
+ /** Sets the pin state for the item at a path.
+ *
+ * Usually this would forward to setting the pin state flag in the db table,
+ * but some vfs plugins will store the pin state in file attributes instead.
+ *
+ * folderPath is relative to the sync folder.
+ */
+ virtual bool setPinState(const QString &folderPath, PinState state) = 0;
+
+ /** Returns the pin state of an item at a path.
+ *
+ * Usually backed by the db's effectivePinState() function but some vfs
+ * plugins will override it to retrieve the state from elsewhere.
+ *
+ * folderPath is relative to the sync folder.
+ */
+ virtual Optional<PinState> getPinState(const QString &folderPath) = 0;
+
public slots:
/** Update in-sync state based on SyncFileStatusTracker signal.
*
@@ -176,8 +195,27 @@ signals:
void doneHydrating();
};
+class OCSYNC_EXPORT VfsDefaults : public Vfs
+{
+public:
+ explicit VfsDefaults(QObject* parent = nullptr);
+
+ // stores the params
+ void start(const VfsSetupParams &params) override;
+
+ // use the journal to back the pinstates
+ bool setPinState(const QString &folderPath, PinState state) override;
+ Optional<PinState> getPinState(const QString &folderPath) override;
+
+ // access initial setup data
+ const VfsSetupParams &params() const { return _setupParams; }
+
+protected:
+ VfsSetupParams _setupParams;
+};
+
/// Implementation of Vfs for Vfs::Off mode - does nothing
-class OCSYNC_EXPORT VfsOff : public Vfs
+class OCSYNC_EXPORT VfsOff : public VfsDefaults
{
Q_OBJECT
@@ -189,12 +227,9 @@ public:
QString fileSuffix() const override { return QString(); }
- void registerFolder(const VfsSetupParams &) override {}
- void start(const VfsSetupParams &) override {}
void stop() override {}
void unregisterFolder() override {}
-
bool isHydrating() const override { return false; }
bool updateMetadata(const QString &, time_t, quint64, const QByteArray &, QString *) override { return true; }
diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp
index 7aef748dd..eb4672ca3 100644
--- a/src/gui/folder.cpp
+++ b/src/gui/folder.cpp
@@ -474,7 +474,6 @@ void Folder::startVfs()
connect(&_engine->syncFileStatusTracker(), &SyncFileStatusTracker::fileStatusChanged,
_vfs.data(), &Vfs::fileStatusChanged);
- _vfs->registerFolder(vfsParams); // Do this always?
_vfs->start(vfsParams);
}
diff --git a/src/gui/folder.h b/src/gui/folder.h
index 286b4ccbd..4cbfedfa9 100644
--- a/src/gui/folder.h
+++ b/src/gui/folder.h
@@ -211,6 +211,7 @@ public:
// Used by the Socket API
SyncJournalDb *journalDb() { return &_journal; }
SyncEngine &syncEngine() { return *_engine; }
+ Vfs &vfs() { return *_vfs; }
RequestEtagJob *etagJob() { return _requestEtagJob; }
std::chrono::milliseconds msecSinceLastSync() const { return std::chrono::milliseconds(_timeSinceLastSyncDone.elapsed()); }
diff --git a/src/gui/folderwatcher_win.cpp b/src/gui/folderwatcher_win.cpp
index 4f963fbe2..5ecfe0e2c 100644
--- a/src/gui/folderwatcher_win.cpp
+++ b/src/gui/folderwatcher_win.cpp
@@ -67,7 +67,10 @@ void WatcherThread::watchChanges(size_t fileNotifyBufferSize,
SecureZeroMemory(pFileNotifyBuffer, fileNotifyBufferSize);
if (!ReadDirectoryChangesW(_directory, (LPVOID)pFileNotifyBuffer,
fileNotifyBufferSize, true,
- FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
+ FILE_NOTIFY_CHANGE_FILE_NAME
+ | FILE_NOTIFY_CHANGE_DIR_NAME
+ | FILE_NOTIFY_CHANGE_LAST_WRITE
+ | FILE_NOTIFY_CHANGE_ATTRIBUTES, // attributes are for vfs pin state changes
&dwBytesReturned,
&overlapped,
NULL)) {
diff --git a/src/gui/socketapi.cpp b/src/gui/socketapi.cpp
index 6d879bb0f..16fa5859a 100644
--- a/src/gui/socketapi.cpp
+++ b/src/gui/socketapi.cpp
@@ -619,9 +619,8 @@ void SocketApi::command_MAKE_AVAILABLE_LOCALLY(const QString &filesArg, SocketLi
continue;
// Update the pin state on all items
- auto pinPath = data.folderRelativePathNoVfsSuffix().toUtf8();
- data.folder->journalDb()->wipePinStateForPathAndBelow(pinPath);
- data.folder->journalDb()->setPinStateForPath(pinPath, PinState::AlwaysLocal);
+ auto pinPath = data.folderRelativePathNoVfsSuffix();
+ data.folder->vfs().setPinState(pinPath, PinState::AlwaysLocal);
// Trigger the recursive download
data.folder->downloadVirtualFile(data.folderRelativePath);
@@ -639,9 +638,8 @@ void SocketApi::command_MAKE_ONLINE_ONLY(const QString &filesArg, SocketListener
continue;
// Update the pin state on all items
- auto pinPath = data.folderRelativePathNoVfsSuffix().toUtf8();
- data.folder->journalDb()->wipePinStateForPathAndBelow(pinPath);
- data.folder->journalDb()->setPinStateForPath(pinPath, PinState::OnlineOnly);
+ auto pinPath = data.folderRelativePathNoVfsSuffix();
+ data.folder->vfs().setPinState(pinPath, PinState::OnlineOnly);
// Trigger recursive dehydration
data.folder->dehydrateFile(data.folderRelativePath);
@@ -917,7 +915,7 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe
for (const auto &file : files) {
auto fileData = FileData::get(file);
auto path = fileData.folderRelativePathNoVfsSuffix();
- auto pinState = folder->journalDb()->effectivePinStateForPath(path.toUtf8());
+ auto pinState = folder->vfs().getPinState(path);
if (!pinState) {
// db error
hasAlwaysLocal = true;
diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp
index 5cd33463d..b00e7451e 100644
--- a/src/libsync/discovery.cpp
+++ b/src/libsync/discovery.cpp
@@ -427,14 +427,10 @@ 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) {
+ && _pinState != PinState::AlwaysLocal) {
item->_type = ItemTypeVirtualFile;
if (isVfsWithSuffix())
addVirtualFileSuffix(path._original);
@@ -981,8 +977,7 @@ void ProcessDirectoryJob::processFileFinalize(
if (!checkPermissions(item))
recurse = false;
if (recurse) {
- auto job = new ProcessDirectoryJob(item, recurseQueryLocal, recurseQueryServer, _discoveryData, this);
- job->_currentFolder = path;
+ auto job = new ProcessDirectoryJob(path, item, recurseQueryLocal, recurseQueryServer, this);
if (item->_instruction == CSYNC_INSTRUCTION_REMOVE) {
job->setParent(_discoveryData);
_discoveryData->_queuedDeletedDirectories[path._original] = job;
@@ -1023,8 +1018,7 @@ void ProcessDirectoryJob::processBlacklisted(const PathTuple &path, const OCC::L
qCInfo(lcDisco) << "Discovered (blacklisted) " << item->_file << item->_instruction << item->_direction << item->isDirectory();
if (item->isDirectory() && item->_instruction != CSYNC_INSTRUCTION_IGNORE) {
- auto job = new ProcessDirectoryJob(item, NormalQuery, InBlackList, _discoveryData, this);
- job->_currentFolder = path;
+ auto job = new ProcessDirectoryJob(path, item, NormalQuery, InBlackList, this);
connect(job, &ProcessDirectoryJob::finished, this, &ProcessDirectoryJob::subJobFinished);
_queuedJobs.push_back(job);
} else {
@@ -1349,19 +1343,18 @@ bool ProcessDirectoryJob::runLocalQuery()
return true;
}
-Optional<PinState> ProcessDirectoryJob::directoryPinState()
+bool ProcessDirectoryJob::isVfsWithSuffix() const
{
- if (!_pinStateCache) {
- _pinStateCache = _discoveryData->_statedb->effectivePinStateForPath(
- _currentFolder._original.toUtf8());
- // don't cache db errors, just retry next time
- }
- return _pinStateCache;
+ return _discoveryData->_syncOptions._vfs->mode() == Vfs::WithSuffix;
}
-bool ProcessDirectoryJob::isVfsWithSuffix() const
+void ProcessDirectoryJob::computePinState(PinState parentState)
{
- return _discoveryData->_syncOptions._vfs->mode() == Vfs::WithSuffix;
+ _pinState = parentState;
+ if (_queryLocal != ParentDontExist) {
+ if (auto state = _discoveryData->_syncOptions._vfs->getPinState(_currentFolder._local)) // ouch! pin local or original?
+ _pinState = *state;
+ }
}
}
diff --git a/src/libsync/discovery.h b/src/libsync/discovery.h
index bfb6856a3..6cc059bbd 100644
--- a/src/libsync/discovery.h
+++ b/src/libsync/discovery.h
@@ -48,6 +48,8 @@ class SyncJournalDb;
class ProcessDirectoryJob : public QObject
{
Q_OBJECT
+
+ struct PathTuple;
public:
enum QueryMode {
NormalQuery,
@@ -56,14 +58,30 @@ public:
InBlackList // Do not query this folder because it is in the blacklist (remote entries only)
};
Q_ENUM(QueryMode)
- explicit ProcessDirectoryJob(const SyncFileItemPtr &dirItem, QueryMode queryLocal, QueryMode queryServer,
- DiscoveryPhase *data, QObject *parent)
+
+ /** For creating the root job
+ *
+ * The base pin state is used if the root dir's pin state can't be retrieved.
+ */
+ explicit ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, QObject *parent)
+ : QObject(parent)
+ , _discoveryData(data)
+ {
+ computePinState(basePinState);
+ }
+
+ /// For creating subjobs
+ explicit ProcessDirectoryJob(const PathTuple &path, const SyncFileItemPtr &dirItem,
+ QueryMode queryLocal, QueryMode queryServer,
+ ProcessDirectoryJob *parent)
: QObject(parent)
, _dirItem(dirItem)
, _queryServer(queryServer)
, _queryLocal(queryLocal)
- , _discoveryData(data)
+ , _discoveryData(parent->_discoveryData)
+ , _currentFolder(path)
{
+ computePinState(parent->_pinState);
}
void start();
@@ -180,11 +198,15 @@ private:
*/
bool runLocalQuery();
- /** Retrieve and cache directory pin state */
- Optional<PinState> directoryPinState();
+ /** Sets _pinState
+ *
+ * If the folder exists locally its state is retrieved, otherwise the
+ * parent's pin state is inherited.
+ */
+ void computePinState(PinState parentState);
- QueryMode _queryServer;
- QueryMode _queryLocal;
+ QueryMode _queryServer = QueryMode::NormalQuery;
+ QueryMode _queryLocal = QueryMode::NormalQuery;
// Holds entries that resulted from a NormalQuery
QVector<RemoteInfo> _serverNormalQueryEntries;
@@ -222,7 +244,7 @@ private:
PathTuple _currentFolder;
bool _childModified = false; // the directory contains modified item what would prevent deletion
bool _childIgnored = false; // The directory contains ignored item that would prevent deletion
- Optional<PinState> _pinStateCache; // The directories pin-state, once retrieved, see directoryPinState()
+ PinState _pinState = PinState::Unspecified; // The directory's pin-state, see setParentPinState()
signals:
void finished();
diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp
index d7f81f16b..313010d7f 100644
--- a/src/libsync/syncengine.cpp
+++ b/src/libsync/syncengine.cpp
@@ -568,8 +568,8 @@ void SyncEngine::startSync()
connect(_discoveryPhase.data(), &DiscoveryPhase::silentlyExcluded,
_syncFileStatusTracker.data(), &SyncFileStatusTracker::slotAddSilentlyExcluded);
- auto discoveryJob = new ProcessDirectoryJob(SyncFileItemPtr(), ProcessDirectoryJob::NormalQuery, ProcessDirectoryJob::NormalQuery,
- _discoveryPhase.data(), _discoveryPhase.data());
+ auto discoveryJob = new ProcessDirectoryJob(
+ _discoveryPhase.data(), PinState::AlwaysLocal, _discoveryPhase.data());
_discoveryPhase->startJob(discoveryJob);
connect(discoveryJob, &ProcessDirectoryJob::etag, this, &SyncEngine::slotRootEtagReceived);
}
diff --git a/src/libsync/vfs/suffix/vfs_suffix.cpp b/src/libsync/vfs/suffix/vfs_suffix.cpp
index 60d753a1b..518decf70 100644
--- a/src/libsync/vfs/suffix/vfs_suffix.cpp
+++ b/src/libsync/vfs/suffix/vfs_suffix.cpp
@@ -22,7 +22,7 @@
namespace OCC {
VfsSuffix::VfsSuffix(QObject *parent)
- : Vfs(parent)
+ : VfsDefaults(parent)
{
}
@@ -40,14 +40,6 @@ QString VfsSuffix::fileSuffix() const
return QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX);
}
-void VfsSuffix::registerFolder(const VfsSetupParams &)
-{
-}
-
-void VfsSuffix::start(const VfsSetupParams &)
-{
-}
-
void VfsSuffix::stop()
{
}
diff --git a/src/libsync/vfs/suffix/vfs_suffix.h b/src/libsync/vfs/suffix/vfs_suffix.h
index 2949533aa..9c2a2cc08 100644
--- a/src/libsync/vfs/suffix/vfs_suffix.h
+++ b/src/libsync/vfs/suffix/vfs_suffix.h
@@ -21,7 +21,7 @@
namespace OCC {
-class VfsSuffix : public Vfs
+class VfsSuffix : public VfsDefaults
{
Q_OBJECT
@@ -32,8 +32,6 @@ public:
Mode mode() const override;
QString fileSuffix() const override;
- void registerFolder(const VfsSetupParams &params) override;
- void start(const VfsSetupParams &params) override;
void stop() override;
void unregisterFolder() override;
diff --git a/test/syncenginetestutils.h b/test/syncenginetestutils.h
index b4f9e89d5..549d0092f 100644
--- a/test/syncenginetestutils.h
+++ b/test/syncenginetestutils.h
@@ -12,6 +12,7 @@
#include "filesystem.h"
#include "syncengine.h"
#include "common/syncjournaldb.h"
+#include "common/vfs.h"
#include "csync_exclude.h"
#include <cstring>
@@ -1139,12 +1140,41 @@ public:
// Ignore temporary files from the download. (This is in the default exclude list, but we don't load it)
_syncEngine->excludedFiles().addManualExclude("]*.~*");
+ // Ensure we have a valid VfsOff instance "running"
+ switchToVfs(_syncEngine->syncOptions()._vfs);
+
// A new folder will update the local file state database on first sync.
// To have a state matching what users will encounter, we have to a sync
// using an identical local/remote file tree first.
syncOnce();
}
+ void switchToVfs(QSharedPointer<OCC::Vfs> vfs)
+ {
+ auto opts = _syncEngine->syncOptions();
+
+ opts._vfs->stop();
+ QObject::disconnect(_syncEngine.get(), 0, opts._vfs.data(), 0);
+
+ opts._vfs = vfs;
+ _syncEngine->setSyncOptions(opts);
+
+ OCC::VfsSetupParams vfsParams;
+ vfsParams.filesystemPath = localPath();
+ vfsParams.remotePath = "";
+ vfsParams.account = _account;
+ vfsParams.journal = _journalDb.get();
+ vfsParams.providerName = "OC-TEST";
+ vfsParams.providerVersion = "0.1";
+ vfsParams.enableShellIntegration = false;
+ QObject::connect(_syncEngine.get(), &QObject::destroyed, vfs.data(), [vfs]() {
+ vfs->stop();
+ vfs->unregisterFolder();
+ });
+
+ vfs->start(vfsParams);
+ }
+
OCC::AccountPtr account() const { return _account; }
OCC::SyncEngine &syncEngine() const { return *_syncEngine; }
OCC::SyncJournalDb &syncJournal() const { return *_journalDb; }
diff --git a/test/testsyncvirtualfiles.cpp b/test/testsyncvirtualfiles.cpp
index 7a3b154cf..bb17f3e5b 100644
--- a/test/testsyncvirtualfiles.cpp
+++ b/test/testsyncvirtualfiles.cpp
@@ -59,12 +59,15 @@ void markForDehydration(FakeFolder &folder, const QByteArray &path)
journal.avoidReadFromDbOnNextSync(record._path);
}
-SyncOptions vfsSyncOptions(FakeFolder &fakeFolder)
+QSharedPointer<Vfs> setupVfs(FakeFolder &folder)
{
- SyncOptions options;
- options._vfs.reset(createVfsFromPlugin(Vfs::WithSuffix).release());
- fakeFolder.syncJournal().setPinStateForPath("", PinState::OnlineOnly);
- return options;
+ auto suffixVfs = QSharedPointer<Vfs>(createVfsFromPlugin(Vfs::WithSuffix).release());
+ folder.switchToVfs(suffixVfs);
+
+ // Using this directly doesn't recursively unpin everything
+ folder.syncJournal().setPinStateForPath("", PinState::OnlineOnly);
+
+ return suffixVfs;
}
class TestSyncVirtualFiles : public QObject
@@ -85,7 +88,7 @@ private slots:
QFETCH(bool, doLocalDiscovery);
FakeFolder fakeFolder{ FileInfo() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
@@ -206,7 +209,7 @@ private slots:
void testVirtualFileConflict()
{
FakeFolder fakeFolder{ FileInfo() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
@@ -277,7 +280,7 @@ private slots:
void testWithNormalSync()
{
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
@@ -313,7 +316,7 @@ private slots:
void testVirtualFileDownload()
{
FakeFolder fakeFolder{ FileInfo() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
@@ -381,7 +384,7 @@ private slots:
void testVirtualFileDownloadResume()
{
FakeFolder fakeFolder{ FileInfo() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
@@ -422,8 +425,7 @@ private slots:
void testNewFilesNotVirtual()
{
FakeFolder fakeFolder{ FileInfo() };
- SyncOptions syncOptions = vfsSyncOptions(fakeFolder);
- fakeFolder.syncEngine().setSyncOptions(syncOptions);
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
fakeFolder.remoteModifier().mkdir("A");
@@ -443,7 +445,7 @@ private slots:
void testDownloadRecursive()
{
FakeFolder fakeFolder{ FileInfo() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
// Create a virtual file for remote files
@@ -540,7 +542,7 @@ private slots:
void testRenameToVirtual()
{
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
@@ -578,7 +580,7 @@ private slots:
void testRenameVirtual()
{
FakeFolder fakeFolder{ FileInfo() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
@@ -620,7 +622,7 @@ private slots:
void testSyncDehydration()
{
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QVERIFY(fakeFolder.syncOnce());
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
@@ -697,7 +699,7 @@ private slots:
void testWipeVirtualSuffixFiles()
{
FakeFolder fakeFolder{ FileInfo{} };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
// Create a suffix-vfs baseline
@@ -733,7 +735,7 @@ private slots:
QVERIFY(fakeFolder.currentLocalState().find("A/a3.owncloud"));
QVERIFY(!fakeFolder.currentLocalState().find("A/B/b1.owncloud"));
- fakeFolder.syncEngine().setSyncOptions(SyncOptions{});
+ fakeFolder.switchToVfs(QSharedPointer<Vfs>(new VfsOff));
QVERIFY(fakeFolder.syncOnce());
QVERIFY(fakeFolder.currentRemoteState().find("A/a3.owncloud")); // regular upload
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
@@ -742,7 +744,7 @@ private slots:
void testNewVirtuals()
{
FakeFolder fakeFolder{ FileInfo() };
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
auto setPin = [&] (const QByteArray &path, PinState state) {
@@ -757,6 +759,7 @@ private slots:
setPin("local", PinState::AlwaysLocal);
setPin("online", PinState::OnlineOnly);
+ setPin("unspec", PinState::Unspecified);
// Test 1: root is OnlineOnly
fakeFolder.remoteModifier().insert("file1");
@@ -782,7 +785,7 @@ private slots:
QVERIFY(fakeFolder.currentLocalState().find("file2"));
QVERIFY(fakeFolder.currentLocalState().find("online/file2.owncloud"));
QVERIFY(fakeFolder.currentLocalState().find("local/file2"));
- QVERIFY(fakeFolder.currentLocalState().find("unspec/file2"));
+ QVERIFY(fakeFolder.currentLocalState().find("unspec/file2.owncloud"));
// file1 is unchanged
QVERIFY(fakeFolder.currentLocalState().find("file1.owncloud"));
@@ -810,7 +813,7 @@ private slots:
cleanup();
// Enable suffix vfs
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions(fakeFolder));
+ setupVfs(fakeFolder);
// Local changes of suffixed file do nothing
fakeFolder.localModifier().appendByte("A/file1.owncloud");