Skip sync exclude file from list of exclude files if it doesn't exist.
authorCamila <hello@camila.codes>
Wed, 9 Dec 2020 15:59:10 +0000 (16:59 +0100)
committerCamila <hello@camila.codes>
Thu, 28 Oct 2021 09:37:56 +0000 (11:37 +0200)
The file might not exist anymore because the user deleted it by hand or
the folder where it was located got unchecked in the selective sync
view. It is a fix for #2632.

Signed-off-by: Camila <hello@camila.codes>
src/csync/csync_exclude.cpp
src/csync/csync_exclude.h
test/testexcludedfiles.cpp

index c15fc5e017efe1b41944331b3f27802ff94c0284..eb850758917aa830ac3f9640f234cacdc333319b 100644 (file)
 
 #include <QString>
 #include <QFileInfo>
-#include <QFile>
 #include <QDir>
 
-
 /** Expands C-like escape sequences (in place)
  */
 OCSYNC_EXPORT void csync_exclude_expand_escapes(QByteArray &input)
@@ -238,18 +236,17 @@ ExcludedFiles::~ExcludedFiles() = default;
 
 void ExcludedFiles::addExcludeFilePath(const QString &path)
 {
-    auto &excludeFilesLocalPath = _excludeFiles[_localPath];
+    const QFileInfo excludeFileInfo(path);
+    const auto fileName = excludeFileInfo.fileName();
+    const auto basePath = fileName.compare(QStringLiteral("sync-exclude.lst"), Qt::CaseInsensitive) == 0
+                                                                    ? _localPath
+                                                                    : leftIncludeLast(path, QLatin1Char('/'));
+    auto &excludeFilesLocalPath = _excludeFiles[basePath];
     if (std::find(excludeFilesLocalPath.cbegin(), excludeFilesLocalPath.cend(), path) == excludeFilesLocalPath.cend()) {
         excludeFilesLocalPath.append(path);
     }
 }
 
-void ExcludedFiles::addInTreeExcludeFilePath(const QString &path)
-{
-    BasePathString basePath = leftIncludeLast(path, QLatin1Char('/'));
-    _excludeFiles[basePath].append(path);
-}
-
 void ExcludedFiles::setExcludeConflictFiles(bool onoff)
 {
     _excludeConflictFiles = onoff;
@@ -287,32 +284,26 @@ void ExcludedFiles::setClientVersion(ExcludedFiles::Version version)
     _clientVersion = version;
 }
 
-bool ExcludedFiles::loadExcludeFile(const QString &basePath, const QString & file)
+void ExcludedFiles::loadExcludeFilePatterns(const QString &basePath, QFile &file)
 {
-    QFile f(file);
-    if (!f.open(QIODevice::ReadOnly))
-        return false;
-
     QStringList patterns;
-    while (!f.atEnd()) {
-        QByteArray line = f.readLine().trimmed();
+    while (!file.atEnd()) {
+        QByteArray line = file.readLine().trimmed();
         if (line.startsWith("#!version")) {
             if (!versionDirectiveKeepNextLine(line))
-                f.readLine();
+                file.readLine();
         }
         if (line.isEmpty() || line.startsWith('#'))
             continue;
         csync_exclude_expand_escapes(line);
         patterns.append(QString::fromUtf8(line));
     }
-    _allExcludes.insert(basePath, patterns);
+    _allExcludes[basePath].append(patterns);
 
     // nothing to prepare if the user decided to not exclude anything
     if (!_allExcludes.value(basePath).isEmpty()){
         prepare(basePath);
     }
-
-    return true;
 }
 
 bool ExcludedFiles::reloadExcludeFiles()
@@ -329,8 +320,14 @@ bool ExcludedFiles::reloadExcludeFiles()
     bool success = true;
     const auto keys = _excludeFiles.keys();
     for (const auto& basePath : keys) {
-        for (const auto& file : _excludeFiles.value(basePath)) {
-            success = loadExcludeFile(basePath, file);
+        for (const auto &excludeFile : _excludeFiles.value(basePath)) {
+            QFile file(excludeFile);
+            if (file.exists() && file.open(QIODevice::ReadOnly)) {
+                loadExcludeFilePatterns(basePath, file);
+            } else {
+                success = false;
+                qWarning() << "System exclude list file could not be opened:" << excludeFile;
+            }
         }
     }
 
@@ -421,11 +418,14 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
     // Directories are guaranteed to be visited before their files
     if (filetype == ItemTypeDirectory) {
         const auto basePath = QString(_localPath + path + QLatin1Char('/'));
-        const auto fi = QFileInfo(basePath + QStringLiteral(".sync-exclude.lst"));
+        const QString absolutePath = basePath + QStringLiteral(".sync-exclude.lst");
+        QFileInfo excludeFileInfo(absolutePath);
 
-        if (fi.isReadable()) {
-            addInTreeExcludeFilePath(fi.absoluteFilePath());
-            loadExcludeFile(basePath, fi.absoluteFilePath());
+        if (excludeFileInfo.isReadable()) {
+            addExcludeFilePath(absolutePath);
+            reloadExcludeFiles();
+        } else {
+            qWarning() << "System exclude list file could not be read:" << absolutePath;
         }
     }
 
index cc4de99233c0bcc9d6e3f4d7d5f46264d2f545e6..856ac67eff8ad393d48820849c0a4f649e34251c 100644 (file)
@@ -48,6 +48,7 @@ enum CSYNC_EXCLUDE_TYPE {
 };
 
 class ExcludedFilesTest;
+class QFile;
 
 /**
  * Manages file/directory exclusion.
@@ -77,7 +78,6 @@ public:
      * Does not load the file. Use reloadExcludeFiles() afterwards.
      */
     void addExcludeFilePath(const QString &path);
-    void addInTreeExcludeFilePath(const QString &path);
 
     /**
      * Whether conflict files shall be excluded.
@@ -148,7 +148,7 @@ public slots:
     /**
      * Loads the exclude patterns from file the registered base paths.
      */
-    bool loadExcludeFile(const QString &basePath, const QString &file);
+    void loadExcludeFilePatterns(const QString &basePath, QFile &file);
 
 private:
     /**
index 94b23b5b45db96cdb196dce06c54105ea5148c06..7dc8b19f0d7b413ef9a84c789847c716244b3a6b 100644 (file)
@@ -265,7 +265,7 @@ private slots:
         QCOMPARE(excludeList.write("bar"), 3);
         excludeList.close();
 
-        excludedFiles->addInTreeExcludeFilePath(fooExcludeList);
+        excludedFiles->addExcludeFilePath(fooExcludeList);
         excludedFiles->reloadExcludeFiles();
         QCOMPARE(check_file_full(QByteArray(fooDir.toUtf8() + "/bar")), CSYNC_FILE_EXCLUDE_LIST);
         QCOMPARE(check_file_full(QByteArray(fooDir.toUtf8() + "/baz")), CSYNC_NOT_EXCLUDED);