Skip to content

Commit 01f9ffb

Browse files
committed
Merge branch 'jk/haves-from-alternate-odb'
* jk/haves-from-alternate-odb: receive-pack: eliminate duplicate .have refs bisect: refactor sha1_array into a generic sha1 list refactor refs_from_alternate_cb to allow passing extra data
2 parents a9930e3 + cff38a5 commit 01f9ffb

File tree

8 files changed

+132
-63
lines changed

8 files changed

+132
-63
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ LIB_H += rerere.h
545545
LIB_H += resolve-undo.h
546546
LIB_H += revision.h
547547
LIB_H += run-command.h
548+
LIB_H += sha1-array.h
548549
LIB_H += sha1-lookup.h
549550
LIB_H += sideband.h
550551
LIB_H += sigchain.h
@@ -647,6 +648,7 @@ LIB_OBJS += revision.o
647648
LIB_OBJS += run-command.o
648649
LIB_OBJS += server-info.o
649650
LIB_OBJS += setup.o
651+
LIB_OBJS += sha1-array.o
650652
LIB_OBJS += sha1-lookup.o
651653
LIB_OBJS += sha1_file.o
652654
LIB_OBJS += sha1_name.o

bisect.c

Lines changed: 15 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@
99
#include "run-command.h"
1010
#include "log-tree.h"
1111
#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"
1913

