diff options
author | Junio C Hamano <gitster@pobox.com> | 2008-12-14 19:40:09 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-12-15 02:39:57 -0800 |
commit | c5ab03f26c992e30f355fba129f70db0f290fcd7 (patch) | |
tree | 799ffb275675e682cc9b4375eddd7c0e70139187 | |
parent | 7bb1fcc6fcc5a2d0164f243fd10f346eb0822ddf (diff) | |
download | git-c5ab03f26c992e30f355fba129f70db0f290fcd7.tar.gz |
merge-recursive: do not clobber untracked working tree garbage
When merge-recursive wanted to create a new file in the work tree (either
as the final result, or a hint for reference purposes while delete/modify
conflicts), it unconditionally overwrote an untracked file in the working
tree. Be careful not to lose whatever the user has that is not tracked.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | builtin-merge-recursive.c | 32 | ||||
-rwxr-xr-x | t/t7607-merge-overwrite.sh | 2 |
2 files changed, 33 insertions, 1 deletions
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c index b9738655ad..ab9f6e0f14 100644 --- a/builtin-merge-recursive.c +++ b/builtin-merge-recursive.c @@ -471,6 +471,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; @@ -486,6 +510,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; diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh index 513097c1a1..49f4e1599a 100755 --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@ -53,7 +53,7 @@ test_expect_success 'will not overwrite staged changes' ' test_cmp important c2.c ' -test_expect_failure 'will not overwrite removed file' ' +test_expect_success 'will not overwrite removed file' ' git reset --hard c1 && git rm c1.c && git commit -m "rm c1.c" && |