Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
4f4fd60
gitignore: Ignore clangd-generated directory .cache/
taminob Oct 31, 2023
ed5fdd8
cmake: Export compile_commands.json by default
taminob Oct 31, 2023
5812d5c
libsync: Remove auto-exclude for symlinks
taminob Oct 31, 2023
40145c9
libsync/common: Store actual type for items
taminob Oct 31, 2023
0370594
libsync: Add header field OC-File-Type for symlink synchronization
taminob Oct 31, 2023
d66c704
libsync: Add SymLinkUploadDevice for reading symlinks
taminob Nov 2, 2023
c34659b
libsync: Use SymLinkUploadDevice for single symlink uploads
taminob Nov 2, 2023
7b92b2e
libsync: Add support for symlinks in bulk uploads
taminob Nov 4, 2023
390e8f6
libsync: Fix _read for SymLinkUploadDevice
taminob Nov 5, 2023
af53d58
libsync: Allow download of symlinks
taminob Nov 5, 2023
aee6601
libsync: Fix Content-Length for symlinks in bulk upload
taminob Nov 12, 2023
a551b24
common: Do not dereference symlink when checking existence
taminob Nov 15, 2023
7876341
libsync: Fix checksum and size for symlinks in bulk upload
taminob Nov 15, 2023
c5b8235
libsync: Add symlink type to DiscoveryPhase
taminob Nov 23, 2023
10d0fcc
common: Allow checksum calculation on QIODevice again
taminob Nov 27, 2023
e7c357c
libsync: Add readlink to FileSystem and fix getSize for symlinks
taminob Nov 27, 2023
719e014
BulkPropagatorJob: Remove symlink size special case
taminob Nov 28, 2023
8f05e93
FileSystem: Fix fileEquals for symlinks
taminob Nov 28, 2023
f5d6110
gui/config: Add symlink synchronization as sync option
taminob Nov 30, 2023
4866922
Revert "common: Allow checksum calculation on QIODevice again"
taminob Dec 2, 2023
6df006d
filesystem: Move readlink from libsync/filesystem.h to common/filesys…
taminob Dec 4, 2023
97f015c
ChecksumCalculator: Calculate symlink checksum on symlink target
taminob Dec 4, 2023
845e108
discoveryphase: Fix local entry size for symlinks
taminob Dec 4, 2023
7a6df0e
ChecksumCalculator: Fix creation of QBuffer
taminob Dec 4, 2023
81dbb9d
FileSystem: Make readlink C++20 compliant
taminob Dec 4, 2023
91a5e54
csync/FileSystem: Adjust c_utimes to not follow symlinks
taminob Dec 6, 2023
d5b61b2
discovery: Check if symlink for server entries
taminob Dec 6, 2023
d36b7b9
OwncloudPropagator: Fix condition for deletion of previous remote item
taminob Dec 6, 2023
5bcf57a
OwncloudPropagator: Only download symlink if enabled by option
taminob Dec 6, 2023
fa16c33
PropagateDownloadFile: Allow symlink to be larger than 8kB
taminob Dec 6, 2023
f779b3e
PropagateDownloadFile/FileSystem: Preserve permissions for symlinks
taminob Dec 8, 2023
5265ed4
PropagateDownloadFile/FileSystem: Improve previous commit (by mainly …
taminob Dec 8, 2023
c61a574
ConflictDialog: Fix size and mtime for symlinks in conflict resolution
taminob Dec 10, 2023
38f5dac
ActivityListModel: Modify ignore text to not include symlinks
taminob Dec 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
gui/config: Add symlink synchronization as sync option
This commit reverts the effects of commit
"libsync: Remove auto-exclude for symlinks"
(5812d5c).

Signed-off-by: Tamino Bauknecht <[email protected]>
  • Loading branch information
taminob committed Dec 10, 2023
commit f5d611007cf406059bf74667d8908a161e28b477
1 change: 1 addition & 0 deletions src/gui/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,7 @@ SyncOptions Folder::initializeSyncOptions() const
auto newFolderLimit = cfgFile.newBigFolderSizeLimit();
opt._newBigFolderSizeLimit = newFolderLimit.first ? newFolderLimit.second * 1000LL * 1000LL : -1; // convert from MB to B
opt._confirmExternalStorage = cfgFile.confirmExternalStorage();
opt._synchronizeSymlinks = cfgFile.synchronizeSymlinks();
opt._moveFilesToTrash = cfgFile.moveToTrash();
opt._vfs = _vfs;
opt._parallelNetworkJobs = _accountState->account()->isHttp2Supported() ? 20 : 6;
Expand Down
4 changes: 4 additions & 0 deletions src/gui/generalsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ GeneralSettings::GeneralSettings(QWidget *parent)
connect(_ui->existingFolderLimitCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);
connect(_ui->stopExistingFolderNowBigSyncCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);
connect(_ui->newExternalStorage, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);
connect(_ui->synchronizeSymlinks, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);
connect(_ui->moveFilesToTrashCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);

#ifndef WITH_CRASHREPORTER
Expand Down Expand Up @@ -259,6 +260,7 @@ void GeneralSettings::loadMiscSettings()
_ui->showInExplorerNavigationPaneCheckBox->setChecked(cfgFile.showInExplorerNavigationPane());
_ui->crashreporterCheckBox->setChecked(cfgFile.crashReporter());
_ui->newExternalStorage->setChecked(cfgFile.confirmExternalStorage());
_ui->synchronizeSymlinks->setChecked(cfgFile.synchronizeSymlinks());
_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
_ui->moveFilesToTrashCheckBox->setChecked(cfgFile.moveToTrash());

Expand All @@ -270,6 +272,7 @@ void GeneralSettings::loadMiscSettings()
_ui->stopExistingFolderNowBigSyncCheckBox->setEnabled(_ui->existingFolderLimitCheckBox->isChecked());
_ui->stopExistingFolderNowBigSyncCheckBox->setChecked(_ui->existingFolderLimitCheckBox->isChecked() && cfgFile.stopSyncingExistingFoldersOverLimit());
_ui->newExternalStorage->setChecked(cfgFile.confirmExternalStorage());
_ui->synchronizeSymlinks->setChecked(cfgFile.synchronizeSymlinks());
_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
}

