summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-07-23 17:01:49 (GMT)
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-23 17:01:49 (GMT)
commit4311d328fee11fbd80862e3c5de06a26a0e80046 (patch)
tree0c6727da4f1a0ab0d81beba8348235029da6601f
parenta692b9656a7975b933fde40cdd6319f9ca898a29 (diff)
downloadgit-4311d328fee11fbd80862e3c5de06a26a0e80046.zip
git-4311d328fee11fbd80862e3c5de06a26a0e80046.tar.gz
git-4311d328fee11fbd80862e3c5de06a26a0e80046.tar.bz2
Be more aggressive about marking trees uninteresting
We'll mark all the trees at the edges (as deep as we had to go to realize that we have all the commits needed) as uninteresting. Otherwise we'll occasionally list a lot of objects that were actually available at the edge in a commit that we just never ended up parsing because we could determine early that we had all relevant commits. NOTE! The object listing is still just a _heuristic_. It's guaranteed to list a superset of the actual new objects, but there might be the occasional old object in the list, just because the commit that referenced it was much further back in the history. For example, let's say that a recent commit is a revert of part of the tree to much older state: since we didn't walk _that_ far back in the commit history tree to list the commits necessary, git-rev-tree will never have marked the old objects uninteresting, and we'll end up listing them as "new". That's ok.
-rw-r--r--rev-list.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/rev-list.c b/rev-list.c
index fdb531c..46a35d3 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -241,8 +241,9 @@ static void mark_parents_uninteresting(struct commit *commit)
}
}
-static int everybody_uninteresting(struct commit_list *list)
+static int everybody_uninteresting(struct commit_list *orig)
{
+ struct commit_list *list = orig;
while (list) {
struct commit *commit = list->item;
list = list->next;
@@ -250,6 +251,29 @@ static int everybody_uninteresting(struct commit_list *list)
continue;
return 0;
}
+
+ /*
+ * Ok, go back and mark all the edge trees uninteresting,
+ * since otherwise we can have situations where a parent
+ * that was marked uninteresting (and we never even had
+ * to look at) had lots of objects that we don't want to
+ * include.
+ *
+ * NOTE! This still doesn't mean that the object list is
+ * "correct", since we may end up listing objects that
+ * even older commits (that we don't list) do actually
+ * reference, but it gets us to a minimal list (or very
+ * close) in practice.
+ */
+ if (!tree_objects)
+ return 1;
+
+ while (orig) {
+ struct commit *commit = orig->item;
+ if (!parse_commit(commit) && commit->tree)
+ mark_tree_uninteresting(commit->tree);
+ orig = orig->next;
+ }
return 1;
}