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,31 +416,29 @@ static char *squash_slash(char *name)
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *find_name(const char *line, char *def, int p_value, int terminate)
|
static char *find_name_gnu(const char *line, char *def, int p_value)
|
||||||
{
|
{
|
||||||
int len;
|
|
||||||
const char *start = NULL;
|
|
||||||
|
|
||||||
if (p_value == 0)
|
|
||||||
start = line;
|
|
||||||
|
|
||||||
if (*line == '"') {
|
|
||||||
struct strbuf name = STRBUF_INIT;
|
struct strbuf name = STRBUF_INIT;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Proposed "new-style" GNU patch/diff format; see
|
* Proposed "new-style" GNU patch/diff format; see
|
||||||
* http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
|
* http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
|
||||||
*/
|
*/
|
||||||
if (!unquote_c_style(&name, line, NULL)) {
|
if (unquote_c_style(&name, line, NULL)) {
|
||||||
char *cp;
|
strbuf_release(&name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
for (cp = name.buf; p_value; p_value--) {
|
for (cp = name.buf; p_value; p_value--) {
|
||||||
cp = strchr(cp, '/');
|
cp = strchr(cp, '/');
|
||||||
if (!cp)
|
if (!cp) {
|
||||||
break;
|
strbuf_release(&name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
cp++;
|
cp++;
|
||||||
}
|
}
|
||||||
if (cp) {
|
|
||||||
/* name can later be freed, so we need
|
/* name can later be freed, so we need
|
||||||
* to memmove, not just return cp
|
* to memmove, not just return cp
|
||||||
*/
|
*/
|
||||||
@ -449,11 +447,21 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
|
|||||||
if (root)
|
if (root)
|
||||||
strbuf_insert(&name, 0, root, root_len);
|
strbuf_insert(&name, 0, root, root_len);
|
||||||
return squash_slash(strbuf_detach(&name, NULL));
|
return squash_slash(strbuf_detach(&name, NULL));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
strbuf_release(&name);
|
static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
const char *start = NULL;
|
||||||
|
|
||||||
|
if (*line == '"') {
|
||||||
|
char *name = find_name_gnu(line, def, p_value);
|
||||||
|
if (name)
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_value == 0)
|
||||||
|
start = line;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char c = *line;
|
char c = *line;
|
||||||
|
|
||||||
|
@ -10,21 +10,50 @@ test_description='git apply -p handling.'
|
|||||||
test_expect_success setup '
|
test_expect_success setup '
|
||||||
mkdir sub &&
|
mkdir sub &&
|
||||||
echo A >sub/file1 &&
|
echo A >sub/file1 &&
|
||||||
cp sub/file1 file1 &&
|
cp sub/file1 file1.saved &&
|
||||||
git add sub/file1 &&
|
git add sub/file1 &&
|
||||||
echo B >sub/file1 &&
|
echo B >sub/file1 &&
|
||||||
git diff >patch.file &&
|
git diff >patch.file &&
|
||||||
rm sub/file1 &&
|
git checkout -- sub/file1 &&
|
||||||
rmdir sub
|
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' '
|
test_expect_success 'apply git diff with -p2' '
|
||||||
|
cp file1.saved file1 &&
|
||||||
git apply -p2 patch.file
|
git apply -p2 patch.file
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'apply with too large -p' '
|
test_expect_success 'apply with too large -p' '
|
||||||
|
cp file1.saved file1 &&
|
||||||
test_must_fail git apply --stat -p3 patch.file 2>err &&
|
test_must_fail git apply --stat -p3 patch.file 2>err &&
|
||||||
grep "removing 3 leading" 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
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user