Expand Down Expand Up @@ -447,6 +450,7 @@ void GeneralSettings::saveMiscSettings()
cfgFile.setMoveToTrash(_ui->moveFilesToTrashCheckBox->isChecked());
cfgFile.setNewBigFolderSizeLimit(newFolderLimitEnabled, _ui->newFolderLimitSpinBox->value());
cfgFile.setConfirmExternalStorage(_ui->newExternalStorage->isChecked());
cfgFile.setSynchronizeSymlinks(_ui->synchronizeSymlinks->isChecked());
cfgFile.setNotifyExistingFoldersOverLimit(existingFolderLimitEnabled);
cfgFile.setStopSyncingExistingFoldersOverLimit(stopSyncingExistingFoldersOverLimit);

Expand Down
11 changes: 11 additions & 0 deletions src/gui/generalsettings.ui
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QCheckBox" name="synchronizeSymlinks">
<property name="text">
<string>[experimental] Synchronize symlinks</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
Expand Down
12 changes: 12 additions & 0 deletions src/libsync/configfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static constexpr char useNewBigFolderSizeLimitC[] = "useNewBigFolderSizeLimit";
static constexpr char notifyExistingFoldersOverLimitC[] = "notifyExistingFoldersOverLimit";
static constexpr char stopSyncingExistingFoldersOverLimitC[] = "stopSyncingExistingFoldersOverLimit";
static constexpr char confirmExternalStorageC[] = "confirmExternalStorage";
static constexpr char synchronizeSymlinksC[] = "synchronizeSymlinks";
static constexpr char moveToTrashC[] = "moveToTrash";

static constexpr char certPath[] = "http_certificatePath";
Expand Down Expand Up @@ -947,6 +948,12 @@ bool ConfigFile::confirmExternalStorage() const
return getPolicySetting(QLatin1String(confirmExternalStorageC), fallback).toBool();
}

bool ConfigFile::synchronizeSymlinks() const
{
const auto fallback = getValue(synchronizeSymlinksC, QString(), false);
return getPolicySetting(QLatin1String(synchronizeSymlinksC), fallback).toBool();
}

