@@ -312,11 +312,12 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len,
312312struct filter_params {
313313 const char * src ;
314314 unsigned long size ;
315+ int fd ;
315316 const char * cmd ;
316317 const char * path ;
317318};
318319
319- static int filter_buffer (int in , int out , void * data )
320+ static int filter_buffer_or_fd (int in , int out , void * data )
320321{
321322 /*
322323 * Spawn cmd and feed the buffer contents through its stdin.
@@ -354,7 +355,12 @@ static int filter_buffer(int in, int out, void *data)
354355
355356 sigchain_push (SIGPIPE , SIG_IGN );
356357
357- write_err = (write_in_full (child_process .in , params -> src , params -> size ) < 0 );
358+ if (params -> src ) {
359+ write_err = (write_in_full (child_process .in , params -> src , params -> size ) < 0 );
360+ } else {
361+ write_err = copy_fd (params -> fd , child_process .in );
362+ }
363+
358364 if (close (child_process .in ))
359365 write_err = 1 ;
360366 if (write_err )
@@ -370,7 +376,7 @@ static int filter_buffer(int in, int out, void *data)
370376 return (write_err || status );
371377}
372378
373- static int apply_filter (const char * path , const char * src , size_t len ,
379+ static int apply_filter (const char * path , const char * src , size_t len , int fd ,
374380 struct strbuf * dst , const char * cmd )
375381{
376382 /*
@@ -391,11 +397,12 @@ static int apply_filter(const char *path, const char *src, size_t len,
391397 return 1 ;
392398
393399 memset (& async , 0 , sizeof (async ));
394- async .proc = filter_buffer ;
400+ async .proc = filter_buffer_or_fd ;
395401 async .data = & params ;
396402 async .out = -1 ;
397403 params .src = src ;
398404 params .size = len ;
405+ params .fd = fd ;
399406 params .cmd = cmd ;
400407 params .path = path ;
401408
@@ -746,6 +753,25 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
746753 }
747754}
748755
756+ int would_convert_to_git_filter_fd (const char * path )
757+ {
758+ struct conv_attrs ca ;
759+
760+ convert_attrs (& ca , path );
761+ if (!ca .drv )
762+ return 0 ;
763+
764+ /*
765+ * Apply a filter to an fd only if the filter is required to succeed.
766+ * We must die if the filter fails, because the original data before
767+ * filtering is not available.
768+ */
769+ if (!ca .drv -> required )
770+ return 0 ;
771+
772+ return apply_filter (path , NULL , 0 , -1 , NULL , ca .drv -> clean );
773+ }
774+
749775int convert_to_git (const char * path , const char * src , size_t len ,
750776 struct strbuf * dst , enum safe_crlf checksafe )
751777{
@@ -760,7 +786,7 @@ int convert_to_git(const char *path, const char *src, size_t len,
760786 required = ca .drv -> required ;
761787 }
762788
763- ret |= apply_filter (path , src , len , dst , filter );
789+ ret |= apply_filter (path , src , len , -1 , dst , filter );
764790 if (!ret && required )
765791 die ("%s: clean filter '%s' failed" , path , ca .drv -> name );
766792
@@ -777,6 +803,23 @@ int convert_to_git(const char *path, const char *src, size_t len,
777803 return ret | ident_to_git (path , src , len , dst , ca .ident );
778804}
779805
806+ void convert_to_git_filter_fd (const char * path , int fd , struct strbuf * dst ,
807+ enum safe_crlf checksafe )
808+ {
809+ struct conv_attrs ca ;
810+ convert_attrs (& ca , path );
811+
812+ assert (ca .drv );
813+ assert (ca .drv -> clean );
814+
815+ if (!apply_filter (path , NULL , 0 , fd , dst , ca .drv -> clean ))
816+ die ("%s: clean filter '%s' failed" , path , ca .drv -> name );
817+
818+ ca .crlf_action = input_crlf_action (ca .crlf_action , ca .eol_attr );
819+ crlf_to_git (path , dst -> buf , dst -> len , dst , ca .crlf_action , checksafe );
820+ ident_to_git (path , dst -> buf , dst -> len , dst , ca .ident );
821+ }
822+
780823static int convert_to_working_tree_internal (const char * path , const char * src ,
781824 size_t len , struct strbuf * dst ,
782825 int normalizing )
@@ -810,7 +853,7 @@ static int convert_to_working_tree_internal(const char *path, const char *src,
810853 }
811854 }
812855
813- ret_filter = apply_filter (path , src , len , dst , filter );
856+ ret_filter = apply_filter (path , src , len , -1 , dst , filter );
814857 if (!ret_filter && required )
815858 die ("%s: smudge filter %s failed" , path , ca .drv -> name );
816859
0 commit comments