@@ -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! */
@@ -533,7 +534,8 @@ static int start_multi_file_filter_fn(struct subprocess_entry *subprocess)
533
534
if (err )
534
535
goto done ;
535
536
536
- err = packet_writel (process -> in , "capability=clean" , "capability=smudge" , NULL );
537
+ err = packet_writel (process -> in ,
538
+ "capability=clean" , "capability=smudge" , "capability=delay" , NULL );
537
539
538
540
for (;;) {
539
541
cap_buf = packet_read_line (process -> out , NULL );
@@ -549,6 +551,8 @@ static int start_multi_file_filter_fn(struct subprocess_entry *subprocess)
549
551
entry -> supported_capabilities |= CAP_CLEAN ;
550
552
} else if (!strcmp (cap_name , "smudge" )) {
551
553
entry -> supported_capabilities |= CAP_SMUDGE ;
554
+ } else if (!strcmp (cap_name , "delay" )) {
555
+ entry -> supported_capabilities |= CAP_DELAY ;
552
556
} else {
553
557
warning (
554
558
"external filter '%s' requested unsupported filter capability '%s'" ,
@@ -590,9 +594,11 @@ static void handle_filter_error(const struct strbuf *filter_status,
590
594
591
595
static int apply_multi_file_filter (const char * path , const char * src , size_t len ,
592
596
int fd , struct strbuf * dst , const char * cmd ,
593
- const unsigned int wanted_capability )
597
+ const unsigned int wanted_capability ,
598
+ struct delayed_checkout * dco )
594
599
{
595
600
int err ;
601
+ int can_delay = 0 ;
596
602
struct cmd2process * entry ;
597
603
struct child_process * process ;
598
604
struct strbuf nbuf = STRBUF_INIT ;
@@ -647,6 +653,14 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len
647
653
if (err )
648
654
goto done ;
649
655
656
+ if ((entry -> supported_capabilities & CAP_DELAY ) &&
657
+ dco && dco -> state == CE_CAN_DELAY ) {
658
+ can_delay = 1 ;
659
+ err = packet_write_fmt_gently (process -> in , "can-delay=1\n" );
660
+ if (err )
661
+ goto done ;
662
+ }
663
+
650
664
err = packet_flush_gently (process -> in );
651
665
if (err )
652
666
goto done ;
@@ -662,14 +676,74 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len
662
676
if (err )
663
677
goto done ;
664
678
665
- err = strcmp (filter_status .buf , "success" );
679
+ if (can_delay && !strcmp (filter_status .buf , "delayed" )) {
680
+ dco -> is_delayed = 1 ;
681
+ string_list_insert (& dco -> filters , cmd );
682
+ string_list_insert (& dco -> paths , path );
683
+ } else {
684
+ /* The filter got the blob and wants to send us a response. */
685
+ err = strcmp (filter_status .buf , "success" );
686
+ if (err )
687
+ goto done ;
688
+
689
+ err = read_packetized_to_strbuf (process -> out , & nbuf ) < 0 ;
690
+ if (err )
691
+ goto done ;
692
+
693
+ err = subprocess_read_status (process -> out , & filter_status );
694
+ if (err )
695
+ goto done ;
696
+
697
+ err = strcmp (filter_status .buf , "success" );
698
+ }
699
+
700
+ done :
701
+ sigchain_pop (SIGPIPE );
702
+
703
+ if (err )
704
+ handle_filter_error (& filter_status , entry , wanted_capability );
705
+ else
706
+ strbuf_swap (dst , & nbuf );
707
+ strbuf_release (& nbuf );
708
+ return !err ;
709
+ }
710
+
711
+
712
+ int async_query_available_blobs (const char * cmd , struct string_list * available_paths )
713
+ {
714
+ int err ;
715
+ char * line ;
716
+ struct cmd2process * entry ;
717
+ struct child_process * process ;
718
+ struct strbuf filter_status = STRBUF_INIT ;
719
+
720
+ assert (subprocess_map_initialized );
721
+ entry = (struct cmd2process * )subprocess_find_entry (& subprocess_map , cmd );
722
+ if (!entry ) {
723
+ error ("external filter '%s' is not available anymore although "
724
+ "not all paths have been filtered" , cmd );
725
+ return 0 ;
726
+ }
727
+ process = & entry -> subprocess .process ;
728
+ sigchain_push (SIGPIPE , SIG_IGN );
729
+
730
+ err = packet_write_fmt_gently (
731
+ process -> in , "command=list_available_blobs\n" );
666
732
if (err )
667
733
goto done ;
668
734
669
- err = read_packetized_to_strbuf (process -> out , & nbuf ) < 0 ;
735
+ err = packet_flush_gently (process -> in ) ;
670
736
if (err )
671
737
goto done ;
672
738
739
+ while ((line = packet_read_line (process -> out , NULL ))) {
740
+ const char * path ;
741
+ if (skip_prefix (line , "pathname=" , & path ))
742
+ string_list_insert (available_paths , xstrdup (path ));
743
+ else
744
+ ; /* ignore unknown keys */
745
+ }
746
+
673
747
err = subprocess_read_status (process -> out , & filter_status );
674
748
if (err )
675
749
goto done ;
@@ -680,10 +754,7 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len
680
754
sigchain_pop (SIGPIPE );
681
755
682
756
if (err )
683
- handle_filter_error (& filter_status , entry , wanted_capability );
684
- else
685
- strbuf_swap (dst , & nbuf );
686
- strbuf_release (& nbuf );
757
+ handle_filter_error (& filter_status , entry , 0 );
687
758
return !err ;
688
759
}
689
760
@@ -698,7 +769,8 @@ static struct convert_driver {
698
769
699
770
static int apply_filter (const char * path , const char * src , size_t len ,
700
771
int fd , struct strbuf * dst , struct convert_driver * drv ,
701
- const unsigned int wanted_capability )
772
+ const unsigned int wanted_capability ,
773
+ struct delayed_checkout * dco )
702
774
{
703
775
const char * cmd = NULL ;
704
776
@@ -716,7 +788,8 @@ static int apply_filter(const char *path, const char *src, size_t len,
716
788
if (cmd && * cmd )
717
789
return apply_single_file_filter (path , src , len , fd , dst , cmd );
718
790
else if (drv -> process && * drv -> process )
719
- return apply_multi_file_filter (path , src , len , fd , dst , drv -> process , wanted_capability );
791
+ return apply_multi_file_filter (path , src , len , fd , dst ,
792
+ drv -> process , wanted_capability , dco );
720
793
721
794
return 0 ;
722
795
}
@@ -1057,7 +1130,7 @@ int would_convert_to_git_filter_fd(const char *path)
1057
1130
if (!ca .drv -> required )
1058
1131
return 0 ;
1059
1132
1060
- return apply_filter (path , NULL , 0 , -1 , NULL , ca .drv , CAP_CLEAN );
1133
+ return apply_filter (path , NULL , 0 , -1 , NULL , ca .drv , CAP_CLEAN , NULL );
1061
1134
}
1062
1135
1063
1136
const char * get_convert_attr_ascii (const char * path )
@@ -1094,7 +1167,7 @@ int convert_to_git(const char *path, const char *src, size_t len,
1094
1167
1095
1168
convert_attrs (& ca , path );
1096
1169
1097
- ret |= apply_filter (path , src , len , -1 , dst , ca .drv , CAP_CLEAN );
1170
+ ret |= apply_filter (path , src , len , -1 , dst , ca .drv , CAP_CLEAN , NULL );
1098
1171
if (!ret && ca .drv && ca .drv -> required )
1099
1172
die ("%s: clean filter '%s' failed" , path , ca .drv -> name );
1100
1173
@@ -1119,7 +1192,7 @@ void convert_to_git_filter_fd(const char *path, int fd, struct strbuf *dst,
1119
1192
assert (ca .drv );
1120
1193
assert (ca .drv -> clean || ca .drv -> process );
1121
1194
1122
- if (!apply_filter (path , NULL , 0 , fd , dst , ca .drv , CAP_CLEAN ))
1195
+ if (!apply_filter (path , NULL , 0 , fd , dst , ca .drv , CAP_CLEAN , NULL ))
1123
1196
die ("%s: clean filter '%s' failed" , path , ca .drv -> name );
1124
1197
1125
1198
crlf_to_git (path , dst -> buf , dst -> len , dst , ca .crlf_action , checksafe );
@@ -1128,7 +1201,7 @@ void convert_to_git_filter_fd(const char *path, int fd, struct strbuf *dst,
1128
1201
1129
1202
static int convert_to_working_tree_internal (const char * path , const char * src ,
1130
1203
size_t len , struct strbuf * dst ,
1131
- int normalizing )
1204
+ int normalizing , struct delayed_checkout * dco )
1132
1205
{
1133
1206
int ret = 0 , ret_filter = 0 ;
1134
1207
struct conv_attrs ca ;
@@ -1153,21 +1226,29 @@ static int convert_to_working_tree_internal(const char *path, const char *src,
1153
1226
}
1154
1227
}
1155
1228
1156
- ret_filter = apply_filter (path , src , len , -1 , dst , ca .drv , CAP_SMUDGE );
1229
+ ret_filter = apply_filter (
1230
+ path , src , len , -1 , dst , ca .drv , CAP_SMUDGE , dco );
1157
1231
if (!ret_filter && ca .drv && ca .drv -> required )
1158
1232
die ("%s: smudge filter %s failed" , path , ca .drv -> name );
1159
1233
1160
1234
return ret | ret_filter ;
1161
1235
}
1162
1236
1237
+ int async_convert_to_working_tree (const char * path , const char * src ,
1238
+ size_t len , struct strbuf * dst ,
1239
+ void * dco )
1240
+ {
1241
+ return convert_to_working_tree_internal (path , src , len , dst , 0 , dco );
1242
+ }
1243
+
1163
1244
int convert_to_working_tree (const char * path , const char * src , size_t len , struct strbuf * dst )
1164
1245
{
1165
- return convert_to_working_tree_internal (path , src , len , dst , 0 );
1246
+ return convert_to_working_tree_internal (path , src , len , dst , 0 , NULL );
1166
1247
}
1167
1248
1168
1249
int renormalize_buffer (const char * path , const char * src , size_t len , struct strbuf * dst )
1169
1250
{
1170
- int ret = convert_to_working_tree_internal (path , src , len , dst , 1 );
1251
+ int ret = convert_to_working_tree_internal (path , src , len , dst , 1 , NULL );
1171
1252
if (ret ) {
1172
1253
src = dst -> buf ;
1173
1254
len = dst -> len ;
0 commit comments