Merge branch 'jk/tag-contains-ab' (early part) into next

* 'jk/tag-contains-ab' (early part):
  default core.clockskew variable to one day
  limit "contains" traversals based on commit timestamp
  tag: speed up --contains calculation
This commit is contained in:
Junio C Hamano
2011-07-05 15:47:37 -07:00

View File

@@ -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>]",
@@ -23,6 +25,8 @@ static const char * const git_tag_usage[] = {
static char signingkey[1000];
static int core_clock_skew = 86400;
struct tag_filter {
const char **patterns;
int lines;
@@ -40,6 +44,68 @@ 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,
unsigned long cutoff)
{
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;
/* stop searching if we go too far back in time */
if (candidate->date < cutoff)
return 0;
/* Otherwise recurse and mark ourselves for future traversals. */
for (p = candidate->parents; p; p = p->next) {
if (contains_recurse(p->item, want, cutoff)) {
candidate->object.flags |= TMP_MARK;
return 1;
}
}
candidate->object.flags |= UNINTERESTING;
return 0;
}
static int contains(struct commit *candidate, const struct commit_list *want)
{
unsigned long cutoff = 0;
if (core_clock_skew >= 0) {
const struct commit_list *c;
unsigned long min_date = ULONG_MAX;
for (c = want; c; c = c->next) {
if (parse_commit(c->item) < 0)
continue;
if (c->item->date < min_date)
min_date = c->item->date;
}
if (min_date > core_clock_skew)
cutoff = min_date - core_clock_skew;
}
return contains_recurse(candidate, want, cutoff);
}
static int show_reference(const char *refname, const unsigned char *sha1,
int flag, void *cb_data)
{
@@ -58,7 +124,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;
}
@@ -241,6 +307,14 @@ static int git_tag_config(const char *var, const char *value, void *cb)
return 0;
}
if (!strcmp(var, "core.clockskew")) {
if (!value || !strcmp(value, "none"))
core_clock_skew = -1;
else
core_clock_skew = git_config_int(var, value);
return 0;
}
return git_default_config(var, value, cb);
}