Add "--patch" option to git-add--interactive

When the "--patch" option is supplied, the patch_update_cmd() function is
called bypassing the main_loop() and exits.

Seeing as builtin-add is the only caller of git-add--interactive we can
impose a strict requirement on the format of the arguments to avoid
possible ambiguity: an "--" argument must be used whenever any pathspecs
are passed, both with the "--patch" option and without it.

Signed-off-by: Wincent Colaiuta <win@wincent.com>
maint
Wincent Colaiuta 2007-11-25 14:15:42 +01:00 committed by Junio C Hamano
parent 3f061887c5
commit b63e995001
3 changed files with 65 additions and 19 deletions

View File

@ -61,7 +61,14 @@ OPTIONS


-i, \--interactive:: -i, \--interactive::
Add modified contents in the working tree interactively to Add modified contents in the working tree interactively to
the index. the index. Optional path arguments may be supplied to limit
operation to a subset of the working tree. See ``Interactive
mode'' for details.

-p, \--patch:
Similar to Interactive mode but the initial command loop is
bypassed and the 'patch' subcommand is invoked using each of
the specified filepatterns before exiting.


-u:: -u::
Update only files that git already knows about. This is similar Update only files that git already knows about. This is similar

View File

@ -19,7 +19,7 @@ static const char * const builtin_add_usage[] = {
"git-add [options] [--] <filepattern>...", "git-add [options] [--] <filepattern>...",
NULL NULL
}; };

static int patch_interactive = 0, add_interactive = 0;
static int take_worktree_changes; static int take_worktree_changes;


static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
@ -144,7 +144,7 @@ static const char **validate_pathspec(int argc, const char **argv, const char *p


int interactive_add(int argc, const char **argv, const char *prefix) int interactive_add(int argc, const char **argv, const char *prefix)
{ {
int status; int status, ac;
const char **args; const char **args;
const char **pathspec = NULL; const char **pathspec = NULL;


@ -154,11 +154,17 @@ int interactive_add(int argc, const char **argv, const char *prefix)
return -1; return -1;
} }


args = xcalloc(sizeof(const char *), (argc + 2)); args = xcalloc(sizeof(const char *), (argc + 4));
args[0] = "add--interactive"; ac = 0;
if (argc) args[ac++] = "add--interactive";
memcpy(&(args[1]), pathspec, sizeof(const char *) * argc); if (patch_interactive)
args[argc + 1] = NULL; args[ac++] = "--patch";
args[ac++] = "--";
if (argc) {
memcpy(&(args[ac]), pathspec, sizeof(const char *) * argc);
ac += argc;
}
args[ac] = NULL;


status = run_command_v_opt(args, RUN_GIT_CMD); status = run_command_v_opt(args, RUN_GIT_CMD);
free(args); free(args);
@ -171,13 +177,13 @@ static const char ignore_error[] =
"The following paths are ignored by one of your .gitignore files:\n"; "The following paths are ignored by one of your .gitignore files:\n";


static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0; static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
static int add_interactive = 0;


static struct option builtin_add_options[] = { static struct option builtin_add_options[] = {
OPT__DRY_RUN(&show_only), OPT__DRY_RUN(&show_only),
OPT__VERBOSE(&verbose), OPT__VERBOSE(&verbose),
OPT_GROUP(""), OPT_GROUP(""),
OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"), OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
OPT_BOOLEAN('f', NULL, &ignored_too, "allow adding otherwise ignored files"), OPT_BOOLEAN('f', NULL, &ignored_too, "allow adding otherwise ignored files"),
OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update tracked files"), OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update tracked files"),
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"), OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
@ -192,6 +198,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)


argc = parse_options(argc, argv, builtin_add_options, argc = parse_options(argc, argv, builtin_add_options,
builtin_add_usage, 0); builtin_add_usage, 0);
if (patch_interactive)
add_interactive = 1;
if (add_interactive) if (add_interactive)
exit(interactive_add(argc, argv, prefix)); exit(interactive_add(argc, argv, prefix));



View File

@ -2,6 +2,9 @@


use strict; use strict;


# command line options
my $patch_mode;

sub run_cmd_pipe { sub run_cmd_pipe {
if ($^O eq 'MSWin32') { if ($^O eq 'MSWin32') {
my @invalid = grep {m/[":*]/} @_; my @invalid = grep {m/[":*]/} @_;
@ -552,8 +555,8 @@ sub help_patch_cmd {
print <<\EOF ; print <<\EOF ;
y - stage this hunk y - stage this hunk
n - do not stage this hunk n - do not stage this hunk
a - stage this and all the remaining hunks a - stage this and all the remaining hunks in the file
d - do not stage this hunk nor any of the remaining hunks d - do not stage this hunk nor any of the remaining hunks in the file
j - leave this hunk undecided, see next undecided hunk j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk k - leave this hunk undecided, see previous undecided hunk
@ -563,13 +566,21 @@ EOF
} }


sub patch_update_cmd { sub patch_update_cmd {
my @mods = list_modified('file-only'); my @mods = grep { !($_->{BINARY}) } list_modified('file-only');
@mods = grep { !($_->{BINARY}) } @mods; my @them;
return if (!@mods);


my (@them) = list_and_choose({ PROMPT => 'Patch update', if (!@mods) {
HEADER => $status_head, }, print STDERR "No changes.\n";
@mods); return 0;
}
if ($patch_mode) {
@them = @mods;
}
else {
@them = list_and_choose({ PROMPT => 'Patch update',
HEADER => $status_head, },
@mods);
}
for (@them) { for (@them) {
patch_update_file($_->{VALUE}); patch_update_file($_->{VALUE});
} }
@ -783,6 +794,20 @@ add untracked - add contents of untracked files to the staged set of changes
EOF EOF
} }


sub process_args {
return unless @ARGV;
my $arg = shift @ARGV;
if ($arg eq "--patch") {
$patch_mode = 1;
$arg = shift @ARGV or die "missing --";
die "invalid argument $arg, expecting --"
unless $arg eq "--";
}
elsif ($arg ne "--") {
die "invalid argument $arg, expecting --";
}
}

sub main_loop { sub main_loop {
my @cmd = ([ 'status', \&status_cmd, ], my @cmd = ([ 'status', \&status_cmd, ],
[ 'update', \&update_cmd, ], [ 'update', \&update_cmd, ],
@ -811,6 +836,12 @@ sub main_loop {
} }
} }


process_args();
refresh(); refresh();
status_cmd(); if ($patch_mode) {
main_loop(); patch_update_cmd();
}
else {
status_cmd();
main_loop();
}