Git fork

Merge branch 'by/log-follow'

* by/log-follow:
tests: rename duplicate t4205
Make git log --follow find copies among unmodified files.
Make diffcore_std only can run once before a diff_flush
Add a macro DIFF_QUEUE_CLEAR.

+82 -18
+1 -1
Documentation/git-log.txt
··· 57 57 commits, and doesn't limit diff for those commits. 58 58 59 59 --follow:: 60 - Continue listing the history of a file beyond renames. 60 + Continue listing the history of a file beyond renames/copies. 61 61 62 62 --log-size:: 63 63 Before the log message print out its size in bytes. Intended
+13 -8
diff.c
··· 2600 2600 void diff_setup(struct diff_options *options) 2601 2601 { 2602 2602 memset(options, 0, sizeof(*options)); 2603 + memset(&diff_queued_diff, 0, sizeof(diff_queued_diff)); 2603 2604 2604 2605 options->file = stdout; 2605 2606 ··· 3541 3542 diff_free_filepair(q->queue[i]); 3542 3543 3543 3544 free(q->queue); 3544 - q->queue = NULL; 3545 - q->nr = q->alloc = 0; 3545 + DIFF_QUEUE_CLEAR(q); 3546 3546 3547 3547 return result; 3548 3548 } ··· 3670 3670 diff_free_filepair(q->queue[i]); 3671 3671 free_queue: 3672 3672 free(q->queue); 3673 - q->queue = NULL; 3674 - q->nr = q->alloc = 0; 3673 + DIFF_QUEUE_CLEAR(q); 3675 3674 if (options->close_file) 3676 3675 fclose(options->file); 3677 3676 ··· 3693 3692 int i; 3694 3693 struct diff_queue_struct *q = &diff_queued_diff; 3695 3694 struct diff_queue_struct outq; 3696 - outq.queue = NULL; 3697 - outq.nr = outq.alloc = 0; 3695 + DIFF_QUEUE_CLEAR(&outq); 3698 3696 3699 3697 if (!filter) 3700 3698 return; ··· 3762 3760 int i; 3763 3761 struct diff_queue_struct *q = &diff_queued_diff; 3764 3762 struct diff_queue_struct outq; 3765 - outq.queue = NULL; 3766 - outq.nr = outq.alloc = 0; 3763 + DIFF_QUEUE_CLEAR(&outq); 3767 3764 3768 3765 for (i = 0; i < q->nr; i++) { 3769 3766 struct diff_filepair *p = q->queue[i]; ··· 3824 3821 3825 3822 void diffcore_std(struct diff_options *options) 3826 3823 { 3824 + /* We never run this function more than one time, because the 3825 + * rename/copy detection logic can only run once. 3826 + */ 3827 + if (diff_queued_diff.run) 3828 + return; 3829 + 3827 3830 if (options->skip_stat_unmatch) 3828 3831 diffcore_skip_stat_unmatch(options); 3829 3832 if (options->break_opt != -1) ··· 3843 3846 DIFF_OPT_SET(options, HAS_CHANGES); 3844 3847 else 3845 3848 DIFF_OPT_CLR(options, HAS_CHANGES); 3849 + 3850 + diff_queued_diff.run = 1; 3846 3851 } 3847 3852 3848 3853 int diff_result_code(struct diff_options *opt, int status)
+2 -4
diffcore-break.c
··· 162 162 if (!merge_score) 163 163 merge_score = DEFAULT_MERGE_SCORE; 164 164 165 - outq.nr = outq.alloc = 0; 166 - outq.queue = NULL; 165 + DIFF_QUEUE_CLEAR(&outq); 167 166 168 167 for (i = 0; i < q->nr; i++) { 169 168 struct diff_filepair *p = q->queue[i]; ··· 256 255 struct diff_queue_struct outq; 257 256 int i, j; 258 257 259 - outq.nr = outq.alloc = 0; 260 - outq.queue = NULL; 258 + DIFF_QUEUE_CLEAR(&outq); 261 259 262 260 for (i = 0; i < q->nr; i++) { 263 261 struct diff_filepair *p = q->queue[i];
+1 -2
diffcore-pickaxe.c
··· 55 55 int i, has_changes; 56 56 regex_t regex, *regexp = NULL; 57 57 struct diff_queue_struct outq; 58 - outq.queue = NULL; 59 - outq.nr = outq.alloc = 0; 58 + DIFF_QUEUE_CLEAR(&outq); 60 59 61 60 if (opts & DIFF_PICKAXE_REGEX) { 62 61 int err;
+1 -2
diffcore-rename.c
··· 569 569 /* At this point, we have found some renames and copies and they 570 570 * are recorded in rename_dst. The original list is still in *q. 571 571 */ 572 - outq.queue = NULL; 573 - outq.nr = outq.alloc = 0; 572 + DIFF_QUEUE_CLEAR(&outq); 574 573 for (i = 0; i < q->nr; i++) { 575 574 struct diff_filepair *p = q->queue[i]; 576 575 struct diff_filepair *pair_to_free = NULL;
+7
diffcore.h
··· 91 91 struct diff_filepair **queue; 92 92 int alloc; 93 93 int nr; 94 + int run; 94 95 }; 96 + #define DIFF_QUEUE_CLEAR(q) \ 97 + do { \ 98 + (q)->queue = NULL; \ 99 + (q)->nr = (q)->alloc = 0; \ 100 + (q)->run = 0; \ 101 + } while(0); 95 102 96 103 extern struct diff_queue_struct diff_queued_diff; 97 104 extern struct diff_filepair *diff_queue(struct diff_queue_struct *,
+56
t/t4206-log-follow-harder-copies.sh
··· 1 + #!/bin/sh 2 + # 3 + # Copyright (c) 2010 Bo Yang 4 + # 5 + 6 + test_description='Test --follow should always find copies hard in git log. 7 + 8 + ' 9 + . ./test-lib.sh 10 + . "$TEST_DIRECTORY"/diff-lib.sh 11 + 12 + echo >path0 'Line 1 13 + Line 2 14 + Line 3 15 + ' 16 + 17 + test_expect_success \ 18 + 'add a file path0 and commit.' \ 19 + 'git add path0 && 20 + git commit -m "Add path0"' 21 + 22 + echo >path0 'New line 1 23 + New line 2 24 + New line 3 25 + ' 26 + test_expect_success \ 27 + 'Change path0.' \ 28 + 'git add path0 && 29 + git commit -m "Change path0"' 30 + 31 + cat <path0 >path1 32 + test_expect_success \ 33 + 'copy path0 to path1.' \ 34 + 'git add path1 && 35 + git commit -m "Copy path1 from path0"' 36 + 37 + test_expect_success \ 38 + 'find the copy path0 -> path1 harder' \ 39 + 'git log --follow --name-status --pretty="format:%s" path1 > current' 40 + 41 + cat >expected <<\EOF 42 + Copy path1 from path0 43 + C100 path0 path1 44 + 45 + Change path0 46 + M path0 47 + 48 + Add path0 49 + A path0 50 + EOF 51 + 52 + test_expect_success \ 53 + 'validate the output.' \ 54 + 'compare_diff_patch current expected' 55 + 56 + test_done
+1 -1
tree-diff.c
··· 346 346 347 347 diff_setup(&diff_opts); 348 348 DIFF_OPT_SET(&diff_opts, RECURSIVE); 349 - diff_opts.detect_rename = DIFF_DETECT_RENAME; 349 + DIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER); 350 350 diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; 351 351 diff_opts.single_follow = opt->paths[0]; 352 352 diff_opts.break_opt = opt->break_opt;