mirror of
https://github.com/nextcloud/desktop.git
synced 2025-10-26 11:17:43 +00:00
Use remote rename if local rename is detected.
This commit is contained in:
parent
28d28ecac6
commit
253605758e
@ -159,6 +159,7 @@ struct csync_file_stat_s {
|
||||
mode_t mode; /* u32 */
|
||||
int nlink; /* u32 */
|
||||
int type; /* u32 */
|
||||
char *destpath; /* for renames */
|
||||
enum csync_instructions_e instruction; /* u32 */
|
||||
char path[1]; /* u8 */
|
||||
}
|
||||
|
||||
@ -550,6 +550,68 @@ static int _csync_new_file(CSYNC *ctx, csync_file_stat_t *st) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) {
|
||||
int rc = 0;
|
||||
char errbuf[256] = {0};
|
||||
char *suri = NULL;
|
||||
char *duri = NULL;
|
||||
|
||||
switch (ctx->current) {
|
||||
case REMOTE_REPLCIA:
|
||||
if( !(st->path && st->destpath) ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Rename failed: src or dest path empty");
|
||||
rc = -1;
|
||||
}
|
||||
if (asprintf(&suri, "%s/%s", ctx->remote.uri, st->path) < 0) {
|
||||
rc = -1;
|
||||
}
|
||||
if (asprintf(&duri, "%s/%s", ctx->remote.uri, st->destpath) < 0) {
|
||||
rc = -1;
|
||||
}
|
||||
break;
|
||||
case LOCAL_REPLICA:
|
||||
/* No renaming supported by updater */
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "RENAME is only supported on local filesystem.");
|
||||
rc = -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Renaming %s => %s", suri, duri);
|
||||
|
||||
if (rc > -1 && csync_vio_rename(ctx, suri, duri) < 0) {
|
||||
switch (errno) {
|
||||
default:
|
||||
strerror_r(errno, errbuf, sizeof(errbuf));
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
|
||||
"dir: %s, command: rename, error: %s",
|
||||
suri,
|
||||
errbuf);
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* set instruction for the statedb merger */
|
||||
if( rc > -1 ) {
|
||||
st->instruction = CSYNC_INSTRUCTION_RENAME;
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "RENAME file: %s", suri);
|
||||
}
|
||||
|
||||
out:
|
||||
SAFE_FREE(suri);
|
||||
SAFE_FREE(duri);
|
||||
SAFE_FREE(st->destpath);
|
||||
|
||||
/* set instruction for the statedb merger */
|
||||
if (rc != 0) {
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _csync_sync_file(CSYNC *ctx, csync_file_stat_t *st) {
|
||||
int rc = -1;
|
||||
|
||||
@ -947,7 +1009,13 @@ static int _csync_propagation_file_visitor(void *obj, void *data) {
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_SYNC:
|
||||
case CSYNC_INSTRUCTION_RENAME:
|
||||
if (_csync_rename_file(ctx, st) < 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"FAIL RENAME: %s",st->path);
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_SYNC:
|
||||
if (_csync_sync_file(ctx, st) < 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"FAIL SYNC: %s",st->path);
|
||||
goto err;
|
||||
|
||||
@ -23,6 +23,8 @@
|
||||
#include "csync_private.h"
|
||||
#include "csync_reconcile.h"
|
||||
#include "csync_util.h"
|
||||
#include "csync_statedb.h"
|
||||
#include "c_jhash.h"
|
||||
|
||||
#define CSYNC_LOG_CATEGORY_NAME "csync.reconciler"
|
||||
#include "csync_log.h"
|
||||
@ -43,6 +45,10 @@
|
||||
static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||
csync_file_stat_t *cur = NULL;
|
||||
csync_file_stat_t *other = NULL;
|
||||
csync_file_stat_t *tmp = NULL;
|
||||
uint64_t h = 0;
|
||||
int len = 0;
|
||||
|
||||
CSYNC *ctx = NULL;
|
||||
c_rbtree_t *tree = NULL;
|
||||
c_rbnode_t *node = NULL;
|
||||
@ -75,7 +81,28 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_RENAME:
|
||||
cur->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
/* use the old name to find the "other" node */
|
||||
tmp = csync_statedb_get_stat_by_inode(ctx, cur->inode);
|
||||
/* Find the opposite node. */
|
||||
if( tmp ) {
|
||||
/* We need to calculate the phash again because of the phash being stored as int in db. */
|
||||
if( tmp->path ) {
|
||||
len = strlen( tmp->path );
|
||||
h = c_jhash64((uint8_t *) tmp->path, len, 0);
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"PHash of temporar opposite: %llu", h);
|
||||
node = c_rbtree_find(tree, &h);
|
||||
}
|
||||
if(node) {
|
||||
other = (csync_file_stat_t*)node->data;
|
||||
other->instruction = CSYNC_INSTRUCTION_RENAME;
|
||||
other->destpath = c_strdup( cur->path );
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
}
|
||||
if( ! other ) {
|
||||
cur->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user