Merge branch 'jc/grep-c'
* jc/grep-c: Split grep arguments in a way that does not requires to add /dev/null. Documentation/git-config.txt: AsciiDoc tweak to avoid leading dot Add test to check recent fix to "git add -u" Documentation/git-archive.txt: a couple of clarifications. Fix the rename detection limit checking diff --no-index: do not forget to run diff_setup_done()maint
commit
f6336167e9
|
@ -15,7 +15,8 @@ SYNOPSIS
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Creates an archive of the specified format containing the tree
|
Creates an archive of the specified format containing the tree
|
||||||
structure for the named tree. If <prefix> is specified it is
|
structure for the named tree, and writes it out to the standard
|
||||||
|
output. If <prefix> is specified it is
|
||||||
prepended to the filenames in the archive.
|
prepended to the filenames in the archive.
|
||||||
|
|
||||||
'git-archive' behaves differently when given a tree ID versus when
|
'git-archive' behaves differently when given a tree ID versus when
|
||||||
|
@ -31,7 +32,7 @@ OPTIONS
|
||||||
-------
|
-------
|
||||||
|
|
||||||
--format=<fmt>::
|
--format=<fmt>::
|
||||||
Format of the resulting archive: 'tar', 'zip'... The default
|
Format of the resulting archive: 'tar' or 'zip'. The default
|
||||||
is 'tar'.
|
is 'tar'.
|
||||||
|
|
||||||
--list, -l::
|
--list, -l::
|
||||||
|
|
|
@ -142,7 +142,7 @@ FILES
|
||||||
If not set explicitly with '--file', there are three files where
|
If not set explicitly with '--file', there are three files where
|
||||||
git-config will search for configuration options:
|
git-config will search for configuration options:
|
||||||
|
|
||||||
.git/config::
|
$GIT_DIR/config::
|
||||||
Repository specific configuration file. (The filename is
|
Repository specific configuration file. (The filename is
|
||||||
of course relative to the repository root, not the working
|
of course relative to the repository root, not the working
|
||||||
directory.)
|
directory.)
|
||||||
|
|
|
@ -95,7 +95,7 @@ static void update_callback(struct diff_queue_struct *q,
|
||||||
const char *path = p->one->path;
|
const char *path = p->one->path;
|
||||||
switch (p->status) {
|
switch (p->status) {
|
||||||
default:
|
default:
|
||||||
die("unexpacted diff status %c", p->status);
|
die("unexpected diff status %c", p->status);
|
||||||
case DIFF_STATUS_UNMERGED:
|
case DIFF_STATUS_UNMERGED:
|
||||||
case DIFF_STATUS_MODIFIED:
|
case DIFF_STATUS_MODIFIED:
|
||||||
case DIFF_STATUS_TYPE_CHANGED:
|
case DIFF_STATUS_TYPE_CHANGED:
|
||||||
|
|
|
@ -187,6 +187,78 @@ static int exec_grep(int argc, const char **argv)
|
||||||
else die("maximum number of args exceeded"); \
|
else die("maximum number of args exceeded"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you send a singleton filename to grep, it does not give
|
||||||
|
* the name of the file. GNU grep has "-H" but we would want
|
||||||
|
* that behaviour in a portable way.
|
||||||
|
*
|
||||||
|
* So we keep two pathnames in argv buffer unsent to grep in
|
||||||
|
* the main loop if we need to do more than one grep.
|
||||||
|
*/
|
||||||
|
static int flush_grep(struct grep_opt *opt,
|
||||||
|
int argc, int arg0, const char **argv, int *kept)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
int count = argc - arg0;
|
||||||
|
const char *kept_0 = NULL;
|
||||||
|
|
||||||
|
if (count <= 2) {
|
||||||
|
/*
|
||||||
|
* Because we keep at least 2 paths in the call from
|
||||||
|
* the main loop (i.e. kept != NULL), and MAXARGS is
|
||||||
|
* far greater than 2, this usually is a call to
|
||||||
|
* conclude the grep. However, the user could attempt
|
||||||
|
* to overflow the argv buffer by giving too many
|
||||||
|
* options to leave very small number of real
|
||||||
|
* arguments even for the call in the main loop.
|
||||||
|
*/
|
||||||
|
if (kept)
|
||||||
|
die("insanely many options to grep");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have two or more paths, we do not have to do
|
||||||
|
* anything special, but we need to push /dev/null to
|
||||||
|
* get "-H" behaviour of GNU grep portably but when we
|
||||||
|
* are not doing "-l" nor "-L" nor "-c".
|
||||||
|
*/
|
||||||
|
if (count == 1 &&
|
||||||
|
!opt->name_only &&
|
||||||
|
!opt->unmatch_name_only &&
|
||||||
|
!opt->count) {
|
||||||
|
argv[argc++] = "/dev/null";
|
||||||
|
argv[argc] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (kept) {
|
||||||
|
/*
|
||||||
|
* Called because we found many paths and haven't finished
|
||||||
|
* iterating over the cache yet. We keep two paths
|
||||||
|
* for the concluding call. argv[argc-2] and argv[argc-1]
|
||||||
|
* has the last two paths, so save the first one away,
|
||||||
|
* replace it with NULL while sending the list to grep,
|
||||||
|
* and recover them after we are done.
|
||||||
|
*/
|
||||||
|
*kept = 2;
|
||||||
|
kept_0 = argv[argc-2];
|
||||||
|
argv[argc-2] = NULL;
|
||||||
|
argc -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = exec_grep(argc, argv);
|
||||||
|
|
||||||
|
if (kept_0) {
|
||||||
|
/*
|
||||||
|
* Then recover them. Now the last arg is beyond the
|
||||||
|
* terminating NULL which is at argc, and the second
|
||||||
|
* from the last is what we saved away in kept_0
|
||||||
|
*/
|
||||||
|
argv[arg0++] = kept_0;
|
||||||
|
argv[arg0] = argv[argc+1];
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static int external_grep(struct grep_opt *opt, const char **paths, int cached)
|
static int external_grep(struct grep_opt *opt, const char **paths, int cached)
|
||||||
{
|
{
|
||||||
int i, nr, argc, hit, len, status;
|
int i, nr, argc, hit, len, status;
|
||||||
|
@ -253,22 +325,12 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
|
||||||
push_arg(p->pattern);
|
push_arg(p->pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* To make sure we get the header printed out when we want it,
|
|
||||||
* add /dev/null to the paths to grep. This is unnecessary
|
|
||||||
* (and wrong) with "-l" or "-L", which always print out the
|
|
||||||
* name anyway.
|
|
||||||
*
|
|
||||||
* GNU grep has "-H", but this is portable.
|
|
||||||
*/
|
|
||||||
if (!opt->name_only && !opt->unmatch_name_only)
|
|
||||||
push_arg("/dev/null");
|
|
||||||
|
|
||||||
hit = 0;
|
hit = 0;
|
||||||
argc = nr;
|
argc = nr;
|
||||||
for (i = 0; i < active_nr; i++) {
|
for (i = 0; i < active_nr; i++) {
|
||||||
struct cache_entry *ce = active_cache[i];
|
struct cache_entry *ce = active_cache[i];
|
||||||
char *name;
|
char *name;
|
||||||
|
int kept;
|
||||||
if (!S_ISREG(ntohl(ce->ce_mode)))
|
if (!S_ISREG(ntohl(ce->ce_mode)))
|
||||||
continue;
|
continue;
|
||||||
if (!pathspec_matches(paths, ce->name))
|
if (!pathspec_matches(paths, ce->name))
|
||||||
|
@ -283,10 +345,10 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
|
||||||
argv[argc++] = name;
|
argv[argc++] = name;
|
||||||
if (argc < MAXARGS && !ce_stage(ce))
|
if (argc < MAXARGS && !ce_stage(ce))
|
||||||
continue;
|
continue;
|
||||||
status = exec_grep(argc, argv);
|
status = flush_grep(opt, argc, nr, argv, &kept);
|
||||||
if (0 < status)
|
if (0 < status)
|
||||||
hit = 1;
|
hit = 1;
|
||||||
argc = nr;
|
argc = nr + kept;
|
||||||
if (ce_stage(ce)) {
|
if (ce_stage(ce)) {
|
||||||
do {
|
do {
|
||||||
i++;
|
i++;
|
||||||
|
@ -296,7 +358,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (argc > nr) {
|
if (argc > nr) {
|
||||||
status = exec_grep(argc, argv);
|
status = flush_grep(opt, argc, nr, argv, NULL);
|
||||||
if (0 < status)
|
if (0 < status)
|
||||||
hit = 1;
|
hit = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,6 +298,8 @@ int setup_diff_no_index(struct rev_info *revs,
|
||||||
revs->diffopt.nr_paths = 2;
|
revs->diffopt.nr_paths = 2;
|
||||||
revs->diffopt.no_index = 1;
|
revs->diffopt.no_index = 1;
|
||||||
revs->max_count = -2;
|
revs->max_count = -2;
|
||||||
|
if (diff_setup_done(&revs->diffopt) < 0)
|
||||||
|
die("diff_setup_done failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
diff.c
2
diff.c
|
@ -17,7 +17,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int diff_detect_rename_default;
|
static int diff_detect_rename_default;
|
||||||
static int diff_rename_limit_default = -1;
|
static int diff_rename_limit_default = 100;
|
||||||
static int diff_use_color_default;
|
static int diff_use_color_default;
|
||||||
int diff_auto_refresh_index = 1;
|
int diff_auto_refresh_index = 1;
|
||||||
|
|
||||||
|
|
|
@ -298,10 +298,25 @@ void diffcore_rename(struct diff_options *options)
|
||||||
else if (detect_rename == DIFF_DETECT_COPY)
|
else if (detect_rename == DIFF_DETECT_COPY)
|
||||||
register_rename_src(p->one, 1, p->score);
|
register_rename_src(p->one, 1, p->score);
|
||||||
}
|
}
|
||||||
if (rename_dst_nr == 0 || rename_src_nr == 0 ||
|
if (rename_dst_nr == 0 || rename_src_nr == 0)
|
||||||
(0 < rename_limit && rename_limit < rename_dst_nr))
|
|
||||||
goto cleanup; /* nothing to do */
|
goto cleanup; /* nothing to do */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This basically does a test for the rename matrix not
|
||||||
|
* growing larger than a "rename_limit" square matrix, ie:
|
||||||
|
*
|
||||||
|
* rename_dst_nr * rename_src_nr > rename_limit * rename_limit
|
||||||
|
*
|
||||||
|
* but handles the potential overflow case specially (and we
|
||||||
|
* assume at least 32-bit integers)
|
||||||
|
*/
|
||||||
|
if (rename_limit <= 0 || rename_limit > 32767)
|
||||||
|
rename_limit = 32767;
|
||||||
|
if (rename_dst_nr > rename_limit && rename_src_nr > rename_limit)
|
||||||
|
goto cleanup;
|
||||||
|
if (rename_dst_nr * rename_src_nr > rename_limit * rename_limit)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
/* We really want to cull the candidates list early
|
/* We really want to cull the candidates list early
|
||||||
* with cheap tests in order to avoid doing deltas.
|
* with cheap tests in order to avoid doing deltas.
|
||||||
* The first round matches up the up-to-date entries,
|
* The first round matches up the up-to-date entries,
|
||||||
|
|
|
@ -16,11 +16,12 @@ only the updates to dir/sub.'
|
||||||
test_expect_success setup '
|
test_expect_success setup '
|
||||||
echo initial >check &&
|
echo initial >check &&
|
||||||
echo initial >top &&
|
echo initial >top &&
|
||||||
|
echo initial >foo &&
|
||||||
mkdir dir1 dir2 &&
|
mkdir dir1 dir2 &&
|
||||||
echo initial >dir1/sub1 &&
|
echo initial >dir1/sub1 &&
|
||||||
echo initial >dir1/sub2 &&
|
echo initial >dir1/sub2 &&
|
||||||
echo initial >dir2/sub3 &&
|
echo initial >dir2/sub3 &&
|
||||||
git add check dir1 dir2 top &&
|
git add check dir1 dir2 top foo &&
|
||||||
test_tick
|
test_tick
|
||||||
git-commit -m initial &&
|
git-commit -m initial &&
|
||||||
|
|
||||||
|
@ -76,4 +77,12 @@ test_expect_success 'change gets noticed' '
|
||||||
|
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'replace a file with a symlink' '
|
||||||
|
|
||||||
|
rm foo &&
|
||||||
|
ln -s top foo &&
|
||||||
|
git add -u -- foo
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -107,6 +107,10 @@ do
|
||||||
diff expected actual
|
diff expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_failure "grep -c $L (no /dev/null)" '
|
||||||
|
git grep -c test $H | grep -q "/dev/null"
|
||||||
|
'
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -227,6 +227,7 @@ static void wt_status_print_updated(struct wt_status *s)
|
||||||
rev.diffopt.format_callback = wt_status_print_updated_cb;
|
rev.diffopt.format_callback = wt_status_print_updated_cb;
|
||||||
rev.diffopt.format_callback_data = s;
|
rev.diffopt.format_callback_data = s;
|
||||||
rev.diffopt.detect_rename = 1;
|
rev.diffopt.detect_rename = 1;
|
||||||
|
rev.diffopt.rename_limit = 100;
|
||||||
wt_read_cache(s);
|
wt_read_cache(s);
|
||||||
run_diff_index(&rev, 1);
|
run_diff_index(&rev, 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue