Skip to contentSkip to conversation

ls-files: Add eol diagnostics

PATCH Superseded Torsten Bögershausen 2 participants 2 messages Jun 15, 2016 Documentation

v5 of 12 Superseded Latest is v12 →

lore
Share & tools
lore
#0 lore raw

PATCH v5 1/1 ls-files: Add eol diagnostics

When working in a cross-platform environment, a user wants to check if text files are stored normalized in the repository and if .gitattributes are set appropriately.

Make it possible to let Git show the line endings in the index and in the working tree and the effective text/eol attributes.

The end of line ("eolinfo") are shown like this:

"binary"       binary file
"text-no-eol"  text file without any EOL
"text-lf"      text file with LF
"text-crlf"    text file with CRLF

"text-crlf-lf" text file with mixed line endings.

The effective text/eol attribute is one of these:
"", "-text", "text", "text=auto", "eol=lf", "eol=crlf"

git ls-files --eol gives an output like this:

i/text-no-eol   w/text-no-eol   attr/text=auto t/t5100/empty
i/binary        w/binary        attr/-text     t/test-binary-2.png
i/text-lf       w/text-lf       attr/eol=lf    t/t5100/rfc2047-info-0007
i/text-lf       w/text-crlf     attr/eol=crlf  doit.bat
i/text-crlf-lf  w/text-crlf-lf  attr/          locale/XX.po

Note that the output is meant to be human-readable and may change.

---
Changes since v4:
- gather_convert_stats_ascii() is static (Thanks Ramsay)
Changes since v3:
- typos (thanks for careful review)
- Remove un-intended changes in check-attr.c (they should not have been there)
- Improved t0027 (Thanks Eric)
Changes since v2:
- Major rework
- New prefix, more common to what we use in Git (i/, w/ attr/)
- Only one option: git ls-files --eol (may be combined with -s or -o or -d
- Simplify the diagnostics: either the file is binary or text
As empty files are not binary, they are text-no-eol
- Test cases in t0027

 Documentation/git-ls-files.txt |  22 +++++++++
 builtin/ls-files.c             |  19 +++++++
 convert.c                      |  86 ++++++++++++++++++++++++++++++++
 convert.h                      |   3 ++
 t/t0027-auto-crlf.sh           | 109 ++++++++++++++++++++++++++++++++++++-----
 5 files changed, 227 insertions(+), 12 deletions(-)
Documentation/git-ls-files.txt +22 -0
index e26f01f..8f29c99 100644
@@ -12,6 +12,7 @@ SYNOPSIS
 'git ls-files' [-z] [-t] [-v]
 		(--[cached|deleted|others|ignored|stage|unmerged|killed|modified])*
 		(-[c|d|o|i|s|u|k|m])*
+		[--eol]
 		[-x <pattern>|--exclude=<pattern>]
 		[-X <file>|--exclude-from=<file>]
 		[--exclude-per-directory=<file>]
@@ -147,6 +148,18 @@ a space) at the start of each line:
 	possible for manual inspection; the exact format may change at
 	any time.
 
