diff options
author | Junio C Hamano <gitster@pobox.com> | 2008-02-27 11:52:20 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-02-27 11:52:20 -0800 |
commit | c6a7c606a6fb89f51258d2a60bc27cfe2530a0a1 (patch) | |
tree | cdfae919c70cc8e085b664ed258f5d1c2822fdd2 | |
parent | Add '--fixed-strings' option to "git log --grep" and friends (diff) | |
parent | Use git-describe --exact-match in bash prompt on detached HEAD (diff) | |
download | tgif-c6a7c606a6fb89f51258d2a60bc27cfe2530a0a1.tar.xz |
Merge branch 'sp/describe'
* sp/describe:
Use git-describe --exact-match in bash prompt on detached HEAD
Teach git-describe --exact-match to avoid expensive tag searches
Avoid accessing non-tag refs in git-describe unless --all is requested
Teach git-describe to use peeled ref information when scanning tags
Optimize peel_ref for the current ref of a for_each_ref callback
-rw-r--r-- | Documentation/git-describe.txt | 5 | ||||
-rw-r--r-- | builtin-describe.c | 35 | ||||
-rwxr-xr-x | contrib/completion/git-completion.bash | 5 | ||||
-rw-r--r-- | refs.c | 25 |
4 files changed, 56 insertions, 14 deletions
diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt index 1c3dfb40c6..fbb40a2916 100644 --- a/Documentation/git-describe.txt +++ b/Documentation/git-describe.txt @@ -45,6 +45,11 @@ OPTIONS candidates to describe the input committish consider up to <n> candidates. Increasing <n> above 10 will take slightly longer but may produce a more accurate result. + An <n> of 0 will cause only exact matches to be output. + +--exact-match:: + Only output exact matches (a tag directly references the + supplied commit). This is a synonym for --candidates=0. --debug:: Verbosely display information about the searching strategy diff --git a/builtin-describe.c b/builtin-describe.c index 3428483134..05e309f5ad 100644 --- a/builtin-describe.c +++ b/builtin-describe.c @@ -46,19 +46,34 @@ static void add_to_known_names(const char *path, static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data) { - struct commit *commit = lookup_commit_reference_gently(sha1, 1); + int might_be_tag = !prefixcmp(path, "refs/tags/"); + struct commit *commit; struct object *object; - int prio; + unsigned char peeled[20]; + int is_tag, prio; - if (!commit) + if (!all && !might_be_tag) return 0; - object = parse_object(sha1); + + if (!peel_ref(path, peeled) && !is_null_sha1(peeled)) { + commit = lookup_commit_reference_gently(peeled, 1); + if (!commit) + return 0; + is_tag = !!hashcmp(sha1, commit->object.sha1); + } else { + commit = lookup_commit_reference_gently(sha1, 1); + object = parse_object(sha1); + if (!commit || !object) + return 0; + is_tag = object->type == OBJ_TAG; + } + /* If --all, then any refs are used. * If --tags, then any tags are used. * Otherwise only annotated tags are used. */ - if (!prefixcmp(path, "refs/tags/")) { - if (object->type == OBJ_TAG) { + if (might_be_tag) { + if (is_tag) { prio = 2; if (pattern && fnmatch(pattern, path + 10, 0)) prio = 0; @@ -159,6 +174,8 @@ static void describe(const char *arg, int last_one) return; } + if (!max_candidates) + die("no tag exactly matches '%s'", sha1_to_hex(cmit->object.sha1)); if (debug) fprintf(stderr, "searching to describe %s\n", arg); @@ -255,6 +272,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix) OPT_BOOLEAN(0, "all", &all, "use any ref in .git/refs"), OPT_BOOLEAN(0, "tags", &tags, "use any tag in .git/refs/tags"), OPT__ABBREV(&abbrev), + OPT_SET_INT(0, "exact-match", &max_candidates, + "only output exact matches", 0), OPT_INTEGER(0, "candidates", &max_candidates, "consider <n> most recent tags (default: 10)"), OPT_STRING(0, "match", &pattern, "pattern", @@ -263,8 +282,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix) }; argc = parse_options(argc, argv, options, describe_usage, 0); - if (max_candidates < 1) - max_candidates = 1; + if (max_candidates < 0) + max_candidates = 0; else if (max_candidates > MAX_TAGS) max_candidates = MAX_TAGS; diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 4ea727b143..8722a68795 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -91,7 +91,10 @@ __git_ps1 () fi if ! b="$(git symbolic-ref HEAD 2>/dev/null)" then - b="$(cut -c1-7 $g/HEAD)..." + if ! b="$(git describe --exact-match HEAD 2>/dev/null)" + then + b="$(cut -c1-7 $g/HEAD)..." + fi fi fi @@ -157,6 +157,7 @@ static struct cached_refs { struct ref_list *loose; struct ref_list *packed; } cached_refs; +static struct ref_list *current_ref; static void free_ref_list(struct ref_list *list) { @@ -476,6 +477,7 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim, error("%s does not point to a valid object!", entry->name); return 0; } + current_ref = entry; return fn(entry->name + trim, entry->sha1, entry->flag, cb_data); } @@ -485,6 +487,16 @@ int peel_ref(const char *ref, unsigned char *sha1) unsigned char base[20]; struct object *o; + if (current_ref && (current_ref->name == ref + || !strcmp(current_ref->name, ref))) { + if (current_ref->flag & REF_KNOWS_PEELED) { + hashcpy(sha1, current_ref->peeled); + return 0; + } + hashcpy(base, current_ref->sha1); + goto fallback; + } + if (!resolve_ref(ref, base, 1, &flag)) return -1; @@ -504,7 +516,7 @@ int peel_ref(const char *ref, unsigned char *sha1) } } - /* fallback - callers should not call this for unpacked refs */ +fallback: o = parse_object(base); if (o && o->type == OBJ_TAG) { o = deref_tag(o, ref, 0); @@ -519,7 +531,7 @@ int peel_ref(const char *ref, unsigned char *sha1) static int do_for_each_ref(const char *base, each_ref_fn fn, int trim, void *cb_data) { - int retval; + int retval = 0; struct ref_list *packed = get_packed_refs(); struct ref_list *loose = get_loose_refs(); @@ -539,15 +551,18 @@ static int do_for_each_ref(const char *base, each_ref_fn fn, int trim, } retval = do_one_ref(base, fn, trim, cb_data, entry); if (retval) - return retval; + goto end_each; } for (packed = packed ? packed : loose; packed; packed = packed->next) { retval = do_one_ref(base, fn, trim, cb_data, packed); if (retval) - return retval; + goto end_each; } - return 0; + +end_each: + current_ref = NULL; + return retval; } int head_ref(each_ref_fn fn, void *cb_data) |