Skip to content

Commit

Permalink
reflog --fix-stale: do not check the same trees and commits repeatedly.
Browse files Browse the repository at this point in the history
Since we use the reachability tracking machinery now, we should
keep the already checked trees and commits whose completeness is
known, to avoid checking the same thing over and over again.

Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Junio C Hamano committed Jan 7, 2007
1 parent 1389d9d commit cd1f9c3
Showing 1 changed file with 54 additions and 23 deletions.
77 changes: 54 additions & 23 deletions builtin-reflog.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,35 +34,51 @@ struct expire_reflog_cb {
struct cmd_reflog_expire_cb *cmd;
};

#define INCOMPLETE (1u<<10)
#define STUDYING (1u<<11)

static int tree_is_complete(const unsigned char *sha1)
{
struct tree_desc desc;
void *buf;
char type[20];
struct name_entry entry;
int complete;
struct tree *tree;

buf = read_sha1_file(sha1, type, &desc.size);
if (!buf)
tree = lookup_tree(sha1);
if (!tree)
return 0;
if (tree->object.flags & SEEN)
return 1;
if (tree->object.flags & INCOMPLETE)
return 0;
desc.buf = buf;
while (desc.size) {
const unsigned char *elem;
const char *name;
unsigned mode;

elem = tree_entry_extract(&desc, &name, &mode);
if (!has_sha1_file(elem) ||
(S_ISDIR(mode) && !tree_is_complete(elem))) {
free(buf);

desc.buf = tree->buffer;
desc.size = tree->size;
if (!desc.buf) {
char type[20];
void *data = read_sha1_file(sha1, type, &desc.size);
if (!data) {
tree->object.flags |= INCOMPLETE;
return 0;
}
update_tree_entry(&desc);
desc.buf = data;
tree->buffer = data;
}
free(buf);
return 1;
}
complete = 1;
while (tree_entry(&desc, &entry)) {
if (!has_sha1_file(entry.sha1) ||
(S_ISDIR(entry.mode) && !tree_is_complete(entry.sha1))) {
tree->object.flags |= INCOMPLETE;
complete = 0;
}
}
free(tree->buffer);
tree->buffer = NULL;

#define INCOMPLETE (1u<<10)
#define STUDYING (1u<<11)
if (complete)
tree->object.flags |= SEEN;
return complete;
}

static int commit_is_complete(struct commit *commit)
{
Expand Down Expand Up @@ -112,14 +128,17 @@ static int commit_is_complete(struct commit *commit)
}
}
if (!is_incomplete) {
/* make sure all commits in found have all the
/*
* make sure all commits in "found" array have all the
* necessary objects.
*/
for (i = 0; !is_incomplete && i < found.nr; i++) {
for (i = 0; i < found.nr; i++) {
struct commit *c =
(struct commit *)found.objects[i].item;
if (!tree_is_complete(c->tree->object.sha1))
if (!tree_is_complete(c->tree->object.sha1)) {
is_incomplete = 1;
c->object.flags |= INCOMPLETE;
}
}
if (!is_incomplete) {
/* mark all found commits as complete, iow SEEN */
Expand All @@ -132,6 +151,18 @@ static int commit_is_complete(struct commit *commit)
found.objects[i].item->flags &= ~STUDYING;
if (is_incomplete)
commit->object.flags |= INCOMPLETE;
else {
/*
* If we come here, we have (1) traversed the ancestry chain
* from the "commit" until we reach SEEN commits (which are
* known to be complete), and (2) made sure that the commits
* encountered during the above traversal refer to trees that
* are complete. Which means that we know *all* the commits
* we have seen during this process are complete.
*/
for (i = 0; i < found.nr; i++)
found.objects[i].item->flags |= SEEN;
}
/* free object arrays */
free(study.objects);
free(found.objects);
Expand Down

0 comments on commit cd1f9c3

Please sign in to comment.