builtin-mv: minimum fix to avoid losing files
authorJunio C Hamano <gitster@pobox.com>
Mon, 4 Feb 2008 07:59:17 +0000 (23:59 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 5 Feb 2008 08:44:10 +0000 (00:44 -0800)
An incorrect command "git mv subdir /outer/space" threw the
subdirectory to outside of the repository and then noticed that
/outer/space/subdir/ would be outside of the repository.  The
error checking is backwards.

This fixes the issue by being careful about use of the return
value of get_pathspec().  Since the implementation already has
handcrafted loop to munge each path on the command line, we use
prefix_path() instead.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-mv.c
t/t7001-mv.sh

index 94f6dd2aad2da512bab0be2e84859eced6553cc9..68aa2a68bb8f4232732829ba7d9459bbef3c7ad5 100644 (file)
@@ -19,6 +19,7 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
                                  int count, int base_name)
 {
        int i;
+       int len = prefix ? strlen(prefix) : 0;
        const char **result = xmalloc((count + 1) * sizeof(const char *));
        memcpy(result, pathspec, count * sizeof(const char *));
        result[count] = NULL;
@@ -32,8 +33,11 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
                        if (last_slash)
                                result[i] = last_slash + 1;
                }
+               result[i] = prefix_path(prefix, len, result[i]);
+               if (!result[i])
+                       exit(1); /* error already given */
        }
-       return get_pathspec(prefix, result);
+       return result;
 }
 
 static void show_list(const char *label, struct path_list *list)
index b1243b4163d231bb0f29fd91fe7fa15c34463c82..fa382c58da08a6eeca1aa51d4af47215e3e1c107 100755 (executable)
@@ -118,4 +118,42 @@ test_expect_success "Sergey Vlasov's test case" '
        git mv ab a
 '
 
+test_expect_success 'absolute pathname' '(
+
+       rm -fr mine &&
+       mkdir mine &&
+       cd mine &&
+       test_create_repo one &&
+       cd one &&
+       mkdir sub &&
+       >sub/file &&
+       git add sub/file &&
+
+       git mv sub "$(pwd)/in" &&
+       ! test -d sub &&
+       test -d in &&
+       git ls-files --error-unmatch in/file
+
+
+)'
+
+test_expect_success 'absolute pathname outside should fail' '(
+
+       rm -fr mine &&
+       mkdir mine &&
+       cd mine &&
+       out=$(pwd) &&
+       test_create_repo one &&
+       cd one &&
+       mkdir sub &&
+       >sub/file &&
+       git add sub/file &&
+
+       ! git mv sub "$out/out" &&
+       test -d sub &&
+       ! test -d ../in &&
+       git ls-files --error-unmatch sub/file
+
+)'
+
 test_done