@@ -44,6 +44,7 @@ static int fix_thin = 1;
4444static const char * head_name ;
4545static void * head_name_to_free ;
4646static int sent_capabilities ;
47+ static int shallow_update ;
4748static const char * alt_shallow_file ;
4849
4950static enum deny_action parse_deny_action (const char * var , const char * value )
@@ -123,6 +124,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
123124 return 0 ;
124125 }
125126
127+ if (strcmp (var , "receive.shallowupdate" ) == 0 ) {
128+ shallow_update = git_config_bool (var , value );
129+ return 0 ;
130+ }
131+
126132 return git_default_config (var , value , cb );
127133}
128134
@@ -423,7 +429,46 @@ static void refuse_unconfigured_deny_delete_current(void)
423429 rp_error ("%s" , refuse_unconfigured_deny_delete_current_msg [i ]);
424430}
425431
426- static const char * update (struct command * cmd )
432+ static int command_singleton_iterator (void * cb_data , unsigned char sha1 [20 ]);
433+ static int update_shallow_ref (struct command * cmd , struct shallow_info * si )
434+ {
435+ static struct lock_file shallow_lock ;
436+ struct sha1_array extra = SHA1_ARRAY_INIT ;
437+ const char * alt_file ;
438+ uint32_t mask = 1 << (cmd -> index % 32 );
439+ int i ;
440+
441+ trace_printf_key ("GIT_TRACE_SHALLOW" ,
442+ "shallow: update_shallow_ref %s\n" , cmd -> ref_name );
443+ for (i = 0 ; i < si -> shallow -> nr ; i ++ )
444+ if (si -> used_shallow [i ] &&
445+ (si -> used_shallow [i ][cmd -> index / 32 ] & mask ) &&
446+ !delayed_reachability_test (si , i ))
447+ sha1_array_append (& extra , si -> shallow -> sha1 [i ]);
448+
449+ setup_alternate_shallow (& shallow_lock , & alt_file , & extra );
450+ if (check_shallow_connected (command_singleton_iterator ,
451+ 0 , cmd , alt_file )) {
452+ rollback_lock_file (& shallow_lock );
453+ sha1_array_clear (& extra );
454+ return -1 ;
455+ }
456+
457+ commit_lock_file (& shallow_lock );
458+
459+ /*
460+ * Make sure setup_alternate_shallow() for the next ref does
461+ * not lose these new roots..
462+ */
463+ for (i = 0 ; i < extra .nr ; i ++ )
464+ register_shallow (extra .sha1 [i ]);
465+
466+ si -> shallow_ref [cmd -> index ] = 0 ;
467+ sha1_array_clear (& extra );
468+ return 0 ;
469+ }
470+
471+ static const char * update (struct command * cmd , struct shallow_info * si )
427472{
428473 const char * name = cmd -> ref_name ;
429474 struct strbuf namespaced_name_buf = STRBUF_INIT ;
@@ -531,6 +576,10 @@ static const char *update(struct command *cmd)
531576 return NULL ; /* good */
532577 }
533578 else {
579+ if (shallow_update && si -> shallow_ref [cmd -> index ] &&
580+ update_shallow_ref (cmd , si ))
581+ return "shallow error" ;
582+
534583 lock = lock_any_ref_for_update (namespaced_name , old_sha1 ,
535584 0 , NULL );
536585 if (!lock ) {
@@ -671,31 +720,43 @@ static int command_singleton_iterator(void *cb_data, unsigned char sha1[20])
671720 return 0 ;
672721}
673722
674- static void set_connectivity_errors (struct command * commands )
723+ static void set_connectivity_errors (struct command * commands ,
724+ struct shallow_info * si )
675725{
676726 struct command * cmd ;
677727
678728 for (cmd = commands ; cmd ; cmd = cmd -> next ) {
679729 struct command * singleton = cmd ;
730+ if (shallow_update && si -> shallow_ref [cmd -> index ])
731+ /* to be checked in update_shallow_ref() */
732+ continue ;
680733 if (!check_everything_connected (command_singleton_iterator ,
681734 0 , & singleton ))
682735 continue ;
683736 cmd -> error_string = "missing necessary objects" ;
684737 }
685738}
686739
740+ struct iterate_data {
741+ struct command * cmds ;
742+ struct shallow_info * si ;
743+ };
744+
687745static int iterate_receive_command_list (void * cb_data , unsigned char sha1 [20 ])
688746{
689- struct command * * cmd_list = cb_data ;
747+ struct iterate_data * data = cb_data ;
748+ struct command * * cmd_list = & data -> cmds ;
690749 struct command * cmd = * cmd_list ;
691750
692- while (cmd ) {
751+ for (; cmd ; cmd = cmd -> next ) {
752+ if (shallow_update && data -> si -> shallow_ref [cmd -> index ])
753+ /* to be checked in update_shallow_ref() */
754+ continue ;
693755 if (!is_null_sha1 (cmd -> new_sha1 ) && !cmd -> skip_update ) {
694756 hashcpy (sha1 , cmd -> new_sha1 );
695757 * cmd_list = cmd -> next ;
696758 return 0 ;
697759 }
698- cmd = cmd -> next ;
699760 }
700761 * cmd_list = NULL ;
701762 return -1 ; /* end of list */
@@ -715,21 +776,25 @@ static void reject_updates_to_hidden(struct command *commands)
715776 }
716777}
717778
718- static void execute_commands (struct command * commands , const char * unpacker_error )
779+ static void execute_commands (struct command * commands ,
780+ const char * unpacker_error ,
781+ struct shallow_info * si )
719782{
783+ int checked_connectivity ;
720784 struct command * cmd ;
721785 unsigned char sha1 [20 ];
786+ struct iterate_data data ;
722787
723788 if (unpacker_error ) {
724789 for (cmd = commands ; cmd ; cmd = cmd -> next )
725790 cmd -> error_string = "unpacker error" ;
726791 return ;
727792 }
728793
729- cmd = commands ;
730- if ( check_everything_connected ( iterate_receive_command_list ,
731- 0 , & cmd ))
732- set_connectivity_errors (commands );
794+ data . cmds = commands ;
795+ data . si = si ;
796+ if ( check_everything_connected ( iterate_receive_command_list , 0 , & data ))
797+ set_connectivity_errors (commands , si );
733798
734799 reject_updates_to_hidden (commands );
735800
@@ -746,14 +811,30 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
746811 free (head_name_to_free );
747812 head_name = head_name_to_free = resolve_refdup ("HEAD" , sha1 , 0 , NULL );
748813
814+ checked_connectivity = 1 ;
749815 for (cmd = commands ; cmd ; cmd = cmd -> next ) {
750816 if (cmd -> error_string )
751817 continue ;
752818
753819 if (cmd -> skip_update )
754820 continue ;
755821
756- cmd -> error_string = update (cmd );
822+ cmd -> error_string = update (cmd , si );
823+ if (shallow_update && !cmd -> error_string &&
824+ si -> shallow_ref [cmd -> index ]) {
825+ error ("BUG: connectivity check has not been run on ref %s" ,
826+ cmd -> ref_name );
827+ checked_connectivity = 0 ;
828+ }
829+ }
830+
831+ if (shallow_update ) {
832+ if (!checked_connectivity )
833+ error ("BUG: run 'git fsck' for safety.\n"
834+ "If there are errors, try to remove "
835+ "the reported refs above" );
836+ if (alt_shallow_file && * alt_shallow_file )
837+ unlink (alt_shallow_file );
757838 }
758839}
759840
@@ -924,6 +1005,53 @@ static const char *unpack_with_sideband(struct shallow_info *si)
9241005 return ret ;
9251006}
9261007
1008+ static void prepare_shallow_update (struct command * commands ,
1009+ struct shallow_info * si )
1010+ {
1011+ int i , j , k , bitmap_size = (si -> ref -> nr + 31 ) / 32 ;
1012+
1013+ si -> used_shallow = xmalloc (sizeof (* si -> used_shallow ) *
1014+ si -> shallow -> nr );
1015+ assign_shallow_commits_to_refs (si , si -> used_shallow , NULL );
1016+
1017+ si -> need_reachability_test =
1018+ xcalloc (si -> shallow -> nr , sizeof (* si -> need_reachability_test ));
1019+ si -> reachable =
1020+ xcalloc (si -> shallow -> nr , sizeof (* si -> reachable ));
1021+ si -> shallow_ref = xcalloc (si -> ref -> nr , sizeof (* si -> shallow_ref ));
1022+
1023+ for (i = 0 ; i < si -> nr_ours ; i ++ )
1024+ si -> need_reachability_test [si -> ours [i ]] = 1 ;
1025+
1026+ for (i = 0 ; i < si -> shallow -> nr ; i ++ ) {
1027+ if (!si -> used_shallow [i ])
1028+ continue ;
1029+ for (j = 0 ; j < bitmap_size ; j ++ ) {
1030+ if (!si -> used_shallow [i ][j ])
1031+ continue ;
1032+ si -> need_reachability_test [i ]++ ;
1033+ for (k = 0 ; k < 32 ; k ++ )
1034+ if (si -> used_shallow [i ][j ] & (1 << k ))
1035+ si -> shallow_ref [j * 32 + k ]++ ;
1036+ }
1037+
1038+ /*
1039+ * true for those associated with some refs and belong
1040+ * in "ours" list aka "step 7 not done yet"
1041+ */
1042+ si -> need_reachability_test [i ] =
1043+ si -> need_reachability_test [i ] > 1 ;
1044+ }
1045+
1046+ /*
1047+ * keep hooks happy by forcing a temporary shallow file via
1048+ * env variable because we can't add --shallow-file to every
1049+ * command. check_everything_connected() will be done with
1050+ * true .git/shallow though.
1051+ */
1052+ setenv (GIT_SHALLOW_FILE_ENVIRONMENT , alt_shallow_file , 1 );
1053+ }
1054+
9271055static void update_shallow_info (struct command * commands ,
9281056 struct shallow_info * si ,
9291057 struct sha1_array * ref )
@@ -932,8 +1060,10 @@ static void update_shallow_info(struct command *commands,
9321060 int * ref_status ;
9331061 remove_nonexistent_theirs_shallow (si );
9341062 /* XXX remove_nonexistent_ours_in_pack() */
935- if (!si -> nr_ours && !si -> nr_theirs )
1063+ if (!si -> nr_ours && !si -> nr_theirs ) {
1064+ shallow_update = 0 ;
9361065 return ;
1066+ }
9371067
9381068 for (cmd = commands ; cmd ; cmd = cmd -> next ) {
9391069 if (is_null_sha1 (cmd -> new_sha1 ))
@@ -943,6 +1073,11 @@ static void update_shallow_info(struct command *commands,
9431073 }
9441074 si -> ref = ref ;
9451075
1076+ if (shallow_update ) {
1077+ prepare_shallow_update (commands , si );
1078+ return ;
1079+ }
1080+
9461081 ref_status = xmalloc (sizeof (* ref_status ) * ref -> nr );
9471082 assign_shallow_commits_to_refs (si , NULL , ref_status );
9481083 for (cmd = commands ; cmd ; cmd = cmd -> next ) {
@@ -1064,11 +1199,13 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
10641199 const char * unpack_status = NULL ;
10651200
10661201 prepare_shallow_info (& si , & shallow );
1202+ if (!si .nr_ours && !si .nr_theirs )
1203+ shallow_update = 0 ;
10671204 if (!delete_only (commands )) {
10681205 unpack_status = unpack_with_sideband (& si );
10691206 update_shallow_info (commands , & si , & ref );
10701207 }
1071- execute_commands (commands , unpack_status );
1208+ execute_commands (commands , unpack_status , & si );
10721209 if (pack_lockfile )
10731210 unlink_or_warn (pack_lockfile );
10741211 if (report_status )
0 commit comments