summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-31 01:46:32 (GMT)
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-31 01:46:32 (GMT)
commit8906300f65a3b0c3e061af9d2c7ba48fedfa26a4 (patch)
tree086cf50471d8b222b5b4a5a4ba90f7f99400db1a
parentac5155ef59a686f02e984d449476208ffe33b66d (diff)
downloadgit-8906300f65a3b0c3e061af9d2c7ba48fedfa26a4.zip
git-8906300f65a3b0c3e061af9d2c7ba48fedfa26a4.tar.gz
git-8906300f65a3b0c3e061af9d2c7ba48fedfa26a4.tar.bz2
git-rev-list: use proper lazy reachability analysis
This mean sthat you can give a beginning/end pair to git-rev-list, and it will show all entries that are reachable from the beginning but not the end. For example git-rev-list v2.6.12-rc5 v2.6.12-rc4 shows all commits that are in -rc5 but are not in -rc4.
-rw-r--r--rev-list.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/rev-list.c b/rev-list.c
index 93bee19..cb1de39 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -1,6 +1,10 @@
#include "cache.h"
#include "commit.h"
+#define SEEN (1u << 0)
+#define INTERESTING (1u << 1)
+#define UNINTERESTING (1u << 2)
+
static const char rev_list_usage[] =
"usage: git-rev-list [OPTION] commit-id <commit-id>\n"
" --max-count=nr\n"
@@ -8,6 +12,29 @@ static const char rev_list_usage[] =
" --min-age=epoch\n"
" --header";
+static void mark_parents_uninteresting(struct commit *commit)
+{
+ struct commit_list *parents = commit->parents;
+
+ while (parents) {
+ struct commit *commit = parents->item;
+ commit->object.flags |= UNINTERESTING;
+ parents = parents->next;
+ }
+}
+
+static int everybody_uninteresting(struct commit_list *list)
+{
+ while (list) {
+ struct commit *commit = list->item;
+ list = list->next;
+ if (commit->object.flags & UNINTERESTING)
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
int main(int argc, char **argv)
{
int nr_sha;
@@ -60,11 +87,29 @@ int main(int argc, char **argv)
}
commit_list_insert(commit, &list);
- do {
- struct commit *commit = pop_most_recent_commit(&list, 0x1);
+ if (end) {
+ struct commit_list *newlist = NULL;
+ struct commit_list **p = &newlist;
+ do {
+ struct commit *commit = pop_most_recent_commit(&list, SEEN);
+ struct object *obj = &commit->object;
- if (commit == end)
- break;
+ if (commit == end || (obj->flags & UNINTERESTING)) {
+ mark_parents_uninteresting(commit);
+ if (everybody_uninteresting(list))
+ break;
+ continue;
+ }
+ p = &commit_list_insert(commit, p)->next;
+ } while (list);
+ list = newlist;
+ }
+
+ while (list) {
+ struct commit *commit = pop_most_recent_commit(&list, SEEN);
+
+ if (commit->object.flags & UNINTERESTING)
+ continue;
if (min_age != -1 && (commit->date > min_age))
continue;
if (max_age != -1 && (commit->date < max_age))
@@ -74,6 +119,6 @@ int main(int argc, char **argv)
printf("%s\n", sha1_to_hex(commit->object.sha1));
if (verbose_header)
printf("%s%c", commit->buffer, 0);
- } while (list);
+ }
return 0;
}