@@ -317,3 +317,297 @@ void remove_nonexistent_ours_in_pack(struct shallow_info *info,
317317 }
318318 info -> nr_ours = dst ;
319319}
320+
321+ define_commit_slab (ref_bitmap , uint32_t * );
322+
323+ struct paint_info {
324+ struct ref_bitmap ref_bitmap ;
325+ unsigned nr_bits ;
326+ char * * slab ;
327+ char * free , * end ;
328+ unsigned slab_count ;
329+ };
330+
331+ static uint32_t * paint_alloc (struct paint_info * info )
332+ {
333+ unsigned nr = (info -> nr_bits + 31 ) / 32 ;
334+ unsigned size = nr * sizeof (uint32_t );
335+ void * p ;
336+ if (!info -> slab_count || info -> free + size > info -> end ) {
337+ info -> slab_count ++ ;
338+ info -> slab = xrealloc (info -> slab ,
339+ info -> slab_count * sizeof (* info -> slab ));
340+ info -> free = xmalloc (COMMIT_SLAB_SIZE );
341+ info -> slab [info -> slab_count - 1 ] = info -> free ;
342+ info -> end = info -> free + COMMIT_SLAB_SIZE ;
343+ }
344+ p = info -> free ;
345+ info -> free += size ;
346+ return p ;
347+ }
348+
349+ /*
350+ * Given a commit SHA-1, walk down to parents until either SEEN,
351+ * UNINTERESTING or BOTTOM is hit. Set the id-th bit in ref_bitmap for
352+ * all walked commits.
353+ */
354+ static void paint_down (struct paint_info * info , const unsigned char * sha1 ,
355+ int id )
356+ {
357+ unsigned int i , nr ;
358+ struct commit_list * head = NULL ;
359+ int bitmap_nr = (info -> nr_bits + 31 ) / 32 ;
360+ int bitmap_size = bitmap_nr * sizeof (uint32_t );
361+ uint32_t * tmp = xmalloc (bitmap_size ); /* to be freed before return */
362+ uint32_t * bitmap = paint_alloc (info );
363+ struct commit * c = lookup_commit_reference_gently (sha1 , 1 );
364+ if (!c )
365+ return ;
366+ memset (bitmap , 0 , bitmap_size );
367+ bitmap [id / 32 ] |= (1 << (id % 32 ));
368+ commit_list_insert (c , & head );
369+ while (head ) {
370+ struct commit_list * p ;
371+ struct commit * c = head -> item ;
372+ uint32_t * * refs = ref_bitmap_at (& info -> ref_bitmap , c );
373+
374+ p = head ;
375+ head = head -> next ;
376+ free (p );
377+
378+ /* XXX check "UNINTERESTING" from pack bitmaps if available */
379+ if (c -> object .flags & (SEEN | UNINTERESTING ))
380+ continue ;
381+ else
382+ c -> object .flags |= SEEN ;
383+
384+ if (* refs == NULL )
385+ * refs = bitmap ;
386+ else {
387+ memcpy (tmp , * refs , bitmap_size );
388+ for (i = 0 ; i < bitmap_nr ; i ++ )
389+ tmp [i ] |= bitmap [i ];
390+ if (memcmp (tmp , * refs , bitmap_size )) {
391+ * refs = paint_alloc (info );
392+ memcpy (* refs , tmp , bitmap_size );
393+ }
394+ }
395+
396+ if (c -> object .flags & BOTTOM )
397+ continue ;
398+
399+ if (parse_commit (c ))
400+ die ("unable to parse commit %s" ,
401+ sha1_to_hex (c -> object .sha1 ));
402+
403+ for (p = c -> parents ; p ; p = p -> next ) {
404+ uint32_t * * p_refs = ref_bitmap_at (& info -> ref_bitmap ,
405+ p -> item );
406+ if (p -> item -> object .flags & SEEN )
407+ continue ;
408+ if (* p_refs == NULL || * p_refs == * refs )
409+ * p_refs = * refs ;
410+ commit_list_insert (p -> item , & head );
411+ }
412+ }
413+
414+ nr = get_max_object_index ();
415+ for (i = 0 ; i < nr ; i ++ ) {
416+ struct object * o = get_indexed_object (i );
417+ if (o && o -> type == OBJ_COMMIT )
418+ o -> flags &= ~SEEN ;
419+ }
420+
421+ free (tmp );
422+ }
423+
424+ static int mark_uninteresting (const char * refname ,
425+ const unsigned char * sha1 ,
426+ int flags , void * cb_data )
427+ {
428+ struct commit * commit = lookup_commit_reference_gently (sha1 , 1 );
429+ if (!commit )
430+ return 0 ;
431+ commit -> object .flags |= UNINTERESTING ;
432+ mark_parents_uninteresting (commit );
433+ return 0 ;
434+ }
435+
436+ static void post_assign_shallow (struct shallow_info * info ,
437+ struct ref_bitmap * ref_bitmap ,
438+ int * ref_status );
439+ /*
440+ * Step 6(+7), associate shallow commits with new refs
441+ *
442+ * info->ref must be initialized before calling this function.
443+ *
444+ * If used is not NULL, it's an array of info->shallow->nr
445+ * bitmaps. The n-th bit set in the m-th bitmap if ref[n] needs the
446+ * m-th shallow commit from info->shallow.
447+ *
448+ * If used is NULL, "ours" and "theirs" are updated. And if ref_status
449+ * is not NULL it's an array of ref->nr ints. ref_status[i] is true if
450+ * the ref needs some shallow commits from either info->ours or
451+ * info->theirs.
452+ */
453+ void assign_shallow_commits_to_refs (struct shallow_info * info ,
454+ uint32_t * * used , int * ref_status )
455+ {
456+ unsigned char (* sha1 )[20 ] = info -> shallow -> sha1 ;
457+ struct sha1_array * ref = info -> ref ;
458+ unsigned int i , nr ;
459+ int * shallow , nr_shallow = 0 ;
460+ struct paint_info pi ;
461+
462+ trace_printf_key (TRACE_KEY , "shallow: assign_shallow_commits_to_refs\n" );
463+ shallow = xmalloc (sizeof (* shallow ) * (info -> nr_ours + info -> nr_theirs ));
464+ for (i = 0 ; i < info -> nr_ours ; i ++ )
465+ shallow [nr_shallow ++ ] = info -> ours [i ];
466+ for (i = 0 ; i < info -> nr_theirs ; i ++ )
467+ shallow [nr_shallow ++ ] = info -> theirs [i ];
468+
469+ /*
470+ * Prepare the commit graph to track what refs can reach what
471+ * (new) shallow commits.
472+ */
473+ nr = get_max_object_index ();
474+ for (i = 0 ; i < nr ; i ++ ) {
475+ struct object * o = get_indexed_object (i );
476+ if (!o || o -> type != OBJ_COMMIT )
477+ continue ;
478+
479+ o -> flags &= ~(UNINTERESTING | BOTTOM | SEEN );
480+ }
481+
482+ memset (& pi , 0 , sizeof (pi ));
483+ init_ref_bitmap (& pi .ref_bitmap );
484+ pi .nr_bits = ref -> nr ;
485+
486+ /*
487+ * "--not --all" to cut short the traversal if new refs
488+ * connect to old refs. If not (e.g. force ref updates) it'll
489+ * have to go down to the current shallow commits.
490+ */
491+ head_ref (mark_uninteresting , NULL );
492+ for_each_ref (mark_uninteresting , NULL );
493+
494+ /* Mark potential bottoms so we won't go out of bound */
495+ for (i = 0 ; i < nr_shallow ; i ++ ) {
496+ struct commit * c = lookup_commit (sha1 [shallow [i ]]);
497+ c -> object .flags |= BOTTOM ;
498+ }
499+
500+ for (i = 0 ; i < ref -> nr ; i ++ )
501+ paint_down (& pi , ref -> sha1 [i ], i );
502+
503+ if (used ) {
504+ int bitmap_size = ((pi .nr_bits + 31 ) / 32 ) * sizeof (uint32_t );
505+ memset (used , 0 , sizeof (* used ) * info -> shallow -> nr );
506+ for (i = 0 ; i < nr_shallow ; i ++ ) {
507+ const struct commit * c = lookup_commit (sha1 [shallow [i ]]);
508+ uint32_t * * map = ref_bitmap_at (& pi .ref_bitmap , c );
509+ if (* map )
510+ used [shallow [i ]] = xmemdupz (* map , bitmap_size );
511+ }
512+ /*
513+ * unreachable shallow commits are not removed from
514+ * "ours" and "theirs". The user is supposed to run
515+ * step 7 on every ref separately and not trust "ours"
516+ * and "theirs" any more.
517+ */
518+ } else
519+ post_assign_shallow (info , & pi .ref_bitmap , ref_status );
520+
521+ clear_ref_bitmap (& pi .ref_bitmap );
522+ for (i = 0 ; i < pi .slab_count ; i ++ )
523+ free (pi .slab [i ]);
524+ free (pi .slab );
525+ free (shallow );
526+ }
527+
528+ struct commit_array {
529+ struct commit * * commits ;
530+ int nr , alloc ;
531+ };
532+
533+ static int add_ref (const char * refname ,
534+ const unsigned char * sha1 , int flags , void * cb_data )
535+ {
536+ struct commit_array * ca = cb_data ;
537+ ALLOC_GROW (ca -> commits , ca -> nr + 1 , ca -> alloc );
538+ ca -> commits [ca -> nr ] = lookup_commit_reference_gently (sha1 , 1 );
539+ if (ca -> commits [ca -> nr ])
540+ ca -> nr ++ ;
541+ return 0 ;
542+ }
543+
544+ static void update_refstatus (int * ref_status , int nr , uint32_t * bitmap )
545+ {
546+ int i ;
547+ if (!ref_status )
548+ return ;
549+ for (i = 0 ; i < nr ; i ++ )
550+ if (bitmap [i / 32 ] & (1 << (i % 32 )))
551+ ref_status [i ]++ ;
552+ }
553+
554+ /*
555+ * Step 7, reachability test on "ours" at commit level
556+ */
557+ static void post_assign_shallow (struct shallow_info * info ,
558+ struct ref_bitmap * ref_bitmap ,
559+ int * ref_status )
560+ {
561+ unsigned char (* sha1 )[20 ] = info -> shallow -> sha1 ;
562+ struct commit * c ;
563+ uint32_t * * bitmap ;
564+ int dst , i , j ;
565+ int bitmap_nr = (info -> ref -> nr + 31 ) / 32 ;
566+ struct commit_array ca ;
567+
568+ trace_printf_key (TRACE_KEY , "shallow: post_assign_shallow\n" );
569+ if (ref_status )
570+ memset (ref_status , 0 , sizeof (* ref_status ) * info -> ref -> nr );
571+
572+ /* Remove unreachable shallow commits from "theirs" */
573+ for (i = dst = 0 ; i < info -> nr_theirs ; i ++ ) {
574+ if (i != dst )
575+ info -> theirs [dst ] = info -> theirs [i ];
576+ c = lookup_commit (sha1 [info -> theirs [i ]]);
577+ bitmap = ref_bitmap_at (ref_bitmap , c );
578+ if (!* bitmap )
579+ continue ;
580+ for (j = 0 ; j < bitmap_nr ; j ++ )
581+ if (bitmap [0 ][j ]) {
582+ update_refstatus (ref_status , info -> ref -> nr , * bitmap );
583+ dst ++ ;
584+ break ;
585+ }
586+ }
587+ info -> nr_theirs = dst ;
588+
589+ memset (& ca , 0 , sizeof (ca ));
590+ head_ref (add_ref , & ca );
591+ for_each_ref (add_ref , & ca );
592+
593+ /* Remove unreachable shallow commits from "ours" */
594+ for (i = dst = 0 ; i < info -> nr_ours ; i ++ ) {
595+ if (i != dst )
596+ info -> ours [dst ] = info -> ours [i ];
597+ c = lookup_commit (sha1 [info -> ours [i ]]);
598+ bitmap = ref_bitmap_at (ref_bitmap , c );
599+ if (!* bitmap )
600+ continue ;
601+ for (j = 0 ; j < bitmap_nr ; j ++ )
602+ if (bitmap [0 ][j ] &&
603+ /* Step 7, reachability test at commit level */
604+ !in_merge_bases_many (c , ca .nr , ca .commits )) {
605+ update_refstatus (ref_status , info -> ref -> nr , * bitmap );
606+ dst ++ ;
607+ break ;
608+ }
609+ }
610+ info -> nr_ours = dst ;
611+
612+ free (ca .commits );
613+ }
0 commit comments