apply: split quoted filename handling into new function
The new find_name_gnu() function handles new-style '--- "a/foo"' patch header lines, leaving find_name() itself a bit less daunting. Functional change: do not clobber the p-value when there are not enough path components in a quoted file name to honor it. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
64fdc08dac
commit
bb7306b5a3
@ -416,44 +416,52 @@ static char *squash_slash(char *name)
|
||||
return name;
|
||||
}
|
||||
|
||||
static char *find_name_gnu(const char *line, char *def, int p_value)
|
||||
{
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
char *cp;
|
||||
|
||||
/*
|
||||
* Proposed "new-style" GNU patch/diff format; see
|
||||
* http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
|
||||
*/
|
||||
if (unquote_c_style(&name, line, NULL)) {
|
||||
strbuf_release(&name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (cp = name.buf; p_value; p_value--) {
|
||||
cp = strchr(cp, '/');
|
||||
if (!cp) {
|
||||
strbuf_release(&name);
|
||||
return NULL;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
|
||||
/* name can later be freed, so we need
|
||||
* to memmove, not just return cp
|
||||
*/
|
||||
strbuf_remove(&name, 0, cp - name.buf);
|
||||
free(def);
|
||||
if (root)
|
||||
strbuf_insert(&name, 0, root, root_len);
|
||||
return squash_slash(strbuf_detach(&name, NULL));
|
||||
}
|
||||
|
||||
static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||
{
|
||||
int len;
|
||||
const char *start = NULL;
|
||||
|
||||
if (p_value == 0)
|
||||
start = line;
|
||||
|
||||
if (*line == '"') {
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
|
||||
/*
|
||||
* Proposed "new-style" GNU patch/diff format; see
|
||||
* http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
|
||||
*/
|
||||
if (!unquote_c_style(&name, line, NULL)) {
|
||||
char *cp;
|
||||
|
||||
for (cp = name.buf; p_value; p_value--) {
|
||||
cp = strchr(cp, '/');
|
||||
if (!cp)
|
||||
break;
|
||||
cp++;
|
||||
}
|
||||
if (cp) {
|
||||
/* name can later be freed, so we need
|
||||
* to memmove, not just return cp
|
||||
*/
|
||||
strbuf_remove(&name, 0, cp - name.buf);
|
||||
free(def);
|
||||
if (root)
|
||||
strbuf_insert(&name, 0, root, root_len);
|
||||
return squash_slash(strbuf_detach(&name, NULL));
|
||||
}
|
||||
}
|
||||
strbuf_release(&name);
|
||||
char *name = find_name_gnu(line, def, p_value);
|
||||
if (name)
|
||||
return name;
|
||||
}
|
||||
|
||||
if (p_value == 0)
|
||||
start = line;
|
||||
for (;;) {
|
||||
char c = *line;
|
||||
|
||||
|
@ -10,21 +10,50 @@ test_description='git apply -p handling.'
|
||||
test_expect_success setup '
|
||||
mkdir sub &&
|
||||
echo A >sub/file1 &&
|
||||
cp sub/file1 file1 &&
|
||||
cp sub/file1 file1.saved &&
|
||||
git add sub/file1 &&
|
||||
echo B >sub/file1 &&
|
||||
git diff >patch.file &&
|
||||
rm sub/file1 &&
|
||||
rmdir sub
|
||||
git checkout -- sub/file1 &&
|
||||
git mv sub süb &&
|
||||
echo B >süb/file1 &&
|
||||
git diff >patch.escaped &&
|
||||
grep "[\]" patch.escaped &&
|
||||
rm süb/file1 &&
|
||||
rmdir süb
|
||||
'
|
||||
|
||||
test_expect_success 'apply git diff with -p2' '
|
||||
cp file1.saved file1 &&
|
||||
git apply -p2 patch.file
|
||||
'
|
||||
|
||||
test_expect_success 'apply with too large -p' '
|
||||
cp file1.saved file1 &&
|
||||
test_must_fail git apply --stat -p3 patch.file 2>err &&
|
||||
grep "removing 3 leading" err
|
||||
'
|
||||
|
||||
test_expect_success 'apply (-p2) traditional diff with funny filenames' '
|
||||
cat >patch.quotes <<-\EOF &&
|
||||
diff -u "a/"sub/file1 "b/"sub/file1
|
||||
--- "a/"sub/file1
|
||||
+++ "b/"sub/file1
|
||||
@@ -1 +1 @@
|
||||
-A
|
||||
+B
|
||||
EOF
|
||||
echo B >expected &&
|
||||
|
||||
cp file1.saved file1 &&
|
||||
git apply -p2 patch.quotes &&
|
||||
test_cmp expected file1
|
||||
'
|
||||
|
||||
test_expect_success 'apply with too large -p and fancy filename' '
|
||||
cp file1.saved file1 &&
|
||||
test_must_fail git apply --stat -p3 patch.escaped 2>err &&
|
||||
grep "removing 3 leading" err
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user