+--eol::
+	Show line endings ("eolinfo") and the text/eol attributes ("texteolattr") of files.
+	"eolinfo" is the file content identification used by Git when
+	the "text" attribute is "auto", or core.autocrlf != false.
+
+	"eolinfo" is either "" (when the the info is not available"), or one of "binary",
+	"text-no-eol", "text-lf", "text-crlf" or "text-crlf-lf".
+	The "texteolattr" can be "", "-text", "text", "text=auto", "eol=lf", "eol=crlf".
+
+	Both the content in the index ("i/") and the content in the working tree ("w/")
+	are shown for regular files, followed by the "texteolattr ("attr/").
+
 \--::
 	Do not interpret any more arguments as options.
 
@@ -161,6 +174,15 @@ which case it outputs:
 
         [<tag> ]<mode> <object> <stage> <file>
 
+'git ls-files --eol' will show
+	i/<eolinfo> w/<eolinfo> attr/<eolattr> <file>
+
+'git ls-files --eol -o' will show
+	i/          w/<eolinfo> attr/<eolattr> <file>
+
+'git ls-files --eol -s' will show
+[<tag> ]<mode> <object> <stage> i/<eolinfo> w/<eolinfo> attr/<eolattr> <file>
+
 'git ls-files --unmerged' and 'git ls-files --stage' can be used to examine
 detailed information on unmerged paths.
 
builtin/ls-files.c +19 -0
index b6a7cb0..ef892bc 100644
@@ -27,6 +27,7 @@ static int show_killed;
 static int show_valid_bit;
 static int line_terminator = '\n';
 static int debug_mode;
+static int show_eol;
 
 static const char *prefix;
 static int max_prefix_len;
@@ -47,6 +48,21 @@ static const char *tag_modified = "";
 static const char *tag_skip_worktree = "";
 static const char *tag_resolve_undo = "";
 
+static void write_eolinfo(const struct cache_entry *ce, const char *path)
+{
+	struct stat st;
+	const char *i_txt = "";
+	const char *w_txt = "";
+	if (!show_eol)
+		return;
+	if (ce && S_ISREG(ce->ce_mode))
+		i_txt = get_cached_convert_stats_ascii(ce->name);
+	if (!lstat(path, &st) && (S_ISREG(st.st_mode)))
+		w_txt = get_wt_convert_stats_ascii(path);
+	printf("i/%-13s w/%-13s attr/%-9s ", i_txt, w_txt,
+				 get_convert_attr_ascii(path));
+}
+
 static void write_name(const char *name)
 {
 	/*
@@ -68,6 +84,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
 		return;
 
 	fputs(tag, stdout);
+	write_eolinfo(NULL, ent->name);
 	write_name(ent->name);
 }
 
@@ -170,6 +187,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 		       find_unique_abbrev(ce->sha1,abbrev),
 		       ce_stage(ce));
 	}
+	write_eolinfo(ce, ce->name);
 	write_name(ce->name);
 	if (debug_mode) {
 		const struct stat_data *sd = &ce->ce_stat_data;
@@ -433,6 +451,7 @@ 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", &show_eol, N_("show line endings of files")),
 		OPT_NEGBIT(0, "empty-directory", &dir.flags,
 			N_("don't show empty directories"),
 			DIR_HIDE_EMPTY_DIRECTORIES),
convert.c +86 -0

104 lines not on this page · raw message

convert.h +3 -0
index d9d853c..ccf436b 100644
@@ -32,6 +32,9 @@ enum eol {
 };
 
 extern enum eol core_eol;
+extern const char *get_cached_convert_stats_ascii(const char *path);
+extern const char *get_wt_convert_stats_ascii(const char *path);
+extern const char *get_convert_attr_ascii(const char *path);
 
 /* returns 1 if *dst was used */
 extern int convert_to_git(const char *path, const char *src, size_t len,
t/t0027-auto-crlf.sh +97 -12

148 lines not on this page · raw message

Signature · 1 line
2.6.2.403.gd7a84e3
#1 lore raw

t/t0027-auto-crlf.sh checkout_files () { · line 242

Quoted 8 lines · Torsten Bögershausen
t/t0027-auto-crlf.sh +2 -1
@@ -213,7 +238,20 @@ checkout_files () {
                        git -c core.eol=$eol checkout $src$f.txt
                fi
        done
-
+       test_expect_success "ls-files --eol $lfname ${pfx}LF.txt" "
+               cat >e <<-EOF &&

This here-doc requires interpolation, hence -EOF is fine, however...

Quoted 25 lines
t/t0027-auto-crlf.sh +18 -0
+               i/text-crlf w/$(stats_ascii $crlfname) ${src}CRLF.txt
+               i/text-crlf-lf w/$(stats_ascii $lfmixcrlf) ${src}CRLF_mix_LF.txt
+               i/text-lf w/$(stats_ascii $lfname) ${src}LF.txt
+               i/binary w/$(stats_ascii $lfmixcr) ${src}LF_mix_CR.txt
+               i/binary w/$(stats_ascii $crlfnul) ${src}CRLF_nul.txt
+               i/binary w/$(stats_ascii $crlfnul) ${src}LF_nul.txt
+               EOF
+               sort <e >expect &&
+               git ls-files --eol $src* | sed -e 's!attr/[=a-z-]*!!g' -e 's/  */ /g' | sort >actual &&
+               test_cmp expect actual &&
+               rm e expect actual
+       "
        test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=LF" "
                compare_ws_file $pfx $lfname    ${src}LF.txt
        "
@@ -231,6 +269,37 @@ checkout_files () {
        "
 }
 
+# Test control characters
+# NUL SOH CR EOF==^Z
+test_expect_success 'ls-files --eol -o Text/Binary' '
+       test_when_finished "rm e expect actual TeBi_*" &&
+       STRT=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA &&
+       STR=$STRT$STRT$STRT$STRT &&

t/t0027-auto-crlf.sh checkout_files () { · line 287

Quoted 10 lines
t/t0027-auto-crlf.sh +10 -0
+       printf "${STR}BBB\001" >TeBi_127_S &&
+       printf "${STR}BBBB\001">TeBi_128_S &&
+       printf "${STR}BBB\032" >TeBi_127_E &&
+       printf "\032${STR}BBB" >TeBi_E_127 &&
+       printf "${STR}BBBB\000">TeBi_128_N &&
+       printf "${STR}BBB\012">TeBi_128_L &&
+       printf "${STR}BBB\015">TeBi_127_C &&
+       printf "${STR}BB\015\012" >TeBi_126_CL &&
+       printf "${STR}BB\015\012\015" >TeBi_126_CLC &&
+       cat >e <<-EOF &&

Nit: [1] suggested using -\EOF since this here-doc needs no interpolation.

Quoted 15 lines
t/t0027-auto-crlf.sh +14 -0
+       i/ w/binary TeBi_127_S
+       i/ w/text-no-eol TeBi_128_S
+       i/ w/text-no-eol TeBi_127_E
+       i/ w/binary TeBi_E_127
+       i/ w/binary TeBi_128_N
+       i/ w/text-lf TeBi_128_L
+       i/ w/binary TeBi_127_C
+       i/ w/text-crlf TeBi_126_CL
+       i/ w/binary TeBi_126_CLC
+       EOF
+       sort <e >expect &&
+       git ls-files --eol -o | egrep "TeBi_" | sed -e 's!attr/[=a-z-]*!!g' -e "s/  */ /g" | sort >actual &&
+       test_cmp expect actual
+'

t/t0027-auto-crlf.sh checkout_files native true "lf" LF CRLF CRLF_mix_LF LF_mix_CR · line 552

Quoted 4 lines
t/t0027-auto-crlf.sh +4 -0
@@ -480,4 +549,20 @@ checkout_files    native  true  "lf"      LF    CRLF  CRLF_mix_LF  LF_mix_CR
+# Should be the last test case
+test_expect_success 'ls-files --eol -d' "
+       rm  crlf_false_attr__CRLF.txt crlf_false_attr__CRLF_mix_LF.txt crlf_false_attr__LF.txt .gitattributes &&
+       cat >expect <<-EOF &&

Likewise.

[1]: http://marc.info/?l=git&m=144829967800565&w=2

Quoted 14 lines
t/t0027-auto-crlf.sh +11 -1
+       i/text-crlf w/ crlf_false_attr__CRLF.txt
+       i/text-crlf-lf w/ crlf_false_attr__CRLF_mix_LF.txt
+       i/text-lf w/ .gitattributes
+       i/text-lf w/ crlf_false_attr__LF.txt
+       EOF
+       git ls-files --eol -d | sed -e 's!attr/[=a-z-]*!!g' -e 's/  */ /g' | sort >actual &&
+       test_cmp expect actual &&
+       rm expect actual
+"
+
+
 test_done
--

2.6.2.403.gd7a84e3