Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exclude placeholder #8836

Merged
merged 3 commits into from
Jul 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions changelog/unreleased/8836
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Bugfix: Always exclude .owncloud files

Our Linux virtual files implementation is using the file name extension .owncloud
those files where only ignored if the Linux VFS was enabled.
Under some circumstances it could lead to undefined client states.
We now always ignore those files as system reserved.

https://github.com/owncloud/client/pull/8836
5 changes: 5 additions & 0 deletions src/csync/csync_exclude.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "config.h"
#include "config_csync.h"

#ifndef _GNU_SOURCE
Expand Down Expand Up @@ -154,6 +155,10 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(const QStringRef &path, bool ex
}
}

if (bname.endsWith(QLatin1String(APPLICATION_DOTVIRTUALFILE_SUFFIX), Qt::CaseInsensitive)) { // ".owncloud" placeholder
return CSYNC_FILE_EXCLUDE_RESERVED;
}

// check the strlen and ignore the file if its name is longer than 254 chars.
// whenever changing this also check createDownloadTmpFileName
if (blen > 254) {
Expand Down
30 changes: 14 additions & 16 deletions src/csync/csync_exclude.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,21 @@

#include <functional>

enum csync_exclude_type_e {
CSYNC_NOT_EXCLUDED = 0,
CSYNC_FILE_SILENTLY_EXCLUDED,
CSYNC_FILE_EXCLUDE_AND_REMOVE,
CSYNC_FILE_EXCLUDE_LIST,
CSYNC_FILE_EXCLUDE_INVALID_CHAR,
CSYNC_FILE_EXCLUDE_TRAILING_SPACE,
CSYNC_FILE_EXCLUDE_LONG_FILENAME,
CSYNC_FILE_EXCLUDE_HIDDEN,
CSYNC_FILE_EXCLUDE_STAT_FAILED,
CSYNC_FILE_EXCLUDE_CONFLICT,
CSYNC_FILE_EXCLUDE_CANNOT_ENCODE,
CSYNC_FILE_EXCLUDE_SERVER_BLACKLISTED,
enum CSYNC_EXCLUDE_TYPE {
CSYNC_NOT_EXCLUDED = 0,
CSYNC_FILE_SILENTLY_EXCLUDED,
CSYNC_FILE_EXCLUDE_AND_REMOVE, // TODO: is there still a difference to CSYNC_FILE_SILENTLY_EXCLUDED
CSYNC_FILE_EXCLUDE_LIST,
CSYNC_FILE_EXCLUDE_INVALID_CHAR,
CSYNC_FILE_EXCLUDE_TRAILING_SPACE,
CSYNC_FILE_EXCLUDE_LONG_FILENAME,
CSYNC_FILE_EXCLUDE_HIDDEN,
CSYNC_FILE_EXCLUDE_STAT_FAILED,
CSYNC_FILE_EXCLUDE_CONFLICT,
CSYNC_FILE_EXCLUDE_CANNOT_ENCODE,
CSYNC_FILE_EXCLUDE_SERVER_BLACKLISTED,
CSYNC_FILE_EXCLUDE_RESERVED,
};
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;

class ExcludedFilesTest;

/**
* Manages file/directory exclusion.
Expand Down
3 changes: 3 additions & 0 deletions src/gui/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ Folder::Folder(const FolderDefinition &definition,

connect(ProgressDispatcher::instance(), &ProgressDispatcher::folderConflicts,
this, &Folder::slotFolderConflicts);
connect(_engine.data(), &SyncEngine::excluded, this, [this](const QString &path, CSYNC_EXCLUDE_TYPE reason) {
Q_EMIT ProgressDispatcher::instance()->excluded(this, path, reason);
});

_localDiscoveryTracker.reset(new LocalDiscoveryTracker);
connect(_engine.data(), &SyncEngine::finished,
Expand Down
22 changes: 20 additions & 2 deletions src/gui/issueswidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,23 @@ IssuesWidget::IssuesWidget(QWidget *parent)
auto item = SyncFileItemPtr::create();
item->_status = SyncFileItem::NormalError;
item->_errorString = message;
item->_responseTimeStamp = QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8();
_model->addProtocolItem(ProtocolItem { folderAlias, item });
});

connect(ProgressDispatcher::instance(), &ProgressDispatcher::excluded, this, [this](Folder *f, const QString &file, CSYNC_EXCLUDE_TYPE reason) {
auto item = SyncFileItemPtr::create();
item->_status = SyncFileItem::FileIgnored;
item->_file = file;
switch (reason) {
case CSYNC_FILE_EXCLUDE_RESERVED:
item->_errorString = tr("The file %1 was ignored as its name is reserved by %2").arg(file, Theme::instance()->appNameGUI());
break;
default:
Q_UNREACHABLE();
}
_model->addProtocolItem(ProtocolItem { f, item });
});

_model = new ProtocolItemModel(this);
_sortModel = new QSortFilterProxyModel(this);
_sortModel->setSourceModel(_model);
Expand Down Expand Up @@ -126,7 +139,12 @@ void IssuesWidget::slotProgressInfo(const QString &folder, const ProgressInfo &p
const auto &engine = f->syncEngine();
const auto style = engine.lastLocalDiscoveryStyle();
_model->remove_if([&](const ProtocolItem &item) {
if (item.folder()->path() != folder) {
if (item.folder() != f) {
return false;
}
if (item.direction() == SyncFileItem::None) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be easier to

return item.folder() == f && item.direction() != SyncFileItem::None;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we still have a TODO here I'd like to keep it.
(Currently we get one warning per sync run..., without skipping them the issues will get removed after the discovery which doesn't make much sense)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what it is worth, I love the verbose version without the && because I think it is easier to read and understand.

// TODO: don't clear syncErrors and excludes for now.
// make them either unique or remove them on the next sync?
return false;
}
if (style == LocalDiscoveryStyle::FilesystemOnly) {
Expand Down
10 changes: 8 additions & 2 deletions src/gui/protocolitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@

using namespace OCC;

ProtocolItem::ProtocolItem(const QString &folder, const SyncFileItemPtr &item)

ProtocolItem::ProtocolItem(Folder *folder, const SyncFileItemPtr &item)
: _path(item->destination())
, _folder(FolderMan::instance()->folder(folder))
, _folder(folder)
, _size(item->_size)
, _status(item->_status)
, _direction(item->_direction)
Expand All @@ -43,6 +44,11 @@ ProtocolItem::ProtocolItem(const QString &folder, const SyncFileItemPtr &item)
}
}

ProtocolItem::ProtocolItem(const QString &folder, const SyncFileItemPtr &item)
: ProtocolItem(FolderMan::instance()->folder(folder), item)
{
}

QString ProtocolItem::path() const
{
return _path;
Expand Down
1 change: 1 addition & 0 deletions src/gui/protocolitem.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ProtocolItem
Q_GADGET
public:
ProtocolItem() = default;
explicit ProtocolItem(Folder *folder, const SyncFileItemPtr &item);
explicit ProtocolItem(const QString &folder, const SyncFileItemPtr &item);

QString path() const;
Expand Down
16 changes: 4 additions & 12 deletions src/libsync/discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const QString &loc
} else if (excluded == CSYNC_FILE_SILENTLY_EXCLUDED || excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) {
emit _discoveryData->silentlyExcluded(path);
return true;
} else if (excluded == CSYNC_FILE_EXCLUDE_RESERVED) {
emit _discoveryData->excluded(path, excluded);
return true;
}

auto item = SyncFileItemPtr::create();
Expand All @@ -234,6 +237,7 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const QString &loc
case CSYNC_NOT_EXCLUDED:
case CSYNC_FILE_SILENTLY_EXCLUDED:
case CSYNC_FILE_EXCLUDE_AND_REMOVE:
case CSYNC_FILE_EXCLUDE_RESERVED:
qFatal("These were handled earlier");
case CSYNC_FILE_EXCLUDE_LIST:
item->_errorString = tr("File is listed on the ignore list.");
Expand Down Expand Up @@ -326,18 +330,6 @@ void ProcessDirectoryJob::processFile(PathTuple path,
if (item->_type == ItemTypeVirtualFileDehydration)
item->_type = ItemTypeFile;

// VFS suffixed files on the server are ignored
if (isVfsWithSuffix()) {
if (hasVirtualFileSuffix(serverEntry.name)
|| (localEntry.isVirtualFile && !dbEntry.isVirtualFile() && hasVirtualFileSuffix(QString::fromUtf8(dbEntry._path)))) {
item->_instruction = CSYNC_INSTRUCTION_IGNORE;
item->_errorString = tr("File has extension reserved for virtual files.");
_childIgnored = true;
emit _discoveryData->itemDiscovered(item);
return;
}
}

if (serverEntry.isValid()) {
processFileAnalyzeRemoteInfo(item, path, localEntry, serverEntry, dbEntry);
return;
Expand Down
2 changes: 0 additions & 2 deletions src/libsync/discoveryphase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ Q_LOGGING_CATEGORY(lcDiscovery, "sync.discovery", QtInfoMsg)
/* Given a sorted list of paths ending with '/', return whether or not the given path is within one of the paths of the list*/
static bool findPathInList(const QStringList &list, const QString &path)
{
Q_ASSERT(std::is_sorted(list.begin(), list.end()));

if (list.size() == 1 && list.first() == QLatin1String("/")) {
// Special case for the case "/" is there, it matches everything
return true;
Expand Down
3 changes: 2 additions & 1 deletion src/libsync/discoveryphase.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "syncoptions.h"
#include "syncfileitem.h"

class ExcludedFiles;
#include "csync/csync_exclude.h"

namespace OCC {

Expand Down Expand Up @@ -270,6 +270,7 @@ class DiscoveryPhase : public QObject
* The path is relative to the sync folder, similar to item->_file
*/
void silentlyExcluded(const QString &folderPath);
void excluded(const QString &folderPath, CSYNC_EXCLUDE_TYPE reason);
};

/// Implementation of DiscoveryPhase::adjustRenamedPath
Expand Down
14 changes: 6 additions & 8 deletions src/libsync/owncloudpropagator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,10 +369,8 @@ qint64 OwncloudPropagator::smallFileSize()
return smallFileSize;
}

void OwncloudPropagator::start(SyncFileItemVector &&items)
void OwncloudPropagator::start(SyncFileItemSet &&items)
{
Q_ASSERT(std::is_sorted(items.begin(), items.end()));

/* This builds all the jobs needed for the propagation.
* Each directory is a PropagateDirectory job, which contains the files in it.
* In order to do that we loop over the items. (which are sorted by destination)
Expand Down Expand Up @@ -833,9 +831,9 @@ bool PropagatorCompositeJob::scheduleSelfOrChild()

// Now it's our turn, check if we have something left to do.
// First, convert a task to a job if necessary
while (_jobsToDo.isEmpty() && !_tasksToDo.isEmpty()) {
SyncFileItemPtr nextTask = _tasksToDo.first();
_tasksToDo.remove(0);
while (_jobsToDo.empty() && !_tasksToDo.empty()) {
const SyncFileItemPtr nextTask = *_tasksToDo.begin();
_tasksToDo.erase(_tasksToDo.begin());
PropagatorJob *job = propagator()->createJob(nextTask);
if (!job) {
qCWarning(lcDirectory) << "Useless task found for file" << nextTask->destination() << "instruction" << nextTask->_instruction;
Expand All @@ -854,7 +852,7 @@ bool PropagatorCompositeJob::scheduleSelfOrChild()

// If neither us or our children had stuff left to do we could hang. Make sure
// we mark this job as finished so that the propagator can schedule a new one.
if (_jobsToDo.isEmpty() && _tasksToDo.isEmpty() && _runningJobs.isEmpty()) {
if (_jobsToDo.isEmpty() && _tasksToDo.empty() && _runningJobs.isEmpty()) {
// Our parent jobs are already iterating over their running jobs, post to the event loop
// to avoid removing ourself from that list while they iterate.
QMetaObject::invokeMethod(this, "finalize", Qt::QueuedConnection);
Expand Down Expand Up @@ -883,7 +881,7 @@ void PropagatorCompositeJob::slotSubJobFinished(SyncFileItem::Status status)
_hasError = status;
}

if (_jobsToDo.isEmpty() && _tasksToDo.isEmpty() && _runningJobs.isEmpty()) {
if (_jobsToDo.isEmpty() && _tasksToDo.empty() && _runningJobs.isEmpty()) {
finalize();
} else {
propagator()->scheduleNextJob();
Expand Down
6 changes: 3 additions & 3 deletions src/libsync/owncloudpropagator.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class PropagatorCompositeJob : public PropagatorJob
Q_OBJECT
public:
QVector<PropagatorJob *> _jobsToDo;
SyncFileItemVector _tasksToDo;
SyncFileItemSet _tasksToDo;
QVector<PropagatorJob *> _runningJobs;
SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error
quint64 _abortsCount;
Expand All @@ -233,7 +233,7 @@ class PropagatorCompositeJob : public PropagatorJob
void appendJob(PropagatorJob *job);
void appendTask(const SyncFileItemPtr &item)
{
_tasksToDo.append(item);
_tasksToDo.insert(item);
}

bool scheduleSelfOrChild() override;
Expand Down Expand Up @@ -412,7 +412,7 @@ class OWNCLOUDSYNC_EXPORT OwncloudPropagator : public QObject

~OwncloudPropagator() override;

void start(SyncFileItemVector &&_syncedItems);
void start(SyncFileItemSet &&_syncedItems);

const SyncOptions &syncOptions() const;
void setSyncOptions(const SyncOptions &syncOptions);
Expand Down
7 changes: 6 additions & 1 deletion src/libsync/progressdispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@

#include "syncfileitem.h"

namespace OCC {
#include "csync/csync_exclude.h"

namespace OCC {
class Folder;
/**
* @brief The ProgressInfo class
* @ingroup libsync
Expand Down Expand Up @@ -311,6 +313,9 @@ class OWNCLOUDSYNC_EXPORT ProgressDispatcher : public QObject
*/
void syncError(const QString &folder, const QString &message, ErrorCategory category);

void excluded(Folder *folder, const QString &path, CSYNC_EXCLUDE_TYPE reason);


/**
* @brief Emitted for a folder when a sync is done, listing all pending conflicts
*/
Expand Down
Loading