12
12
13
13
static const char upload_pack_usage [] = "git-upload-pack [--strict] [--timeout=nn] <dir>" ;
14
14
15
- #define THEY_HAVE (1U << 0)
16
- #define OUR_REF (1U << 1)
17
- #define WANTED (1U << 2)
15
+ /* bits #0..7 in revision.h, #8..10 in commit.c */
16
+ #define THEY_HAVE (1u << 11)
17
+ #define OUR_REF (1u << 12)
18
+ #define WANTED (1u << 13)
19
+ #define COMMON_KNOWN (1u << 14)
20
+ #define REACHABLE (1u << 15)
21
+
22
+ static unsigned long oldest_have ;
23
+
18
24
static int multi_ack , nr_our_refs ;
19
25
static int use_thin_pack , use_ofs_delta ;
20
26
static struct object_array have_obj ;
@@ -303,11 +309,12 @@ static void create_pack_file(void)
303
309
static int got_sha1 (char * hex , unsigned char * sha1 )
304
310
{
305
311
struct object * o ;
312
+ int we_knew_they_have = 0 ;
306
313
307
314
if (get_sha1_hex (hex , sha1 ))
308
315
die ("git-upload-pack: expected SHA1 object, got '%s'" , hex );
309
316
if (!has_sha1_file (sha1 ))
310
- return 0 ;
317
+ return -1 ;
311
318
312
319
o = lookup_object (sha1 );
313
320
if (!(o && o -> parsed ))
@@ -316,15 +323,84 @@ static int got_sha1(char *hex, unsigned char *sha1)
316
323
die ("oops (%s)" , sha1_to_hex (sha1 ));
317
324
if (o -> type == OBJ_COMMIT ) {
318
325
struct commit_list * parents ;
326
+ struct commit * commit = (struct commit * )o ;
319
327
if (o -> flags & THEY_HAVE )
320
- return 0 ;
321
- o -> flags |= THEY_HAVE ;
322
- for (parents = ((struct commit * )o )-> parents ;
328
+ we_knew_they_have = 1 ;
329
+ else
330
+ o -> flags |= THEY_HAVE ;
331
+ if (!oldest_have || (commit -> date < oldest_have ))
332
+ oldest_have = commit -> date ;
333
+ for (parents = commit -> parents ;
323
334
parents ;
324
335
parents = parents -> next )
325
336
parents -> item -> object .flags |= THEY_HAVE ;
326
337
}
327
- add_object_array (o , NULL , & have_obj );
338
+ if (!we_knew_they_have ) {
339
+ add_object_array (o , NULL , & have_obj );
340
+ return 1 ;
341
+ }
342
+ return 0 ;
343
+ }
344
+
345
+ static int reachable (struct commit * want )
346
+ {
347
+ struct commit_list * work = NULL ;
348
+
349
+ insert_by_date (want , & work );
350
+ while (work ) {
351
+ struct commit_list * list = work -> next ;
352
+ struct commit * commit = work -> item ;
353
+ free (work );
354
+ work = list ;
355
+
356
+ if (commit -> object .flags & THEY_HAVE ) {
357
+ want -> object .flags |= COMMON_KNOWN ;
358
+ break ;
359
+ }
360
+ if (!commit -> object .parsed )
361
+ parse_object (commit -> object .sha1 );
362
+ if (commit -> object .flags & REACHABLE )
363
+ continue ;
364
+ commit -> object .flags |= REACHABLE ;
365
+ if (commit -> date < oldest_have )
366
+ continue ;
367
+ for (list = commit -> parents ; list ; list = list -> next ) {
368
+ struct commit * parent = list -> item ;
369
+ if (!(parent -> object .flags & REACHABLE ))
370
+ insert_by_date (parent , & work );
371
+ }
372
+ }
373
+ want -> object .flags |= REACHABLE ;
374
+ clear_commit_marks (want , REACHABLE );
375
+ free_commit_list (work );
376
+ return (want -> object .flags & COMMON_KNOWN );
377
+ }
378
+
379
+ static int ok_to_give_up (void )
380
+ {
381
+ int i ;
382
+
383
+ if (!have_obj .nr )
384
+ return 0 ;
385
+
386
+ for (i = 0 ; i < want_obj .nr ; i ++ ) {
387
+ struct object * want = want_obj .objects [i ].item ;
388
+
389
+ if (want -> flags & COMMON_KNOWN )
390
+ continue ;
391
+ want = deref_tag (want , "a want line" , 0 );
392
+ if (!want || want -> type != OBJ_COMMIT ) {
393
+ /* no way to tell if this is reachable by
394
+ * looking at the ancestry chain alone, so
395
+ * leave a note to ourselves not to worry about
396
+ * this object anymore.
397
+ */
398
+ want_obj .objects [i ].item -> flags |= COMMON_KNOWN ;
399
+ continue ;
400
+ }
401
+ if (!reachable ((struct commit * )want ))
402
+ return 0 ;
403
+ }
328
404
return 1 ;
329
405
}
330
406
@@ -349,7 +425,13 @@ static int get_common_commits(void)
349
425
}
350
426
len = strip (line , len );
351
427
if (!strncmp (line , "have " , 5 )) {
352
- if (got_sha1 (line + 5 , sha1 )) {
428
+ switch (got_sha1 (line + 5 , sha1 )) {
429
+ case -1 : /* they have what we do not */
430
+ if (multi_ack && ok_to_give_up ())
431
+ packet_write (1 , "ACK %s continue\n" ,
432
+ sha1_to_hex (sha1 ));
433
+ break ;
434
+ default :
353
435
memcpy (hex , sha1_to_hex (sha1 ), 41 );
354
436
if (multi_ack ) {
355
437
const char * msg = "ACK %s continue\n" ;
@@ -358,6 +440,7 @@ static int get_common_commits(void)
358
440
}
359
441
else if (have_obj .nr == 1 )
360
442
packet_write (1 , "ACK %s\n" , hex );
443
+ break ;
361
444
}
362
445
continue ;
363
446
}
0 commit comments