* [PATCH v2] git-add--interactive pathspec and patch additions
@ 2007-11-23 19:20 Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 1/7] Add -q/--quiet switch to git-ls-files Wincent Colaiuta
2007-11-23 21:07 ` [PATCH v2] git-add--interactive pathspec and patch additions Junio C Hamano
0 siblings, 2 replies; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 19:20 UTC (permalink / raw)
To: git; +Cc: gitster, peff
This is a revised series based on the feedback and suggestions
received to date. The purpose of the series is to implement these
two user-visible changes:
1. "git-add --interactive" now takes optional pathspec parameters
which can be used to limit the scope of an interactive session
2. We now have "git-add --patch" which takes you straight to the
"patch" subcommand using the given pathspecs and then exits
The series implements these changes in seven steps that apply on top of
"master"; these patches are rebased/squashed ones which *replace* the
ones sent the other day:
1. Add -q/--quiet switch to git-ls-files
Needed because run_cmd_pipe() doesn't propagate the child exit status
and system() likes to be chatty on the standard out. Of the possible
workarounds adding this switch seems to be the cleanest and most
portable.
2. Rename patch_update_file function to patch_update_pathspec
Merely cosmetic.
3. Add path-limiting to git-add--interactive
4. Bail if user supplies an invalid pathspec
For consistency with many other Git commands. It also shields us from
errors if the user starts passing funny pathspecs; eg. consider what
happens if the user passes a non-existent file "foo", and that
eventually hits git-diff-files; note how the error message changes
depending on where "foo" appears in the list:
$ git diff-files --numstat --summary --
1 0 git-commit.sh
$ git diff-files --numstat --summary -- .
1 0 git-commit.sh
$ git diff-files --numstat --summary -- . foo
error: Could not access ''
$ git diff-files --numstat --summary -- foo .
error: Could not access 'foo'
$ git diff-files --numstat --summary -- . . foo
1 0 git-commit.sh
5. Teach builtin-add to pass path arguments to git-add--interactive
6. Add "--patch" option to git-add--interactive
7. Teach builtin-add to handle "--patch" option
And that's all. Here's the diff stat:
Documentation/git-add.txt | 9 +++++-
Documentation/git-ls-files.txt | 7 ++++-
builtin-add.c | 28 ++++++++++++--------
builtin-ls-files.c | 12 ++++++++-
commit.h | 2 +-
git-add--interactive.perl | 52 +++++++++++++++++++++++++++++++-----
t/t3020-ls-files-error-unmatch.sh | 12 ++++++++
7 files changed, 99 insertions(+), 23 deletions(-)
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 1/7] Add -q/--quiet switch to git-ls-files
2007-11-23 19:20 [PATCH v2] git-add--interactive pathspec and patch additions Wincent Colaiuta
@ 2007-11-23 19:20 ` Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 2/7] Rename patch_update_file function to patch_update_pathspec Wincent Colaiuta
2007-11-23 19:25 ` [PATCH 1/7] Add -q/--quiet switch to git-ls-files Wincent Colaiuta
2007-11-23 21:07 ` [PATCH v2] git-add--interactive pathspec and patch additions Junio C Hamano
1 sibling, 2 replies; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 19:20 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
When using the --error-unmatch switch to git-ls-files you may only be
interested in the exit status rather than the actual listing that would
normally be printed to the stdout.
To make this kind of workflow easier, the -q/--quiet switch suppresses
all non-error output.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
Documentation/git-ls-files.txt | 7 ++++++-
builtin-ls-files.c | 12 +++++++++++-
t/t3020-ls-files-error-unmatch.sh | 12 ++++++++++++
3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 2ec0c0d..33481b6 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -9,7 +9,7 @@ git-ls-files - Show information about files in the index and the working tree
SYNOPSIS
--------
[verse]
-'git-ls-files' [-z] [-t] [-v]
+'git-ls-files' [-z] [-t] [-v] [-q]
(--[cached|deleted|others|ignored|stage|unmerged|killed|modified])\*
(-[c|d|o|i|s|u|k|m])\*
[-x <pattern>|--exclude=<pattern>]
@@ -107,6 +107,11 @@ OPTIONS
Similar to `-t`, but use lowercase letters for files
that are marked as 'always matching index'.
+-q|--quiet::
+ Suppress all non-error output. This may be useful in conjunction
+ with --error-unmatch when you are only interested in the exit
+ status.
+
--full-name::
When run from a subdirectory, the command usually
outputs paths relative to the current directory. This
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index 7f60709..6c710a8 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -20,6 +20,7 @@ static int show_unmerged;
static int show_modified;
static int show_killed;
static int show_valid_bit;
+static int quiet;
static int line_terminator = '\n';
static int prefix_len;
@@ -83,6 +84,8 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
if (pathspec && !match(pathspec, ps_matched, ent->name, len))
return;
+ if (quiet)
+ return;
fputs(tag, stdout);
write_name_quoted(ent->name + offset, stdout, line_terminator);
}
@@ -205,6 +208,8 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
tag = alttag;
}
+ if (quiet)
+ return;
if (!show_stage) {
fputs(tag, stdout);
} else {
@@ -385,7 +390,8 @@ static void overlay_tree(const char *tree_name, const char *prefix)
}
static const char ls_files_usage[] =
- "git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
+ "git-ls-files [-z] [-t] [-v] [-q|--quiet] "
+ "(--[cached|deleted|others|stage|unmerged|killed|modified])* "
"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
"[ --exclude-per-directory=<filename> ] [--exclude-standard] "
"[--full-name] [--abbrev] [--] [<file>]*";
@@ -423,6 +429,10 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
show_valid_bit = 1;
continue;
}
+ if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet")) {
+ quiet = 1;
+ continue;
+ }
if (!strcmp(arg, "-c") || !strcmp(arg, "--cached")) {
show_cached = 1;
continue;
diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh
index c83f820..5178322 100755
--- a/t/t3020-ls-files-error-unmatch.sh
+++ b/t/t3020-ls-files-error-unmatch.sh
@@ -23,5 +23,17 @@ test_expect_success \
'git ls-files --error-unmatch should succeed eith matched paths.' \
'git ls-files --error-unmatch foo bar'
+test_expect_success \
+ 'git ls-files -q --error-unmatch should be quiet with unmatched path.' \
+ 'git ls-files -q --error-unmatch foo bar-does-not-match 1> out 2> err ||
+ test $(cat out | wc -l) -eq 0 &&
+ test $(cat err | wc -l) -gt 0'
+
+test_expect_success \
+ 'git ls-files -q --error-unmatch should be quiet with matched paths.' \
+ 'git ls-files -q --error-unmatch foo bar 1> out 2> err ||
+ test $(cat out | wc -l) -eq 0 &&
+ test $(cat err | wc -l) -eq 0'
+
test_done
1
--
1.5.3.6.886.g3364
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 2/7] Rename patch_update_file function to patch_update_pathspec
2007-11-23 19:20 ` [PATCH 1/7] Add -q/--quiet switch to git-ls-files Wincent Colaiuta
@ 2007-11-23 19:20 ` Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 3/7] Add path-limiting to git-add--interactive Wincent Colaiuta
2007-11-23 19:25 ` [PATCH 1/7] Add -q/--quiet switch to git-ls-files Wincent Colaiuta
1 sibling, 1 reply; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 19:20 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
The patch_update_file function really works on pathspecs, not files, so
rename it to reflect its actual purpose.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
git-add--interactive.perl | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index fb1e92a..81575e5 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -564,10 +564,10 @@ sub patch_update_cmd {
IMMEDIATE => 1,
HEADER => $status_head, },
@mods);
- patch_update_file($it->{VALUE}) if ($it);
+ patch_update_pathspec($it->{VALUE}) if ($it);
}
-sub patch_update_file {
+sub patch_update_pathspec {
my ($ix, $num);
my $path = shift;
my ($head, @hunk) = parse_diff($path);
--
1.5.3.6.886.g3364
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 3/7] Add path-limiting to git-add--interactive
2007-11-23 19:20 ` [PATCH 2/7] Rename patch_update_file function to patch_update_pathspec Wincent Colaiuta
@ 2007-11-23 19:20 ` Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 4/7] Bail if user supplies an invalid pathspec Wincent Colaiuta
0 siblings, 1 reply; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 19:20 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
Implement Junio's suggestion that git-add--interactive should reproduce the
path-limiting semantics of non-interactive git-add.
In otherwords, if "git add -i" (unrestricted) shows paths from a set A,
"git add -i paths..." should show paths from a subset of the set A and that
subset should be defined with the existing ls-files pathspec semantics.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
git-add--interactive.perl | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 81575e5..5fc48a5 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -37,7 +37,7 @@ sub list_untracked {
chomp $_;
$_;
}
- run_cmd_pipe(qw(git ls-files --others --exclude-standard --), @_);
+ run_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);
}
my $status_fmt = '%12s %12s %s';
@@ -58,7 +58,7 @@ sub list_modified {
my ($add, $del, $adddel, $file);
for (run_cmd_pipe(qw(git diff-index --cached
- --numstat --summary HEAD))) {
+ --numstat --summary HEAD --), @ARGV)) {
if (($add, $del, $file) =
/^([-\d]+) ([-\d]+) (.*)/) {
my ($change, $bin);
@@ -81,7 +81,7 @@ sub list_modified {
}
}
- for (run_cmd_pipe(qw(git diff-files --numstat --summary))) {
+ for (run_cmd_pipe(qw(git diff-files --numstat --summary --), @ARGV)) {
if (($add, $del, $file) =
/^([-\d]+) ([-\d]+) (.*)/) {
if (!exists $data{$file}) {
--
1.5.3.6.886.g3364
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 4/7] Bail if user supplies an invalid pathspec
2007-11-23 19:20 ` [PATCH 3/7] Add path-limiting to git-add--interactive Wincent Colaiuta
@ 2007-11-23 19:20 ` Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 5/7] Teach builtin-add to pass path arguments to git-add--interactive Wincent Colaiuta
0 siblings, 1 reply; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 19:20 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
Use git-ls-files to detect whether the user has supplied an invalid
pathspec.
Note that the run_cmd_pipe function unfortunately does not transmit the
exit status of the child process, so there is no way to use it in
conjunction with a command like "git-ls-files --error-unmatch".
The alternative is to use Perl's system() function, but that floods the
standard output. So here we make use of the new -q switch to git-ls-files
so that we can both obtain the exit status of the command and not have to
worry about the standard output. Error conditions are still echoed back to
the user because they come through on the standard error.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
git-add--interactive.perl | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 5fc48a5..8706528 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -775,6 +775,12 @@ add untracked - add contents of untracked files to the staged set of changes
EOF
}
+sub check_args {
+ return unless @ARGV;
+ exit $? if system(qw(git ls-files -q --exclude-standard
+ --error-unmatch --with-tree=HEAD --), @ARGV);
+}
+
sub main_loop {
my @cmd = ([ 'status', \&status_cmd, ],
[ 'update', \&update_cmd, ],
@@ -804,5 +810,6 @@ sub main_loop {
}
refresh();
+check_args();
status_cmd();
main_loop();
--
1.5.3.6.886.g3364
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 5/7] Teach builtin-add to pass path arguments to git-add--interactive
2007-11-23 19:20 ` [PATCH 4/7] Bail if user supplies an invalid pathspec Wincent Colaiuta
@ 2007-11-23 19:20 ` Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 6/7] Add "--patch" option " Wincent Colaiuta
0 siblings, 1 reply; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 19:20 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
The previous patches in the series taught git-add--interactive to handle
optional path arguments. This patch teaches builtin-add to pass
these arguments through to the script.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
Documentation/git-add.txt | 4 +++-
builtin-add.c | 23 +++++++++++++----------
commit.h | 2 +-
3 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 63829d9..0b0ab1d 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -61,7 +61,9 @@ OPTIONS
-i, \--interactive::
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 files in the working tree.
+ See ``Interactive mode'' for details.
-u::
Update only files that git already knows about. This is similar
diff --git a/builtin-add.c b/builtin-add.c
index cf815a0..3646a45 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -135,11 +135,17 @@ static void refresh(int verbose, const char **pathspec)
free(seen);
}
-int interactive_add(void)
+int interactive_add(int argc, const char **argv)
{
- const char *argv[2] = { "add--interactive", NULL };
-
- return run_command_v_opt(argv, RUN_GIT_CMD);
+ int status;
+ const char **args = xmalloc(sizeof(const char *) * (argc + 1));
+ args[0] = "add--interactive";
+ memcpy((void *)args + sizeof(const char *), argv, sizeof(const char *) * argc);
+ args[argc + 1] = NULL;
+
+ status = run_command_v_opt(args, RUN_GIT_CMD);
+ free(args);
+ return status;
}
static struct lock_file lock_file;
@@ -163,17 +169,14 @@ static struct option builtin_add_options[] = {
int cmd_add(int argc, const char **argv, const char *prefix)
{
- int i, newfd, orig_argc = argc;
+ int i, newfd = argc;
const char **pathspec;
struct dir_struct dir;
argc = parse_options(argc, argv, builtin_add_options,
builtin_add_usage, 0);
- if (add_interactive) {
- if (add_interactive != 1 || orig_argc != 2)
- die("add --interactive does not take any parameters");
- exit(interactive_add());
- }
+ if (add_interactive)
+ exit(interactive_add(argc, argv));
git_config(git_default_config);
diff --git a/commit.h b/commit.h
index aa67986..d82b8bc 100644
--- a/commit.h
+++ b/commit.h
@@ -113,7 +113,7 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads,
int in_merge_bases(struct commit *, struct commit **, int);
-extern int interactive_add(void);
+extern int interactive_add(int argc, const char **argv);
extern void add_files_to_cache(int verbose, const char *prefix, const char **files);
extern int rerere(void);
--
1.5.3.6.886.g3364
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 6/7] Add "--patch" option to git-add--interactive
2007-11-23 19:20 ` [PATCH 5/7] Teach builtin-add to pass path arguments to git-add--interactive Wincent Colaiuta
@ 2007-11-23 19:20 ` Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 7/7] Teach builtin-add to handle "--patch" option Wincent Colaiuta
0 siblings, 1 reply; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 19:20 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
When the "--patch" option is supplied, the patch_update_file function is
called, once for each supplied pathspec argument, and then we exit.
This commit adds an early return mechanism to the patch_update_pathspec
function to prevent spurious line feeds from being echoed when the user
passes in pathspecs which match unchanged files.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
git-add--interactive.perl | 35 ++++++++++++++++++++++++++++++++---
1 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 8706528..43a5344 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1,6 +1,10 @@
#!/usr/bin/perl -w
use strict;
+use Getopt::Long;
+
+# command line options
+my $patch;
sub run_cmd_pipe {
if ($^O eq 'MSWin32') {
@@ -335,7 +339,8 @@ sub add_untracked_cmd {
sub parse_diff {
my ($path) = @_;
- my @diff = run_cmd_pipe(qw(git diff-files -p --), $path);
+ my @diff = run_cmd_pipe(qw(git diff-files -p --), $path)
+ or return undef;
my (@hunk) = { TEXT => [] };
for (@diff) {
@@ -571,6 +576,7 @@ sub patch_update_pathspec {
my ($ix, $num);
my $path = shift;
my ($head, @hunk) = parse_diff($path);
+ return unless $head;
for (@{$head->{TEXT}}) {
print;
}
@@ -781,6 +787,19 @@ sub check_args {
--error-unmatch --with-tree=HEAD --), @ARGV);
}
+sub usage {
+ print <<EOT;
+git-add--interactive [options] [--] [<filepattern>...]
+Options:
+ -p, --patch Execute the "patch" subcommand and exit
+EOT
+ exit(1);
+}
+
+sub process_options {
+ GetOptions("patch!" => \$patch) or usage();
+}
+
sub main_loop {
my @cmd = ([ 'status', \&status_cmd, ],
[ 'update', \&update_cmd, ],
@@ -809,7 +828,17 @@ sub main_loop {
}
}
+process_options();
refresh();
check_args();
-status_cmd();
-main_loop();
+if ($patch) {
+ print "No filepattern specified: what did you want to patch?\n"
+ unless @ARGV;
+ foreach my $pathspec (@ARGV) {
+ patch_update_pathspec($pathspec);
+ }
+}
+else {
+ status_cmd();
+ main_loop();
+}
--
1.5.3.6.886.g3364
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 7/7] Teach builtin-add to handle "--patch" option
2007-11-23 19:20 ` [PATCH 6/7] Add "--patch" option " Wincent Colaiuta
@ 2007-11-23 19:20 ` Wincent Colaiuta
0 siblings, 0 replies; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 19:20 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
Now builtin-add can take a "--patch" option; when found, it passes control
over to git-add--interactive, passing the --patch switch and the supplied
pathspecs.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
Documentation/git-add.txt | 5 +++++
builtin-add.c | 13 ++++++++-----
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 0b0ab1d..1acf10f 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -65,6 +65,11 @@ OPTIONS
operation to a subset of the files in 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::
Update only files that git already knows about. This is similar
to what "git commit -a" does in preparation for making a commit,
diff --git a/builtin-add.c b/builtin-add.c
index 3646a45..c8335f1 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -19,6 +19,7 @@ static const char * const builtin_add_usage[] = {
"git-add [options] [--] <filepattern>...",
NULL
};
+static int patch_interactive = 0, add_interactive = 0;
static int take_worktree_changes;
@@ -138,10 +139,12 @@ static void refresh(int verbose, const char **pathspec)
int interactive_add(int argc, const char **argv)
{
int status;
- const char **args = xmalloc(sizeof(const char *) * (argc + 1));
+ int pre_argc = patch_interactive ? 2 : 1;
+ const char **args = xmalloc(sizeof(const char *) * (argc + pre_argc + 1));
args[0] = "add--interactive";
- memcpy((void *)args + sizeof(const char *), argv, sizeof(const char *) * argc);
- args[argc + 1] = NULL;
+ args[1] = "--patch";
+ memcpy((void *)args + sizeof(const char *) * pre_argc, argv, sizeof(const char *) * argc);
+ args[argc + pre_argc] = NULL;
status = run_command_v_opt(args, RUN_GIT_CMD);
free(args);
@@ -154,13 +157,13 @@ static const char ignore_error[] =
"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 add_interactive = 0;
static struct option builtin_add_options[] = {
OPT__DRY_RUN(&show_only),
OPT__VERBOSE(&verbose),
OPT_GROUP(""),
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('u', NULL, &take_worktree_changes, "update tracked files"),
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
@@ -175,7 +178,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, builtin_add_options,
builtin_add_usage, 0);
- if (add_interactive)
+ if (add_interactive || patch_interactive)
exit(interactive_add(argc, argv));
git_config(git_default_config);
--
1.5.3.6.886.g3364
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 1/7] Add -q/--quiet switch to git-ls-files
2007-11-23 19:20 ` [PATCH 1/7] Add -q/--quiet switch to git-ls-files Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 2/7] Rename patch_update_file function to patch_update_pathspec Wincent Colaiuta
@ 2007-11-23 19:25 ` Wincent Colaiuta
1 sibling, 0 replies; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 19:25 UTC (permalink / raw)
To: Wincent Colaiuta; +Cc: git, gitster, peff
El 23/11/2007, a las 20:20, Wincent Colaiuta escribió:
> +test_expect_success \
> + 'git ls-files -q --error-unmatch should be quiet with unmatched
> path.' \
> + 'git ls-files -q --error-unmatch foo bar-does-not-match 1> out
> 2> err ||
> + test $(cat out | wc -l) -eq 0 &&
> + test $(cat err | wc -l) -gt 0'
> +
> +test_expect_success \
> + 'git ls-files -q --error-unmatch should be quiet with matched
> paths.' \
> + 'git ls-files -q --error-unmatch foo bar 1> out 2> err ||
> + test $(cat out | wc -l) -eq 0 &&
> + test $(cat err | wc -l) -eq 0'
> +
> test_done
Doh, in that last test it should be:
+ 'git ls-files -q --error-unmatch foo bar 1> out 2> err &&
Instead of:
+ 'git ls-files -q --error-unmatch foo bar 1> out 2> err ||
Cheers,
Wincent
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] git-add--interactive pathspec and patch additions
2007-11-23 19:20 [PATCH v2] git-add--interactive pathspec and patch additions Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 1/7] Add -q/--quiet switch to git-ls-files Wincent Colaiuta
@ 2007-11-23 21:07 ` Junio C Hamano
2007-11-23 22:20 ` Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 0/3] Updates to git-add--interactive Wincent Colaiuta
1 sibling, 2 replies; 19+ messages in thread
From: Junio C Hamano @ 2007-11-23 21:07 UTC (permalink / raw)
To: Wincent Colaiuta; +Cc: git, peff
Wincent Colaiuta <win@wincent.com> writes:
> The series implements these changes in seven steps that apply on top of
> "master"; these patches are rebased/squashed ones which *replace* the
> ones sent the other day:
That's very unfortunate, as some already usable bits from the
series are already in 'next'.
> 1. Add -q/--quiet switch to git-ls-files
>
> Needed because run_cmd_pipe() doesn't propagate the child exit status
> and system() likes to be chatty on the standard out. Of the possible
> workarounds adding this switch seems to be the cleanest and most
> portable.
I do not like this very much. If it is a problem that
run_cmd_pipe() does not properly signal you an error, wouldn't
it be much better to fix _that_ problem? That way we do not
have to add kludge to all commands we need to run and get the
exit status out of.
> 2. Rename patch_update_file function to patch_update_pathspec
>
> Merely cosmetic.
>
> 3. Add path-limiting to git-add--interactive
> 4. Bail if user supplies an invalid pathspec
On the first read, I did not quite like 4, but I'd agree it is
probably the cleanest implementation for 3 to reject a wrong
invocation early.
> 5. Teach builtin-add to pass path arguments to git-add--interactive
I think this is already in 'next'.
> 6. Add "--patch" option to git-add--interactive
> 7. Teach builtin-add to handle "--patch" option
These should be straightforward, but use of Getopt::Long feels
way overkill for an internal command like add--interactive which
is called by only a very limited known callers (exactly one).
If we assume "a single caller", we probably can do without 1 and
4, by making the caller in builtin-add to validate the list of
pathspecs, reusing the code for "ls-files --error-unmatch",
before calling the external helper "add--interactive".
There are functions refactored as part of the builtin-commit
series to be usable from outside "ls-files", and you can build a
imple function called from interactive_add(ac, av) using them:
static int validate_pathspec(const char *prefix, const char **pattern)
{
int i, ret;
char *m;
if (!pattern || !*pattern)
return 0;
for (i = 0; pattern[i]; i++)
;
m = xcalloc(1, i);
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
(void) pathspec_match(pattern, m, ce->name, 0);
}
ret = report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
free(m);
return ret;
}
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] git-add--interactive pathspec and patch additions
2007-11-23 21:07 ` [PATCH v2] git-add--interactive pathspec and patch additions Junio C Hamano
@ 2007-11-23 22:20 ` Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 0/3] Updates to git-add--interactive Wincent Colaiuta
1 sibling, 0 replies; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-23 22:20 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, peff
El 23/11/2007, a las 22:07, Junio C Hamano escribió:
> Wincent Colaiuta <win@wincent.com> writes:
>
>> The series implements these changes in seven steps that apply on
>> top of
>> "master"; these patches are rebased/squashed ones which *replace* the
>> ones sent the other day:
>
> That's very unfortunate, as some already usable bits from the
> series are already in 'next'.
Well, no problem, I'll redo this tomorrow if I can get some free time.
Otherwise it will have to wait to Monday.
>> 1. Add -q/--quiet switch to git-ls-files
>>
>> Needed because run_cmd_pipe() doesn't propagate the child exit status
>> and system() likes to be chatty on the standard out. Of the possible
>> workarounds adding this switch seems to be the cleanest and most
>> portable.
>
> I do not like this very much. If it is a problem that
> run_cmd_pipe() does not properly signal you an error, wouldn't
> it be much better to fix _that_ problem? That way we do not
> have to add kludge to all commands we need to run and get the
> exit status out of.
The problem is that run_cmd_pipe has two code paths, one for Windows
and one for all the rest.
I could "fix" the non-Windows path by reading in all the command input
at once and explicitly doing a close() before returning. In that case
I believe that the exit status would be correctly set before the
function returns. The Windows code path, however, I am reluctant to
touch as I don't know its behaviour and can't test it.
The other alternative was to use qx() or backticks, but then I would
have to start worrying about sanitizing paths and once again because
of the dual-platform issues I was hesitant to do that. And how do you
redirect to /dev/null on Windows?
In any case, I actually *like* the addition of -q to git-ls-files. I
can see some places in the codebase (look in git-commit.sh, for
instance) where git-ls-files is run and the output is thrown away
(redirected to /dev/null) because it's not at all interesting to the
caller. It seems that there is a real use case there which amounts to
"just tell me whether these pathspecs are valid or not, I don't care
about any of the rest".
>> 6. Add "--patch" option to git-add--interactive
>> 7. Teach builtin-add to handle "--patch" option
>
> These should be straightforward, but use of Getopt::Long feels
> way overkill for an internal command like add--interactive which
> is called by only a very limited known callers (exactly one).
>
> If we assume "a single caller", we probably can do without 1 and
> 4, by making the caller in builtin-add to validate the list of
> pathspecs, reusing the code for "ls-files --error-unmatch",
> before calling the external helper "add--interactive".
Well, you're probably right. I was thinking, "just in case we ever
need to add more options"; but it may be that we never do, and perhaps
git-add--interactive will become builtin one day anyway.
> There are functions refactored as part of the builtin-commit
> series to be usable from outside "ls-files", and you can build a
> imple function called from interactive_add(ac, av) using them:
>
> static int validate_pathspec(const char *prefix, const char **pattern)
Ok, thanks for the tip, Junio. Like I said, will look at this either
tomorrow or Monday and get something posted that applies on top of
"next".
Cheers,
Wincent
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 0/3] Updates to git-add--interactive
2007-11-23 21:07 ` [PATCH v2] git-add--interactive pathspec and patch additions Junio C Hamano
2007-11-23 22:20 ` Wincent Colaiuta
@ 2007-11-24 12:55 ` Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 1/3] Rename patch_update_file function to patch_update_pathspec Wincent Colaiuta
1 sibling, 1 reply; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-24 12:55 UTC (permalink / raw)
To: git; +Cc: gitster, peff
Based on feedback from Junio last night here is a new series. This one
goes on top of the "next" branch.
I moved the pathspec validity checking into builtin-add, thus
simplifying things considerably. I also enforced some strict assumptions
about how the optional arguments will be passed from builtin-add to
git-add--interactive; I can do this because it is the only caller, and
it once again makes things a bit simpler.
I don't expect this to actually be applied as-is, as there are some
doubts I have which I have added to the emails for each patch. In
particular there is a performance issue with the pathspec validity
checking (no idea why it is so much slower than just invoking
git-ls-files), and the behaviour is not exactly where I'd like it to be
(things like "git-add -i ." don't work because "." is considered
invalid).
So looking for feedback on how to address this issues and will resubmit.
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 1/3] Rename patch_update_file function to patch_update_pathspec
2007-11-24 12:55 ` [PATCH 0/3] Updates to git-add--interactive Wincent Colaiuta
@ 2007-11-24 12:55 ` Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 2/3] Move pathspec validation into interactive_add Wincent Colaiuta
0 siblings, 1 reply; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-24 12:55 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
The patch_update_file function really works on pathspecs, not files, so
rename it to reflect its actual purpose.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
git-add--interactive.perl | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index e347216..15b2c9f 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -571,11 +571,11 @@ sub patch_update_cmd {
HEADER => $status_head, },
@mods);
for (@them) {
- patch_update_file($_->{VALUE});
+ patch_update_pathspec($_->{VALUE});
}
}
-sub patch_update_file {
+sub patch_update_pathspec {
my ($ix, $num);
my $path = shift;
my ($head, @hunk) = parse_diff($path);
--
1.5.3.6.1992.gd646-dirty
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 2/3] Move pathspec validation into interactive_add
2007-11-24 12:55 ` [PATCH 1/3] Rename patch_update_file function to patch_update_pathspec Wincent Colaiuta
@ 2007-11-24 12:55 ` Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 3/3] Add "--patch" option to git-add--interactive Wincent Colaiuta
2007-11-24 19:15 ` [PATCH 2/3] Move pathspec validation into interactive_add Junio C Hamano
0 siblings, 2 replies; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-24 12:55 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
Simplify git-add--interactive by moving the pathspec validation into the
interactive_add() function of builtin-add. We can do this because
builtin-add is the only caller of git-add--interactive.
The validate_pathspec() function added by this commit is based on a
sample posted to the mailing list by Junio Hamano.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
Note that I made a couple of changes to the code posted by Junio on the
mailing list to make the behaviour a little more convenient. At this
stage it's just a proposal, and there are some issues that I'd like to
see ironed out.
Instead of throwing away the return status of pathspec_match() I am
keeping it, and any successful match breaks out of the loop early. I
observed that passing in a file parameter like "commit.h" in the Git
repo the loop would execute over a thousand times, with pathspec_match
returning 0 some of the time and 1 at others. Evidently any time it
returns 1 that's enough to indicate that it's a valid pathspec.
One issue is that performance is very slow. If you do something like
"git-add -i *.c" then there is a very noticeable delay.
Another issue is that simple shell shortcuts don't work, so something
as simple as "git-add -i ." will report:
error: pathspec '.' did not match any file(s) known to git.
It would be nice if that could be detected as valid because it does
work when you pass it to git-add--interactive.
Likewise it's not possible to validate pathspecs like "\*.sh" either,
but seeing as these won't work when passed to git-add--interactive
guess it doesn't matter (because they don't work with git-diff-files
either, which is what git-add--interactive is using).
builtin-add.c | 38 ++++++++++++++++++++++++++++++++++----
builtin-commit.c | 2 +-
commit.h | 2 +-
git-add--interactive.perl | 12 ++----------
4 files changed, 38 insertions(+), 16 deletions(-)
diff --git a/builtin-add.c b/builtin-add.c
index dd895df..06212c3 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -135,10 +135,40 @@ static void refresh(int verbose, const char **pathspec)
free(seen);
}
-int interactive_add(int argc, const char **argv)
+static int validate_pathspec(const char *prefix, const char **pattern)
{
- int status;
- const char **args = xmalloc(sizeof(const char *) * (argc + 1));
+ int i, ret = 0;
+ char *m;
+
+ if (!pattern || !*pattern)
+ return 0;
+
+ for (i = 0; pattern[i]; i++)
+ ;
+ m = xcalloc(1, i);
+ for (i = 0; i < active_nr; i++) {
+ struct cache_entry *ce = active_cache[i];
+ if ((ret = pathspec_match(pattern, m, ce->name, 0)))
+ break;
+ }
+ if (!ret)
+ report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
+ free(m);
+ return ret;
+}
+
+int interactive_add(const char *prefix, int argc, const char **argv)
+{
+ int i, status;
+ const char **args;
+ if (read_cache() < 0)
+ die("index file corrupt");
+ for (i = 0; i < argc; i++) {
+ if (!(status = validate_pathspec(prefix, &argv[i])))
+ return 1;
+ }
+
+ args = xmalloc(sizeof(const char *) * (argc + 2));
args[0] = "add--interactive";
memcpy((void *)args + sizeof(const char *), argv, sizeof(const char *) * argc);
args[argc + 1] = NULL;
@@ -176,7 +206,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, builtin_add_options,
builtin_add_usage, 0);
if (add_interactive)
- exit(interactive_add(argc, argv));
+ exit(interactive_add(prefix, argc, argv));
git_config(git_default_config);
diff --git a/builtin-commit.c b/builtin-commit.c
index 5d27102..95d1c0d 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -165,7 +165,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
const char **pathspec = NULL;
if (interactive) {
- interactive_add(argc, argv);
+ interactive_add(prefix, argc, argv);
commit_style = COMMIT_AS_IS;
return get_index_file();
}
diff --git a/commit.h b/commit.h
index 9f0765b..dc6fe31 100644
--- a/commit.h
+++ b/commit.h
@@ -113,7 +113,7 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads,
int in_merge_bases(struct commit *, struct commit **, int);
-extern int interactive_add(int argc, const char **argv);
+extern int interactive_add(const char *prefix, int argc, const char **argv);
extern int rerere(void);
static inline int single_parent(struct commit *commit)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 15b2c9f..381bcbe 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -56,17 +56,9 @@ sub list_modified {
my ($only) = @_;
my (%data, @return);
my ($add, $del, $adddel, $file);
- my @tracked = ();
-
- if (@ARGV) {
- @tracked = map {
- chomp $_; $_;
- } run_cmd_pipe(qw(git ls-files --exclude-standard --), @ARGV);
- return if (!@tracked);
- }
for (run_cmd_pipe(qw(git diff-index --cached
- --numstat --summary HEAD --), @tracked)) {
+ --numstat --summary HEAD --), @ARGV)) {
if (($add, $del, $file) =
/^([-\d]+) ([-\d]+) (.*)/) {
my ($change, $bin);
@@ -89,7 +81,7 @@ sub list_modified {
}
}
- for (run_cmd_pipe(qw(git diff-files --numstat --summary --), @tracked)) {
+ for (run_cmd_pipe(qw(git diff-files --numstat --summary --), @ARGV)) {
if (($add, $del, $file) =
/^([-\d]+) ([-\d]+) (.*)/) {
if (!exists $data{$file}) {
--
1.5.3.6.1992.gd646-dirty
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 3/3] Add "--patch" option to git-add--interactive
2007-11-24 12:55 ` [PATCH 2/3] Move pathspec validation into interactive_add Wincent Colaiuta
@ 2007-11-24 12:55 ` Wincent Colaiuta
2007-11-24 19:15 ` [PATCH 2/3] Move pathspec validation into interactive_add Junio C Hamano
1 sibling, 0 replies; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-24 12:55 UTC (permalink / raw)
To: git; +Cc: gitster, peff, Wincent Colaiuta
When the "--patch" option is supplied, the patch_update_file function is
called, once for each supplied pathspec argument, and then we exit.
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.
This commit adds an early return mechanism to the patch_update_pathspec
function to prevent spurious line feeds from being echoed when the user
passes in pathspecs which match unchanged files.
Signed-off-by: Wincent Colaiuta <win@wincent.com>
---
I am sure that someone who actually knows Perl will be able to come up
with a more compact implementation of the process_args() function.
This works, but it's written by a Perl amateur.
Documentation/git-add.txt | 9 ++++++++-
builtin-add.c | 17 ++++++++++-------
git-add--interactive.perl | 35 ++++++++++++++++++++++++++++++++---
3 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 63829d9..ce22de8 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -61,7 +61,14 @@ OPTIONS
-i, \--interactive::
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::
Update only files that git already knows about. This is similar
diff --git a/builtin-add.c b/builtin-add.c
index 06212c3..e69bc13 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -19,7 +19,7 @@ static const char * const builtin_add_usage[] = {
"git-add [options] [--] <filepattern>...",
NULL
};
-
+static int patch_interactive = 0, add_interactive = 0;
static int take_worktree_changes;
static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
@@ -159,7 +159,7 @@ static int validate_pathspec(const char *prefix, const char **pattern)
int interactive_add(const char *prefix, int argc, const char **argv)
{
- int i, status;
+ int i, status, pre_argc;
const char **args;
if (read_cache() < 0)
die("index file corrupt");
@@ -168,10 +168,13 @@ int interactive_add(const char *prefix, int argc, const char **argv)
return 1;
}
- args = xmalloc(sizeof(const char *) * (argc + 2));
+ pre_argc = patch_interactive ? 3 : 2;
+ args = xmalloc(sizeof(const char *) * (argc + pre_argc + 1));
args[0] = "add--interactive";
- memcpy((void *)args + sizeof(const char *), argv, sizeof(const char *) * argc);
- args[argc + 1] = NULL;
+ args[1] = patch_interactive ? "--patch" : "--";
+ args[2] = "--";
+ memcpy((void *)args + sizeof(const char *) * pre_argc, argv, sizeof(const char *) * argc);
+ args[argc + pre_argc] = NULL;
status = run_command_v_opt(args, RUN_GIT_CMD);
free(args);
@@ -184,13 +187,13 @@ static const char ignore_error[] =
"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 add_interactive = 0;
static struct option builtin_add_options[] = {
OPT__DRY_RUN(&show_only),
OPT__VERBOSE(&verbose),
OPT_GROUP(""),
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('u', NULL, &take_worktree_changes, "update tracked files"),
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
@@ -205,7 +208,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, builtin_add_options,
builtin_add_usage, 0);
- if (add_interactive)
+ if (add_interactive || patch_interactive)
exit(interactive_add(prefix, argc, argv));
git_config(git_default_config);
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 381bcbe..7d62ceb 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -2,6 +2,9 @@
use strict;
+# command line options
+my $patch;
+
sub run_cmd_pipe {
if ($^O eq 'MSWin32') {
my @invalid = grep {m/[":*]/} @_;
@@ -335,7 +338,8 @@ sub add_untracked_cmd {
sub parse_diff {
my ($path) = @_;
- my @diff = run_cmd_pipe(qw(git diff-files -p --), $path);
+ my @diff = run_cmd_pipe(qw(git diff-files -p --), $path)
+ or return undef;
my (@hunk) = { TEXT => [] };
for (@diff) {
@@ -571,6 +575,7 @@ sub patch_update_pathspec {
my ($ix, $num);
my $path = shift;
my ($head, @hunk) = parse_diff($path);
+ return unless $head;
for (@{$head->{TEXT}}) {
print;
}
@@ -775,6 +780,20 @@ add untracked - add contents of untracked files to the staged set of changes
EOF
}
+sub process_args {
+ return unless @ARGV;
+ my $arg = shift @ARGV;
+ if ($arg eq "--patch") {
+ $patch = 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 {
my @cmd = ([ 'status', \&status_cmd, ],
[ 'update', \&update_cmd, ],
@@ -803,6 +822,16 @@ sub main_loop {
}
}
+process_args();
refresh();
-status_cmd();
-main_loop();
+if ($patch) {
+ print "No filepattern specified: what did you want to patch?\n"
+ unless @ARGV;
+ foreach my $pathspec (@ARGV) {
+ patch_update_pathspec($pathspec);
+ }
+}
+else {
+ status_cmd();
+ main_loop();
+}
--
1.5.3.6.1992.gd646-dirty
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 2/3] Move pathspec validation into interactive_add
2007-11-24 12:55 ` [PATCH 2/3] Move pathspec validation into interactive_add Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 3/3] Add "--patch" option to git-add--interactive Wincent Colaiuta
@ 2007-11-24 19:15 ` Junio C Hamano
2007-11-24 21:50 ` Wincent Colaiuta
1 sibling, 1 reply; 19+ messages in thread
From: Junio C Hamano @ 2007-11-24 19:15 UTC (permalink / raw)
To: Wincent Colaiuta; +Cc: git, peff
Wincent Colaiuta <win@wincent.com> writes:
> Instead of throwing away the return status of pathspec_match() I am
> keeping it, and any successful match breaks out of the loop early.
Leaving it early before checking if all the given pathspecs are
used defeats the whole "error-unmatch" business, doesn't it?
> Another issue is that simple shell shortcuts don't work, so something
> as simple as "git-add -i ." will report:
>
> error: pathspec '.' did not match any file(s) known to git.
The sample code snippet I sent you probably is not doing
get_pathspec() before using the "pattern" thing. And I suspect
that ...
> Likewise it's not possible to validate pathspecs like "\*.sh" either,
... may be related to that.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/3] Move pathspec validation into interactive_add
2007-11-24 19:15 ` [PATCH 2/3] Move pathspec validation into interactive_add Junio C Hamano
@ 2007-11-24 21:50 ` Wincent Colaiuta
2007-11-24 22:34 ` Junio C Hamano
0 siblings, 1 reply; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-24 21:50 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, peff
El 24/11/2007, a las 20:15, Junio C Hamano escribió:
> Wincent Colaiuta <win@wincent.com> writes:
>
>> Instead of throwing away the return status of pathspec_match() I am
>> keeping it, and any successful match breaks out of the loop early.
>
> Leaving it early before checking if all the given pathspecs are
> used defeats the whole "error-unmatch" business, doesn't it?
No, I probably didn't explain that clearly enough... If you look at
the patch, I break out of the *inner* loop the first time a particular
pattern matches. Then I move on to the next pattern, and any single
invalid pattern will be enough to provide the "error-unmatch"
indication.
>> Another issue is that simple shell shortcuts don't work, so something
>> as simple as "git-add -i ." will report:
>>
>> error: pathspec '.' did not match any file(s) known to git.
>
> The sample code snippet I sent you probably is not doing
> get_pathspec() before using the "pattern" thing. And I suspect
> that ...
>
>> Likewise it's not possible to validate pathspecs like "\*.sh" either,
>
> ... may be related to that.
Ok, thanks for the pointer. Didn't know what the get_pathspec()
function was for, but will have a play with it.
Cheers,
Wincent
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/3] Move pathspec validation into interactive_add
2007-11-24 21:50 ` Wincent Colaiuta
@ 2007-11-24 22:34 ` Junio C Hamano
0 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2007-11-24 22:34 UTC (permalink / raw)
To: Wincent Colaiuta; +Cc: git, peff
Wincent Colaiuta <win@wincent.com> writes:
> El 24/11/2007, a las 20:15, Junio C Hamano escribió:
>
>> Wincent Colaiuta <win@wincent.com> writes:
>>
>>> Instead of throwing away the return status of pathspec_match() I am
>>> keeping it, and any successful match breaks out of the loop early.
>>
>> Leaving it early before checking if all the given pathspecs are
>> used defeats the whole "error-unmatch" business, doesn't it?
>
> No, I probably didn't explain that clearly enough... If you look at
> the patch, I break out of the *inner* loop the first time a particular
> pattern matches. Then I move on to the next pattern, and any single
> invalid pattern will be enough to provide the "error-unmatch"
> indication.
Heh, I missed that the code was doing something so stupid ;-).
The helper function pathspec_match() takes a single path and a
set of pathspecs (NULL terminated), and says if the path is
covered with that set, while recording which one of the
pathspecs caused the match in the ps_matched array.
You are checking first with the full set of patterns, then the
full set minus the first pattern, and then the full set minus
the first two patterns, and so on. No wonder it is inefficient.
Why are you trying to micro-optimize this part in the first
place? Have you benchmarked and determined that iterating over
full cache is the bottleneck?
In order to prove that there is a pathspec (or more) that does
not match anything in the cache, you need to interate over the
whole cache at least once. The only case you can short-cut is
when you can tell that all of them have been used before you
iterated over all cache entries.
So lose that silly outer loop, and replace the inner function
with something like this:
static int validate_pathspec(const char *prefix, const char **pattern)
{
int i, ret = 0, num_patterns;
char *m;
if (!pattern || !*pattern)
return 0;
for (num_patterns = 0; pattern[num_patterns]; num_patterns++)
;
m = xcalloc(1, num_patterns + 1);
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
if (pathspec_match(pattern, m, ce->name, 0)) {
/*
* You could micro optimize by leaving
* the loop early when you notice that all
* patterns are used.
*
* if (strlen(m) == num_patterns)
* goto ok;
*
*/
; /* nothing */
}
}
report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
ok:
free(m);
return ret;
}
My gut feeling is that the micro-optimization is not worth it here, but
I didn't try. I think without the micro-optimization the above is the
same as I gave you earlier.
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 0/3] Updates to git-add--interactive
@ 2007-11-25 13:15 Wincent Colaiuta
0 siblings, 0 replies; 19+ messages in thread
From: Wincent Colaiuta @ 2007-11-25 13:15 UTC (permalink / raw)
To: git; +Cc: gitster, peff
Here's an updated series, this time hopefully with the braindead
parts removed.
[PATCH 1/3] Add "--patch" option to git-add--interactive
Unchanged.
[PATCH 2/3] Move pathspec validation into interactive_add
Braindeadness removed.
[PATCH 3/3] Rename patch_update_file function to patch_update_pathspec
Only modified insofar as to make it apply on top of PATCH 2.
The one remaining issue is that pathspecs like "\*.h" don't work.
But from comments earlier on in this thread I had the impression
that they should.
They don't work because such pathspecs don't work for the underlying
git-diff-files implementation that's used by git-add--interactive:
git diff-files --numstat --summary -- \*.h
Is some alternative being proposed that would allow them to work?
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2007-11-25 13:16 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-23 19:20 [PATCH v2] git-add--interactive pathspec and patch additions Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 1/7] Add -q/--quiet switch to git-ls-files Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 2/7] Rename patch_update_file function to patch_update_pathspec Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 3/7] Add path-limiting to git-add--interactive Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 4/7] Bail if user supplies an invalid pathspec Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 5/7] Teach builtin-add to pass path arguments to git-add--interactive Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 6/7] Add "--patch" option " Wincent Colaiuta
2007-11-23 19:20 ` [PATCH 7/7] Teach builtin-add to handle "--patch" option Wincent Colaiuta
2007-11-23 19:25 ` [PATCH 1/7] Add -q/--quiet switch to git-ls-files Wincent Colaiuta
2007-11-23 21:07 ` [PATCH v2] git-add--interactive pathspec and patch additions Junio C Hamano
2007-11-23 22:20 ` Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 0/3] Updates to git-add--interactive Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 1/3] Rename patch_update_file function to patch_update_pathspec Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 2/3] Move pathspec validation into interactive_add Wincent Colaiuta
2007-11-24 12:55 ` [PATCH 3/3] Add "--patch" option to git-add--interactive Wincent Colaiuta
2007-11-24 19:15 ` [PATCH 2/3] Move pathspec validation into interactive_add Junio C Hamano
2007-11-24 21:50 ` Wincent Colaiuta
2007-11-24 22:34 ` Junio C Hamano
-- strict thread matches above, loose matches on Subject: below --
2007-11-25 13:15 [PATCH 0/3] Updates to git-add--interactive Wincent Colaiuta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).