From: Philip Oakley Date: Sun, 18 Oct 2015 10:03:37 GMT Subject: Re: [PATCH] Add ls-files --eol-staged, --eol-worktree Message-ID: <3D2D9DFC85644BD1A6A39E819D90ACAA@PhilipOakley> In-Reply-To: From: "Torsten Bögershausen" > Make it possible to show the line endings of files. > Files which are staged and/or files in the working tree: > > git ls-files --eol-staged > git ls-files --eol-worktree > > Both will show an output like this: > > empty empty_file > bin binary_file_or_with_cr_handled_as_binary > txt-crlf text_file_with_crlf > txt-mix text_file_with_crlf_and_lf > txt-lf text_file_with_lf > txt text_file_with_no_eol_at_all I think that this last generic 'txt' should be explicit, e.g. 'txt-no-eols', so that the categories are explicit and mutually exclusive. Also, does this need a documentation update for the options, and can the distinction between txt and bin be documented /referenced. > > Implementation details: > Make struct text_stat, is_binary() and gather_stats() from convert.c > public, add a new function get_convert_stats_ascii() and use it > in and use them in ls-files. > git ls-files --eol-staged will give a line like this: > > Signed-off-by: Torsten Bögershausen > --- > This needs to go on top of tb/t0027-crlf > > builtin/ls-files.c | 21 +++++++++++++++++++++ > convert.c | 51 > +++++++++++++++++++++++++++++++++++++++++---------- > convert.h | 14 ++++++++++++++ > 3 files changed, 76 insertions(+), 10 deletions(-) > > diff --git a/builtin/ls-files.c b/builtin/ls-files.c > index b6a7cb0..c989e94 100644 > --- a/builtin/ls-files.c > +++ b/builtin/ls-files.c > @@ -27,6 +27,8 @@ static int show_killed; > static int show_valid_bit; > static int line_terminator = '\n'; > static int debug_mode; > +static int show_eol_staged; > +static int show_eol_wt; > > static const char *prefix; > static int max_prefix_len; > @@ -68,6 +70,11 @@ static void show_dir_entry(const char *tag, struct > dir_entry *ent) > return; > > fputs(tag, stdout); > + if (show_eol_wt) { > + printf("%s ", get_convert_stats_ascii(ent->name, > + GET_CONVERT_STATS_ASCII_WT, 0)); > + } > + > write_name(ent->name); > } > > @@ -170,6 +177,14 @@ static void show_ce_entry(const char *tag, const > struct cache_entry *ce) > find_unique_abbrev(ce->sha1,abbrev), > ce_stage(ce)); > } > + if (show_eol_staged) { > + printf("%s ", > + get_convert_stats_ascii(ce->name, GET_CONVERT_STATS_ASCII_BLOB, 0)); > + } > + if (show_eol_wt) { > + printf("%s ", > get_convert_stats_ascii(ce->name,GET_CONVERT_STATS_ASCII_WT, > + ce->ce_stat_data.sd_size)); > + } > write_name(ce->name); > if (debug_mode) { > const struct stat_data *sd = &ce->ce_stat_data; > @@ -206,6 +221,10 @@ static void show_ru_info(void) > printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i], > find_unique_abbrev(ui->sha1[i], abbrev), > i + 1); > + if (show_eol_wt) { > + printf("%s ", > + get_convert_stats_ascii(path, GET_CONVERT_STATS_ASCII_WT, 0)); > + } > write_name(path); > } > } > @@ -433,6 +452,8 @@ int cmd_ls_files(int argc, const char **argv, const > char *cmd_prefix) > OPT_BIT(0, "directory", &dir.flags, > N_("show 'other' directories' names only"), > DIR_SHOW_OTHER_DIRECTORIES), > + OPT_BOOL(0, "eol-staged", &show_eol_staged, N_("show line endings of the > staged file")), > + OPT_BOOL(0, "eol-worktree", &show_eol_wt, N_("show line endings of the > file in work tree")), > OPT_NEGBIT(0, "empty-directory", &dir.flags, > N_("don't show empty directories"), > DIR_HIDE_EMPTY_DIRECTORIES), > diff --git a/convert.c b/convert.c > index 814e814..a1c24cd 100644 > --- a/convert.c > +++ b/convert.c > @@ -22,15 +22,7 @@ enum crlf_action { > CRLF_AUTO > }; > > -struct text_stat { > - /* NUL, CR, LF and CRLF counts */ > - unsigned nul, cr, lf, crlf; > - > - /* These are just approximations! */ > - unsigned printable, nonprintable; > -}; > - > -static void gather_stats(const char *buf, unsigned long size, struct > text_stat *stats) > +void gather_stats(const char *buf, unsigned long size, struct text_stat > *stats) > { > unsigned long i; > > @@ -76,7 +68,7 @@ static void gather_stats(const char *buf, unsigned long > size, struct text_stat * > /* > * The same heuristics as diff.c::mmfile_is_binary() > */ > -static int is_binary(unsigned long size, struct text_stat *stats) > +int is_binary(unsigned long size, struct text_stat *stats) > { > > if (stats->nul) > @@ -95,6 +87,45 @@ static int is_binary(unsigned long size, struct > text_stat *stats) > return 0; > } > > + > +const char *gather_stats_ascii(const char *data, unsigned long size) > +{ > + struct text_stat stats; > + if (!data || !size) > + return("empty "); > + gather_stats(data, size, &stats); > + if (is_binary(size, &stats)) > + return("bin "); > + else if (stats.cr != stats.crlf) > + return("bin "); > + else if (stats.crlf && (stats.crlf == stats.lf)) > + return("txt-crlf"); > + else if (stats.crlf && stats.lf) > + return("txt-mix "); > + else if (stats.lf) > + return("txt-lf "); > + else > + return("txt "); > +} > + > +const char *get_convert_stats_ascii(const char *path, int flags, size_t > hint) > +{ > + const char *ret = ""; > + if (flags & GET_CONVERT_STATS_ASCII_BLOB) { > + unsigned long sz; > + void *data = read_blob_data_from_cache(path, &sz); > + ret = gather_stats_ascii(data, sz); > + if (data) > + free(data); > + } else if (flags & GET_CONVERT_STATS_ASCII_WT){ > + struct strbuf sb = STRBUF_INIT; > + strbuf_read_file(&sb, path, hint); > + ret = gather_stats_ascii(sb.buf, sb.len); > + strbuf_release(&sb); > + } > + return ret; > +} > + > static enum eol output_eol(enum crlf_action crlf_action) > { > switch (crlf_action) { > diff --git a/convert.h b/convert.h > index d9d853c..566cf0e 100644 > --- a/convert.h > +++ b/convert.h > @@ -31,6 +31,20 @@ enum eol { > #endif > }; > > +struct text_stat { > + /* NUL, CR, LF and CRLF counts */ > + unsigned nul, cr, lf, crlf; > + > + /* These are just approximations! */ > + unsigned printable, nonprintable; > +}; > +void gather_stats(const char *buf, unsigned long size, struct text_stat > *stats); > +int is_binary(unsigned long size, struct text_stat *stats); > +const char *gather_stats_ascii(const char *buf, unsigned long size); > +#define GET_CONVERT_STATS_ASCII_BLOB (1<<0) > +#define GET_CONVERT_STATS_ASCII_WT (1<<1) > +const char *get_convert_stats_ascii(const char *path, int isBlob, size_t > hint); > + > extern enum eol core_eol; > > /* returns 1 if *dst was used */ > -- > 2.6.1.443.g36d7748 > > -- Philip