From: Christian Kamm Date: Mon, 18 Sep 2017 08:23:20 +0000 (+0200) Subject: Conflicts: Upload them files if env variable says so X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~701^2~74 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=2cac92881010f07b5a680df8276974afcfd82fe4;p=nextcloud-desktop.git Conflicts: Upload them files if env variable says so Set OWNCLOUD_UPLOAD_CONFLICT_FILES=1 to trigger this behavior. Note that this is experimental and unsupported. The real feature is likely to end up in 2.5. Uploading conflict files is simply done by removing the pattern from csync_exclude. The rest here deals with making the conflict notification ui approximately work. There are still some concerns about where an uploaded conflict file appears in the sync protocol and issues list (it should be in both, but is only in one of them currently!). See #4557. --- diff --git a/src/common/utility.cpp b/src/common/utility.cpp index b3b7df19e..53aaf2b9d 100644 --- a/src/common/utility.cpp +++ b/src/common/utility.cpp @@ -545,4 +545,41 @@ QUrl Utility::concatUrlPath(const QUrl &url, const QString &concatPath, return tmpUrl; } +bool Utility::isConflictFile(const char *name) +{ + auto bname = strrchr(name, '/'); + if (bname) { + bname += 1; + } else { + bname = name; + } + + if (strstr(bname, "_conflict-")) + return true; + + if (shouldUploadConflictFiles()) { + // For uploads, we want to consider files with any kind of username tag + // as conflict files. (pattern *_conflict_*-) + auto startOfMarker = strstr(bname, "_conflict_"); + if (startOfMarker && strchr(startOfMarker, '-')) + return true; + } else { + // Old behavior: optionally, files with the specific string in the env variable + // appended are also considered conflict files. + static auto conflictFileUsername = qgetenv("CSYNC_CONFLICT_FILE_USERNAME"); + static auto usernameConflictId = QByteArray("_conflict_" + conflictFileUsername + "-"); + if (!conflictFileUsername.isEmpty() && strstr(bname, usernameConflictId.constData())) { + return true; + } + } + + return false; +} + +bool Utility::shouldUploadConflictFiles() +{ + static bool uploadConflictFiles = qgetenv("OWNCLOUD_UPLOAD_CONFLICT_FILES").toInt() != 0; + return uploadConflictFiles; +} + } // namespace OCC diff --git a/src/common/utility.h b/src/common/utility.h index d32a7bb3f..9fc0a72d7 100644 --- a/src/common/utility.h +++ b/src/common/utility.h @@ -175,6 +175,18 @@ namespace Utility { /** Returns a new settings pre-set in a specific group. The Settings will be created with the given parent. If no parent is specified, the caller must destroy the settings */ OCSYNC_EXPORT std::unique_ptr settingsWithGroup(const QString &group, QObject *parent = 0); + + /** Returns whether a file name indicates a conflict file + * + * See FileSystem::makeConflictFileName. + */ + OCSYNC_EXPORT bool isConflictFile(const char *name); + + /** Returns whether conflict files should be uploaded. + * + * Experimental! Real feature planned for 2.5. + */ + OCSYNC_EXPORT bool shouldUploadConflictFiles(); } /** @} */ // \addtogroup diff --git a/src/csync/csync_exclude.cpp b/src/csync/csync_exclude.cpp index 7a177b840..dbc54f2bb 100644 --- a/src/csync/csync_exclude.cpp +++ b/src/csync/csync_exclude.cpp @@ -37,6 +37,8 @@ #include "csync_exclude.h" #include "csync_misc.h" +#include "common/utility.h" + #ifdef _WIN32 #include #else @@ -218,7 +220,6 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const ch size_t i = 0; const char *bname = NULL; size_t blen = 0; - char *conflict = NULL; int rc = -1; CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED; CSYNC_EXCLUDE_TYPE type = CSYNC_NOT_EXCLUDED; @@ -308,25 +309,11 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const ch goto out; } - /* Always ignore conflict files, not only via the exclude list */ - rc = csync_fnmatch("*_conflict-*", bname, 0); - if (rc == 0) { - match = CSYNC_FILE_EXCLUDE_CONFLICT; - goto out; - } - - if (getenv("CSYNC_CONFLICT_FILE_USERNAME")) { - rc = asprintf(&conflict, "*_conflict_%s-*", getenv("CSYNC_CONFLICT_FILE_USERNAME")); - if (rc < 0) { - goto out; - } - rc = csync_fnmatch(conflict, path, 0); - if (rc == 0) { + if (!OCC::Utility::shouldUploadConflictFiles()) { + if (OCC::Utility::isConflictFile(bname)) { match = CSYNC_FILE_EXCLUDE_CONFLICT; - SAFE_FREE(conflict); goto out; } - SAFE_FREE(conflict); } if( ! excludes ) { diff --git a/src/csync/csync_update.cpp b/src/csync/csync_update.cpp index e90c9dd19..71be03be8 100644 --- a/src/csync/csync_update.cpp +++ b/src/csync/csync_update.cpp @@ -46,6 +46,8 @@ #include "csync_log.h" #include "csync_rename.h" +#include "common/utility.h" + // Needed for PRIu64 on MinGW in C++ mode. #define __STDC_FORMAT_MACROS #include @@ -371,6 +373,15 @@ out: && fs->type != CSYNC_FTW_TYPE_DIR) { fs->child_modified = true; } + + // If conflict files are uploaded, they won't be marked as IGNORE / CSYNC_FILE_EXCLUDE_CONFLICT + // but we still want them marked! + if (OCC::Utility::shouldUploadConflictFiles()) { + if (OCC::Utility::isConflictFile(fs->path.constData())) { + fs->error_status = CSYNC_STATUS_INDIVIDUAL_IS_CONFLICT_FILE; + } + } + ctx->current_fs = fs.get(); CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "file: %s, instruction: %s <<=", fs->path.constData(), diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 4b4836ad3..b133df115 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -479,7 +479,17 @@ int SyncEngine::treewalkFile(csync_file_stat_t *file, csync_file_stat_t *other, break; case CSYNC_STATUS_INDIVIDUAL_IS_CONFLICT_FILE: item->_status = SyncFileItem::Conflict; - item->_errorString = tr("Conflict: Server version downloaded, local copy renamed and not uploaded."); + if (Utility::shouldUploadConflictFiles()) { + // For uploaded conflict files, files with no action performed on them should + // be displayed: but we mustn't overwrite the instruction if something happens + // to the file! + if (remote && item->_instruction == CSYNC_INSTRUCTION_NONE) { + item->_errorString = tr("Unresolved conflict."); + item->_instruction = CSYNC_INSTRUCTION_IGNORE; + } + } else { + item->_errorString = tr("Conflict: Server version downloaded, local copy renamed and not uploaded."); + } break; case CYSNC_STATUS_FILE_LOCKED_OR_OPEN: item->_errorString = QLatin1String("File locked"); // don't translate, internal use! @@ -549,6 +559,12 @@ int SyncEngine::treewalkFile(csync_file_stat_t *file, csync_file_stat_t *other, if (!isDirectory && (!other || other->instruction == CSYNC_INSTRUCTION_NONE)) { _hasNoneFiles = true; } + // Put none-instruction conflict files into the syncfileitem list + if (Utility::shouldUploadConflictFiles() + && file->error_status == CSYNC_STATUS_INDIVIDUAL_IS_CONFLICT_FILE + && item->_instruction == CSYNC_INSTRUCTION_IGNORE) { + break; + } // No syncing or update to be done. return re; }