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.
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
/** 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<QSettings> 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
#include "csync_exclude.h"
#include "csync_misc.h"
+#include "common/utility.h"
+
#ifdef _WIN32
#include <io.h>
#else
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;
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 ) {
#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 <inttypes.h>
&& 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(),
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!
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;
}