зеркало из https://github.com/microsoft/git.git
rev-parse --glob
Add --glob=<glob-pattern> option to rev-parse and everything that accepts its options. This option matches all refs that match given shell glob pattern (complete with some DWIM logic). Example: 'git log --branches --not --glob=remotes/origin' To show what you have that origin doesn't. Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
5b15950ac4
Коммит
d08bae7e22
|
@ -107,6 +107,17 @@ git log --follow builtin-rev-list.c::
|
|||
those commits that occurred before the file was given its
|
||||
present name.
|
||||
|
||||
git log --branches --not --glob=remotes/origin/*::
|
||||
|
||||
Shows all commits that are in any of local branches but not in
|
||||
any of remote tracking branches for 'origin' (what you have that
|
||||
origin doesn't).
|
||||
|
||||
git log master --not --glob=remotes/*/master::
|
||||
|
||||
Shows all commits that are in local master but not in any remote
|
||||
repository master branches.
|
||||
|
||||
Discussion
|
||||
----------
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ SYNOPSIS
|
|||
[ \--branches ]
|
||||
[ \--tags ]
|
||||
[ \--remotes ]
|
||||
[ \--glob=glob-pattern ]
|
||||
[ \--stdin ]
|
||||
[ \--quiet ]
|
||||
[ \--topo-order ]
|
||||
|
|
|
@ -112,6 +112,11 @@ OPTIONS
|
|||
--remotes::
|
||||
Show tag refs found in `$GIT_DIR/refs/remotes`.
|
||||
|
||||
--glob=glob-pattern::
|
||||
Show refs matching shell glob pattern `glob-pattern`. If pattern
|
||||
specified lacks leading 'refs/', it is automatically prepended.
|
||||
If pattern lacks '?', '*', or '[', '/*' at the end is impiled.
|
||||
|
||||
--show-prefix::
|
||||
When the command is invoked from a subdirectory, show the
|
||||
path of the current directory relative to the top-level
|
||||
|
|
|
@ -243,6 +243,13 @@ endif::git-rev-list[]
|
|||
Pretend as if all the refs in `$GIT_DIR/refs/remotes` are listed
|
||||
on the command line as '<commit>'.
|
||||
|
||||
--glob=glob-pattern::
|
||||
Pretend as if all the refs matching shell glob `glob-pattern`
|
||||
are listed on the command line as '<commit>'. Leading 'refs/',
|
||||
is automatically prepended if missing. If pattern lacks '?', '*',
|
||||
or '[', '/*' at the end is impiled.
|
||||
|
||||
|
||||
ifndef::git-rev-list[]
|
||||
--bisect::
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ static int is_rev_argument(const char *arg)
|
|||
"--parents",
|
||||
"--pretty",
|
||||
"--remotes",
|
||||
"--glob=",
|
||||
"--sparse",
|
||||
"--tags",
|
||||
"--topo-order",
|
||||
|
@ -577,6 +578,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||
for_each_tag_ref(show_reference, NULL);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--glob=")) {
|
||||
for_each_glob_ref(show_reference, arg + 7, NULL);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--remotes")) {
|
||||
for_each_remote_ref(show_reference, NULL);
|
||||
continue;
|
||||
|
|
45
refs.c
45
refs.c
|
@ -519,6 +519,13 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
|
|||
return ref;
|
||||
}
|
||||
|
||||
/* The argument to filter_refs */
|
||||
struct ref_filter {
|
||||
const char *pattern;
|
||||
each_ref_fn *fn;
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
int read_ref(const char *ref, unsigned char *sha1)
|
||||
{
|
||||
if (resolve_ref(ref, sha1, 1, NULL))
|
||||
|
@ -545,6 +552,15 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
|
|||
return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
|
||||
}
|
||||
|
||||
static int filter_refs(const char *ref, const unsigned char *sha, int flags,
|
||||
void *data)
|
||||
{
|
||||
struct ref_filter *filter = (struct ref_filter *)data;
|
||||
if (fnmatch(filter->pattern, ref, 0))
|
||||
return 0;
|
||||
return filter->fn(ref, sha, flags, filter->cb_data);
|
||||
}
|
||||
|
||||
int peel_ref(const char *ref, unsigned char *sha1)
|
||||
{
|
||||
int flag;
|
||||
|
@ -674,6 +690,35 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data)
|
|||
return do_for_each_ref("refs/replace/", fn, 13, 0, cb_data);
|
||||
}
|
||||
|
||||
int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
|
||||
{
|
||||
struct strbuf real_pattern = STRBUF_INIT;
|
||||
struct ref_filter filter;
|
||||
const char *has_glob_specials;
|
||||
int ret;
|
||||
|
||||
if (prefixcmp(pattern, "refs/"))
|
||||
strbuf_addstr(&real_pattern, "refs/");
|
||||
strbuf_addstr(&real_pattern, pattern);
|
||||
|
||||
has_glob_specials = strpbrk(pattern, "?*[");
|
||||
if (!has_glob_specials) {
|
||||
/* Append impiled '/' '*' if not present. */
|
||||
if (real_pattern.buf[real_pattern.len - 1] != '/')
|
||||
strbuf_addch(&real_pattern, '/');
|
||||
/* No need to check for '*', there is none. */
|
||||
strbuf_addch(&real_pattern, '*');
|
||||
}
|
||||
|
||||
filter.pattern = real_pattern.buf;
|
||||
filter.fn = fn;
|
||||
filter.cb_data = cb_data;
|
||||
ret = for_each_ref(filter_refs, &filter);
|
||||
|
||||
strbuf_release(&real_pattern);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int for_each_rawref(each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref("refs/", fn, 0,
|
||||
|
|
1
refs.h
1
refs.h
|
@ -25,6 +25,7 @@ extern int for_each_tag_ref(each_ref_fn, void *);
|
|||
extern int for_each_branch_ref(each_ref_fn, void *);
|
||||
extern int for_each_remote_ref(each_ref_fn, void *);
|
||||
extern int for_each_replace_ref(each_ref_fn, void *);
|
||||
extern int for_each_glob_ref(each_ref_fn, const char *pattern, void *);
|
||||
|
||||
/* can be used to learn about broken ref and symref */
|
||||
extern int for_each_rawref(each_ref_fn, void *);
|
||||
|
|
16
revision.c
16
revision.c
|
@ -699,12 +699,18 @@ static int handle_one_ref(const char *path, const unsigned char *sha1, int flag,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
|
||||
unsigned flags)
|
||||
{
|
||||
cb->all_revs = revs;
|
||||
cb->all_flags = flags;
|
||||
}
|
||||
|
||||
static void handle_refs(struct rev_info *revs, unsigned flags,
|
||||
int (*for_each)(each_ref_fn, void *))
|
||||
{
|
||||
struct all_refs_cb cb;
|
||||
cb.all_revs = revs;
|
||||
cb.all_flags = flags;
|
||||
init_all_refs_cb(&cb, revs, flags);
|
||||
for_each(handle_one_ref, &cb);
|
||||
}
|
||||
|
||||
|
@ -1352,6 +1358,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
|
|||
handle_refs(revs, flags, for_each_remote_ref);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--glob=")) {
|
||||
struct all_refs_cb cb;
|
||||
init_all_refs_cb(&cb, revs, flags);
|
||||
for_each_glob_ref(handle_one_ref, arg + 7, &cb);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--reflog")) {
|
||||
handle_reflog(revs, flags);
|
||||
continue;
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='rev-list/rev-parse --glob'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
commit () {
|
||||
test_tick &&
|
||||
echo $1 > foo &&
|
||||
git add foo &&
|
||||
git commit -m "$1"
|
||||
}
|
||||
|
||||
compare () {
|
||||
# Split arguments on whitespace.
|
||||
git $1 $2 >expected &&
|
||||
git $1 $3 >actual &&
|
||||
test_cmp expected actual
|
||||
}
|
||||
|
||||
test_expect_success 'setup' '
|
||||
|
||||
commit master &&
|
||||
git checkout -b subspace/one master &&
|
||||
commit one &&
|
||||
git checkout -b subspace/two master &&
|
||||
commit two &&
|
||||
git checkout -b subspace-x master &&
|
||||
commit subspace-x &&
|
||||
git checkout -b other/three master &&
|
||||
commit three &&
|
||||
git checkout -b someref master &&
|
||||
commit some &&
|
||||
git checkout master &&
|
||||
commit master2
|
||||
'
|
||||
|
||||
test_expect_success 'rev-parse --glob=refs/heads/subspace/*' '
|
||||
|
||||
compare rev-parse "subspace/one subspace/two" "--glob=refs/heads/subspace/*"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-parse --glob=heads/subspace/*' '
|
||||
|
||||
compare rev-parse "subspace/one subspace/two" "--glob=heads/subspace/*"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-parse --glob=refs/heads/subspace/' '
|
||||
|
||||
compare rev-parse "subspace/one subspace/two" "--glob=refs/heads/subspace/"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-parse --glob=heads/subspace/' '
|
||||
|
||||
compare rev-parse "subspace/one subspace/two" "--glob=heads/subspace/"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-parse --glob=heads/subspace' '
|
||||
|
||||
compare rev-parse "subspace/one subspace/two" "--glob=heads/subspace"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-parse --glob=heads/subspace/* --glob=heads/other/*' '
|
||||
|
||||
compare rev-parse "subspace/one subspace/two other/three" "--glob=heads/subspace/* --glob=heads/other/*"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-parse --glob=heads/someref/* master' '
|
||||
|
||||
compare rev-parse "master" "--glob=heads/someref/* master"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-parse --glob=heads/*' '
|
||||
|
||||
compare rev-parse "master other/three someref subspace-x subspace/one subspace/two" "--glob=heads/*"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --glob=refs/heads/subspace/*' '
|
||||
|
||||
compare rev-list "subspace/one subspace/two" "--glob=refs/heads/subspace/*"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --glob=heads/subspace/*' '
|
||||
|
||||
compare rev-list "subspace/one subspace/two" "--glob=heads/subspace/*"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --glob=refs/heads/subspace/' '
|
||||
|
||||
compare rev-list "subspace/one subspace/two" "--glob=refs/heads/subspace/"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --glob=heads/subspace/' '
|
||||
|
||||
compare rev-list "subspace/one subspace/two" "--glob=heads/subspace/"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --glob=heads/subspace' '
|
||||
|
||||
compare rev-list "subspace/one subspace/two" "--glob=heads/subspace"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --glob=heads/someref/* master' '
|
||||
|
||||
compare rev-list "master" "--glob=heads/someref/* master"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --glob=heads/subspace/* --glob=heads/other/*' '
|
||||
|
||||
compare rev-list "subspace/one subspace/two other/three" "--glob=heads/subspace/* --glob=heads/other/*"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --glob=heads/*' '
|
||||
|
||||
compare rev-list "master other/three someref subspace-x subspace/one subspace/two" "--glob=heads/*"
|
||||
|
||||
'
|
||||
|
||||
test_done
|
Загрузка…
Ссылка в новой задаче