@matheusbsbs / matheus-bagliano / commits / 8f0bef6df9
Fork 0

git-apply--interactive: Refactor patch mode code

This makes some aspects of the 'git add -p' loop configurable (within the code), so that we can later reuse git-add--interactive for other similar tools. Most fields are fairly straightforward, but APPLY gets a subroutine (instead of just a string a la 'apply --cached') so that we can handle 'checkout -p', which will need to atomically apply the patch twice (index and worktree). Signed-off-by: Thomas Rast <trast@student.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Thomas Rast committed Aug 13, 2009 at 14:29 UTC 8f0bef6df91c48d79f982bdb55f784ce445ba5b2
1 file changed +55 -27
git-add--interactive.perl
+55 -27
@@ -73,6 +73,22 @@ sub colored {
73 # command line options
74 my $patch_mode;
75
76 +sub apply_patch;
77 +
78 +my %patch_modes = (
79 + 'stage' => {
80 + DIFF => 'diff-files -p',
81 + APPLY => sub { apply_patch 'apply --cached', @_; },
82 + APPLY_CHECK => 'apply --cached',
83 + VERB => 'Stage',
84 + TARGET => '',
85 + PARTICIPLE => 'staging',
86 + FILTER => 'file-only',
87 + },
88 +);
89 +
90 +my %patch_mode_flavour = %{$patch_modes{stage}};
91 +
92 sub run_cmd_pipe {
93 if ($^O eq 'MSWin32' || $^O eq 'msys') {
94 my @invalid = grep {m/[":*]/} @_;
@@ -613,12 +629,21 @@ sub add_untracked_cmd {
629 print "\n";
630 }
631
632 +sub run_git_apply {
633 + my $cmd = shift;
634 + my $fh;
635 + open $fh, '| git ' . $cmd;
636 + print $fh @_;
637 + return close $fh;
638 +}
639 +
640 sub parse_diff {
641 my ($path) = @_;
618 - my @diff = run_cmd_pipe(qw(git diff-files -p --), $path);
642 + my @diff_cmd = split(" ", $patch_mode_flavour{DIFF});
643 + my @diff = run_cmd_pipe("git", @diff_cmd, "--", $path);
644 my @colored = ();
645 if ($diff_use_color) {
621 - @colored = run_cmd_pipe(qw(git diff-files -p --color --), $path);
646 + @colored = run_cmd_pipe("git", @diff_cmd, qw(--color --), $path);
647 }
648 my (@hunk) = { TEXT => [], DISPLAY => [], TYPE => 'header' };
649
@@ -877,6 +902,7 @@ sub edit_hunk_manually {
902 or die "failed to open hunk edit file for writing: " . $!;
903 print $fh "# Manual hunk edit mode -- see bottom for a quick guide\n";
904 print $fh @$oldtext;
905 + my $participle = $patch_mode_flavour{PARTICIPLE};
906 print $fh <<EOF;
907 # ---
908 # To remove '-' lines, make them ' ' lines (context).
@@ -884,7 +910,7 @@ sub edit_hunk_manually {
910 # Lines starting with # will be removed.
911 #
912 # If the patch applies cleanly, the edited hunk will immediately be
887 -# marked for staging. If it does not apply cleanly, you will be given
913 +# marked for $participle. If it does not apply cleanly, you will be given
914 # an opportunity to edit again. If all lines of the hunk are removed,
915 # then the edit is aborted and the hunk is left unchanged.
916 EOF
@@ -918,11 +944,8 @@ EOF
944
945 sub diff_applies {
946 my $fh;
921 - open $fh, '| git apply --recount --cached --check';
922 - for my $h (@_) {
923 - print $fh @{$h->{TEXT}};
924 - }
925 - return close $fh;
947 + return run_git_apply($patch_mode_flavour{APPLY_CHECK} . ' --recount --check',
948 + map { @{$_->{TEXT}} } @_);
949 }
950
951 sub _restore_terminal_and_die {
@@ -988,12 +1011,14 @@ sub edit_hunk_loop {
1011 }
1012
1013 sub help_patch_cmd {
991 - print colored $help_color, <<\EOF ;
992 -y - stage this hunk
993 -n - do not stage this hunk
994 -q - quit, do not stage this hunk nor any of the remaining ones
995 -a - stage this and all the remaining hunks in the file
996 -d - do not stage this hunk nor any of the remaining hunks in the file
1014 + my $verb = lc $patch_mode_flavour{VERB};
1015 + my $target = $patch_mode_flavour{TARGET};
1016 + print colored $help_color, <<EOF ;
1017 +y - $verb this hunk$target
1018 +n - do not $verb this hunk$target
1019 +q - quit, do not $verb this hunk nor any of the remaining ones
1020 +a - $verb this and all the remaining hunks in the file
1021 +d - do not $verb this hunk nor any of the remaining hunks in the file
1022 g - select a hunk to go to
1023 / - search for a hunk matching the given regex
1024 j - leave this hunk undecided, see next undecided hunk
@@ -1006,8 +1031,17 @@ e - manually edit the current hunk
1031 EOF
1032 }
1033
1034 +sub apply_patch {
1035 + my $cmd = shift;
1036 + my $ret = run_git_apply $cmd . ' --recount', @_;
1037 + if (!$ret) {
1038 + print STDERR @_;
1039 + }
1040 + return $ret;
1041 +}
1042 +
1043 sub patch_update_cmd {
1010 - my @all_mods = list_modified('file-only');
1044 + my @all_mods = list_modified($patch_mode_flavour{FILTER});
1045 my @mods = grep { !($_->{BINARY}) } @all_mods;
1046 my @them;
1047
@@ -1138,8 +1172,9 @@ sub patch_update_file {
1172 for (@{$hunk[$ix]{DISPLAY}}) {
1173 print;
1174 }
1141 - print colored $prompt_color, 'Stage ',
1142 - ($hunk[$ix]{TYPE} eq 'mode' ? 'mode change' : 'this hunk'),
1175 + print colored $prompt_color, $patch_mode_flavour{VERB},
1176 + ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' : ' this hunk'),
1177 + $patch_mode_flavour{TARGET},
1178 " [y,n,q,a,d,/$other,?]? ";
1179 my $line = prompt_single_character;
1180 if ($line) {
@@ -1313,16 +1348,9 @@ sub patch_update_file {
1348
1349 if (@result) {
1350 my $fh;
1316 -
1317 - open $fh, '| git apply --cached --recount';
1318 - for (@{$head->{TEXT}}, @result) {
1319 - print $fh $_;
1320 - }
1321 - if (!close $fh) {
1322 - for (@{$head->{TEXT}}, @result) {
1323 - print STDERR $_;
1324 - }
1325 - }
1351 + my @patch = (@{$head->{TEXT}}, @result);
1352 + my $apply_routine = $patch_mode_flavour{APPLY};
1353 + &$apply_routine(@patch);
1354 refresh();
1355 }
1356