summaryrefslogtreecommitdiffstats
path: root/src/merge.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/merge.c')
-rw-r--r--src/merge.c58
1 files changed, 42 insertions, 16 deletions
diff --git a/src/merge.c b/src/merge.c
index 4c77e43..a6c303d 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -149,6 +149,28 @@ static int conflict_phase(DB *ddb, struct syrep_name *name, struct diff_entry *d
return 0;
}
+static int do_copy(const char *a, const char *b) {
+ int (*copy_proc) (const char *, const char*, int c) = args.always_copy_flag ? copy_file : copy_or_link_file;
+
+ if (!args.always_replace_flag) {
+ int r, q;
+
+ if ((r = copy_proc(a, b, 0)) >= 0)
+ return r;
+
+ if (errno != EEXIST)
+ return r;
+
+ if (!(q = question("Replace existing file?", "ny")))
+ return -1;
+
+ if (q != 'y')
+ return -1;
+ }
+
+ return copy_proc(a, b, 1);
+}
+
static int copy_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, void *p) {
struct cb_info *cb_info = p;
struct syrep_name name2;
@@ -158,9 +180,6 @@ static int copy_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, v
int f;
char d[SYREP_DIGESTLENGTH*2+1];
- int (*copy_proc) (const char *, const char*, int c) = args.always_copy_flag ? copy_file : copy_or_link_file;
-
-
assert(ddb && name && de && p);
if (de->action != DIFF_COPY && de->action != DIFF_REPLACE)
@@ -203,18 +222,21 @@ static int copy_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, v
if (makeprefixpath(path, 0777) < 0)
return -1;
- if (!access(path2, R_OK)) {
- if (copy_proc(path2, path, 0) < 0)
+ if (do_copy(path2, path) < 0) {
+ if (errno != ENOENT) {
+ fprintf(stderr, "COPY: Failed to copy file '%s' to '%s': %s\n", path2, path, strerror(errno));
return -1;
- } else {
- snprintf(path2, sizeof(path2), "%s/%s", cb_info->trash_dir, name2.path);
-
- if (!access(path2, R_OK)) {
- if (copy_proc(path2, path, de->action == DIFF_REPLACE) < 0)
- return -1;
} else {
- fprintf(stderr, "COPY: Local file <%s> vanished. Snapshot not up to date.\n", name2.path);
- return -1;
+ snprintf(path2, sizeof(path2), "%s/%s", cb_info->trash_dir, name2.path);
+
+ if (do_copy(path2, path) < 0) {
+ if (errno == ENOENT)
+ fprintf(stderr, "COPY: Local file <%s> vanished. Snapshot not up to date\n", name2.path);
+ else
+ fprintf(stderr, "COPY: Failed to copy file '%s' to '%s': %s\n", path2, path, strerror(errno));
+
+ return -1;
+ }
}
}
@@ -244,7 +266,7 @@ static int copy_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de, v
if (makeprefixpath(path, 0777) < 0)
return -1;
- if (copy_proc(a, path, de->action == DIFF_REPLACE) < 0)
+ if (do_copy(a, path) < 0)
return -1;
} else
if (args.verbose_flag)
@@ -313,8 +335,12 @@ static int delete_phase(DB *ddb, struct syrep_name *name, struct diff_entry *de,
if (makeprefixpath(target, 0777) < 0)
return -1;
- if (move_file(path, target, 1) < 0)
- return -1;
+ if (move_file(path, target, 1) < 0) {
+ if (errno == ENOENT && !access(target, F_OK))
+ fprintf(stderr, "DELETE: File is probably already in trash, continuing\n");
+ else
+ return -1;
+ }
if (args.prune_empty_flag)
prune_empty_directories(path, cb_info->root);