bool ConfigFile::useNewBigFolderSizeLimit() const
{
const auto fallback = getValue(useNewBigFolderSizeLimitC, QString(), true);
Expand Down Expand Up @@ -981,6 +988,11 @@ void ConfigFile::setConfirmExternalStorage(bool isChecked)
setValue(confirmExternalStorageC, isChecked);
}

void ConfigFile::setSynchronizeSymlinks(bool isChecked)
{
setValue(synchronizeSymlinksC, isChecked);
}

bool ConfigFile::moveToTrash() const
{
return getValue(moveToTrashC, QString(), false).toBool();
Expand Down
3 changes: 3 additions & 0 deletions src/libsync/configfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ class OWNCLOUDSYNC_EXPORT ConfigFile
[[nodiscard]] bool confirmExternalStorage() const;
void setConfirmExternalStorage(bool);

[[nodiscard]] bool synchronizeSymlinks() const;
void setSynchronizeSymlinks(bool);

/** If we should move the files deleted on the server in the trash */
[[nodiscard]] bool moveToTrash() const;
void setMoveToTrash(bool);
Expand Down
20 changes: 13 additions & 7 deletions src/libsync/discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,35 +39,38 @@ namespace OCC {

Q_LOGGING_CATEGORY(lcDisco, "nextcloud.sync.discovery", QtInfoMsg)

ProcessDirectoryJob::ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, qint64 lastSyncTimestamp, QObject *parent)
ProcessDirectoryJob::ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, qint64 lastSyncTimestamp, bool synchronizeSymlinks, QObject *parent)
: QObject(parent)
, _lastSyncTimestamp(lastSyncTimestamp)
, _discoveryData(data)
, _synchronizeSymlinks(synchronizeSymlinks)
{
qCDebug(lcDisco) << data;
computePinState(basePinState);
}

ProcessDirectoryJob::ProcessDirectoryJob(const PathTuple &path, const SyncFileItemPtr &dirItem, QueryMode queryLocal, QueryMode queryServer, qint64 lastSyncTimestamp, ProcessDirectoryJob *parent)
ProcessDirectoryJob::ProcessDirectoryJob(const PathTuple &path, const SyncFileItemPtr &dirItem, QueryMode queryLocal, QueryMode queryServer, qint64 lastSyncTimestamp, bool synchronizeSymlinks, ProcessDirectoryJob *parent)
: QObject(parent)
, _dirItem(dirItem)
, _lastSyncTimestamp(lastSyncTimestamp)
, _queryServer(queryServer)
, _queryLocal(queryLocal)
, _discoveryData(parent->_discoveryData)
, _currentFolder(path)
, _synchronizeSymlinks(synchronizeSymlinks)
{
qCDebug(lcDisco) << path._server << queryServer << path._local << queryLocal << lastSyncTimestamp;
computePinState(parent->_pinState);
}

ProcessDirectoryJob::ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, const PathTuple &path, const SyncFileItemPtr &dirItem, QueryMode queryLocal, qint64 lastSyncTimestamp, QObject *parent)
ProcessDirectoryJob::ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, const PathTuple &path, const SyncFileItemPtr &dirItem, QueryMode queryLocal, qint64 lastSyncTimestamp, bool synchronizeSymlinks, QObject *parent)
: QObject(parent)
, _dirItem(dirItem)
, _lastSyncTimestamp(lastSyncTimestamp)
, _queryLocal(queryLocal)
, _discoveryData(data)
, _currentFolder(path)
, _synchronizeSymlinks(synchronizeSymlinks)
{
computePinState(basePinState);
}
Expand Down Expand Up @@ -306,7 +309,9 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const Entries &ent
}
}

