fetch-pack: introduce negotiator API
Introduce the new files fetch-negotiator.{h,c}, which contains an API behind which the details of negotiation are abstracted. Currently, only one algorithm is available: the existing one. This patch is written to be easily reviewed: static functions are moved verbatim from fetch-pack.c to negotiator/default.c, and it can be seen that the lines replaced by negotiator->X() calls are present in the X() functions respectively. Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jonathan Tan committed
Jun 14, 2018 at 15:54 UTC
ec06283844a90c3e9440286401e9ad7d86daa5ae
7 files changed
+292
-167
Makefile
+2
@@ -859,6 +859,7 @@ LIB_OBJS += ewah/ewah_bitmap.o
859
LIB_OBJS += ewah/ewah_io.o
860
LIB_OBJS += ewah/ewah_rlw.o
861
LIB_OBJS += exec-cmd.o
862
+LIB_OBJS += fetch-negotiator.o
863
LIB_OBJS += fetch-object.o
864
LIB_OBJS += fetch-pack.o
865
LIB_OBJS += fsck.o
@@ -891,6 +892,7 @@ LIB_OBJS += merge-blobs.o
892
LIB_OBJS += merge-recursive.o
893
LIB_OBJS += mergesort.o
894
LIB_OBJS += name-hash.o
895
+LIB_OBJS += negotiator/default.o
896
LIB_OBJS += notes.o
897
LIB_OBJS += notes-cache.o
898
LIB_OBJS += notes-merge.o
fetch-negotiator.c
new
+8
@@ -0,0 +1,8 @@
1
+#include "git-compat-util.h"
2
+#include "fetch-negotiator.h"
3
+#include "negotiator/default.h"
4
+
5
+void fetch_negotiator_init(struct fetch_negotiator *negotiator)
6
+{
7
+ default_negotiator_init(negotiator);
8
+}
fetch-negotiator.h
new
+57
@@ -0,0 +1,57 @@
1
+#ifndef FETCH_NEGOTIATOR
2
+#define FETCH_NEGOTIATOR
3
+
4
+struct commit;
5
+
6
+/*
7
+ * An object that supplies the information needed to negotiate the contents of
8
+ * the to-be-sent packfile during a fetch.
9
+ *
10
+ * To set up the negotiator, call fetch_negotiator_init(), then known_common()
11
+ * (0 or more times), then add_tip() (0 or more times).
12
+ *
13
+ * Then, when "have" lines are required, call next(). Call ack() to report what
14
+ * the server tells us.
15
+ *
16
+ * Once negotiation is done, call release(). The negotiator then cannot be used
17
+ * (unless reinitialized with fetch_negotiator_init()).
18
+ */
19
+struct fetch_negotiator {
20
+ /*
21
+ * Before negotiation starts, indicate that the server is known to have
22
+ * this commit.
23
+ */
24
+ void (*known_common)(struct fetch_negotiator *, struct commit *);
25
+
26
+ /*
27
+ * Once this function is invoked, known_common() cannot be invoked any
28
+ * more.
29
+ *
30
+ * Indicate that this commit and all its ancestors are to be checked
31
+ * for commonality with the server.
32
+ */
33
+ void (*add_tip)(struct fetch_negotiator *, struct commit *);
34
+
35
+ /*
36
+ * Once this function is invoked, known_common() and add_tip() cannot
37
+ * be invoked any more.
38
+ *
39
+ * Return the next commit that the client should send as a "have" line.
40
+ */
41
+ const struct object_id *(*next)(struct fetch_negotiator *);
42
+
43
+ /*
44
+ * Inform the negotiator that the server has the given commit. This
45
+ * method must only be called on commits returned by next().
46
+ */
47
+ int (*ack)(struct fetch_negotiator *, struct commit *);
48
+
49
+ void (*release)(struct fetch_negotiator *);
50
+
51
+ /* internal use */
52
+ void *data;
53
+};
54
+
55
+void fetch_negotiator_init(struct fetch_negotiator *negotiator);
56
+
57
+#endif
fetch-pack.c
+39
-166
@@ -15,10 +15,10 @@
15
#include "connect.h"
16
#include "transport.h"
17
#include "version.h"
18
-#include "prio-queue.h"
18
#include "sha1-array.h"
19
#include "oidset.h"
20
#include "packfile.h"
21
+#include "fetch-negotiator.h"
22
23
static int transfer_unpack_limit = -1;
24
static int fetch_unpack_limit = -1;
@@ -36,13 +36,7 @@ static const char *alternate_shallow_file;
36
37
/* Remember to update object flag allocation in object.h */
38
#define COMPLETE (1U << 0)
39
-#define COMMON (1U << 1)
40
-#define COMMON_REF (1U << 2)
41
-#define SEEN (1U << 3)
42
-#define POPPED (1U << 4)
43
-#define ALTERNATE (1U << 5)
44
-
45
-static int marked;
39
+#define ALTERNATE (1U << 1)
40
41
/*
42
* After sending this many "have"s if we do not get any new ACK , we
@@ -50,11 +44,6 @@ static int marked;
44
*/
45
#define MAX_IN_VAIN 256
46
53
-struct negotiation_state {
54
- struct prio_queue rev_list;
55
- int non_common_revs;
56
-};
57
-
47
static int multi_ack, use_sideband;
48
/* Allow specifying sha1 if it is a ref tip. */
49
#define ALLOW_TIP_SHA1 01
@@ -97,8 +86,8 @@ static void cache_one_alternate(const char *refname,
86
cache->items[cache->nr++] = obj;
87
}
88
100
-static void for_each_cached_alternate(struct negotiation_state *ns,
101
- void (*cb)(struct negotiation_state *,
89
+static void for_each_cached_alternate(struct fetch_negotiator *negotiator,
90
+ void (*cb)(struct fetch_negotiator *,
91
struct object *))
92
{
93
static int initialized;
@@ -111,33 +100,17 @@ static void for_each_cached_alternate(struct negotiation_state *ns,
100
}
101
102
for (i = 0; i < cache.nr; i++)
114
- cb(ns, cache.items[i]);
115
-}
116
-
117
-static void rev_list_push(struct negotiation_state *ns,
118
- struct commit *commit, int mark)
119
-{
120
- if (!(commit->object.flags & mark)) {
121
- commit->object.flags |= mark;
122
-
123
- if (parse_commit(commit))
124
- return;
125
-
126
- prio_queue_put(&ns->rev_list, commit);
127
-
128
- if (!(commit->object.flags & COMMON))
129
- ns->non_common_revs++;
130
- }
103
+ cb(negotiator, cache.items[i]);
104
}
105
133
-static int rev_list_insert_ref(struct negotiation_state *ns,
106
+static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
107
const char *refname,
108
const struct object_id *oid)
109
{
110
struct object *o = deref_tag(parse_object(oid), refname, 0);
111
112
if (o && o->type == OBJ_COMMIT)
140
- rev_list_push(ns, (struct commit *)o, SEEN);
113
+ negotiator->add_tip(negotiator, (struct commit *)o);
114
115
return 0;
116
}
@@ -148,98 +121,6 @@ static int rev_list_insert_ref_oid(const char *refname, const struct object_id *
121
return rev_list_insert_ref(cb_data, refname, oid);
122
}
123
151
-static int clear_marks(const char *refname, const struct object_id *oid,
152
- int flag, void *cb_data)
153
-{
154
- struct object *o = deref_tag(parse_object(oid), refname, 0);
155
-
156
- if (o && o->type == OBJ_COMMIT)
157
- clear_commit_marks((struct commit *)o,
158
- COMMON | COMMON_REF | SEEN | POPPED);
159
- return 0;
160
-}
161
-
162
-/*
163
- This function marks a rev and its ancestors as common.
164
- In some cases, it is desirable to mark only the ancestors (for example
165
- when only the server does not yet know that they are common).
166
-*/
167
-
168
-static void mark_common(struct negotiation_state *ns, struct commit *commit,
169
- int ancestors_only, int dont_parse)
170
-{
171
- if (commit != NULL && !(commit->object.flags & COMMON)) {
172
- struct object *o = (struct object *)commit;
173
-
174
- if (!ancestors_only)
175
- o->flags |= COMMON;
176
-
177
- if (!(o->flags & SEEN))
178
- rev_list_push(ns, commit, SEEN);
179
- else {
180
- struct commit_list *parents;
181
-
182
- if (!ancestors_only && !(o->flags & POPPED))
183
- ns->non_common_revs--;
184
- if (!o->parsed && !dont_parse)
185
- if (parse_commit(commit))
186
- return;
187
-
188
- for (parents = commit->parents;
189
- parents;
190
- parents = parents->next)
191
- mark_common(ns, parents->item, 0,
192
- dont_parse);
193
- }
194
- }
195
-}
196
-
197
-/*
198
- Get the next rev to send, ignoring the common.
199
-*/
200
-
201
-static const struct object_id *get_rev(struct negotiation_state *ns)
202
-{
203
- struct commit *commit = NULL;
204
-
205
- while (commit == NULL) {
206
- unsigned int mark;
207
- struct commit_list *parents;
208
-
209
- if (ns->rev_list.nr == 0 || ns->non_common_revs == 0)
210
- return NULL;
211
-
212
- commit = prio_queue_get(&ns->rev_list);
213
- parse_commit(commit);
214
- parents = commit->parents;
215
-
216
- commit->object.flags |= POPPED;
217
- if (!(commit->object.flags & COMMON))
218
- ns->non_common_revs--;
219
-
220
- if (commit->object.flags & COMMON) {
221
- /* do not send "have", and ignore ancestors */
222
- commit = NULL;
223
- mark = COMMON | SEEN;
224
- } else if (commit->object.flags & COMMON_REF)
225
- /* send "have", and ignore ancestors */
226
- mark = COMMON | SEEN;
227
- else
228
- /* send "have", also for its ancestors */
229
- mark = SEEN;
230
-
231
- while (parents) {
232
- if (!(parents->item->object.flags & SEEN))
233
- rev_list_push(ns, parents->item, mark);
234
- if (mark & COMMON)
235
- mark_common(ns, parents->item, 1, 0);
236
- parents = parents->next;
237
- }
238
- }
239
-
240
- return &commit->object.oid;
241
-}
242
-
124
enum ack_type {
125
NAK = 0,
126
ACK,
@@ -306,10 +187,10 @@ static void send_request(struct fetch_pack_args *args,
187
write_or_die(fd, buf->buf, buf->len);
188
}
189
309
-static void insert_one_alternate_object(struct negotiation_state *ns,
190
+static void insert_one_alternate_object(struct fetch_negotiator *negotiator,
191
struct object *obj)
192
{
312
- rev_list_insert_ref(ns, NULL, &obj->oid);
193
+ rev_list_insert_ref(negotiator, NULL, &obj->oid);
194
}
195
196
#define INITIAL_FLUSH 16
@@ -332,7 +213,7 @@ static int next_flush(int stateless_rpc, int count)
213
return count;
214
}
215
335
-static int find_common(struct negotiation_state *ns,
216
+static int find_common(struct fetch_negotiator *negotiator,
217
struct fetch_pack_args *args,
218
int fd[2], struct object_id *result_oid,
219
struct ref *refs)
@@ -349,8 +230,8 @@ static int find_common(struct negotiation_state *ns,
230
if (args->stateless_rpc && multi_ack == 1)
231
die(_("--stateless-rpc requires multi_ack_detailed"));
232
352
- for_each_ref(rev_list_insert_ref_oid, ns);
353
- for_each_cached_alternate(ns, insert_one_alternate_object);
233
+ for_each_ref(rev_list_insert_ref_oid, negotiator);
234
+ for_each_cached_alternate(negotiator, insert_one_alternate_object);
235
236
fetching = 0;
237
for ( ; refs ; refs = refs->next) {
@@ -468,7 +349,7 @@ static int find_common(struct negotiation_state *ns,
349
retval = -1;
350
if (args->no_dependents)
351
goto done;
471
- while ((oid = get_rev(ns))) {
352
+ while ((oid = negotiator->next(negotiator))) {
353
packet_buf_write(&req_buf, "have %s\n", oid_to_hex(oid));
354
print_verbose(args, "have %s", oid_to_hex(oid));
355
in_vain++;
@@ -508,8 +389,7 @@ static int find_common(struct negotiation_state *ns,
389
int was_common;
390
if (!commit)
391
die(_("invalid commit %s"), oid_to_hex(result_oid));
511
- was_common = commit->object.flags & COMMON;
512
- mark_common(ns, commit, 0, 1);
392
+ was_common = negotiator->ack(negotiator, commit);
393
if (args->stateless_rpc
394
&& ack == ACK_common
395
&& !was_common) {
@@ -718,7 +598,7 @@ static void filter_refs(struct fetch_pack_args *args,
598
*refs = newlist;
599
}
600
721
-static void mark_alternate_complete(struct negotiation_state *unused,
601
+static void mark_alternate_complete(struct fetch_negotiator *unused,
602
struct object *obj)
603
{
604
mark_complete(&obj->oid);
@@ -756,7 +636,7 @@ static int add_loose_objects_to_set(const struct object_id *oid,
636
* earliest commit time of the objects in refs that are commits and that we know
637
* the commit time of.
638
*/
759
-static void mark_complete_and_common_ref(struct negotiation_state *ns,
639
+static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
640
struct fetch_pack_args *args,
641
struct ref **refs)
642
{
@@ -825,12 +705,8 @@ static void mark_complete_and_common_ref(struct negotiation_state *ns,
705
if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
706
continue;
707
828
- if (!(o->flags & SEEN)) {
829
- rev_list_push(ns, (struct commit *)o,
830
- COMMON_REF | SEEN);
831
-
832
- mark_common(ns, (struct commit *)o, 1, 1);
833
- }
708
+ negotiator->known_common(negotiator,
709
+ (struct commit *)o);
710
}
711
}
712
@@ -1012,7 +888,8 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
888
struct object_id oid;
889
const char *agent_feature;
890
int agent_len;
1015
- struct negotiation_state ns = { { compare_commits_by_commit_date } };
891
+ struct fetch_negotiator negotiator;
892
+ fetch_negotiator_init(&negotiator);
893
894
sort_ref_list(&ref, ref_compare_name);
895
QSORT(sought, nr_sought, cmp_ref_by_name);
@@ -1085,16 +962,13 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
962
if (!server_supports("deepen-relative") && args->deepen_relative)
963
die(_("Server does not support --deepen"));
964
1088
- if (marked)
1089
- for_each_ref(clear_marks, NULL);
1090
- marked = 1;
1091
- mark_complete_and_common_ref(&ns, args, &ref);
965
+ mark_complete_and_common_ref(&negotiator, args, &ref);
966
filter_refs(args, &ref, sought, nr_sought);
967
if (everything_local(args, &ref)) {
968
packet_flush(fd[1]);
969
goto all_done;
970
}
1097
- if (find_common(&ns, args, fd, &oid, ref) < 0)
971
+ if (find_common(&negotiator, args, fd, &oid, ref) < 0)
972
if (!args->keep_pack)
973
/* When cloning, it is not unusual to have
974
* no common commit.
@@ -1114,7 +988,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
988
die(_("git fetch-pack: fetch failed."));
989
990
all_done:
1117
- clear_prio_queue(&ns.rev_list);
991
+ negotiator.release(&negotiator);
992
return ref;
993
}
994
@@ -1176,14 +1050,15 @@ static void add_common(struct strbuf *req_buf, struct oidset *common)
1050
}
1051
}
1052
1179
-static int add_haves(struct negotiation_state *ns, struct strbuf *req_buf,
1053
+static int add_haves(struct fetch_negotiator *negotiator,
1054
+ struct strbuf *req_buf,
1055
int *haves_to_send, int *in_vain)
1056
{
1057
int ret = 0;
1058
int haves_added = 0;
1059
const struct object_id *oid;
1060
1186
- while ((oid = get_rev(ns))) {
1061
+ while ((oid = negotiator->next(negotiator))) {
1062
packet_buf_write(req_buf, "have %s\n", oid_to_hex(oid));
1063
if (++haves_added >= *haves_to_send)
1064
break;
@@ -1202,7 +1077,7 @@ static int add_haves(struct negotiation_state *ns, struct strbuf *req_buf,
1077
return ret;
1078
}
1079
1205
-static int send_fetch_request(struct negotiation_state *ns, int fd_out,
1080
+static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
1081
const struct fetch_pack_args *args,
1082
const struct ref *wants, struct oidset *common,
1083
int *haves_to_send, int *in_vain)
@@ -1259,7 +1134,7 @@ static int send_fetch_request(struct negotiation_state *ns, int fd_out,
1134
add_common(&req_buf, common);
1135
1136
/* Add initial haves */
1262
- ret = add_haves(ns, &req_buf, haves_to_send, in_vain);
1137
+ ret = add_haves(negotiator, &req_buf, haves_to_send, in_vain);
1138
}
1139
1140
/* Send request */
@@ -1296,7 +1171,7 @@ static int process_section_header(struct packet_reader *reader,
1171
return ret;
1172
}
1173
1299
-static int process_acks(struct negotiation_state *ns,
1174
+static int process_acks(struct fetch_negotiator *negotiator,
1175
struct packet_reader *reader,
1176
struct oidset *common)
1177
{
@@ -1317,7 +1192,7 @@ static int process_acks(struct negotiation_state *ns,
1192
struct commit *commit;
1193
oidset_insert(common, &oid);
1194
commit = lookup_commit(&oid);
1320
- mark_common(ns, commit, 0, 1);
1195
+ negotiator->ack(negotiator, commit);
1196
}
1197
continue;
1198
}
@@ -1395,7 +1270,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
1270
struct packet_reader reader;
1271
int in_vain = 0;
1272
int haves_to_send = INITIAL_FLUSH;
1398
- struct negotiation_state ns = { { compare_commits_by_commit_date } };
1273
+ struct fetch_negotiator negotiator;
1274
+ fetch_negotiator_init(&negotiator);
1275
packet_reader_init(&reader, fd[0], NULL, 0,
1276
PACKET_READ_CHOMP_NEWLINE);
1277
@@ -1411,24 +1287,21 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
1287
if (args->depth > 0 || args->deepen_since || args->deepen_not)
1288
args->deepen = 1;
1289
1414
- if (marked)
1415
- for_each_ref(clear_marks, NULL);
1416
- marked = 1;
1417
-
1290
/* Filter 'ref' by 'sought' and those that aren't local */
1419
- mark_complete_and_common_ref(&ns, args, &ref);
1291
+ mark_complete_and_common_ref(&negotiator, args, &ref);
1292
filter_refs(args, &ref, sought, nr_sought);
1293
if (everything_local(args, &ref))
1294
state = FETCH_DONE;
1295
else
1296
state = FETCH_SEND_REQUEST;
1297
1426
- for_each_ref(rev_list_insert_ref_oid, &ns);
1427
- for_each_cached_alternate(&ns,
1298
+ for_each_ref(rev_list_insert_ref_oid, &negotiator);
1299
+ for_each_cached_alternate(&negotiator,
1300
insert_one_alternate_object);
1301
break;
1302
case FETCH_SEND_REQUEST:
1431
- if (send_fetch_request(&ns, fd[1], args, ref, &common,
1303
+ if (send_fetch_request(&negotiator, fd[1], args, ref,
1304
+ &common,
1305
&haves_to_send, &in_vain))
1306
state = FETCH_GET_PACK;
1307
else
@@ -1436,7 +1309,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
1309
break;
1310
case FETCH_PROCESS_ACKS:
1311
/* Process ACKs/NAKs */
1439
- switch (process_acks(&ns, &reader, &common)) {
1312
+ switch (process_acks(&negotiator, &reader, &common)) {
1313
case 2:
1314
state = FETCH_GET_PACK;
1315
break;
@@ -1465,7 +1338,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
1338
}
1339
}
1340
1468
- clear_prio_queue(&ns.rev_list);
1341
+ negotiator.release(&negotiator);
1342
oidset_clear(&common);
1343
return ref;
1344
}
negotiator/default.c
new
+176
@@ -0,0 +1,176 @@
1
+#include "cache.h"
2
+#include "default.h"
3
+#include "../commit.h"
4
+#include "../fetch-negotiator.h"
5
+#include "../prio-queue.h"
6
+#include "../refs.h"
7
+#include "../tag.h"
8
+
9
+/* Remember to update object flag allocation in object.h */
10
+#define COMMON (1U << 2)
11
+#define COMMON_REF (1U << 3)
12
+#define SEEN (1U << 4)
13
+#define POPPED (1U << 5)
14
+
15
+static int marked;
16
+
17
+struct negotiation_state {
18
+ struct prio_queue rev_list;
19
+ int non_common_revs;
20
+};
21
+
22
+static void rev_list_push(struct negotiation_state *ns,
23
+ struct commit *commit, int mark)
24
+{
25
+ if (!(commit->object.flags & mark)) {
26
+ commit->object.flags |= mark;
27
+
28
+ if (parse_commit(commit))
29
+ return;
30
+
31
+ prio_queue_put(&ns->rev_list, commit);
32
+
33
+ if (!(commit->object.flags & COMMON))
34
+ ns->non_common_revs++;
35
+ }
36
+}
37
+
38
+static int clear_marks(const char *refname, const struct object_id *oid,
39
+ int flag, void *cb_data)
40
+{
41
+ struct object *o = deref_tag(parse_object(oid), refname, 0);
42
+
43
+ if (o && o->type == OBJ_COMMIT)
44
+ clear_commit_marks((struct commit *)o,
45
+ COMMON | COMMON_REF | SEEN | POPPED);
46
+ return 0;
47
+}
48
+
49
+/*
50
+ * This function marks a rev and its ancestors as common.
51
+ * In some cases, it is desirable to mark only the ancestors (for example
52
+ * when only the server does not yet know that they are common).
53
+ */
54
+static void mark_common(struct negotiation_state *ns, struct commit *commit,
55
+ int ancestors_only, int dont_parse)
56
+{
57
+ if (commit != NULL && !(commit->object.flags & COMMON)) {
58
+ struct object *o = (struct object *)commit;
59
+
60
+ if (!ancestors_only)
61
+ o->flags |= COMMON;
62
+
63
+ if (!(o->flags & SEEN))
64
+ rev_list_push(ns, commit, SEEN);
65
+ else {
66
+ struct commit_list *parents;
67
+
68
+ if (!ancestors_only && !(o->flags & POPPED))
69
+ ns->non_common_revs--;
70
+ if (!o->parsed && !dont_parse)
71
+ if (parse_commit(commit))
72
+ return;
73
+
74
+ for (parents = commit->parents;
75
+ parents;
76
+ parents = parents->next)
77
+ mark_common(ns, parents->item, 0,
78
+ dont_parse);
79
+ }
80
+ }
81
+}
82
+
83
+/*
84
+ * Get the next rev to send, ignoring the common.
85
+ */
86
+static const struct object_id *get_rev(struct negotiation_state *ns)
87
+{
88
+ struct commit *commit = NULL;
89
+
90
+ while (commit == NULL) {
91
+ unsigned int mark;
92
+ struct commit_list *parents;
93
+
94
+ if (ns->rev_list.nr == 0 || ns->non_common_revs == 0)
95
+ return NULL;
96
+
97
+ commit = prio_queue_get(&ns->rev_list);
98
+ parse_commit(commit);
99
+ parents = commit->parents;
100
+
101
+ commit->object.flags |= POPPED;
102
+ if (!(commit->object.flags & COMMON))
103
+ ns->non_common_revs--;
104
+
105
+ if (commit->object.flags & COMMON) {
106
+ /* do not send "have", and ignore ancestors */
107
+ commit = NULL;
108
+ mark = COMMON | SEEN;
109
+ } else if (commit->object.flags & COMMON_REF)
110
+ /* send "have", and ignore ancestors */
111
+ mark = COMMON | SEEN;
112
+ else
113
+ /* send "have", also for its ancestors */
114
+ mark = SEEN;
115
+
116
+ while (parents) {
117
+ if (!(parents->item->object.flags & SEEN))
118
+ rev_list_push(ns, parents->item, mark);
119
+ if (mark & COMMON)
120
+ mark_common(ns, parents->item, 1, 0);
121
+ parents = parents->next;
122
+ }
123
+ }
124
+
125
+ return &commit->object.oid;
126
+}
127
+
128
+static void known_common(struct fetch_negotiator *n, struct commit *c)
129
+{
130
+ if (!(c->object.flags & SEEN)) {
131
+ rev_list_push(n->data, c, COMMON_REF | SEEN);
132
+ mark_common(n->data, c, 1, 1);
133
+ }
134
+}
135
+
136
+static void add_tip(struct fetch_negotiator *n, struct commit *c)
137
+{
138
+ n->known_common = NULL;
139
+ rev_list_push(n->data, c, SEEN);
140
+}
141
+
142
+static const struct object_id *next(struct fetch_negotiator *n)
143
+{
144
+ n->known_common = NULL;
145
+ n->add_tip = NULL;
146
+ return get_rev(n->data);
147
+}
148
+
149
+static int ack(struct fetch_negotiator *n, struct commit *c)
150
+{
151
+ int known_to_be_common = !!(c->object.flags & COMMON);
152
+ mark_common(n->data, c, 0, 1);
153
+ return known_to_be_common;
154
+}
155
+
156
+static void release(struct fetch_negotiator *n)
157
+{
158
+ clear_prio_queue(&((struct negotiation_state *)n->data)->rev_list);
159
+ FREE_AND_NULL(n->data);
160
+}
161
+
162
+void default_negotiator_init(struct fetch_negotiator *negotiator)
163
+{
164
+ struct negotiation_state *ns;
165
+ negotiator->known_common = known_common;
166
+ negotiator->add_tip = add_tip;
167
+ negotiator->next = next;
168
+ negotiator->ack = ack;
169
+ negotiator->release = release;
170
+ negotiator->data = ns = xcalloc(1, sizeof(*ns));
171
+ ns->rev_list.compare = compare_commits_by_commit_date;
172
+
173
+ if (marked)
174
+ for_each_ref(clear_marks, NULL);
175
+ marked = 1;
176
+}
negotiator/default.h
new
+8
@@ -0,0 +1,8 @@
1
+#ifndef NEGOTIATOR_DEFAULT_H
2
+#define NEGOTIATOR_DEFAULT_H
3
+
4
+struct fetch_negotiator;
5
+
6
+void default_negotiator_init(struct fetch_negotiator *negotiator);
7
+
8
+#endif
object.h
+2
-1
@@ -28,7 +28,8 @@ struct object_array {
28
/*
29
* object flag allocation:
30
* revision.h: 0---------10 26
31
- * fetch-pack.c: 0----5
31
+ * fetch-pack.c: 01
32
+ * negotiator/default.c: 2--5
33
* walker.c: 0-2
34
* upload-pack.c: 4 11----------------19
35
* builtin/blame.c: 12-13