git-mv: fix moving more than one source to a single destination
The code used as if return value from basename(3) were stable, but often the function is implemented to return a pointer to a static storage internal to it. Because basename(3) is also allowed to modify its input parameter in place, casting constness away from the strings we obtained from the caller and giving them to basename is a no-no. Reported, and initial fix and test supplied by David Rydh. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Jan 22, 2010 at 14:17 UTC
af82559b435aa2a18f38a4f47a93729c8dc543d3
2 files changed
+19
-4
builtin-mv.c
+7
-4
@@ -24,10 +24,13 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
24
result[count] = NULL;
25
for (i = 0; i < count; i++) {
26
int length = strlen(result[i]);
27
- if (length > 0 && is_dir_sep(result[i][length - 1]))
28
- result[i] = xmemdupz(result[i], length - 1);
29
- if (base_name)
30
- result[i] = basename((char *)result[i]);
27
+ int to_copy = length;
28
+ while (to_copy > 0 && is_dir_sep(result[i][to_copy - 1]))
29
+ to_copy--;
30
+ if (to_copy != length || base_name) {
31
+ char *it = xmemdupz(result[i], to_copy);
32
+ result[i] = base_name ? strdup(basename(it)) : it;
33
+ }
34
}
35
return get_pathspec(prefix, result);
36
}
t/t7001-mv.sh
+12
@@ -189,6 +189,18 @@ test_expect_success 'absolute pathname outside should fail' '(
189
190
)'
191
192
+test_expect_success 'git mv to move multiple sources into a directory' '
193
+ rm -fr .git && git init &&
194
+ mkdir dir other &&
195
+ >dir/a.txt &&
196
+ >dir/b.txt &&
197
+ git add dir/?.txt &&
198
+ git mv dir/a.txt dir/b.txt other &&
199
+ git ls-files >actual &&
200
+ { echo other/a.txt; echo other/b.txt; } >expect &&
201
+ test_cmp expect actual
202
+'
203
+
204
test_expect_success 'git mv should not change sha1 of moved cache entry' '
205
206
rm -fr .git &&