@@ -44,6 +44,7 @@ static int fix_thin = 1;
44
44
static const char * head_name ;
45
45
static void * head_name_to_free ;
46
46
static int sent_capabilities ;
47
+ static int shallow_update ;
47
48
static const char * alt_shallow_file ;
48
49
49
50
static 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)
123
124
return 0 ;
124
125
}
125
126
127
+ if (strcmp (var , "receive.shallowupdate" ) == 0 ) {
128
+ shallow_update = git_config_bool (var , value );
129
+ return 0 ;
130
+ }
131
+
126
132
return git_default_config (var , value , cb );
127
133
}
128
134
@@ -423,7 +429,46 @@ static void refuse_unconfigured_deny_delete_current(void)
423
429
rp_error ("%s" , refuse_unconfigured_deny_delete_current_msg [i ]);
424
430
}
425
431
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 )
427
472
{
428
473
const char * name = cmd -> ref_name ;
429
474
struct strbuf namespaced_name_buf = STRBUF_INIT ;
@@ -531,6 +576,10 @@ static const char *update(struct command *cmd)
531
576
return NULL ; /* good */
532
577
}
533
578
else {
579
+ if (shallow_update && si -> shallow_ref [cmd -> index ] &&
580
+ update_shallow_ref (cmd , si ))
581
+ return "shallow error" ;
582
+
534
583
lock = lock_any_ref_for_update (namespaced_name , old_sha1 ,
535
584
0 , NULL );
536
585
if (!lock ) {
@@ -671,31 +720,43 @@ static int command_singleton_iterator(void *cb_data, unsigned char sha1[20])
671
720
return 0 ;
672
721
}
673
722
674
- static void set_connectivity_errors (struct command * commands )
723
+ static void set_connectivity_errors (struct command * commands ,
724
+ struct shallow_info * si )
675
725
{
676
726
struct command * cmd ;
677
727
678
728
for (cmd = commands ; cmd ; cmd = cmd -> next ) {
679
729
struct command * singleton = cmd ;
730
+ if (shallow_update && si -> shallow_ref [cmd -> index ])
731
+ /* to be checked in update_shallow_ref() */
732
+ continue ;
680
733
if (!check_everything_connected (command_singleton_iterator ,
681
734
0 , & singleton ))
682
735
continue ;
683
736
cmd -> error_string = "missing necessary objects" ;
684
737
}
685
738
}
686
739
740
+ struct iterate_data {
741
+ struct command * cmds ;
742
+ struct shallow_info * si ;
743
+ };
744
+
687
745
static int iterate_receive_command_list (void * cb_data , unsigned char sha1 [20 ])
688
746
{
689
- struct command * * cmd_list = cb_data ;
747
+ struct iterate_data * data = cb_data ;
748
+ struct command * * cmd_list = & data -> cmds ;
690
749
struct command * cmd = * cmd_list ;
691
750
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 ;
693
755
if (!is_null_sha1 (cmd -> new_sha1 ) && !cmd -> skip_update ) {
694
756
hashcpy (sha1 , cmd -> new_sha1 );
695
757
* cmd_list = cmd -> next ;
696
758
return 0 ;
697
759
}
698
- cmd = cmd -> next ;
699
760
}
700
761
* cmd_list = NULL ;
701
762
return -1 ; /* end of list */
@@ -715,21 +776,25 @@ static void reject_updates_to_hidden(struct command *commands)
715
776
}
716
777
}
717
778
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 )
719
782
{
783
+ int checked_connectivity ;
720
784
struct command * cmd ;
721
785
unsigned char sha1 [20 ];
786
+ struct iterate_data data ;
722
787
723
788
if (unpacker_error ) {
724
789
for (cmd = commands ; cmd ; cmd = cmd -> next )
725
790
cmd -> error_string = "unpacker error" ;
726
791
return ;
727
792
}
728
793
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 );
733
798
734
799
reject_updates_to_hidden (commands );
735
800
@@ -746,14 +811,30 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
746
811
free (head_name_to_free );
747
812
head_name = head_name_to_free = resolve_refdup ("HEAD" , sha1 , 0 , NULL );
748
813
814
+ checked_connectivity = 1 ;
749
815
for (cmd = commands ; cmd ; cmd = cmd -> next ) {
750
816
if (cmd -> error_string )
751
817
continue ;
752
818
753
819
if (cmd -> skip_update )
754
820
continue ;
755
821
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 );
757
838
}
758
839
}
759
840
@@ -924,6 +1005,53 @@ static const char *unpack_with_sideband(struct shallow_info *si)
924
1005
return ret ;
925
1006
}
926
1007
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
+
927
1055
static void update_shallow_info (struct command * commands ,
928
1056
struct shallow_info * si ,
929
1057
struct sha1_array * ref )
@@ -932,8 +1060,10 @@ static void update_shallow_info(struct command *commands,
932
1060
int * ref_status ;
933
1061
remove_nonexistent_theirs_shallow (si );
934
1062
/* 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 ;
936
1065
return ;
1066
+ }
937
1067
938
1068
for (cmd = commands ; cmd ; cmd = cmd -> next ) {
939
1069
if (is_null_sha1 (cmd -> new_sha1 ))
@@ -943,6 +1073,11 @@ static void update_shallow_info(struct command *commands,
943
1073
}
944
1074
si -> ref = ref ;
945
1075
1076
+ if (shallow_update ) {
1077
+ prepare_shallow_update (commands , si );
1078
+ return ;
1079
+ }
1080
+
946
1081
ref_status = xmalloc (sizeof (* ref_status ) * ref -> nr );
947
1082
assign_shallow_commits_to_refs (si , NULL , ref_status );
948
1083
for (cmd = commands ; cmd ; cmd = cmd -> next ) {
@@ -1064,11 +1199,13 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
1064
1199
const char * unpack_status = NULL ;
1065
1200
1066
1201
prepare_shallow_info (& si , & shallow );
1202
+ if (!si .nr_ours && !si .nr_theirs )
1203
+ shallow_update = 0 ;
1067
1204
if (!delete_only (commands )) {
1068
1205
unpack_status = unpack_with_sideband (& si );
1069
1206
update_shallow_info (commands , & si , & ref );
1070
1207
}
1071
- execute_commands (commands , unpack_status );
1208
+ execute_commands (commands , unpack_status , & si );
1072
1209
if (pack_lockfile )
1073
1210
unlink_or_warn (pack_lockfile );
1074
1211
if (report_status )
0 commit comments