Browse Source

rev-list: implement --bisect-all

This is Junio's patch with some stuff to make --bisect-all
compatible with --bisect-vars.

This option makes it possible to see all the potential
bisection points. The best ones are displayed first.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
maint
Christian Couder 17 years ago committed by Junio C Hamano
parent
commit
50e62a8e70
  1. 100
      builtin-rev-list.c
  2. 2
      log-tree.c
  3. 1
      log-tree.h

100
builtin-rev-list.c

@ -9,6 +9,7 @@
#include "revision.h" #include "revision.h"
#include "list-objects.h" #include "list-objects.h"
#include "builtin.h" #include "builtin.h"
#include "log-tree.h"


/* bits #0-15 in revision.h */ /* bits #0-15 in revision.h */


@ -38,7 +39,8 @@ static const char rev_list_usage[] =
" --left-right\n" " --left-right\n"
" special purpose:\n" " special purpose:\n"
" --bisect\n" " --bisect\n"
" --bisect-vars" " --bisect-vars\n"
" --bisect-all"
; ;


static struct rev_info revs; static struct rev_info revs;
@ -74,6 +76,7 @@ static void show_commit(struct commit *commit)
parents = parents->next; parents = parents->next;
} }
} }
show_decorations(commit);
if (revs.commit_format == CMIT_FMT_ONELINE) if (revs.commit_format == CMIT_FMT_ONELINE)
putchar(' '); putchar(' ');
else else
@ -278,6 +281,57 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr)
return best; return best;
} }


struct commit_dist {
struct commit *commit;
int distance;
};

static int compare_commit_dist(const void *a_, const void *b_)
{
struct commit_dist *a, *b;

a = (struct commit_dist *)a_;
b = (struct commit_dist *)b_;
if (a->distance != b->distance)
return b->distance - a->distance; /* desc sort */
return hashcmp(a->commit->object.sha1, b->commit->object.sha1);
}

static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr)
{
struct commit_list *p;
struct commit_dist *array = xcalloc(nr, sizeof(*array));
int cnt, i;

for (p = list, cnt = 0; 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;
array[cnt].commit = p->item;
array[cnt].distance = distance;
cnt++;
}
qsort(array, cnt, sizeof(*array), compare_commit_dist);
for (p = list, i = 0; i < cnt; i++) {
struct name_decoration *r = xmalloc(sizeof(*r) + 100);
struct object *obj = &(array[i].commit->object);

sprintf(r->name, "dist=%d", array[i].distance);
r->next = add_decoration(&name_decoration, obj, r);
p->item = array[i].commit;
p = p->next;
}
if (p)
p->next = NULL;
free(array);
return list;
}

/* /*
* zero or positive weight is the number of interesting commits it can * zero or positive weight is the number of interesting commits it can
* reach, including itself. Especially, weight = 0 means it does not * reach, including itself. Especially, weight = 0 means it does not
@ -292,7 +346,8 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr)
* or positive distance. * or positive distance.
*/ */
static struct commit_list *do_find_bisection(struct commit_list *list, static struct commit_list *do_find_bisection(struct commit_list *list,
int nr, int *weights) int nr, int *weights,
int find_all)
{ {
int n, counted; int n, counted;
struct commit_list *p; struct commit_list *p;
@ -351,7 +406,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
clear_distance(list); clear_distance(list);


/* Does it happen to be at exactly half-way? */ /* Does it happen to be at exactly half-way? */
if (halfway(p, nr)) if (!find_all && halfway(p, nr))
return p; return p;
counted++; counted++;
} }
@ -389,19 +444,22 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
weight_set(p, weight(q)); weight_set(p, weight(q));


/* Does it happen to be at exactly half-way? */ /* Does it happen to be at exactly half-way? */
if (halfway(p, nr)) if (!find_all && halfway(p, nr))
return p; return p;
} }
} }


show_list("bisection 2 counted all", counted, nr, list); show_list("bisection 2 counted all", counted, nr, list);


/* Then find the best one */ if (!find_all)
return best_bisection(list, nr); return best_bisection(list, nr);
else
return best_bisection_sorted(list, nr);
} }