2014
static struct sha1_array good_revs;
2115
static struct sha1_array skipped_revs;
@@ -425,22 +419,15 @@ static void argv_array_push_sha1(struct argv_array *array,
425419
argv_array_push(array, strbuf_detach(&buf, NULL));
426420
}
427421

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-
435422
static int register_ref(const char *refname, const unsigned char *sha1,
436423
int flags, void *cb_data)
437424
{
438425
if (!strcmp(refname, "bad")) {
439426
current_bad_sha1 = sha1;
440427
} else if (!prefixcmp(refname, "good-")) {
441-
sha1_array_push(&good_revs, sha1);
428+
sha1_array_append(&good_revs, sha1);
442429
} else if (!prefixcmp(refname, "skip-")) {
443-
sha1_array_push(&skipped_revs, sha1);
430+
sha1_array_append(&skipped_revs, sha1);
444431
}
445432

446433
return 0;
@@ -477,41 +464,14 @@ static void read_bisect_paths(struct argv_array *array)
477464
fclose(fp);
478465
}
479466

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-
507467
static char *join_sha1_array_hex(struct sha1_array *array, char delim)
508468
{
509469
struct strbuf joined_hexs = STRBUF_INIT;
510470
int i;
511471

512-
for (i = 0; i < array->sha1_nr; i++) {
472+
for (i = 0; i < array->nr; i++) {
513473
strbuf_addstr(&joined_hexs, sha1_to_hex(array->sha1[i]));
514-
if (i + 1 < array->sha1_nr)
474+
if (i + 1 < array->nr)
515475
strbuf_addch(&joined_hexs, delim);
516476
}
517477

@@ -546,13 +506,13 @@ struct commit_list *filter_skipped(struct commit_list *list,
546506
if (count)
547507
*count = 0;
548508

549-
if (!skipped_revs.sha1_nr)
509+
if (!skipped_revs.nr)
550510
return list;
551511

552512
while (list) {
553513
struct commit_list *next = list->next;
554514
list->next = NULL;
555-
if (0 <= lookup_sha1_array(&skipped_revs,
515+
if (0 <= sha1_array_lookup(&skipped_revs,
556516
list->item->object.sha1)) {
557517
if (skipped_first && !*skipped_first)
558518
*skipped_first = 1;
@@ -647,7 +607,7 @@ static struct commit_list *managed_skipped(struct commit_list *list,
647607

648608
*tried = NULL;
649609

650-
if (!skipped_revs.sha1_nr)
610+
if (!skipped_revs.nr)
651611
return list;
652612

653613
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,
672632
/* rev_argv.argv[0] will be ignored by setup_revisions */
673633
argv_array_push(&rev_argv, xstrdup("bisect_rev_setup"));
674634
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++)
676636
argv_array_push_sha1(&rev_argv, good_revs.sha1[i],
677637
good_format);
678638
argv_array_push(&rev_argv, xstrdup("--"));
@@ -772,12 +732,12 @@ static struct commit *get_commit_reference(const unsigned char *sha1)
772732

773733
static struct commit **get_bad_and_good_commits(int *rev_nr)
774734
{
775-
int len = 1 + good_revs.sha1_nr;
735+
int len = 1 + good_revs.nr;
776736
struct commit **rev = xmalloc(len * sizeof(*rev));
777737
int i, n = 0;
778738

779739
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++)
781741
rev[n++] = get_commit_reference(good_revs.sha1[i]);
782742
*rev_nr = n;
783743

@@ -840,9 +800,9 @@ static void check_merge_bases(void)
840800
const unsigned char *mb = result->item->object.sha1;
841801
if (!hashcmp(mb, current_bad_sha1)) {
842802
handle_bad_merge_base();
843-
} else if (0 <= lookup_sha1_array(&good_revs, mb)) {
803+
} else if (0 <= sha1_array_lookup(&good_revs, mb)) {
844804
continue;
845-
} else if (0 <= lookup_sha1_array(&skipped_revs, mb)) {
805+
} else if (0 <= sha1_array_lookup(&skipped_revs, mb)) {
846806
handle_skipped_merge_base(mb);
847807
} else {
848808
printf("Bisecting: a merge base must be tested\n");
@@ -903,7 +863,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix)
903863
return;
904864

905865
/* Bisecting with no good rev is ok. */
906-
if (good_revs.sha1_nr == 0)
866+
if (good_revs.nr == 0)
907867
return;
908868

909869
/* Check if all good revs are ancestor of the bad rev. */
@@ -968,7 +928,7 @@ int bisect_next_all(const char *prefix)
968928
bisect_common(&revs);
969929

970930
revs.commits = find_bisection(revs.commits, &reaches, &all,
971-
!!skipped_revs.sha1_nr);
931+
!!skipped_revs.nr);
972932
revs.commits = managed_skipped(revs.commits, &tried);
973933

974934
if (!revs.commits) {

builtin/fetch-pack.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ static void insert_one_alternate_ref(const struct ref *ref, void *unused)
226226

227227
static void insert_alternate_refs(void)
228228
{
229-
foreach_alt_odb(refs_from_alternate_cb, insert_one_alternate_ref);
229+
for_each_alternate_ref(insert_one_alternate_ref, NULL);
230230
}
231231

232232
#define INITIAL_FLUSH 16

builtin/receive-pack.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "remote.h"
1111
#include "transport.h"
1212
#include "string-list.h"
13+
#include "sha1-array.h"
1314

1415
static const char receive_pack_usage[] = "git receive-pack <git-dir>";
1516

@@ -731,14 +732,23 @@ static int delete_only(struct command *commands)
731732
return 1;
732733
}
733734

734-
static void add_one_alternate_ref(const struct ref *ref, void *unused)
735+
static void add_one_alternate_sha1(const unsigned char sha1[20], void *unused)
735736
{
736-
add_extra_ref(".have", ref->old_sha1, 0);
737+
add_extra_ref(".have", sha1, 0);
738+
}
739+
740+
static void collect_one_alternate_ref(const struct ref *ref, void *data)
741+
{
742+
struct sha1_array *sa = data;
743+
sha1_array_append(sa, ref->old_sha1);
737744
}
738745

739746
static void add_alternate_refs(void)
740747
{
741-
foreach_alt_odb(refs_from_alternate_cb, add_one_alternate_ref);
748+
struct sha1_array sa = SHA1_ARRAY_INIT;
749+
for_each_alternate_ref(collect_one_alternate_ref, &sa);
750+
sha1_array_for_each_unique(&sa, add_one_alternate_sha1, NULL);
751+
sha1_array_clear(&sa);
742752
}
743753

744754
int cmd_receive_pack(int argc, const char **argv, const char *prefix)

sha1-array.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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+
}
44+
45+
void sha1_array_for_each_unique(struct sha1_array *array,
46+
for_each_sha1_fn fn,
47+
void *data)
48+
{
49+
int i;
50+
51+
if (!array->sorted)
52+
sha1_array_sort(array);
53+
54+
for (i = 0; i < array->nr; i++) {
55+
if (i > 0 && !hashcmp(array->sha1[i], array->sha1[i-1]))
56+
continue;
57+
fn(array->sha1[i], data);
58+
}
59+
}

sha1-array.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
typedef void (*for_each_sha1_fn)(const unsigned char sha1[20],
19+
void *data);
20+
void sha1_array_for_each_unique(struct sha1_array *array,
21+
for_each_sha1_fn fn,
22+
void *data);
23+
24+
#endif /* SHA1_ARRAY_H */

transport.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,14 +1190,20 @@ char *transport_anonymize_url(const char *url)
11901190
return xstrdup(url);
11911191
}
11921192

1193-
int refs_from_alternate_cb(struct alternate_object_database *e, void *cb)
1193+
struct alternate_refs_data {
1194+
alternate_ref_fn *fn;
1195+
void *data;
1196+
};
1197+
1198+
static int refs_from_alternate_cb(struct alternate_object_database *e,
1199+
void *data)
11941200
{
11951201
char *other;
11961202
size_t len;
11971203
struct remote *remote;
11981204
struct transport *transport;
11991205
const struct ref *extra;
1200-
alternate_ref_fn *ref_fn = cb;
1206+
struct alternate_refs_data *cb = data;
12011207

12021208
e->name[-1] = '\0';
12031209
other = xstrdup(real_path(e->base));
@@ -1218,8 +1224,16 @@ int refs_from_alternate_cb(struct alternate_object_database *e, void *cb)
12181224
for (extra = transport_get_remote_refs(transport);
12191225
extra;
12201226
extra = extra->next)
1221-
ref_fn(extra, NULL);
1227+
cb->fn(extra, cb->data);
12221228
transport_disconnect(transport);
12231229
free(other);
12241230
return 0;
12251231
}
1232+
1233+
void for_each_alternate_ref(alternate_ref_fn fn, void *data)
1234+
{
1235+
struct alternate_refs_data cb;
1236+
cb.fn = fn;
1237+
cb.data = data;
1238+
foreach_alt_odb(refs_from_alternate_cb, &cb);
1239+
}

transport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,6 @@ void transport_print_push_status(const char *dest, struct ref *refs,
167167
int verbose, int porcelain, int *nonfastforward);
168168

169169
typedef void alternate_ref_fn(const struct ref *, void *);
170-
extern int refs_from_alternate_cb(struct alternate_object_database *e, void *cb);
170+
extern void for_each_alternate_ref(alternate_ref_fn, void *);
171171

172172
#endif

0 commit comments

Comments
 (0)