summaryrefslogtreecommitdiff
path: root/builtin-rev-list.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2007-09-18 17:42:15 -0700
committerJunio C Hamano <gitster@pobox.com>2007-09-18 17:42:15 -0700
commit39bd2eb56af89d43a08ba54699d9a1849ab57b39 (patch)
tree7551a984921081bf2532f68303febe7275107ed1 /builtin-rev-list.c
parent68d3025a805097ec148ec6e9b0b54a5db1ef138e (diff)
parent89df580d0a2e97b0c7c072d87e5e815534deed56 (diff)
downloadgit-39bd2eb56af89d43a08ba54699d9a1849ab57b39.tar.gz
Merge branch 'master' into ph/strbuf
* master: (94 commits) Fixed update-hook example allow-users format. Documentation/git-svn: updated design philosophy notes t/t4014: test "am -3" with mode-only change. git-commit.sh: Shell script cleanup preserve executable bits in zip archives Fix lapsus in builtin-apply.c git-push: documentation and tests for pushing only branches git-svnimport: Use separate arguments in the pipe for git-rev-parse contrib/fast-import: add perl version of simple example contrib/fast-import: add simple shell example rev-list --bisect: Bisection "distance" clean up. rev-list --bisect: Move some bisection code into best_bisection. rev-list --bisect: Move finding bisection into do_find_bisection. Document ls-files --with-tree=<tree-ish> git-commit: partial commit of paths only removed from the index git-commit: Allow partial commit of file removal. send-email: make message-id generation a bit more robust git-apply: fix whitespace stripping git-gui: Disable native platform text selection in "lists" apply --index-info: fall back to current index for mode changes ...
Diffstat (limited to 'builtin-rev-list.c')
-rw-r--r--builtin-rev-list.c133
1 files changed, 72 insertions, 61 deletions
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 4fd4b6bec1..43b88fae29 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -188,7 +188,7 @@ static int count_interesting_parents(struct commit *commit)
return count;
}
-static inline int halfway(struct commit_list *p, int distance, int nr)
+static inline int halfway(struct commit_list *p, int nr)
{
/*
* Don't short-cut something we are not going to return!
@@ -201,8 +201,7 @@ static inline int halfway(struct commit_list *p, int distance, int nr)
* 2 and 3 are halfway of 5.
* 3 is halfway of 6 but 2 and 4 are not.
*/
- distance *= 2;
- switch (distance - nr) {
+ switch (2 * weight(p) - nr) {
case -1: case 0: case 1:
return 1;
default:
@@ -254,6 +253,30 @@ static void show_list(const char *debug, int counted, int nr,
}
#endif /* DEBUG_BISECT */
+static struct commit_list *best_bisection(struct commit_list *list, int nr)
+{
+ struct commit_list *p, *best;
+ int best_distance = -1;
+
+ best = list;
+ for (p = list; p; p = p->next) {
+ int distance;
+ unsigned flags = p->item->object.flags;
+
+ if (revs.prune_fn && !(flags & TREECHANGE))
+ continue;
+ distance = weight(p);
+ if (nr - distance < distance)
+ distance = nr - distance;
+ if (distance > best_distance) {
+ best = p;
+ best_distance = distance;
+ }
+ }
+
+ return best;
+}
+
/*
* zero or positive weight is the number of interesting commits it can
* reach, including itself. Especially, weight = 0 means it does not
@@ -267,39 +290,12 @@ static void show_list(const char *debug, int counted, int nr,
* unknown. After running count_distance() first, they will get zero
* or positive distance.
*/
-
-static struct commit_list *find_bisection(struct commit_list *list,
- int *reaches, int *all)
+static struct commit_list *do_find_bisection(struct commit_list *list,
+ int nr, int *weights)
{
- int n, nr, on_list, counted, distance;
- struct commit_list *p, *best, *next, *last;
- int *weights;
-
- show_list("bisection 2 entry", 0, 0, list);
-
- /*
- * Count the number of total and tree-changing items on the
- * list, while reversing the list.
- */
- for (nr = on_list = 0, last = NULL, p = list;
- p;
- p = next) {
- unsigned flags = p->item->object.flags;
-
- next = p->next;
- if (flags & UNINTERESTING)
- continue;
- p->next = last;
- last = p;
- if (!revs.prune_fn || (flags & TREECHANGE))
- nr++;
- on_list++;
- }
- list = last;
- show_list("bisection 2 sorted", 0, nr, list);
+ int n, counted;
+ struct commit_list *p;
- *all = nr;
- weights = xcalloc(on_list, sizeof(*weights));
counted = 0;
for (n = 0, p = list; p; p = p->next) {
@@ -348,20 +344,14 @@ static struct commit_list *find_bisection(struct commit_list *list,
for (p = list; p; p = p->next) {
if (p->item->object.flags & UNINTERESTING)
continue;
- n = weight(p);
- if (n != -2)
+ if (weight(p) != -2)
continue;
- distance = count_distance(p);
+ weight_set(p, count_distance(p));
clear_distance(list);
- weight_set(p, distance);
/* Does it happen to be at exactly half-way? */
- if (halfway(p, distance, nr)) {
- p->next = NULL;
- *reaches = distance;
- free(weights);
+ if (halfway(p, nr))
return p;
- }
counted++;
}
@@ -398,38 +388,59 @@ static struct commit_list *find_bisection(struct commit_list *list,
weight_set(p, weight(q));
/* Does it happen to be at exactly half-way? */
- distance = weight(p);
- if (halfway(p, distance, nr)) {
- p->next = NULL;
- *reaches = distance;
- free(weights);
+ if (halfway(p, nr))
return p;
- }
}
}
show_list("bisection 2 counted all", counted, nr, list);
/* Then find the best one */
- counted = -1;
- best = list;
- for (p = list; p; p = p->next) {
+ return best_bisection(list, nr);
+}
+
+static struct commit_list *find_bisection(struct commit_list *list,
+ int *reaches, int *all)
+{
+ int nr, on_list;
+ struct commit_list *p, *best, *next, *last;
+ int *weights;
+
+ show_list("bisection 2 entry", 0, 0, list);
+
+ /*
+ * Count the number of total and tree-changing items on the
+ * list, while reversing the list.
+ */
+ for (nr = on_list = 0, last = NULL, p = list;
+ p;
+ p = next) {
unsigned flags = p->item->object.flags;
- if (revs.prune_fn && !(flags & TREECHANGE))
+ next = p->next;
+ if (flags & UNINTERESTING)
continue;
- distance = weight(p);
- if (nr - distance < distance)
- distance = nr - distance;
- if (distance > counted) {
- best = p;
- counted = distance;
- *reaches = weight(p);
- }
+ p->next = last;
+ last = p;
+ if (!revs.prune_fn || (flags & TREECHANGE))
+ nr++;
+ on_list++;
}
+ list = last;
+ show_list("bisection 2 sorted", 0, nr, list);
+
+ *all = nr;
+ weights = xcalloc(on_list, sizeof(*weights));
+
+ /* Do the real work of finding bisection commit. */
+ best = do_find_bisection(list, nr, weights);
+
if (best)
best->next = NULL;
+
+ *reaches = weight(best);
free(weights);
+
return best;
}