static struct commit_list *find_bisection(struct commit_list *list, static struct commit_list *find_bisection(struct commit_list *list,
int *reaches, int *all) int *reaches, int *all,
int find_all)
{ {
int nr, on_list; int nr, on_list;
struct commit_list *p, *best, *next, *last; struct commit_list *p, *best, *next, *last;
@ -434,14 +492,13 @@ static struct commit_list *find_bisection(struct commit_list *list,
weights = xcalloc(on_list, sizeof(*weights)); weights = xcalloc(on_list, sizeof(*weights));


/* Do the real work of finding bisection commit. */ /* Do the real work of finding bisection commit. */
best = do_find_bisection(list, nr, weights); best = do_find_bisection(list, nr, weights, find_all);

if (best) { if (best) {
best->next = NULL; if (!find_all)
best->next = NULL;
*reaches = weight(best); *reaches = weight(best);
} }
free(weights); free(weights);

return best; return best;
} }


@ -468,6 +525,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
int i; int i;
int read_from_stdin = 0; int read_from_stdin = 0;
int bisect_show_vars = 0; int bisect_show_vars = 0;
int bisect_find_all = 0;


git_config(git_default_config); git_config(git_default_config);
init_revisions(&revs, prefix); init_revisions(&revs, prefix);
@ -490,6 +548,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
bisect_list = 1; bisect_list = 1;
continue; continue;
} }
if (!strcmp(arg, "--bisect-all")) {
bisect_list = 1;
bisect_find_all = 1;
continue;
}
if (!strcmp(arg, "--bisect-vars")) { if (!strcmp(arg, "--bisect-vars")) {
bisect_list = 1; bisect_list = 1;
bisect_show_vars = 1; bisect_show_vars = 1;
@ -536,9 +599,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
if (bisect_list) { if (bisect_list) {
int reaches = reaches, all = all; int reaches = reaches, all = all;


revs.commits = find_bisection(revs.commits, &reaches, &all); revs.commits = find_bisection(revs.commits, &reaches, &all,
bisect_find_all);
if (bisect_show_vars) { if (bisect_show_vars) {
int cnt; int cnt;
char hex[41];
if (!revs.commits) if (!revs.commits)
return 1; return 1;
/* /*
@ -550,15 +615,22 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
* A bisect set of size N has (N-1) commits further * A bisect set of size N has (N-1) commits further
* to test, as we already know one bad one. * to test, as we already know one bad one.
*/ */
cnt = all-reaches; cnt = all - reaches;
if (cnt < reaches) if (cnt < reaches)
cnt = reaches; cnt = reaches;
strcpy(hex, sha1_to_hex(revs.commits->item->object.sha1));

if (bisect_find_all) {
traverse_commit_list(&revs, show_commit, show_object);
printf("------\n");
}

printf("bisect_rev=%s\n" printf("bisect_rev=%s\n"
"bisect_nr=%d\n" "bisect_nr=%d\n"
"bisect_good=%d\n" "bisect_good=%d\n"
"bisect_bad=%d\n" "bisect_bad=%d\n"
"bisect_all=%d\n", "bisect_all=%d\n",
sha1_to_hex(revs.commits->item->object.sha1), hex,
cnt - 1, cnt - 1,
all - reaches - 1, all - reaches - 1,
reaches - 1, reaches - 1,

2
log-tree.c

@ -15,7 +15,7 @@ static void show_parents(struct commit *commit, int abbrev)
} }
} }


static void show_decorations(struct commit *commit) void show_decorations(struct commit *commit)
{ {
const char *prefix; const char *prefix;
struct name_decoration *decoration; struct name_decoration *decoration;

1
log-tree.h

@ -12,5 +12,6 @@ int log_tree_diff_flush(struct rev_info *);
int log_tree_commit(struct rev_info *, struct commit *); int log_tree_commit(struct rev_info *, struct commit *);
int log_tree_opt_parse(struct rev_info *, const char **, int); int log_tree_opt_parse(struct rev_info *, const char **, int);
void show_log(struct rev_info *opt, const char *sep); void show_log(struct rev_info *opt, const char *sep);
void show_decorations(struct commit *commit);


#endif #endif

Loading…
Cancel
Save