summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2011-09-12 04:54:32 (GMT)
committerJunio C Hamano <gitster@pobox.com>2011-09-12 04:54:32 (GMT)
commitfcfc2d587962ed307b378074387ad7f472874bda (patch)
treed1bb3edbe2cfd31e417988fb5c6367a8fd8b2338
parent908bb1a9b7765d78b92144bc3a2b585836164376 (diff)
parentffc4b8012d9a4f92ef238ff72c0d15e9e1b402ed (diff)
downloadgit-fcfc2d587962ed307b378074387ad7f472874bda.zip
git-fcfc2d587962ed307b378074387ad7f472874bda.tar.gz
git-fcfc2d587962ed307b378074387ad7f472874bda.tar.bz2
Merge branch 'jk/tag-contains-ab' (early part) into maint
* 'jk/tag-contains-ab' (early part): tag: speed up --contains calculation
-rw-r--r--builtin/tag.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/builtin/tag.c b/builtin/tag.c
index cef2726..667515e 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -12,6 +12,8 @@
#include "tag.h"
#include "run-command.h"
#include "parse-options.h"
+#include "diff.h"
+#include "revision.h"
static const char * const git_tag_usage[] = {
"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
@@ -40,6 +42,48 @@ static int match_pattern(const char **patterns, const char *ref)
return 0;
}
+static int in_commit_list(const struct commit_list *want, struct commit *c)
+{
+ for (; want; want = want->next)
+ if (!hashcmp(want->item->object.sha1, c->object.sha1))
+ return 1;
+ return 0;
+}
+
+static int contains_recurse(struct commit *candidate,
+ const struct commit_list *want)
+{
+ struct commit_list *p;
+
+ /* was it previously marked as containing a want commit? */
+ if (candidate->object.flags & TMP_MARK)
+ return 1;
+ /* or marked as not possibly containing a want commit? */
+ if (candidate->object.flags & UNINTERESTING)
+ return 0;
+ /* or are we it? */
+ if (in_commit_list(want, candidate))
+ return 1;
+
+ if (parse_commit(candidate) < 0)
+ return 0;
+
+ /* Otherwise recurse and mark ourselves for future traversals. */
+ for (p = candidate->parents; p; p = p->next) {
+ if (contains_recurse(p->item, want)) {
+ candidate->object.flags |= TMP_MARK;
+ return 1;
+ }
+ }
+ candidate->object.flags |= UNINTERESTING;
+ return 0;
+}
+
+static int contains(struct commit *candidate, const struct commit_list *want)
+{
+ return contains_recurse(candidate, want);
+}
+
static int show_reference(const char *refname, const unsigned char *sha1,
int flag, void *cb_data)
{
@@ -58,7 +102,7 @@ static int show_reference(const char *refname, const unsigned char *sha1,
commit = lookup_commit_reference_gently(sha1, 1);
if (!commit)
return 0;
- if (!is_descendant_of(commit, filter->with_commit))
+ if (!contains(commit, filter->with_commit))
return 0;
}