@matheusbsbs / matheus-bagliano / commits / bb7306b5a3
Fork 0

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>

Jonathan Nieder committed Aug 18, 2010 at 20:46 UTC bb7306b5a350fd2143347be3d9b7d8588567d715
2 files changed +70 -33
builtin/apply.c
+38 -30
@@ -416,44 +416,52 @@ static char *squash_slash(char *name)
416 return name;
417 }
418
419 +static char *find_name_gnu(const char *line, char *def, int p_value)
420 +{
421 + struct strbuf name = STRBUF_INIT;
422 + char *cp;
423 +
424 + /*
425 + * Proposed "new-style" GNU patch/diff format; see
426 + * http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
427 + */
428 + if (unquote_c_style(&name, line, NULL)) {
429 + strbuf_release(&name);
430 + return NULL;
431 + }
432 +
433 + for (cp = name.buf; p_value; p_value--) {
434 + cp = strchr(cp, '/');
435 + if (!cp) {
436 + strbuf_release(&name);
437 + return NULL;
438 + }
439 + cp++;
440 + }
441 +
442 + /* name can later be freed, so we need
443 + * to memmove, not just return cp
444 + */
445 + strbuf_remove(&name, 0, cp - name.buf);
446 + free(def);
447 + if (root)
448 + strbuf_insert(&name, 0, root, root_len);
449 + return squash_slash(strbuf_detach(&name, NULL));
450 +}
451 +
452 static char *find_name(const char *line, char *def, int p_value, int terminate)
453 {
454 int len;
455 const char *start = NULL;
456
424 - if (p_value == 0)
425 - start = line;
426 -
457 if (*line == '"') {
428 - struct strbuf name = STRBUF_INIT;
429 -
430 - /*
431 - * Proposed "new-style" GNU patch/diff format; see
432 - * http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
433 - */
434 - if (!unquote_c_style(&name, line, NULL)) {
435 - char *cp;
436 -
437 - for (cp = name.buf; p_value; p_value--) {
438 - cp = strchr(cp, '/');
439 - if (!cp)
440 - break;
441 - cp++;
442 - }
443 - if (cp) {
444 - /* name can later be freed, so we need
445 - * to memmove, not just return cp
446 - */
447 - strbuf_remove(&name, 0, cp - name.buf);
448 - free(def);
449 - if (root)
450 - strbuf_insert(&name, 0, root, root_len);
451 - return squash_slash(strbuf_detach(&name, NULL));
452 - }
453 - }
454 - strbuf_release(&name);
458 + char *name = find_name_gnu(line, def, p_value);
459 + if (name)
460 + return name;
461 }
462
463 + if (p_value == 0)
464 + start = line;
465 for (;;) {
466 char c = *line;
467
t/t4120-apply-popt.sh
+32 -3
@@ -10,21 +10,50 @@ test_description='git apply -p handling.'
10 test_expect_success setup '
11 mkdir sub &&
12 echo A >sub/file1 &&
13 - cp sub/file1 file1 &&
13 + cp sub/file1 file1.saved &&
14 git add sub/file1 &&
15 echo B >sub/file1 &&
16 git diff >patch.file &&
17 - rm sub/file1 &&
18 - rmdir sub
17 + git checkout -- sub/file1 &&
18 + git mv sub süb &&
19 + echo B >süb/file1 &&
20 + git diff >patch.escaped &&
21 + grep "[\]" patch.escaped &&
22 + rm süb/file1 &&
23 + rmdir süb
24 '
25
26 test_expect_success 'apply git diff with -p2' '
27 + cp file1.saved file1 &&
28 git apply -p2 patch.file
29 '
30
31 test_expect_success 'apply with too large -p' '
32 + cp file1.saved file1 &&
33 test_must_fail git apply --stat -p3 patch.file 2>err &&
34 grep "removing 3 leading" err
35 '
36
37 +test_expect_success 'apply (-p2) traditional diff with funny filenames' '
38 + cat >patch.quotes <<-\EOF &&
39 + diff -u "a/"sub/file1 "b/"sub/file1
40 + --- "a/"sub/file1
41 + +++ "b/"sub/file1
42 + @@ -1 +1 @@
43 + -A
44 + +B
45 + EOF
46 + echo B >expected &&
47 +
48 + cp file1.saved file1 &&
49 + git apply -p2 patch.quotes &&
50 + test_cmp expected file1
51 +'
52 +
53 +test_expect_success 'apply with too large -p and fancy filename' '
54 + cp file1.saved file1 &&
55 + test_must_fail git apply --stat -p3 patch.escaped 2>err &&
56 + grep "removing 3 leading" err
57 +'
58 +
59 test_done