blob: fbbc99c88856a773326e4bb310d30fe3021e2333 [file] [log] [blame]
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001#include "cache.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07002#include "config.h"
Michael Haggerty697cc8e2014-10-01 12:28:42 +02003#include "lockfile.h"
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07004#include "refs.h"
5#include "pkt-line.h"
6#include "commit.h"
7#include "tag.h"
8#include "exec_cmd.h"
9#include "pack.h"
10#include "sideband.h"
11#include "fetch-pack.h"
12#include "remote.h"
13#include "run-command.h"
Junio C Hamano47a59182013-07-08 13:56:53 -070014#include "connect.h"
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +070015#include "transport.h"
16#include "version.h"
Jeff King099327b2013-07-02 02:24:21 -040017#include "prio-queue.h"
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +070018#include "sha1-array.h"
Jonathan Tanfdb69d32017-05-15 10:32:20 -070019#include "oidset.h"
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +070020
21static int transfer_unpack_limit = -1;
22static int fetch_unpack_limit = -1;
23static int unpack_limit = 100;
24static int prefer_ofs_delta = 1;
25static int no_done;
Nguyễn Thái Ngọc Duy508ea882016-06-12 17:53:59 +070026static int deepen_since_ok;
Nguyễn Thái Ngọc Duya45a2602016-06-12 17:54:04 +070027static int deepen_not_ok;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +070028static int fetch_fsck_objects = -1;
29static int transfer_fsck_objects = -1;
30static int agent_supported;
Nguyễn Thái Ngọc Duy6035d6a2013-05-26 08:16:15 +070031static struct lock_file shallow_lock;
32static const char *alternate_shallow_file;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +070033
Nguyễn Thái Ngọc Duy208acbf2014-03-25 20:23:26 +070034/* Remember to update object flag allocation in object.h */
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +070035#define COMPLETE (1U << 0)
36#define COMMON (1U << 1)
37#define COMMON_REF (1U << 2)
38#define SEEN (1U << 3)
39#define POPPED (1U << 4)
Jeff King41a078c2017-02-08 15:53:03 -050040#define ALTERNATE (1U << 5)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +070041
42static int marked;
43
44/*
45 * After sending this many "have"s if we do not get any new ACK , we
46 * give up traversing our history.
47 */
48#define MAX_IN_VAIN 256
49
Jeff King099327b2013-07-02 02:24:21 -040050static struct prio_queue rev_list = { compare_commits_by_commit_date };
Fredrik Medley7199c092015-05-21 22:23:38 +020051static int non_common_revs, multi_ack, use_sideband;
52/* Allow specifying sha1 if it is a ref tip. */
53#define ALLOW_TIP_SHA1 01
Fredrik Medley68ee6282015-05-21 22:23:39 +020054/* Allow request of a sha1 if it is reachable from a ref (possibly hidden ref). */
55#define ALLOW_REACHABLE_SHA1 02
Fredrik Medley7199c092015-05-21 22:23:38 +020056static unsigned int allow_unadvertised_object_request;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +070057
Nguyễn Thái Ngọc Duy0d789a52016-06-12 17:53:54 +070058__attribute__((format (printf, 2, 3)))
59static inline void print_verbose(const struct fetch_pack_args *args,
60 const char *fmt, ...)
61{
62 va_list params;
63
64 if (!args->verbose)
65 return;
66
67 va_start(params, fmt);
68 vfprintf(stderr, fmt, params);
69 va_end(params);
70 fputc('\n', stderr);
71}
72
Jeff King41a078c2017-02-08 15:53:03 -050073struct alternate_object_cache {
74 struct object **items;
75 size_t nr, alloc;
76};
77
78static void cache_one_alternate(const char *refname,
79 const struct object_id *oid,
80 void *vcache)
81{
82 struct alternate_object_cache *cache = vcache;
brian m. carlsonc251c832017-05-06 22:10:38 +000083 struct object *obj = parse_object(oid);
Jeff King41a078c2017-02-08 15:53:03 -050084
85 if (!obj || (obj->flags & ALTERNATE))
86 return;
87
88 obj->flags |= ALTERNATE;
89 ALLOC_GROW(cache->items, cache->nr + 1, cache->alloc);
90 cache->items[cache->nr++] = obj;
91}
92
93static void for_each_cached_alternate(void (*cb)(struct object *))
94{
95 static int initialized;
96 static struct alternate_object_cache cache;
97 size_t i;
98
99 if (!initialized) {
100 for_each_alternate_ref(cache_one_alternate, &cache);
101 initialized = 1;
102 }
103
104 for (i = 0; i < cache.nr; i++)
105 cb(cache.items[i]);
106}
107
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700108static void rev_list_push(struct commit *commit, int mark)
109{
110 if (!(commit->object.flags & mark)) {
111 commit->object.flags |= mark;
112
Jeff King00640532013-10-24 04:53:01 -0400113 if (parse_commit(commit))
114 return;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700115
Jeff King099327b2013-07-02 02:24:21 -0400116 prio_queue_put(&rev_list, commit);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700117
118 if (!(commit->object.flags & COMMON))
119 non_common_revs++;
120 }
121}
122
brian m. carlson1b283372017-05-01 02:28:54 +0000123static int rev_list_insert_ref(const char *refname, const struct object_id *oid)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700124{
brian m. carlsonc251c832017-05-06 22:10:38 +0000125 struct object *o = deref_tag(parse_object(oid), refname, 0);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700126
127 if (o && o->type == OBJ_COMMIT)
128 rev_list_push((struct commit *)o, SEEN);
129
130 return 0;
131}
132
Michael Haggertyb1b49c62015-05-25 18:39:18 +0000133static int rev_list_insert_ref_oid(const char *refname, const struct object_id *oid,
134 int flag, void *cb_data)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700135{
brian m. carlson1b283372017-05-01 02:28:54 +0000136 return rev_list_insert_ref(refname, oid);
Michael Haggertyb1b49c62015-05-25 18:39:18 +0000137}
138
Michael Haggertyc50fb6c2015-05-25 18:39:15 +0000139static int clear_marks(const char *refname, const struct object_id *oid,
140 int flag, void *cb_data)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700141{
brian m. carlsonc251c832017-05-06 22:10:38 +0000142 struct object *o = deref_tag(parse_object(oid), refname, 0);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700143
144 if (o && o->type == OBJ_COMMIT)
145 clear_commit_marks((struct commit *)o,
146 COMMON | COMMON_REF | SEEN | POPPED);
147 return 0;
148}
149
150/*
151 This function marks a rev and its ancestors as common.
152 In some cases, it is desirable to mark only the ancestors (for example
153 when only the server does not yet know that they are common).
154*/
155
156static void mark_common(struct commit *commit,
157 int ancestors_only, int dont_parse)
158{
159 if (commit != NULL && !(commit->object.flags & COMMON)) {
160 struct object *o = (struct object *)commit;
161
162 if (!ancestors_only)
163 o->flags |= COMMON;
164
165 if (!(o->flags & SEEN))
166 rev_list_push(commit, SEEN);
167 else {
168 struct commit_list *parents;
169
170 if (!ancestors_only && !(o->flags & POPPED))
171 non_common_revs--;
172 if (!o->parsed && !dont_parse)
173 if (parse_commit(commit))
174 return;
175
176 for (parents = commit->parents;
177 parents;
178 parents = parents->next)
179 mark_common(parents->item, 0, dont_parse);
180 }
181 }
182}
183
184/*
185 Get the next rev to send, ignoring the common.
186*/
187
brian m. carlson1b283372017-05-01 02:28:54 +0000188static const struct object_id *get_rev(void)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700189{
190 struct commit *commit = NULL;
191
192 while (commit == NULL) {
193 unsigned int mark;
194 struct commit_list *parents;
195
Jeff King099327b2013-07-02 02:24:21 -0400196 if (rev_list.nr == 0 || non_common_revs == 0)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700197 return NULL;
198
Jeff King099327b2013-07-02 02:24:21 -0400199 commit = prio_queue_get(&rev_list);
Jeff King00640532013-10-24 04:53:01 -0400200 parse_commit(commit);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700201 parents = commit->parents;
202
203 commit->object.flags |= POPPED;
204 if (!(commit->object.flags & COMMON))
205 non_common_revs--;
206
207 if (commit->object.flags & COMMON) {
208 /* do not send "have", and ignore ancestors */
209 commit = NULL;
210 mark = COMMON | SEEN;
211 } else if (commit->object.flags & COMMON_REF)
212 /* send "have", and ignore ancestors */
213 mark = COMMON | SEEN;
214 else
215 /* send "have", also for its ancestors */
216 mark = SEEN;
217
218 while (parents) {
219 if (!(parents->item->object.flags & SEEN))
220 rev_list_push(parents->item, mark);
221 if (mark & COMMON)
222 mark_common(parents->item, 1, 0);
223 parents = parents->next;
224 }
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700225 }
226
brian m. carlson1b283372017-05-01 02:28:54 +0000227 return &commit->object.oid;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700228}
229
230enum ack_type {
231 NAK = 0,
232 ACK,
233 ACK_continue,
234 ACK_common,
235 ACK_ready
236};
237
238static void consume_shallow_list(struct fetch_pack_args *args, int fd)
239{
Nguyễn Thái Ngọc Duy79891cb2016-06-12 17:53:56 +0700240 if (args->stateless_rpc && args->deepen) {
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700241 /* If we sent a depth we will get back "duplicate"
242 * shallow and unshallow commands every time there
243 * is a block of have lines exchanged.
244 */
Jeff King74543a02013-02-20 15:02:57 -0500245 char *line;
246 while ((line = packet_read_line(fd, NULL))) {
Christian Couder59556542013-11-30 21:55:40 +0100247 if (starts_with(line, "shallow "))
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700248 continue;
Christian Couder59556542013-11-30 21:55:40 +0100249 if (starts_with(line, "unshallow "))
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700250 continue;
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700251 die(_("git fetch-pack: expected shallow list"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700252 }
253 }
254}
255
brian m. carlson1b283372017-05-01 02:28:54 +0000256static enum ack_type get_ack(int fd, struct object_id *result_oid)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700257{
Jeff King74543a02013-02-20 15:02:57 -0500258 int len;
259 char *line = packet_read_line(fd, &len);
Jeff King82e56762014-06-18 15:56:03 -0400260 const char *arg;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700261
262 if (!len)
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700263 die(_("git fetch-pack: expected ACK/NAK, got EOF"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700264 if (!strcmp(line, "NAK"))
265 return NAK;
Jeff King82e56762014-06-18 15:56:03 -0400266 if (skip_prefix(line, "ACK ", &arg)) {
brian m. carlson1b283372017-05-01 02:28:54 +0000267 if (!get_oid_hex(arg, result_oid)) {
Jeff King82e56762014-06-18 15:56:03 -0400268 arg += 40;
269 len -= arg - line;
270 if (len < 1)
Jeff King030e9dd2013-02-20 15:00:28 -0500271 return ACK;
Jeff King82e56762014-06-18 15:56:03 -0400272 if (strstr(arg, "continue"))
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700273 return ACK_continue;
Jeff King82e56762014-06-18 15:56:03 -0400274 if (strstr(arg, "common"))
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700275 return ACK_common;
Jeff King82e56762014-06-18 15:56:03 -0400276 if (strstr(arg, "ready"))
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700277 return ACK_ready;
278 return ACK;
279 }
280 }
Jonathan Tan8e2c7be2017-04-12 11:06:02 -0700281 if (skip_prefix(line, "ERR ", &arg))
282 die(_("remote error: %s"), arg);
Ralf Thielowdfbfb9f2016-11-11 18:21:00 +0100283 die(_("git fetch-pack: expected ACK/NAK, got '%s'"), line);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700284}
285
286static void send_request(struct fetch_pack_args *args,
287 int fd, struct strbuf *buf)
288{
289 if (args->stateless_rpc) {
290 send_sideband(fd, -1, buf->buf, buf->len, LARGE_PACKET_MAX);
291 packet_flush(fd);
292 } else
Jeff Kingcdf4fb82013-02-20 15:01:56 -0500293 write_or_die(fd, buf->buf, buf->len);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700294}
295
Jeff King41a078c2017-02-08 15:53:03 -0500296static void insert_one_alternate_object(struct object *obj)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700297{
brian m. carlson1b283372017-05-01 02:28:54 +0000298 rev_list_insert_ref(NULL, &obj->oid);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700299}
300
301#define INITIAL_FLUSH 16
302#define PIPESAFE_FLUSH 32
Jonathan Tanda470982016-07-18 15:21:38 -0700303#define LARGE_FLUSH 16384
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700304
305static int next_flush(struct fetch_pack_args *args, int count)
306{
Jonathan Tanda470982016-07-18 15:21:38 -0700307 if (args->stateless_rpc) {
308 if (count < LARGE_FLUSH)
309 count <<= 1;
310 else
311 count = count * 11 / 10;
312 } else {
313 if (count < PIPESAFE_FLUSH)
314 count <<= 1;
315 else
316 count += PIPESAFE_FLUSH;
317 }
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700318 return count;
319}
320
321static int find_common(struct fetch_pack_args *args,
brian m. carlson1b283372017-05-01 02:28:54 +0000322 int fd[2], struct object_id *result_oid,
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700323 struct ref *refs)
324{
325 int fetching;
326 int count = 0, flushes = 0, flush_at = INITIAL_FLUSH, retval;
brian m. carlson1b283372017-05-01 02:28:54 +0000327 const struct object_id *oid;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700328 unsigned in_vain = 0;
329 int got_continue = 0;
330 int got_ready = 0;
331 struct strbuf req_buf = STRBUF_INIT;
332 size_t state_len = 0;
333
334 if (args->stateless_rpc && multi_ack == 1)
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700335 die(_("--stateless-rpc requires multi_ack_detailed"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700336 if (marked)
337 for_each_ref(clear_marks, NULL);
338 marked = 1;
339
Michael Haggertyb1b49c62015-05-25 18:39:18 +0000340 for_each_ref(rev_list_insert_ref_oid, NULL);
Jeff King41a078c2017-02-08 15:53:03 -0500341 for_each_cached_alternate(insert_one_alternate_object);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700342
343 fetching = 0;
344 for ( ; refs ; refs = refs->next) {
brian m. carlson1b283372017-05-01 02:28:54 +0000345 struct object_id *remote = &refs->old_oid;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700346 const char *remote_hex;
347 struct object *o;
348
349 /*
350 * If that object is complete (i.e. it is an ancestor of a
351 * local ref), we tell them we have it but do not have to
352 * tell them about its ancestors, which they already know
353 * about.
354 *
355 * We use lookup_object here because we are only
356 * interested in the case we *know* the object is
357 * reachable and we have already scanned it.
358 */
brian m. carlson1b283372017-05-01 02:28:54 +0000359 if (((o = lookup_object(remote->hash)) != NULL) &&
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700360 (o->flags & COMPLETE)) {
361 continue;
362 }
363
brian m. carlson1b283372017-05-01 02:28:54 +0000364 remote_hex = oid_to_hex(remote);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700365 if (!fetching) {
366 struct strbuf c = STRBUF_INIT;
367 if (multi_ack == 2) strbuf_addstr(&c, " multi_ack_detailed");
368 if (multi_ack == 1) strbuf_addstr(&c, " multi_ack");
369 if (no_done) strbuf_addstr(&c, " no-done");
370 if (use_sideband == 2) strbuf_addstr(&c, " side-band-64k");
371 if (use_sideband == 1) strbuf_addstr(&c, " side-band");
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +0700372 if (args->deepen_relative) strbuf_addstr(&c, " deepen-relative");
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700373 if (args->use_thin_pack) strbuf_addstr(&c, " thin-pack");
374 if (args->no_progress) strbuf_addstr(&c, " no-progress");
375 if (args->include_tag) strbuf_addstr(&c, " include-tag");
376 if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta");
Nguyễn Thái Ngọc Duy508ea882016-06-12 17:53:59 +0700377 if (deepen_since_ok) strbuf_addstr(&c, " deepen-since");
Nguyễn Thái Ngọc Duya45a2602016-06-12 17:54:04 +0700378 if (deepen_not_ok) strbuf_addstr(&c, " deepen-not");
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700379 if (agent_supported) strbuf_addf(&c, " agent=%s",
380 git_user_agent_sanitized());
381 packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
382 strbuf_release(&c);
383 } else
384 packet_buf_write(&req_buf, "want %s\n", remote_hex);
385 fetching++;
386 }
387
388 if (!fetching) {
389 strbuf_release(&req_buf);
390 packet_flush(fd[1]);
391 return 1;
392 }
393
394 if (is_repository_shallow())
Nguyễn Thái Ngọc Duy1a30f5a2013-12-05 20:02:34 +0700395 write_shallow_commits(&req_buf, 1, NULL);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700396 if (args->depth > 0)
397 packet_buf_write(&req_buf, "deepen %d", args->depth);
Nguyễn Thái Ngọc Duy508ea882016-06-12 17:53:59 +0700398 if (args->deepen_since) {
Johannes Schindelindddbad72017-04-26 21:29:31 +0200399 timestamp_t max_age = approxidate(args->deepen_since);
Johannes Schindelincb71f8b2017-04-21 12:45:48 +0200400 packet_buf_write(&req_buf, "deepen-since %"PRItime, max_age);
Nguyễn Thái Ngọc Duy508ea882016-06-12 17:53:59 +0700401 }
Nguyễn Thái Ngọc Duya45a2602016-06-12 17:54:04 +0700402 if (args->deepen_not) {
403 int i;
404 for (i = 0; i < args->deepen_not->nr; i++) {
405 struct string_list_item *s = args->deepen_not->items + i;
406 packet_buf_write(&req_buf, "deepen-not %s", s->string);
407 }
408 }
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700409 packet_buf_flush(&req_buf);
410 state_len = req_buf.len;
411
Nguyễn Thái Ngọc Duy79891cb2016-06-12 17:53:56 +0700412 if (args->deepen) {
Jeff King74543a02013-02-20 15:02:57 -0500413 char *line;
Jeff Kingae021d82014-06-18 15:47:50 -0400414 const char *arg;
brian m. carlson1b283372017-05-01 02:28:54 +0000415 struct object_id oid;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700416
417 send_request(args, fd[1], &req_buf);
Jeff King74543a02013-02-20 15:02:57 -0500418 while ((line = packet_read_line(fd[0], NULL))) {
Jeff Kingae021d82014-06-18 15:47:50 -0400419 if (skip_prefix(line, "shallow ", &arg)) {
brian m. carlson1b283372017-05-01 02:28:54 +0000420 if (get_oid_hex(arg, &oid))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700421 die(_("invalid shallow line: %s"), line);
brian m. carlsone92b8482017-05-06 22:10:06 +0000422 register_shallow(&oid);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700423 continue;
424 }
Jeff Kingae021d82014-06-18 15:47:50 -0400425 if (skip_prefix(line, "unshallow ", &arg)) {
brian m. carlson1b283372017-05-01 02:28:54 +0000426 if (get_oid_hex(arg, &oid))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700427 die(_("invalid unshallow line: %s"), line);
brian m. carlson1b283372017-05-01 02:28:54 +0000428 if (!lookup_object(oid.hash))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700429 die(_("object not found: %s"), line);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700430 /* make sure that it is parsed as shallow */
brian m. carlsonc251c832017-05-06 22:10:38 +0000431 if (!parse_object(&oid))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700432 die(_("error in object: %s"), line);
brian m. carlsone92b8482017-05-06 22:10:06 +0000433 if (unregister_shallow(&oid))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700434 die(_("no shallow found: %s"), line);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700435 continue;
436 }
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700437 die(_("expected shallow/unshallow, got %s"), line);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700438 }
439 } else if (!args->stateless_rpc)
440 send_request(args, fd[1], &req_buf);
441
442 if (!args->stateless_rpc) {
443 /* If we aren't using the stateless-rpc interface
444 * we don't need to retain the headers.
445 */
446 strbuf_setlen(&req_buf, 0);
447 state_len = 0;
448 }
449
450 flushes = 0;
451 retval = -1;
brian m. carlson1b283372017-05-01 02:28:54 +0000452 while ((oid = get_rev())) {
453 packet_buf_write(&req_buf, "have %s\n", oid_to_hex(oid));
454 print_verbose(args, "have %s", oid_to_hex(oid));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700455 in_vain++;
456 if (flush_at <= ++count) {
457 int ack;
458
459 packet_buf_flush(&req_buf);
460 send_request(args, fd[1], &req_buf);
461 strbuf_setlen(&req_buf, state_len);
462 flushes++;
463 flush_at = next_flush(args, count);
464
465 /*
466 * We keep one window "ahead" of the other side, and
467 * will wait for an ACK only on the next one
468 */
469 if (!args->stateless_rpc && count == INITIAL_FLUSH)
470 continue;
471
472 consume_shallow_list(args, fd[0]);
473 do {
brian m. carlson1b283372017-05-01 02:28:54 +0000474 ack = get_ack(fd[0], result_oid);
Nguyễn Thái Ngọc Duy0d789a52016-06-12 17:53:54 +0700475 if (ack)
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700476 print_verbose(args, _("got %s %d %s"), "ack",
brian m. carlson1b283372017-05-01 02:28:54 +0000477 ack, oid_to_hex(result_oid));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700478 switch (ack) {
479 case ACK:
480 flushes = 0;
481 multi_ack = 0;
482 retval = 0;
483 goto done;
484 case ACK_common:
485 case ACK_ready:
486 case ACK_continue: {
487 struct commit *commit =
brian m. carlsonbc832662017-05-06 22:10:10 +0000488 lookup_commit(result_oid);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700489 if (!commit)
brian m. carlson1b283372017-05-01 02:28:54 +0000490 die(_("invalid commit %s"), oid_to_hex(result_oid));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700491 if (args->stateless_rpc
492 && ack == ACK_common
493 && !(commit->object.flags & COMMON)) {
494 /* We need to replay the have for this object
495 * on the next RPC request so the peer knows
496 * it is in common with us.
497 */
brian m. carlson1b283372017-05-01 02:28:54 +0000498 const char *hex = oid_to_hex(result_oid);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700499 packet_buf_write(&req_buf, "have %s\n", hex);
500 state_len = req_buf.len;
Jonathan Tan06b3d382016-09-23 10:41:35 -0700501 /*
502 * Reset in_vain because an ack
503 * for this commit has not been
504 * seen.
505 */
506 in_vain = 0;
507 } else if (!args->stateless_rpc
508 || ack != ACK_common)
509 in_vain = 0;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700510 mark_common(commit, 0, 1);
511 retval = 0;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700512 got_continue = 1;
513 if (ack == ACK_ready) {
Jeff King099327b2013-07-02 02:24:21 -0400514 clear_prio_queue(&rev_list);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700515 got_ready = 1;
516 }
517 break;
518 }
519 }
520 } while (ack);
521 flushes--;
522 if (got_continue && MAX_IN_VAIN < in_vain) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700523 print_verbose(args, _("giving up"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700524 break; /* give up */
525 }
526 }
527 }
528done:
529 if (!got_ready || !no_done) {
530 packet_buf_write(&req_buf, "done\n");
531 send_request(args, fd[1], &req_buf);
532 }
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700533 print_verbose(args, _("done"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700534 if (retval != 0) {
535 multi_ack = 0;
536 flushes++;
537 }
538 strbuf_release(&req_buf);
539
Nguyễn Thái Ngọc Duyff62eca2014-02-06 22:10:39 +0700540 if (!got_ready || !no_done)
541 consume_shallow_list(args, fd[0]);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700542 while (flushes || multi_ack) {
brian m. carlson1b283372017-05-01 02:28:54 +0000543 int ack = get_ack(fd[0], result_oid);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700544 if (ack) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700545 print_verbose(args, _("got %s (%d) %s"), "ack",
brian m. carlson1b283372017-05-01 02:28:54 +0000546 ack, oid_to_hex(result_oid));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700547 if (ack == ACK)
548 return 0;
549 multi_ack = 1;
550 continue;
551 }
552 flushes--;
553 }
554 /* it is no error to fetch into a completely empty repo */
555 return count ? retval : 0;
556}
557
558static struct commit_list *complete;
559
brian m. carlson1b283372017-05-01 02:28:54 +0000560static int mark_complete(const struct object_id *oid)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700561{
brian m. carlsonc251c832017-05-06 22:10:38 +0000562 struct object *o = parse_object(oid);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700563
564 while (o && o->type == OBJ_TAG) {
565 struct tag *t = (struct tag *) o;
566 if (!t->tagged)
567 break; /* broken repository */
568 o->flags |= COMPLETE;
brian m. carlsonc251c832017-05-06 22:10:38 +0000569 o = parse_object(&t->tagged->oid);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700570 }
571 if (o && o->type == OBJ_COMMIT) {
572 struct commit *commit = (struct commit *)o;
573 if (!(commit->object.flags & COMPLETE)) {
574 commit->object.flags |= COMPLETE;
Jeff King16445242013-07-02 02:16:23 -0400575 commit_list_insert(commit, &complete);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700576 }
577 }
578 return 0;
579}
580
Michael Haggertyf8ee4d82015-05-25 18:39:16 +0000581static int mark_complete_oid(const char *refname, const struct object_id *oid,
582 int flag, void *cb_data)
583{
brian m. carlson1b283372017-05-01 02:28:54 +0000584 return mark_complete(oid);
Michael Haggertyf8ee4d82015-05-25 18:39:16 +0000585}
586
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700587static void mark_recent_complete_commits(struct fetch_pack_args *args,
Johannes Schindelindddbad72017-04-26 21:29:31 +0200588 timestamp_t cutoff)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700589{
590 while (complete && cutoff <= complete->item->date) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700591 print_verbose(args, _("Marking %s as complete"),
Nguyễn Thái Ngọc Duy0d789a52016-06-12 17:53:54 +0700592 oid_to_hex(&complete->item->object.oid));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700593 pop_most_recent_commit(&complete, COMPLETE);
594 }
595}
596
Jonathan Tanfdb69d32017-05-15 10:32:20 -0700597static void add_refs_to_oidset(struct oidset *oids, struct ref *refs)
598{
599 for (; refs; refs = refs->next)
600 oidset_insert(oids, &refs->old_oid);
601}
602
603static int tip_oids_contain(struct oidset *tip_oids,
604 struct ref *unmatched, struct ref *newlist,
605 const struct object_id *id)
606{
607 /*
608 * Note that this only looks at the ref lists the first time it's
609 * called. This works out in filter_refs() because even though it may
610 * add to "newlist" between calls, the additions will always be for
611 * oids that are already in the set.
612 */
613 if (!tip_oids->map.tablesize) {
614 add_refs_to_oidset(tip_oids, unmatched);
615 add_refs_to_oidset(tip_oids, newlist);
616 }
617 return oidset_contains(tip_oids, id);
618}
619
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700620static void filter_refs(struct fetch_pack_args *args,
Junio C Hamanof2db8542013-01-29 14:02:15 -0800621 struct ref **refs,
622 struct ref **sought, int nr_sought)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700623{
624 struct ref *newlist = NULL;
625 struct ref **newtail = &newlist;
Jonathan Tanfdb69d32017-05-15 10:32:20 -0700626 struct ref *unmatched = NULL;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700627 struct ref *ref, *next;
Jonathan Tanfdb69d32017-05-15 10:32:20 -0700628 struct oidset tip_oids = OIDSET_INIT;
Junio C Hamanof2db8542013-01-29 14:02:15 -0800629 int i;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700630
Junio C Hamanof2db8542013-01-29 14:02:15 -0800631 i = 0;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700632 for (ref = *refs; ref; ref = next) {
633 int keep = 0;
634 next = ref->next;
Junio C Hamanof2db8542013-01-29 14:02:15 -0800635
René Scharfe50e19a82014-06-06 19:24:48 +0200636 if (starts_with(ref->name, "refs/") &&
Jeff King4c224082014-01-15 05:46:13 -0500637 check_refname_format(ref->name, 0))
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700638 ; /* trash */
639 else {
Junio C Hamanof2db8542013-01-29 14:02:15 -0800640 while (i < nr_sought) {
641 int cmp = strcmp(ref->name, sought[i]->name);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700642 if (cmp < 0)
643 break; /* definitely do not have it */
644 else if (cmp == 0) {
645 keep = 1; /* definitely have it */
Matt McCutchend56583d2017-02-22 11:05:57 -0500646 sought[i]->match_status = REF_MATCHED;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700647 }
Junio C Hamanof2db8542013-01-29 14:02:15 -0800648 i++;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700649 }
650 }
651
Junio C Hamanof2db8542013-01-29 14:02:15 -0800652 if (!keep && args->fetch_all &&
Nguyễn Thái Ngọc Duy79891cb2016-06-12 17:53:56 +0700653 (!args->deepen || !starts_with(ref->name, "refs/tags/")))
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700654 keep = 1;
655
656 if (keep) {
657 *newtail = ref;
658 ref->next = NULL;
659 newtail = &ref->next;
660 } else {
Jonathan Tanfdb69d32017-05-15 10:32:20 -0700661 ref->next = unmatched;
662 unmatched = ref;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700663 }
664 }
665
Junio C Hamano6e7b66e2013-01-29 14:02:15 -0800666 /* Append unmatched requests to the list */
Matt McCutchend56583d2017-02-22 11:05:57 -0500667 for (i = 0; i < nr_sought; i++) {
brian m. carlson1b283372017-05-01 02:28:54 +0000668 struct object_id oid;
669 const char *p;
Jeff Kingb7916422015-03-19 16:34:51 -0400670
Matt McCutchend56583d2017-02-22 11:05:57 -0500671 ref = sought[i];
672 if (ref->match_status != REF_NOT_MATCHED)
673 continue;
brian m. carlson1b283372017-05-01 02:28:54 +0000674 if (parse_oid_hex(ref->name, &oid, &p) ||
675 *p != '\0' ||
676 oidcmp(&oid, &ref->old_oid))
Matt McCutchend56583d2017-02-22 11:05:57 -0500677 continue;
Junio C Hamano6e7b66e2013-01-29 14:02:15 -0800678
Matt McCutchend56583d2017-02-22 11:05:57 -0500679 if ((allow_unadvertised_object_request &
Jonathan Tanfdb69d32017-05-15 10:32:20 -0700680 (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1)) ||
681 tip_oids_contain(&tip_oids, unmatched, newlist,
682 &ref->old_oid)) {
Matt McCutchend56583d2017-02-22 11:05:57 -0500683 ref->match_status = REF_MATCHED;
Jeff Kingc3c17bf2015-03-19 16:37:09 -0400684 *newtail = copy_ref(ref);
685 newtail = &(*newtail)->next;
Matt McCutchend56583d2017-02-22 11:05:57 -0500686 } else {
687 ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
Junio C Hamano6e7b66e2013-01-29 14:02:15 -0800688 }
689 }
Jonathan Tanfdb69d32017-05-15 10:32:20 -0700690
691 oidset_clear(&tip_oids);
692 for (ref = unmatched; ref; ref = next) {
693 next = ref->next;
694 free(ref);
695 }
696
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700697 *refs = newlist;
698}
699
Jeff King41a078c2017-02-08 15:53:03 -0500700static void mark_alternate_complete(struct object *obj)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700701{
brian m. carlson1b283372017-05-01 02:28:54 +0000702 mark_complete(&obj->oid);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700703}
704
705static int everything_local(struct fetch_pack_args *args,
Junio C Hamanof2db8542013-01-29 14:02:15 -0800706 struct ref **refs,
707 struct ref **sought, int nr_sought)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700708{
709 struct ref *ref;
710 int retval;
Johannes Schindelindddbad72017-04-26 21:29:31 +0200711 timestamp_t cutoff = 0;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700712
713 save_commit_buffer = 0;
714
715 for (ref = *refs; ref; ref = ref->next) {
716 struct object *o;
717
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000718 if (!has_object_file(&ref->old_oid))
Junio C Hamano012a1bb2013-01-26 19:42:09 -0800719 continue;
720
brian m. carlsonc251c832017-05-06 22:10:38 +0000721 o = parse_object(&ref->old_oid);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700722 if (!o)
723 continue;
724
725 /* We already have it -- which may mean that we were
726 * in sync with the other side at some time after
727 * that (it is OK if we guess wrong here).
728 */
729 if (o->type == OBJ_COMMIT) {
730 struct commit *commit = (struct commit *)o;
731 if (!cutoff || cutoff < commit->date)
732 cutoff = commit->date;
733 }
734 }
735
Nguyễn Thái Ngọc Duy79891cb2016-06-12 17:53:56 +0700736 if (!args->deepen) {
Michael Haggertyf8ee4d82015-05-25 18:39:16 +0000737 for_each_ref(mark_complete_oid, NULL);
Jeff King41a078c2017-02-08 15:53:03 -0500738 for_each_cached_alternate(mark_alternate_complete);
Jeff King16445242013-07-02 02:16:23 -0400739 commit_list_sort_by_date(&complete);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700740 if (cutoff)
741 mark_recent_complete_commits(args, cutoff);
742 }
743
744 /*
745 * Mark all complete remote refs as common refs.
746 * Don't mark them common yet; the server has to be told so first.
747 */
748 for (ref = *refs; ref; ref = ref->next) {
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000749 struct object *o = deref_tag(lookup_object(ref->old_oid.hash),
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700750 NULL, 0);
751
752 if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
753 continue;
754
755 if (!(o->flags & SEEN)) {
756 rev_list_push((struct commit *)o, COMMON_REF | SEEN);
757
758 mark_common((struct commit *)o, 1, 1);
759 }
760 }
761
Junio C Hamanof2db8542013-01-29 14:02:15 -0800762 filter_refs(args, refs, sought, nr_sought);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700763
764 for (retval = 1, ref = *refs; ref ; ref = ref->next) {
brian m. carlson1b283372017-05-01 02:28:54 +0000765 const struct object_id *remote = &ref->old_oid;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700766 struct object *o;
767
brian m. carlson1b283372017-05-01 02:28:54 +0000768 o = lookup_object(remote->hash);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700769 if (!o || !(o->flags & COMPLETE)) {
770 retval = 0;
brian m. carlson1b283372017-05-01 02:28:54 +0000771 print_verbose(args, "want %s (%s)", oid_to_hex(remote),
Nguyễn Thái Ngọc Duy0d789a52016-06-12 17:53:54 +0700772 ref->name);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700773 continue;
774 }
brian m. carlson1b283372017-05-01 02:28:54 +0000775 print_verbose(args, _("already have %s (%s)"), oid_to_hex(remote),
Nguyễn Thái Ngọc Duy0d789a52016-06-12 17:53:54 +0700776 ref->name);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700777 }
778 return retval;
779}
780
781static int sideband_demux(int in, int out, void *data)
782{
783 int *xd = data;
Jeff King9ff18fa2016-02-24 02:44:58 -0500784 int ret;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700785
Jeff King9ff18fa2016-02-24 02:44:58 -0500786 ret = recv_sideband("fetch-pack", xd[0], out);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700787 close(out);
788 return ret;
789}
790
791static int get_pack(struct fetch_pack_args *args,
792 int xd[2], char **pack_lockfile)
793{
794 struct async demux;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700795 int do_keep = args->keep_pack;
Jeff King984a43b2015-09-24 17:07:54 -0400796 const char *cmd_name;
797 struct pack_header header;
798 int pass_header = 0;
René Scharfed3180272014-08-19 21:09:35 +0200799 struct child_process cmd = CHILD_PROCESS_INIT;
Nguyễn Thái Ngọc Duyc6807a42013-05-26 08:16:17 +0700800 int ret;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700801
802 memset(&demux, 0, sizeof(demux));
803 if (use_sideband) {
804 /* xd[] is talking with upload-pack; subprocess reads from
805 * xd[0], spits out band#2 to stderr, and feeds us band#1
806 * through demux->out.
807 */
808 demux.proc = sideband_demux;
809 demux.data = xd;
810 demux.out = -1;
Jeff Kingdf857572016-04-19 18:50:29 -0400811 demux.isolate_sigpipe = 1;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700812 if (start_async(&demux))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700813 die(_("fetch-pack: unable to fork off sideband demultiplexer"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700814 }
815 else
816 demux.out = xd[0];
817
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700818 if (!args->keep_pack && unpack_limit) {
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700819
820 if (read_pack_header(demux.out, &header))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700821 die(_("protocol error: bad pack header"));
Jeff King984a43b2015-09-24 17:07:54 -0400822 pass_header = 1;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700823 if (ntohl(header.hdr_entries) < unpack_limit)
824 do_keep = 0;
825 else
826 do_keep = 1;
827 }
828
Nguyễn Thái Ngọc Duy6035d6a2013-05-26 08:16:15 +0700829 if (alternate_shallow_file) {
Jeff King984a43b2015-09-24 17:07:54 -0400830 argv_array_push(&cmd.args, "--shallow-file");
831 argv_array_push(&cmd.args, alternate_shallow_file);
Nguyễn Thái Ngọc Duy6035d6a2013-05-26 08:16:15 +0700832 }
833
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700834 if (do_keep) {
835 if (pack_lockfile)
836 cmd.out = -1;
Jeff King984a43b2015-09-24 17:07:54 -0400837 cmd_name = "index-pack";
838 argv_array_push(&cmd.args, cmd_name);
839 argv_array_push(&cmd.args, "--stdin");
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700840 if (!args->quiet && !args->no_progress)
Jeff King984a43b2015-09-24 17:07:54 -0400841 argv_array_push(&cmd.args, "-v");
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700842 if (args->use_thin_pack)
Jeff King984a43b2015-09-24 17:07:54 -0400843 argv_array_push(&cmd.args, "--fix-thin");
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700844 if (args->lock_pack || unpack_limit) {
René Scharfeda25bdb2017-04-18 17:57:42 -0400845 char hostname[HOST_NAME_MAX + 1];
David Turner5781a9a2017-04-18 17:57:43 -0400846 if (xgethostname(hostname, sizeof(hostname)))
Jeff King984a43b2015-09-24 17:07:54 -0400847 xsnprintf(hostname, sizeof(hostname), "localhost");
848 argv_array_pushf(&cmd.args,
849 "--keep=fetch-pack %"PRIuMAX " on %s",
850 (uintmax_t)getpid(), hostname);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700851 }
Nguyễn Thái Ngọc Duyc6807a42013-05-26 08:16:17 +0700852 if (args->check_self_contained_and_connected)
Jeff King984a43b2015-09-24 17:07:54 -0400853 argv_array_push(&cmd.args, "--check-self-contained-and-connected");
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700854 }
855 else {
Jeff King984a43b2015-09-24 17:07:54 -0400856 cmd_name = "unpack-objects";
857 argv_array_push(&cmd.args, cmd_name);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700858 if (args->quiet || args->no_progress)
Jeff King984a43b2015-09-24 17:07:54 -0400859 argv_array_push(&cmd.args, "-q");
Nguyễn Thái Ngọc Duyc6807a42013-05-26 08:16:17 +0700860 args->check_self_contained_and_connected = 0;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700861 }
Jeff King984a43b2015-09-24 17:07:54 -0400862
863 if (pass_header)
864 argv_array_pushf(&cmd.args, "--pack_header=%"PRIu32",%"PRIu32,
865 ntohl(header.hdr_version),
866 ntohl(header.hdr_entries));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700867 if (fetch_fsck_objects >= 0
868 ? fetch_fsck_objects
869 : transfer_fsck_objects >= 0
870 ? transfer_fsck_objects
871 : 0)
Jeff King984a43b2015-09-24 17:07:54 -0400872 argv_array_push(&cmd.args, "--strict");
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700873
874 cmd.in = demux.out;
875 cmd.git_cmd = 1;
876 if (start_command(&cmd))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700877 die(_("fetch-pack: unable to fork off %s"), cmd_name);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700878 if (do_keep && pack_lockfile) {
879 *pack_lockfile = index_pack_lockfile(cmd.out);
880 close(cmd.out);
881 }
882
Jens Lindstrom37cb1dd2013-10-22 15:36:02 +0200883 if (!use_sideband)
884 /* Closed by start_command() */
885 xd[0] = -1;
886
Nguyễn Thái Ngọc Duyc6807a42013-05-26 08:16:17 +0700887 ret = finish_command(&cmd);
888 if (!ret || (args->check_self_contained_and_connected && ret == 1))
889 args->self_contained_and_connected =
890 args->check_self_contained_and_connected &&
891 ret == 0;
892 else
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700893 die(_("%s failed"), cmd_name);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700894 if (use_sideband && finish_async(&demux))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700895 die(_("error in sideband demultiplexer"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700896 return 0;
897}
898
Junio C Hamanof2db8542013-01-29 14:02:15 -0800899static int cmp_ref_by_name(const void *a_, const void *b_)
900{
901 const struct ref *a = *((const struct ref **)a_);
902 const struct ref *b = *((const struct ref **)b_);
903 return strcmp(a->name, b->name);
904}
905
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700906static struct ref *do_fetch_pack(struct fetch_pack_args *args,
907 int fd[2],
908 const struct ref *orig_ref,
Junio C Hamanof2db8542013-01-29 14:02:15 -0800909 struct ref **sought, int nr_sought,
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +0700910 struct shallow_info *si,
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700911 char **pack_lockfile)
912{
913 struct ref *ref = copy_ref_list(orig_ref);
brian m. carlson1b283372017-05-01 02:28:54 +0000914 struct object_id oid;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700915 const char *agent_feature;
916 int agent_len;
917
918 sort_ref_list(&ref, ref_compare_name);
René Scharfe9ed0d8d2016-09-29 17:27:31 +0200919 QSORT(sought, nr_sought, cmp_ref_by_name);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700920
Mike Edgareb86a502015-06-17 07:48:14 -0400921 if ((args->depth > 0 || is_repository_shallow()) && !server_supports("shallow"))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700922 die(_("Server does not support shallow clients"));
Nguyễn Thái Ngọc Duya45a2602016-06-12 17:54:04 +0700923 if (args->depth > 0 || args->deepen_since || args->deepen_not)
Nguyễn Thái Ngọc Duy79891cb2016-06-12 17:53:56 +0700924 args->deepen = 1;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700925 if (server_supports("multi_ack_detailed")) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700926 print_verbose(args, _("Server supports multi_ack_detailed"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700927 multi_ack = 2;
928 if (server_supports("no-done")) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700929 print_verbose(args, _("Server supports no-done"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700930 if (args->stateless_rpc)
931 no_done = 1;
932 }
933 }
934 else if (server_supports("multi_ack")) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700935 print_verbose(args, _("Server supports multi_ack"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700936 multi_ack = 1;
937 }
938 if (server_supports("side-band-64k")) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700939 print_verbose(args, _("Server supports side-band-64k"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700940 use_sideband = 2;
941 }
942 else if (server_supports("side-band")) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700943 print_verbose(args, _("Server supports side-band"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700944 use_sideband = 1;
945 }
Junio C Hamano6e7b66e2013-01-29 14:02:15 -0800946 if (server_supports("allow-tip-sha1-in-want")) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700947 print_verbose(args, _("Server supports allow-tip-sha1-in-want"));
Fredrik Medley7199c092015-05-21 22:23:38 +0200948 allow_unadvertised_object_request |= ALLOW_TIP_SHA1;
Junio C Hamano6e7b66e2013-01-29 14:02:15 -0800949 }
Fredrik Medley68ee6282015-05-21 22:23:39 +0200950 if (server_supports("allow-reachable-sha1-in-want")) {
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700951 print_verbose(args, _("Server supports allow-reachable-sha1-in-want"));
Fredrik Medley68ee6282015-05-21 22:23:39 +0200952 allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1;
953 }
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700954 if (!server_supports("thin-pack"))
955 args->use_thin_pack = 0;
956 if (!server_supports("no-progress"))
957 args->no_progress = 0;
958 if (!server_supports("include-tag"))
959 args->include_tag = 0;
Nguyễn Thái Ngọc Duy0d789a52016-06-12 17:53:54 +0700960 if (server_supports("ofs-delta"))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700961 print_verbose(args, _("Server supports ofs-delta"));
Nguyễn Thái Ngọc Duy0d789a52016-06-12 17:53:54 +0700962 else
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700963 prefer_ofs_delta = 0;
964
965 if ((agent_feature = server_feature_value("agent", &agent_len))) {
966 agent_supported = 1;
Nguyễn Thái Ngọc Duy0d789a52016-06-12 17:53:54 +0700967 if (agent_len)
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700968 print_verbose(args, _("Server version is %.*s"),
Nguyễn Thái Ngọc Duy0d789a52016-06-12 17:53:54 +0700969 agent_len, agent_feature);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700970 }
Nguyễn Thái Ngọc Duy508ea882016-06-12 17:53:59 +0700971 if (server_supports("deepen-since"))
972 deepen_since_ok = 1;
973 else if (args->deepen_since)
974 die(_("Server does not support --shallow-since"));
Nguyễn Thái Ngọc Duya45a2602016-06-12 17:54:04 +0700975 if (server_supports("deepen-not"))
976 deepen_not_ok = 1;
977 else if (args->deepen_not)
978 die(_("Server does not support --shallow-exclude"));
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +0700979 if (!server_supports("deepen-relative") && args->deepen_relative)
980 die(_("Server does not support --deepen"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700981
Junio C Hamanof2db8542013-01-29 14:02:15 -0800982 if (everything_local(args, &ref, sought, nr_sought)) {
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700983 packet_flush(fd[1]);
984 goto all_done;
985 }
brian m. carlson1b283372017-05-01 02:28:54 +0000986 if (find_common(args, fd, &oid, ref) < 0)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700987 if (!args->keep_pack)
988 /* When cloning, it is not unusual to have
989 * no common commit.
990 */
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +0700991 warning(_("no common commits"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +0700992
993 if (args->stateless_rpc)
994 packet_flush(fd[1]);
Nguyễn Thái Ngọc Duy79891cb2016-06-12 17:53:56 +0700995 if (args->deepen)
Nguyễn Thái Ngọc Duy1a30f5a2013-12-05 20:02:34 +0700996 setup_alternate_shallow(&shallow_lock, &alternate_shallow_file,
997 NULL);
Nguyễn Thái Ngọc Duy4820a332013-12-05 20:02:40 +0700998 else if (si->nr_ours || si->nr_theirs)
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +0700999 alternate_shallow_file = setup_temporary_shallow(si->shallow);
Nguyễn Thái Ngọc Duy6da8bdc2013-08-26 09:17:26 +07001000 else
1001 alternate_shallow_file = NULL;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001002 if (get_pack(args, fd, pack_lockfile))
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +07001003 die(_("git fetch-pack: fetch failed."));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001004
1005 all_done:
1006 return ref;
1007}
1008
Tanay Abhraf44af512014-08-07 09:21:20 -07001009static void fetch_pack_config(void)
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001010{
Tanay Abhraf44af512014-08-07 09:21:20 -07001011 git_config_get_int("fetch.unpacklimit", &fetch_unpack_limit);
1012 git_config_get_int("transfer.unpacklimit", &transfer_unpack_limit);
1013 git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta);
1014 git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
1015 git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001016
Tanay Abhraf44af512014-08-07 09:21:20 -07001017 git_config(git_default_config, NULL);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001018}
1019
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001020static void fetch_pack_setup(void)
1021{
1022 static int did_setup;
1023 if (did_setup)
1024 return;
Tanay Abhraf44af512014-08-07 09:21:20 -07001025 fetch_pack_config();
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001026 if (0 <= transfer_unpack_limit)
1027 unpack_limit = transfer_unpack_limit;
1028 else if (0 <= fetch_unpack_limit)
1029 unpack_limit = fetch_unpack_limit;
1030 did_setup = 1;
1031}
1032
Junio C Hamanof2db8542013-01-29 14:02:15 -08001033static int remove_duplicates_in_refs(struct ref **ref, int nr)
1034{
1035 struct string_list names = STRING_LIST_INIT_NODUP;
1036 int src, dst;
1037
1038 for (src = dst = 0; src < nr; src++) {
1039 struct string_list_item *item;
1040 item = string_list_insert(&names, ref[src]->name);
1041 if (item->util)
1042 continue; /* already have it */
1043 item->util = ref[src];
1044 if (src != dst)
1045 ref[dst] = ref[src];
1046 dst++;
1047 }
1048 for (src = dst; src < nr; src++)
1049 ref[src] = NULL;
1050 string_list_clear(&names, 0);
1051 return dst;
1052}
1053
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001054static void update_shallow(struct fetch_pack_args *args,
Nguyễn Thái Ngọc Duy4820a332013-12-05 20:02:40 +07001055 struct ref **sought, int nr_sought,
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001056 struct shallow_info *si)
Nguyễn Thái Ngọc Duya796cce2013-12-05 20:02:37 +07001057{
brian m. carlson910650d2017-03-31 01:40:00 +00001058 struct oid_array ref = OID_ARRAY_INIT;
Nguyễn Thái Ngọc Duy4820a332013-12-05 20:02:40 +07001059 int *status;
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001060 int i;
1061
Nguyễn Thái Ngọc Duy79891cb2016-06-12 17:53:56 +07001062 if (args->deepen && alternate_shallow_file) {
Nguyễn Thái Ngọc Duya796cce2013-12-05 20:02:37 +07001063 if (*alternate_shallow_file == '\0') { /* --unshallow */
Jeff Kingf9327292015-08-10 05:38:57 -04001064 unlink_or_warn(git_path_shallow());
Nguyễn Thái Ngọc Duya796cce2013-12-05 20:02:37 +07001065 rollback_lock_file(&shallow_lock);
1066 } else
1067 commit_lock_file(&shallow_lock);
1068 return;
1069 }
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001070
1071 if (!si->shallow || !si->shallow->nr)
1072 return;
1073
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001074 if (args->cloning) {
1075 /*
1076 * remote is shallow, but this is a clone, there are
1077 * no objects in repo to worry about. Accept any
1078 * shallow points that exist in the pack (iow in repo
1079 * after get_pack() and reprepare_packed_git())
1080 */
brian m. carlson910650d2017-03-31 01:40:00 +00001081 struct oid_array extra = OID_ARRAY_INIT;
brian m. carlsonee3051b2017-03-26 16:01:37 +00001082 struct object_id *oid = si->shallow->oid;
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001083 for (i = 0; i < si->shallow->nr; i++)
brian m. carlsonee3051b2017-03-26 16:01:37 +00001084 if (has_object_file(&oid[i]))
brian m. carlson910650d2017-03-31 01:40:00 +00001085 oid_array_append(&extra, &oid[i]);
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001086 if (extra.nr) {
1087 setup_alternate_shallow(&shallow_lock,
1088 &alternate_shallow_file,
1089 &extra);
1090 commit_lock_file(&shallow_lock);
1091 }
brian m. carlson910650d2017-03-31 01:40:00 +00001092 oid_array_clear(&extra);
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001093 return;
1094 }
Nguyễn Thái Ngọc Duy4820a332013-12-05 20:02:40 +07001095
1096 if (!si->nr_ours && !si->nr_theirs)
1097 return;
1098
1099 remove_nonexistent_theirs_shallow(si);
Nguyễn Thái Ngọc Duy4820a332013-12-05 20:02:40 +07001100 if (!si->nr_ours && !si->nr_theirs)
1101 return;
1102 for (i = 0; i < nr_sought; i++)
brian m. carlson910650d2017-03-31 01:40:00 +00001103 oid_array_append(&ref, &sought[i]->old_oid);
Nguyễn Thái Ngọc Duy4820a332013-12-05 20:02:40 +07001104 si->ref = &ref;
1105
Nguyễn Thái Ngọc Duy48d25ca2013-12-05 20:02:42 +07001106 if (args->update_shallow) {
1107 /*
1108 * remote is also shallow, .git/shallow may be updated
1109 * so all refs can be accepted. Make sure we only add
1110 * shallow roots that are actually reachable from new
1111 * refs.
1112 */
brian m. carlson910650d2017-03-31 01:40:00 +00001113 struct oid_array extra = OID_ARRAY_INIT;
brian m. carlsonee3051b2017-03-26 16:01:37 +00001114 struct object_id *oid = si->shallow->oid;
Nguyễn Thái Ngọc Duy48d25ca2013-12-05 20:02:42 +07001115 assign_shallow_commits_to_refs(si, NULL, NULL);
1116 if (!si->nr_ours && !si->nr_theirs) {
brian m. carlson910650d2017-03-31 01:40:00 +00001117 oid_array_clear(&ref);
Nguyễn Thái Ngọc Duy48d25ca2013-12-05 20:02:42 +07001118 return;
1119 }
1120 for (i = 0; i < si->nr_ours; i++)
brian m. carlson910650d2017-03-31 01:40:00 +00001121 oid_array_append(&extra, &oid[si->ours[i]]);
Nguyễn Thái Ngọc Duy48d25ca2013-12-05 20:02:42 +07001122 for (i = 0; i < si->nr_theirs; i++)
brian m. carlson910650d2017-03-31 01:40:00 +00001123 oid_array_append(&extra, &oid[si->theirs[i]]);
Nguyễn Thái Ngọc Duy48d25ca2013-12-05 20:02:42 +07001124 setup_alternate_shallow(&shallow_lock,
1125 &alternate_shallow_file,
1126 &extra);
1127 commit_lock_file(&shallow_lock);
brian m. carlson910650d2017-03-31 01:40:00 +00001128 oid_array_clear(&extra);
1129 oid_array_clear(&ref);
Nguyễn Thái Ngọc Duy48d25ca2013-12-05 20:02:42 +07001130 return;
1131 }
1132
Nguyễn Thái Ngọc Duy4820a332013-12-05 20:02:40 +07001133 /*
1134 * remote is also shallow, check what ref is safe to update
1135 * without updating .git/shallow
1136 */
1137 status = xcalloc(nr_sought, sizeof(*status));
1138 assign_shallow_commits_to_refs(si, NULL, status);
1139 if (si->nr_ours || si->nr_theirs) {
1140 for (i = 0; i < nr_sought; i++)
1141 if (status[i])
1142 sought[i]->status = REF_STATUS_REJECT_SHALLOW;
1143 }
1144 free(status);
brian m. carlson910650d2017-03-31 01:40:00 +00001145 oid_array_clear(&ref);
Nguyễn Thái Ngọc Duya796cce2013-12-05 20:02:37 +07001146}
1147
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001148struct ref *fetch_pack(struct fetch_pack_args *args,
1149 int fd[], struct child_process *conn,
1150 const struct ref *ref,
1151 const char *dest,
Junio C Hamanof2db8542013-01-29 14:02:15 -08001152 struct ref **sought, int nr_sought,
brian m. carlson910650d2017-03-31 01:40:00 +00001153 struct oid_array *shallow,
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001154 char **pack_lockfile)
1155{
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001156 struct ref *ref_cpy;
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001157 struct shallow_info si;
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001158
1159 fetch_pack_setup();
Junio C Hamanof2db8542013-01-29 14:02:15 -08001160 if (nr_sought)
1161 nr_sought = remove_duplicates_in_refs(sought, nr_sought);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001162
1163 if (!ref) {
1164 packet_flush(fd[1]);
Nguyễn Thái Ngọc Duy1dd73e22016-06-12 17:53:55 +07001165 die(_("no matching remote head"));
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001166 }
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001167 prepare_shallow_info(&si, shallow);
1168 ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
1169 &si, pack_lockfile);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001170 reprepare_packed_git();
Nguyễn Thái Ngọc Duy4820a332013-12-05 20:02:40 +07001171 update_shallow(args, sought, nr_sought, &si);
Nguyễn Thái Ngọc Duybeea4152013-12-05 20:02:39 +07001172 clear_shallow_info(&si);
Nguyễn Thái Ngọc Duy745f7a82012-10-26 22:53:55 +07001173 return ref_cpy;
1174}
Matt McCutchene860d962017-02-22 11:01:22 -05001175
1176int report_unmatched_refs(struct ref **sought, int nr_sought)
1177{
1178 int i, ret = 0;
1179
1180 for (i = 0; i < nr_sought; i++) {
Matt McCutchend56583d2017-02-22 11:05:57 -05001181 if (!sought[i])
Matt McCutchene860d962017-02-22 11:01:22 -05001182 continue;
Matt McCutchend56583d2017-02-22 11:05:57 -05001183 switch (sought[i]->match_status) {
1184 case REF_MATCHED:
1185 continue;
1186 case REF_NOT_MATCHED:
1187 error(_("no such remote ref %s"), sought[i]->name);
1188 break;
1189 case REF_UNADVERTISED_NOT_ALLOWED:
1190 error(_("Server does not allow request for unadvertised object %s"),
1191 sought[i]->name);
1192 break;
1193 }
Matt McCutchene860d962017-02-22 11:01:22 -05001194 ret = 1;
1195 }
1196 return ret;
1197}