1111#include "quote.h"
1212#include "dir.h"
1313#include "builtin.h"
14+ #include "strbuf.h"
1415#include "tree.h"
1516#include "cache-tree.h"
1617#include "parse-options.h"
@@ -48,6 +49,7 @@ static char *ps_matched;
4849static const char * with_tree ;
4950static int exc_given ;
5051static int exclude_args ;
52+ static const char * format ;
5153
5254static const char * tag_cached = "" ;
5355static const char * tag_unmerged = "" ;
@@ -85,6 +87,16 @@ static void write_name(const char *name)
8587 stdout , line_terminator );
8688}
8789
90+ static void write_name_to_buf (struct strbuf * sb , const char * name )
91+ {
92+ const char * rel = relative_path (name , prefix_len ? prefix : NULL , sb );
93+
94+ if (line_terminator )
95+ quote_c_style (rel , sb , NULL , 0 );
96+ else
97+ strbuf_addstr (sb , rel );
98+ }
99+
88100static const char * get_tag (const struct cache_entry * ce , const char * tag )
89101{
90102 static char alttag [4 ];
@@ -222,6 +234,73 @@ static void show_submodule(struct repository *superproject,
222234 repo_clear (& subrepo );
223235}
224236
237+ struct show_index_data {
238+ const char * pathname ;
239+ struct index_state * istate ;
240+ const struct cache_entry * ce ;
241+ };
242+
243+ static size_t expand_show_index (struct strbuf * sb , const char * start ,
244+ void * context )
245+ {
246+ struct show_index_data * data = context ;
247+ const char * end ;
248+ const char * p ;
249+ size_t len = strbuf_expand_literal_cb (sb , start , NULL );
250+ struct stat st ;
251+
252+ if (len )
253+ return len ;
254+ if (* start != '(' )
255+ die (_ ("bad ls-files format: element '%s' "
256+ "does not start with '('" ), start );
257+
258+ end = strchr (start + 1 , ')' );
259+ if (!end )
260+ die (_ ("bad ls-files format: element '%s'"
261+ "does not end in ')'" ), start );
262+
263+ len = end - start + 1 ;
264+ if (skip_prefix (start , "(objectmode)" , & p ))
265+ strbuf_addf (sb , "%06o" , data -> ce -> ce_mode );
266+ else if (skip_prefix (start , "(objectname)" , & p ))
267+ strbuf_add_unique_abbrev (sb , & data -> ce -> oid , abbrev );
268+ else if (skip_prefix (start , "(stage)" , & p ))
269+ strbuf_addf (sb , "%d" , ce_stage (data -> ce ));
270+ else if (skip_prefix (start , "(eolinfo:index)" , & p ))
271+ strbuf_addstr (sb , S_ISREG (data -> ce -> ce_mode ) ?
272+ get_cached_convert_stats_ascii (data -> istate ,
273+ data -> ce -> name ) : "" );
274+ else if (skip_prefix (start , "(eolinfo:worktree)" , & p ))
275+ strbuf_addstr (sb , !lstat (data -> pathname , & st ) &&
276+ S_ISREG (st .st_mode ) ?
277+ get_wt_convert_stats_ascii (data -> pathname ) : "" );
278+ else if (skip_prefix (start , "(eolattr)" , & p ))
279+ strbuf_addstr (sb , get_convert_attr_ascii (data -> istate ,
280+ data -> pathname ));
281+ else if (skip_prefix (start , "(path)" , & p ))
282+ write_name_to_buf (sb , data -> pathname );
283+ else
284+ die (_ ("bad ls-files format: %%%.*s" ), (int )len , start );
285+
286+ return len ;
287+ }
288+
289+ static void show_ce_fmt (struct repository * repo , const struct cache_entry * ce ,
290+ const char * format , const char * fullname ) {
291+ struct show_index_data data = {
292+ .pathname = fullname ,
293+ .istate = repo -> index ,
294+ .ce = ce ,
295+ };
296+ struct strbuf sb = STRBUF_INIT ;
297+
298+ strbuf_expand (& sb , format , expand_show_index , & data );
299+ strbuf_addch (& sb , line_terminator );
300+ fwrite (sb .buf , sb .len , 1 , stdout );
301+ strbuf_release (& sb );
302+ }
303+
225304static void show_ce (struct repository * repo , struct dir_struct * dir ,
226305 const struct cache_entry * ce , const char * fullname ,
227306 const char * tag )
@@ -236,6 +315,12 @@ static void show_ce(struct repository *repo, struct dir_struct *dir,
236315 max_prefix_len , ps_matched ,
237316 S_ISDIR (ce -> ce_mode ) ||
238317 S_ISGITLINK (ce -> ce_mode ))) {
318+ if (format ) {
319+ show_ce_fmt (repo , ce , format , fullname );
320+ print_debug (ce );
321+ return ;
322+ }
323+
239324 tag = get_tag (ce , tag );
240325
241326 if (!show_stage ) {
@@ -675,6 +760,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
675760 N_ ("suppress duplicate entries" )),
676761 OPT_BOOL (0 , "sparse" , & show_sparse_dirs ,
677762 N_ ("show sparse directories in the presence of a sparse index" )),
763+ OPT_STRING_F (0 , "format" , & format , N_ ("format" ),
764+ N_ ("format to use for the output" ),
765+ PARSE_OPT_NONEG ),
678766 OPT_END ()
679767 };
680768 int ret = 0 ;
@@ -699,6 +787,13 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
699787 for (i = 0 ; i < exclude_list .nr ; i ++ ) {
700788 add_pattern (exclude_list .items [i ].string , "" , 0 , pl , -- exclude_args );
701789 }
790+
791+ if (format && (show_stage || show_others || show_killed ||
792+ show_resolve_undo || skipping_duplicates || show_eol || show_tag ))
793+ usage_msg_opt (_ ("--format cannot be used with -s, -o, -k, -t, "
794+ "--resolve-undo, --deduplicate, --eol" ),
795+ ls_files_usage , builtin_ls_files_options );
796+
702797 if (show_tag || show_valid_bit || show_fsmonitor_bit ) {
703798 tag_cached = "H " ;
704799 tag_unmerged = "M " ;
0 commit comments