@@ -220,6 +220,57 @@ int within_depth(const char *name, int namelen,
220220 return 1 ;
221221}
222222
223+ /*
224+ * Read the contents of the blob with the given OID into a buffer.
225+ * Append a trailing LF to the end if the last line doesn't have one.
226+ *
227+ * Returns:
228+ * -1 when the OID is invalid or unknown or does not refer to a blob.
229+ * 0 when the blob is empty.
230+ * 1 along with { data, size } of the (possibly augmented) buffer
231+ * when successful.
232+ *
233+ * Optionally updates the given sha1_stat with the given OID (when valid).
234+ */
235+ static int do_read_blob (const struct object_id * oid ,
236+ struct sha1_stat * sha1_stat ,
237+ size_t * size_out ,
238+ char * * data_out )
239+ {
240+ enum object_type type ;
241+ unsigned long sz ;
242+ char * data ;
243+
244+ * size_out = 0 ;
245+ * data_out = NULL ;
246+
247+ data = read_sha1_file (oid -> hash , & type , & sz );
248+ if (!data || type != OBJ_BLOB ) {
249+ free (data );
250+ return -1 ;
251+ }
252+
253+ if (sha1_stat ) {
254+ memset (& sha1_stat -> stat , 0 , sizeof (sha1_stat -> stat ));
255+ hashcpy (sha1_stat -> sha1 , oid -> hash );
256+ }
257+
258+ if (sz == 0 ) {
259+ free (data );
260+ return 0 ;
261+ }
262+
263+ if (data [sz - 1 ] != '\n' ) {
264+ data = xrealloc (data , st_add (sz , 1 ));
265+ data [sz ++ ] = '\n' ;
266+ }
267+
268+ * size_out = xsize_t (sz );
269+ * data_out = data ;
270+
271+ return 1 ;
272+ }
273+
223274#define DO_MATCH_EXCLUDE (1<<0)
224275#define DO_MATCH_DIRECTORY (1<<1)
225276#define DO_MATCH_SUBMODULE (1<<2)
@@ -600,32 +651,22 @@ void add_exclude(const char *string, const char *base,
600651 x -> el = el ;
601652}
602653
603- static void * read_skip_worktree_file_from_index (const struct index_state * istate ,
604- const char * path , size_t * size ,
605- struct sha1_stat * sha1_stat )
654+ static int read_skip_worktree_file_from_index (const struct index_state * istate ,
655+ const char * path ,
656+ size_t * size_out ,
657+ char * * data_out ,
658+ struct sha1_stat * sha1_stat )
606659{
607660 int pos , len ;
608- unsigned long sz ;
609- enum object_type type ;
610- void * data ;
611661
612662 len = strlen (path );
613663 pos = index_name_pos (istate , path , len );
614664 if (pos < 0 )
615- return NULL ;
665+ return -1 ;
616666 if (!ce_skip_worktree (istate -> cache [pos ]))
617- return NULL ;
618- data = read_sha1_file (istate -> cache [pos ]-> oid .hash , & type , & sz );
619- if (!data || type != OBJ_BLOB ) {
620- free (data );
621- return NULL ;
622- }
623- * size = xsize_t (sz );
624- if (sha1_stat ) {
625- memset (& sha1_stat -> stat , 0 , sizeof (sha1_stat -> stat ));
626- hashcpy (sha1_stat -> sha1 , istate -> cache [pos ]-> oid .hash );
627- }
628- return data ;
667+ return -1 ;
668+
669+ return do_read_blob (& istate -> cache [pos ]-> oid , sha1_stat , size_out , data_out );
629670}
630671
631672/*
@@ -739,6 +780,10 @@ static void invalidate_directory(struct untracked_cache *uc,
739780 dir -> dirs [i ]-> recurse = 0 ;
740781}
741782
783+ static int add_excludes_from_buffer (char * buf , size_t size ,
784+ const char * base , int baselen ,
785+ struct exclude_list * el );
786+
742787/*
743788 * Given a file with name "fname", read it (either from disk, or from
744789 * an index if 'istate' is non-null), parse it and store the
@@ -754,27 +799,24 @@ static int add_excludes(const char *fname, const char *base, int baselen,
754799 struct sha1_stat * sha1_stat )
755800{
756801 struct stat st ;
757- int fd , i , lineno = 1 ;
802+ int r ;
803+ int fd ;
758804 size_t size = 0 ;
759- char * buf , * entry ;
805+ char * buf ;
760806
761807 fd = open (fname , O_RDONLY );
762808 if (fd < 0 || fstat (fd , & st ) < 0 ) {
763809 if (fd < 0 )
764810 warn_on_fopen_errors (fname );
765811 else
766812 close (fd );
767- if (!istate ||
768- (buf = read_skip_worktree_file_from_index (istate , fname , & size , sha1_stat )) == NULL )
813+ if (!istate )
769814 return -1 ;
770- if (size == 0 ) {
771- free (buf );
772- return 0 ;
773- }
774- if (buf [size - 1 ] != '\n' ) {
775- buf = xrealloc (buf , st_add (size , 1 ));
776- buf [size ++ ] = '\n' ;
777- }
815+ r = read_skip_worktree_file_from_index (istate , fname ,
816+ & size , & buf ,
817+ sha1_stat );
818+ if (r != 1 )
819+ return r ;
778820 } else {
779821 size = xsize_t (st .st_size );
780822 if (size == 0 ) {
@@ -813,6 +855,17 @@ static int add_excludes(const char *fname, const char *base, int baselen,
813855 }
814856 }
815857
858+ add_excludes_from_buffer (buf , size , base , baselen , el );
859+ return 0 ;
860+ }
861+
862+ static int add_excludes_from_buffer (char * buf , size_t size ,
863+ const char * base , int baselen ,
864+ struct exclude_list * el )
865+ {
866+ int i , lineno = 1 ;
867+ char * entry ;
868+
816869 el -> filebuf = buf ;
817870
818871 if (skip_utf8_bom (& buf , size ))
@@ -841,6 +894,23 @@ int add_excludes_from_file_to_list(const char *fname, const char *base,
841894 return add_excludes (fname , base , baselen , el , istate , NULL );
842895}
843896
897+ int add_excludes_from_blob_to_list (
898+ struct object_id * oid ,
899+ const char * base , int baselen ,
900+ struct exclude_list * el )
901+ {
902+ char * buf ;
903+ size_t size ;
904+ int r ;
905+
906+ r = do_read_blob (oid , NULL , & size , & buf );
907+ if (r != 1 )
908+ return r ;
909+
910+ add_excludes_from_buffer (buf , size , base , baselen , el );
911+ return 0 ;
912+ }
913+
844914struct exclude_list * add_exclude_list (struct dir_struct * dir ,
845915 int group_type , const char * src )
846916{
0 commit comments