@@ -496,6 +496,7 @@ static int apply_single_file_filter(const char *path, const char *src, size_t le
496
496
497
497
#define CAP_CLEAN (1u<<0)
498
498
#define CAP_SMUDGE (1u<<1)
499
+ #define CAP_DELAY (1u<<2)
499
500
500
501
struct cmd2process {
501
502
struct subprocess_entry subprocess ; /* must be the first member! */
@@ -521,6 +522,7 @@ static int start_multi_file_filter_fn(struct subprocess_entry *subprocess)
521
522
} known_caps [] = {
522
523
{ "clean" , CAP_CLEAN },
523
524
{ "smudge" , CAP_SMUDGE },
525
+ { "delay" , CAP_DELAY },
524
526
};
525
527
526
528
sigchain_push (SIGPIPE , SIG_IGN );
@@ -605,9 +607,11 @@ static void handle_filter_error(const struct strbuf *filter_status,
605
607
606
608
static int apply_multi_file_filter (const char * path , const char * src , size_t len ,
607
609
int fd , struct strbuf * dst , const char * cmd ,
608
- const unsigned int wanted_capability )
610
+ const unsigned int wanted_capability ,
611
+ struct delayed_checkout * dco )
609
612
{
610
613
int err ;
614
+ int can_delay = 0 ;
611
615
struct cmd2process * entry ;
612
616
struct child_process * process ;
613
617
struct strbuf nbuf = STRBUF_INIT ;
@@ -662,6 +666,14 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len
662
666
if (err )
663
667
goto done ;
664
668
669
+ if ((entry -> supported_capabilities & CAP_DELAY ) &&
670
+ dco && dco -> state == CE_CAN_DELAY ) {
671
+ can_delay = 1 ;
672
+ err = packet_write_fmt_gently (process -> in , "can-delay=1\n" );
673
+ if (err )
674
+ goto done ;
675
+ }
676
+
665
677
err = packet_flush_gently (process -> in );
666
678
if (err )
667
679
goto done ;
@@ -677,14 +689,73 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len
677
689
if (err )
678
690
goto done ;
679
691
680
- err = strcmp (filter_status .buf , "success" );
692
+ if (can_delay && !strcmp (filter_status .buf , "delayed" )) {
693
+ string_list_insert (& dco -> filters , cmd );
694
+ string_list_insert (& dco -> paths , path );
695
+ } else {
696
+ /* The filter got the blob and wants to send us a response. */
697
+ err = strcmp (filter_status .buf , "success" );
698
+ if (err )
699
+ goto done ;
700
+
701
+ err = read_packetized_to_strbuf (process -> out , & nbuf ) < 0 ;
702
+ if (err )
703
+ goto done ;
704
+
705
+ err = subprocess_read_status (process -> out , & filter_status );
706
+ if (err )
707
+ goto done ;
708
+
709
+ err = strcmp (filter_status .buf , "success" );
710
+ }
711
+
712
+ done :
713
+ sigchain_pop (SIGPIPE );
714
+
715
+ if (err )
716
+ handle_filter_error (& filter_status , entry , wanted_capability );
717
+ else
718
+ strbuf_swap (dst , & nbuf );
719
+ strbuf_release (& nbuf );
720
+ return !err ;
721
+ }
722
+
723
+
724
+ int async_query_available_blobs (const char * cmd , struct string_list * available_paths )
725
+ {
726
+ int err ;
727
+ char * line ;
728
+ struct cmd2process * entry ;
729
+ struct child_process * process ;
730
+ struct strbuf filter_status = STRBUF_INIT ;
731
+
732
+ assert (subprocess_map_initialized );
733
+ entry = (struct cmd2process * )subprocess_find_entry (& subprocess_map , cmd );
734
+ if (!entry ) {
735
+ error ("external filter '%s' is not available anymore although "
736
+ "not all paths have been filtered" , cmd );
737
+ return 0 ;
738
+ }
739
+ process = & entry -> subprocess .process ;
740
+ sigchain_push (SIGPIPE , SIG_IGN );
741
+
742
+ err = packet_write_fmt_gently (
743
+ process -> in , "command=list_available_blobs\n" );
681
744
if (err )
682
745
goto done ;
683
746
684
- err = read_packetized_to_strbuf (process -> out , & nbuf ) < 0 ;
747
+ err = packet_flush_gently (process -> in ) ;
685
748
if (err )
686
749
goto done ;
687
750
751
+ while ((line = packet_read_line (process -> out , NULL ))) {
752
+ const char * path ;
753
+ if (skip_prefix (line , "pathname=" , & path ))
754
+ string_list_insert (available_paths , xstrdup (path ));
755
+ else
756
+ ; /* ignore unknown keys */
757
+ }
758
+
688
759
err = subprocess_read_status (process -> out , & filter_status );
689
760
if (err )
690
761
goto done ;
@@ -695,10 +766,7 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len
695
766
sigchain_pop (SIGPIPE );
696
767
697
768
if (err )
698
- handle_filter_error (& filter_status , entry , wanted_capability );
699
- else
700
- strbuf_swap (dst , & nbuf );
701
- strbuf_release (& nbuf );
769
+ handle_filter_error (& filter_status , entry , 0 );
702
770
return !err ;
703
771
}
704
772
@@ -713,7 +781,8 @@ static struct convert_driver {
713
781
714
782
static int apply_filter (const char * path , const char * src , size_t len ,
715
783
int fd , struct strbuf * dst , struct convert_driver * drv ,
716
- const unsigned int wanted_capability )
784
+ const unsigned int wanted_capability ,
785
+ struct delayed_checkout * dco )
717
786
{
718
787
const char * cmd = NULL ;
719
788
@@ -731,7 +800,8 @@ static int apply_filter(const char *path, const char *src, size_t len,
731
800
if (cmd && * cmd )
732
801
return apply_single_file_filter (path , src , len , fd , dst , cmd );
733
802
else if (drv -> process && * drv -> process )
734
- return apply_multi_file_filter (path , src , len , fd , dst , drv -> process , wanted_capability );
803
+ return apply_multi_file_filter (path , src , len , fd , dst ,
804
+ drv -> process , wanted_capability , dco );
735
805
736
806
return 0 ;
737
807
}
@@ -1072,7 +1142,7 @@ int would_convert_to_git_filter_fd(const char *path)
1072
1142
if (!ca .drv -> required )
1073
1143
return 0 ;
1074
1144
1075
- return apply_filter (path , NULL , 0 , -1 , NULL , ca .drv , CAP_CLEAN );
1145
+ return apply_filter (path , NULL , 0 , -1 , NULL , ca .drv , CAP_CLEAN , NULL );
1076
1146
}
1077
1147
1078
1148
const char * get_convert_attr_ascii (const char * path )
@@ -1109,7 +1179,7 @@ int convert_to_git(const char *path, const char *src, size_t len,
1109
1179
1110
1180
convert_attrs (& ca , path );
1111
1181
1112
- ret |= apply_filter (path , src , len , -1 , dst , ca .drv , CAP_CLEAN );
1182
+ ret |= apply_filter (path , src , len , -1 , dst , ca .drv , CAP_CLEAN , NULL );
1113
1183
if (!ret && ca .drv && ca .drv -> required )
1114
1184
die ("%s: clean filter '%s' failed" , path , ca .drv -> name );
1115
1185
@@ -1134,7 +1204,7 @@ void convert_to_git_filter_fd(const char *path, int fd, struct strbuf *dst,
1134
1204
assert (ca .drv );
1135
1205
assert (ca .drv -> clean || ca .drv -> process );
1136
1206
1137
- if (!apply_filter (path , NULL , 0 , fd , dst , ca .drv , CAP_CLEAN ))
1207
+ if (!apply_filter (path , NULL , 0 , fd , dst , ca .drv , CAP_CLEAN , NULL ))
1138
1208
die ("%s: clean filter '%s' failed" , path , ca .drv -> name );
1139
1209
1140
1210
crlf_to_git (path , dst -> buf , dst -> len , dst , ca .crlf_action , checksafe );
@@ -1143,7 +1213,7 @@ void convert_to_git_filter_fd(const char *path, int fd, struct strbuf *dst,
1143
1213
1144
1214
static int convert_to_working_tree_internal (const char * path , const char * src ,
1145
1215
size_t len , struct strbuf * dst ,
1146
- int normalizing )
1216
+ int normalizing , struct delayed_checkout * dco )
1147
1217
{
1148
1218
int ret = 0 , ret_filter = 0 ;
1149
1219
struct conv_attrs ca ;
@@ -1168,21 +1238,29 @@ static int convert_to_working_tree_internal(const char *path, const char *src,
1168
1238
}
1169
1239
}
1170
1240
1171
- ret_filter = apply_filter (path , src , len , -1 , dst , ca .drv , CAP_SMUDGE );
1241
+ ret_filter = apply_filter (
1242
+ path , src , len , -1 , dst , ca .drv , CAP_SMUDGE , dco );
1172
1243
if (!ret_filter && ca .drv && ca .drv -> required )
1173
1244
die ("%s: smudge filter %s failed" , path , ca .drv -> name );
1174
1245
1175
1246
return ret | ret_filter ;
1176
1247
}
1177
1248
1249
+ int async_convert_to_working_tree (const char * path , const char * src ,
1250
+ size_t len , struct strbuf * dst ,
1251
+ void * dco )
1252
+ {
1253
+ return convert_to_working_tree_internal (path , src , len , dst , 0 , dco );
1254
+ }
1255
+
1178
1256
int convert_to_working_tree (const char * path , const char * src , size_t len , struct strbuf * dst )
1179
1257
{
1180
- return convert_to_working_tree_internal (path , src , len , dst , 0 );
1258
+ return convert_to_working_tree_internal (path , src , len , dst , 0 , NULL );
1181
1259
}
1182
1260
1183
1261
int renormalize_buffer (const char * path , const char * src , size_t len , struct strbuf * dst )
1184
1262
{
1185
- int ret = convert_to_working_tree_internal (path , src , len , dst , 1 );
1263
+ int ret = convert_to_working_tree_internal (path , src , len , dst , 1 , NULL );
1186
1264
if (ret ) {
1187
1265
src = dst -> buf ;
1188
1266
len = dst -> len ;
0 commit comments