if (excluded == CSYNC_NOT_EXCLUDED) {
bool isSymlink = entries.localEntry.isSymLink || entries.serverEntry.isSymLink;
// All not excluded files except for symlinks if symlink synchronization is disabled
if (excluded == CSYNC_NOT_EXCLUDED && (!isSymlink || (_synchronizeSymlinks && isSymlink))) {
return false;
} else if (excluded == CSYNC_FILE_SILENTLY_EXCLUDED || excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) {
emit _discoveryData->silentlyExcluded(path);
Expand All @@ -326,7 +331,8 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const Entries &ent
return true;
}

if (entries.localEntry.isSymLink) {
if (isSymlink && !_synchronizeSymlinks) {
item->_errorString = tr("Symbolic links synchronization is not enabled.");
} else {
switch (excluded) {
case CSYNC_NOT_EXCLUDED:
Expand Down Expand Up @@ -1653,7 +1659,7 @@ void ProcessDirectoryJob::processFileFinalize(
}
if (recurse) {
auto job = new ProcessDirectoryJob(path, item, recurseQueryLocal, recurseQueryServer,
_lastSyncTimestamp, this);
_lastSyncTimestamp, _synchronizeSymlinks, this);
job->setInsideEncryptedTree(isInsideEncryptedTree() || item->isEncrypted());
if (removed) {
job->setParent(_discoveryData);
Expand Down Expand Up @@ -1697,7 +1703,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(path, item, NormalQuery, InBlackList, _lastSyncTimestamp, this);
auto job = new ProcessDirectoryJob(path, item, NormalQuery, InBlackList, _lastSyncTimestamp, _synchronizeSymlinks, this);
connect(job, &ProcessDirectoryJob::finished, this, &ProcessDirectoryJob::subJobFinished);
_queuedJobs.push_back(job);
} else {
Expand Down
7 changes: 4 additions & 3 deletions src/libsync/discovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,15 @@ class ProcessDirectoryJob : public QObject
* The base pin state is used if the root dir's pin state can't be retrieved.
*/
explicit ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState,
qint64 lastSyncTimestamp, QObject *parent);
qint64 lastSyncTimestamp, bool synchronizeSymlinks, QObject *parent);

/// For creating subjobs
explicit ProcessDirectoryJob(const PathTuple &path, const SyncFileItemPtr &dirItem,
QueryMode queryLocal, QueryMode queryServer, qint64 lastSyncTimestamp,
QueryMode queryLocal, QueryMode queryServer, qint64 lastSyncTimestamp, bool synchronizeSymlinks,
ProcessDirectoryJob *parent);

explicit ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, const PathTuple &path, const SyncFileItemPtr &dirItem,
QueryMode queryLocal, qint64 lastSyncTimestamp, QObject *parent);
QueryMode queryLocal, qint64 lastSyncTimestamp, bool synchronizeSymlinks, QObject *parent);

void start();
/** Start up to nbJobs, return the number of job started; emit finished() when done */
Expand Down Expand Up @@ -296,6 +296,7 @@ class ProcessDirectoryJob : public QObject
bool _childIgnored = false; // The directory contains ignored item that would prevent deletion
PinState _pinState = PinState::Unspecified; // The directory's pin-state, see computePinState()
bool _isInsideEncryptedTree = false; // this directory is encrypted or is within the tree of directories with root directory encrypted
const bool _synchronizeSymlinks = false;

signals:
void finished();
Expand Down
2 changes: 2 additions & 0 deletions src/libsync/syncengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,13 +717,15 @@ void SyncEngine::startSync()
singleItemDiscoveryOptions().discoveryDirItem,
localQueryMode,
_journal->keyValueStoreGetInt("last_sync", 0),
_syncOptions._synchronizeSymlinks,
_discoveryPhase.data()
);
} else {
discoveryJob = new ProcessDirectoryJob(
_discoveryPhase.data(),
PinState::AlwaysLocal,
_journal->keyValueStoreGetInt("last_sync", 0),
_syncOptions._synchronizeSymlinks,
_discoveryPhase.data()
);
}
Expand Down
3 changes: 3 additions & 0 deletions src/libsync/syncoptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class OWNCLOUDSYNC_EXPORT SyncOptions
/** If a confirmation should be asked for external storages */
bool _confirmExternalStorage = false;

/** If symlinks should be synchronized to the server as symlinks */
bool _synchronizeSymlinks = false;

/** If remotely deleted files are needed to move to trash */
bool _moveFilesToTrash = false;

Expand Down