summaryrefslogtreecommitdiff
path: root/merge-recursive.c
diff options
context:
space:
mode:
Diffstat (limited to 'merge-recursive.c')
-rw-r--r--merge-recursive.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/merge-recursive.c b/merge-recursive.c
index 245232a408..b97026bd5c 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -16,7 +16,6 @@
#include "string-list.h"
#include "xdiff-interface.h"
#include "ll-merge.h"
-#include "interpolate.h"
#include "attr.h"
#include "merge-recursive.h"
#include "dir.h"
@@ -448,6 +447,30 @@ static void flush_buffer(int fd, const char *buf, unsigned long size)
}
}
+static int would_lose_untracked(const char *path)
+{
+ int pos = cache_name_pos(path, strlen(path));
+
+ if (pos < 0)
+ pos = -1 - pos;
+ while (pos < active_nr &&
+ !strcmp(path, active_cache[pos]->name)) {
+ /*
+ * If stage #0, it is definitely tracked.
+ * If it has stage #2 then it was tracked
+ * before this merge started. All other
+ * cases the path was not tracked.
+ */
+ switch (ce_stage(active_cache[pos])) {
+ case 0:
+ case 2:
+ return 0;
+ }
+ pos++;
+ }
+ return file_exists(path);
+}
+
static int make_room_for_path(const char *path)
{
int status;
@@ -463,6 +486,14 @@ static int make_room_for_path(const char *path)
die(msg, path, "");
}
+ /*
+ * Do not unlink a file in the work tree if we are not
+ * tracking it.
+ */
+ if (would_lose_untracked(path))
+ return error("refusing to lose untracked file at '%s'",
+ path);
+
/* Successful unlink is good.. */
if (!unlink(path))
return 0;
@@ -526,7 +557,8 @@ static void update_file_flags(struct merge_options *o,
char *lnk = xmemdupz(buf, size);
safe_create_leading_directories_const(path);
unlink(path);
- symlink(lnk, path);
+ if (symlink(lnk, path))
+ die("failed to symlink %s: %s", path, strerror(errno));
free(lnk);
} else
die("do not know what to do with %06o %s '%s'",
@@ -902,6 +934,11 @@ static int process_renames(struct merge_options *o,
ren1_src, ren1_dst, branch1,
branch2);
update_file(o, 0, ren1->pair->two->sha1, ren1->pair->two->mode, ren1_dst);
+ update_stages(ren1_dst, NULL,
+ branch1 == o->branch1 ?
+ ren1->pair->two : NULL,
+ branch1 == o->branch1 ?
+ NULL : ren1->pair->two, 1);
} else if (!sha_eq(dst_other.sha1, null_sha1)) {
const char *new_path;
clean_merge = 0;
@@ -1332,7 +1369,7 @@ static int merge_recursive_config(const char *var, const char *value, void *cb)
o->merge_rename_limit = git_config_int(var, value);
return 0;
}
- return git_default_config(var, value, cb);
+ return git_xmerge_config(var, value, cb);
}
void init_merge_options(struct merge_options *o)