Let git-add--interactive use the "patience diff" algorithm for more
nicely separated hunks if passed the --patience option.  This is
especially useful when adding entire functions to a source file,
because without --patience, diff tends to produce annoying patches
like the following:

+       /* stuff */
+}
+
+int foo(void)
+{
        /* stuff */
 }

Those patches do not respect function boundaries, making it difficult
to commit changes one function at a time.

Reported by Kurt Roeckx <[email protected]> through
<http://bugs.debian.org/518661>.

Signed-off-by: Jonathan Nieder <[email protected]>
---
NEEDSWORK: tests.

 git-add--interactive.perl |   32 ++++++++++++++++++++++++--------
 1 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index cd43c34..faa2eb1 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -39,6 +39,7 @@ my ($diff_new_color) =
        $diff_use_color ? (
                $repo->get_color('color.diff.new', 'green'),
        ) : ();
+my $diff_use_patience = 0;
 
 my $normal_color = $repo->get_color("", "reset");
 
@@ -271,9 +272,11 @@ sub list_modified {
        } else {
                $reference = 'HEAD';
        }
-       for (run_cmd_pipe(qw(git diff-index --cached
-                            --numstat --summary), $reference,
-                            '--', @tracked)) {
+       my @cmd = qw(git diff-index --cached --numstat --summary);
+       if ($diff_use_patience) {
+               push @cmd, "--patience";
+       }
+       for (run_cmd_pipe(@cmd, $reference, '--', @tracked)) {
                if (($add, $del, $file) =
                    /^([-\d]+)  ([-\d]+)        (.*)/) {
                        my ($change, $bin);
@@ -298,7 +301,11 @@ sub list_modified {
                }
        }
 
-       for (run_cmd_pipe(qw(git diff-files --numstat --summary --), @tracked)) 
{
+       @cmd = qw(git diff-files --numstat --summary);
+       if ($diff_use_patience) {
+               push @cmd, "--patience";
+       }
+       for (run_cmd_pipe(@cmd, "--", @tracked)) {
                if (($add, $del, $file) =
                    /^([-\d]+)  ([-\d]+)        (.*)/) {
                        $file = unquote_path($file);
@@ -704,6 +711,9 @@ sub run_git_apply {
 sub parse_diff {
        my ($path) = @_;
        my @diff_cmd = split(" ", $patch_mode_flavour{DIFF});
+       if ($diff_use_patience) {
+               push @diff_cmd, "--patience";
+       }
        if (defined $patch_mode_revision) {
                push @diff_cmd, $patch_mode_revision;
        }
@@ -1473,8 +1483,11 @@ sub diff_cmd {
                                   @mods);
        return if (!...@them);
        my $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';
-       system(qw(git diff -p --cached), $reference, '--',
-               map { $_->{VALUE} } @them);
+       my @cmd = qw(git diff -p --cached);
+       if ($diff_use_patience) {
+               push @cmd, "--patience";
+       }
+       system(@cmd, $reference, '--', map { $_->{VALUE} } @them);
 }
 
 sub quit_cmd {
@@ -1496,6 +1509,10 @@ EOF
 sub process_args {
        return unless @ARGV;
        my $arg = shift @ARGV;
+       if ($arg eq "--patience") {
+               $diff_use_patience = 1;
+               $arg = shift @ARGV;
+       }
        if ($arg =~ /--patch(?:=(.*))?/) {
                if (defined $1) {
                        if ($1 eq 'reset') {
@@ -1531,8 +1548,7 @@ sub process_args {
                die "invalid argument $arg, expecting --"
                    unless $arg eq "--";
                %patch_mode_flavour = %{$patch_modes{$patch_mode}};
-       }
-       elsif ($arg ne "--") {
+       } elsif ($arg ne "--") {
                die "invalid argument $arg, expecting --";
        }
 }
-- 
1.7.0.183.g328ba




-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to