bisect: refactor sha1_array into a generic sha1 list
This is a generally useful abstraction, so let's let others make use of it. The refactoring is more or less a straight copy; however, functions and struct members have had their names changed to match string_list, which is the most similar data structure. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
May 19, 2011 at 17:34 UTC
902bb3645160cae72fe43b5f7f5289968ac01617
4 files changed
+78
-55
Makefile
+2
@@ -547,6 +547,7 @@ LIB_H += rerere.h
547
LIB_H += resolve-undo.h
548
LIB_H += revision.h
549
LIB_H += run-command.h
550
+LIB_H += sha1-array.h
551
LIB_H += sha1-lookup.h
552
LIB_H += sideband.h
553
LIB_H += sigchain.h
@@ -649,6 +650,7 @@ LIB_OBJS += revision.o
650
LIB_OBJS += run-command.o
651
LIB_OBJS += server-info.o
652
LIB_OBJS += setup.o
653
+LIB_OBJS += sha1-array.o
654
LIB_OBJS += sha1-lookup.o
655
LIB_OBJS += sha1_file.o
656
LIB_OBJS += sha1_name.o
bisect.c
+15
-55
@@ -9,13 +9,7 @@
9
#include "run-command.h"
10
#include "log-tree.h"
11
#include "bisect.h"
12
-
13
-struct sha1_array {
14
- unsigned char (*sha1)[20];
15
- int sha1_nr;
16
- int sha1_alloc;
17
- int sorted;
18
-};
12
+#include "sha1-array.h"
13
14
static struct sha1_array good_revs;
15
static struct sha1_array skipped_revs;
@@ -425,22 +419,15 @@ static void argv_array_push_sha1(struct argv_array *array,
419
argv_array_push(array, strbuf_detach(&buf, NULL));
420
}
421
428
-static void sha1_array_push(struct sha1_array *array,
429
- const unsigned char *sha1)
430
-{
431
- ALLOC_GROW(array->sha1, array->sha1_nr + 1, array->sha1_alloc);
432
- hashcpy(array->sha1[array->sha1_nr++], sha1);
433
-}
434
-
422
static int register_ref(const char *refname, const unsigned char *sha1,
423
int flags, void *cb_data)
424
{
425
if (!strcmp(refname, "bad")) {
426
current_bad_sha1 = sha1;
427
} else if (!prefixcmp(refname, "good-")) {
441
- sha1_array_push(&good_revs, sha1);
428
+ sha1_array_append(&good_revs, sha1);
429
} else if (!prefixcmp(refname, "skip-")) {
443
- sha1_array_push(&skipped_revs, sha1);
430
+ sha1_array_append(&skipped_revs, sha1);
431
}
432
433
return 0;
@@ -477,41 +464,14 @@ static void read_bisect_paths(struct argv_array *array)
464
fclose(fp);
465
}
466
480
-static int array_cmp(const void *a, const void *b)
481
-{
482
- return hashcmp(a, b);
483
-}
484
-
485
-static void sort_sha1_array(struct sha1_array *array)
486
-{
487
- qsort(array->sha1, array->sha1_nr, sizeof(*array->sha1), array_cmp);
488
-
489
- array->sorted = 1;
490
-}
491
-
492
-static const unsigned char *sha1_access(size_t index, void *table)
493
-{
494
- unsigned char (*array)[20] = table;
495
- return array[index];
496
-}
497
-
498
-static int lookup_sha1_array(struct sha1_array *array,
499
- const unsigned char *sha1)
500
-{
501
- if (!array->sorted)
502
- sort_sha1_array(array);
503
-
504
- return sha1_pos(sha1, array->sha1, array->sha1_nr, sha1_access);
505
-}
506
-
467
static char *join_sha1_array_hex(struct sha1_array *array, char delim)
468
{
469
struct strbuf joined_hexs = STRBUF_INIT;
470
int i;
471
512
- for (i = 0; i < array->sha1_nr; i++) {
472
+ for (i = 0; i < array->nr; i++) {
473
strbuf_addstr(&joined_hexs, sha1_to_hex(array->sha1[i]));
514
- if (i + 1 < array->sha1_nr)
474
+ if (i + 1 < array->nr)
475
strbuf_addch(&joined_hexs, delim);
476
}
477
@@ -546,13 +506,13 @@ struct commit_list *filter_skipped(struct commit_list *list,
506
if (count)
507
*count = 0;
508
549
- if (!skipped_revs.sha1_nr)
509
+ if (!skipped_revs.nr)
510
return list;
511
512
while (list) {
513
struct commit_list *next = list->next;
514
list->next = NULL;
555
- if (0 <= lookup_sha1_array(&skipped_revs,
515
+ if (0 <= sha1_array_lookup(&skipped_revs,
516
list->item->object.sha1)) {
517
if (skipped_first && !*skipped_first)
518
*skipped_first = 1;
@@ -647,7 +607,7 @@ static struct commit_list *managed_skipped(struct commit_list *list,
607
608
*tried = NULL;
609
650
- if (!skipped_revs.sha1_nr)
610
+ if (!skipped_revs.nr)
611
return list;
612
613
list = filter_skipped(list, tried, 0, &count, &skipped_first);
@@ -672,7 +632,7 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
632
/* rev_argv.argv[0] will be ignored by setup_revisions */
633
argv_array_push(&rev_argv, xstrdup("bisect_rev_setup"));
634
argv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format);
675
- for (i = 0; i < good_revs.sha1_nr; i++)
635
+ for (i = 0; i < good_revs.nr; i++)
636
argv_array_push_sha1(&rev_argv, good_revs.sha1[i],
637
good_format);
638
argv_array_push(&rev_argv, xstrdup("--"));
@@ -772,12 +732,12 @@ static struct commit *get_commit_reference(const unsigned char *sha1)
732
733
static struct commit **get_bad_and_good_commits(int *rev_nr)
734
{
775
- int len = 1 + good_revs.sha1_nr;
735
+ int len = 1 + good_revs.nr;
736
struct commit **rev = xmalloc(len * sizeof(*rev));
737
int i, n = 0;
738
739
rev[n++] = get_commit_reference(current_bad_sha1);
780
- for (i = 0; i < good_revs.sha1_nr; i++)
740
+ for (i = 0; i < good_revs.nr; i++)
741
rev[n++] = get_commit_reference(good_revs.sha1[i]);
742
*rev_nr = n;
743
@@ -840,9 +800,9 @@ static void check_merge_bases(void)
800
const unsigned char *mb = result->item->object.sha1;
801
if (!hashcmp(mb, current_bad_sha1)) {
802
handle_bad_merge_base();
843
- } else if (0 <= lookup_sha1_array(&good_revs, mb)) {
803
+ } else if (0 <= sha1_array_lookup(&good_revs, mb)) {
804
continue;
845
- } else if (0 <= lookup_sha1_array(&skipped_revs, mb)) {
805
+ } else if (0 <= sha1_array_lookup(&skipped_revs, mb)) {
806
handle_skipped_merge_base(mb);
807
} else {
808
printf("Bisecting: a merge base must be tested\n");
@@ -903,7 +863,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix)
863
return;
864
865
/* Bisecting with no good rev is ok. */
906
- if (good_revs.sha1_nr == 0)
866
+ if (good_revs.nr == 0)
867
return;
868
869
/* Check if all good revs are ancestor of the bad rev. */
@@ -968,7 +928,7 @@ int bisect_next_all(const char *prefix)
928
bisect_common(&revs);
929
930
revs.commits = find_bisection(revs.commits, &reaches, &all,
971
- !!skipped_revs.sha1_nr);
931
+ !!skipped_revs.nr);
932
revs.commits = managed_skipped(revs.commits, &tried);
933
934
if (!revs.commits) {
sha1-array.c
new
+43
@@ -0,0 +1,43 @@
1
+#include "cache.h"
2
+#include "sha1-array.h"
3
+#include "sha1-lookup.h"
4
+
5
+void sha1_array_append(struct sha1_array *array, const unsigned char *sha1)
6
+{
7
+ ALLOC_GROW(array->sha1, array->nr + 1, array->alloc);
8
+ hashcpy(array->sha1[array->nr++], sha1);
9
+ array->sorted = 0;
10
+}
11
+
12
+static int void_hashcmp(const void *a, const void *b)
13
+{
14
+ return hashcmp(a, b);
15
+}
16
+
17
+void sha1_array_sort(struct sha1_array *array)
18
+{
19
+ qsort(array->sha1, array->nr, sizeof(*array->sha1), void_hashcmp);
20
+ array->sorted = 1;
21
+}
22
+
23
+static const unsigned char *sha1_access(size_t index, void *table)
24
+{
25
+ unsigned char (*array)[20] = table;
26
+ return array[index];
27
+}
28
+
29
+int sha1_array_lookup(struct sha1_array *array, const unsigned char *sha1)
30
+{
31
+ if (!array->sorted)
32
+ sha1_array_sort(array);
33
+ return sha1_pos(sha1, array->sha1, array->nr, sha1_access);
34
+}
35
+
36
+void sha1_array_clear(struct sha1_array *array)
37
+{
38
+ free(array->sha1);
39
+ array->sha1 = NULL;
40
+ array->nr = 0;
41
+ array->alloc = 0;
42
+ array->sorted = 0;
43
+}
sha1-array.h
new
+18
@@ -0,0 +1,18 @@
1
+#ifndef SHA1_ARRAY_H
2
+#define SHA1_ARRAY_H
3
+
4
+struct sha1_array {
5
+ unsigned char (*sha1)[20];
6
+ int nr;
7
+ int alloc;
8
+ int sorted;
9
+};
10
+
11
+#define SHA1_ARRAY_INIT { NULL, 0, 0, 0 }
12
+
13
+void sha1_array_append(struct sha1_array *array, const unsigned char *sha1);
14
+void sha1_array_sort(struct sha1_array *array);
15
+int sha1_array_lookup(struct sha1_array *array, const unsigned char *sha1);
16
+void sha1_array_clear(struct sha1_array *array);
17
+
18
+#endif /* SHA1_ARRAY_H */