git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/21] nd/list-files updates
@ 2015-01-25 12:37 Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 01/21] ls_colors.c: add $LS_COLORS parsing code Nguyễn Thái Ngọc Duy
                   ` (20 more replies)
  0 siblings, 21 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Changes since 'pu' version:

 - refresh_index() in 09/21 is set not to show "XXX: needs merge"
   messages, cluttering "list-files -u" output
 - new patch 10/21 to add a default alias 'ls' to 'list-files',
   of course overridable by the user
 - fix "list-files -u" not showing anything because
   show_files_compact in 16/21 ignores show_unmerged flag
 - directory listing in 17/21 is rewritten to work filtering
   (e.g. -m, -M...)
 - new patch 21/21 adds tests for the series

Nguyễn Thái Ngọc Duy (21):
  ls_colors.c: add $LS_COLORS parsing code
  ls_colors.c: parse color.ls.* from config file
  ls_colors.c: add a function to color a file name
  ls_colors.c: highlight submodules like directories
  ls-files: buffer full item in strbuf before printing
  ls-files: add --color to highlight file names
  ls-files: add --column
  ls-files: support --max-depth
  list-files: a user friendly version of ls-files and more
  list-files: make alias 'ls' default to 'list-files'
  list-files: -u does not imply showing stages
  list-files: add -R/--recursive short for --max-depth=-1
  list-files: add -1 short for --no-column
  list-files: add -t back
  list-files: sort output and remove duplicates
  list-files: do not show duplicate cached entries
  list-files: show directories as well as files
  list-files: add -F/--classify
  list-files -F: show submodules with the new indicator '&'
  list-files: -M aka diff-cached
  t3080: tests for git-list-files

Total diff against 'pu' is something like this

-- 8< --
diff --git a/Documentation/git-list-files.txt b/Documentation/git-list-files.txt
index c57129b..223f6fd 100644
--- a/Documentation/git-list-files.txt
+++ b/Documentation/git-list-files.txt
@@ -14,7 +14,8 @@ DESCRIPTION
 -----------
 List files (by default in current working directory) that are in the
 index. Depending on the chosen options, maybe only modified files in
-working tree are shown, or untracked files...
+working tree are shown, or untracked files... The builtin alias "ls"
+is set to "list-files".
 
 OPTIONS
 -------
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 02a9ac1..b04c712 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -213,6 +213,37 @@ static void show_killed_files(struct dir_struct *dir)
 	}
 }
 
+static int show_as_directory(const struct cache_entry *ce)
+{
+	struct strbuf sb = STRBUF_INIT;
+	const char *p;
+
+	strbuf_add(&sb, ce->name, ce_namelen(ce));
+	while (sb.len && (p = strrchr(sb.buf, '/')) != NULL) {
+		struct strbuf sb2 = STRBUF_INIT;
+		strbuf_setlen(&sb, p - sb.buf);
+		if (!match_pathspec(&pathspec, sb.buf, sb.len,
+				    max_prefix_len, NULL, 1))
+			continue;
+		write_name(&sb2, sb.buf);
+		if (want_color(use_color)) {
+			struct strbuf sb3 = STRBUF_INIT;
+			color_filename(&sb3, ce->name, sb2.buf, S_IFDIR, 1);
+			strbuf_release(&sb2);
+			sb2 = sb3;
+		}
+		if (show_tag)
+			strbuf_insert(&sb2, 0, tag_cached, strlen(tag_cached));
+		if (show_indicator)
+			append_indicator(&sb2, S_IFDIR);
+		strbuf_fputs(&sb2, strbuf_detach(&sb, NULL), NULL);
+		strbuf_release(&sb2);
+		return 1;
+	}
+	strbuf_release(&sb);
+	return 0;
+}
+
 static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
 {
 	struct strbuf quoted = STRBUF_INIT;
@@ -230,16 +261,31 @@ static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
 static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
 	static struct strbuf sb = STRBUF_INIT;
-	int len = max_prefix_len;
+	int len = max_prefix_len, saved_max_depth;
 
 	if (len >= ce_namelen(ce))
 		die("git ls-files: internal error - cache entry not superset of prefix");
 
+	if (show_dirs) {
+		/* ignore depth to catch dirs that contain matched entries */
+		saved_max_depth = pathspec.max_depth;
+		pathspec.max_depth = -1;
+	}
+
 	if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce),
 			    len, ps_matched,
 			    S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode)))
 		return;
 
+	if (show_dirs) {
+		pathspec.max_depth = saved_max_depth;
+		if (strchr(ce->name, '/') &&
+		    !match_pathspec(&pathspec, ce->name, ce_namelen(ce),
+				    prefix_len, NULL, 1) &&
+		    show_as_directory(ce))
+			return;
+	}
+
 	if (tag && *tag && show_valid_bit &&
 	    (ce->ce_flags & CE_VALID)) {
 		static char alttag[4];
@@ -348,7 +394,7 @@ static void show_files(struct dir_struct *dir)
 				(ce_skip_worktree(ce) ? tag_skip_worktree : tag_cached), ce);
 		}
 	}
-	if (show_deleted || show_modified || show_diff_cached) {
+	if (show_deleted || show_modified) {
 		for (i = 0; i < active_nr; i++) {
 			const struct cache_entry *ce = active_cache[i];
 			struct stat st;
@@ -377,45 +423,6 @@ static void show_files(struct dir_struct *dir)
 	}
 }
 
-static void show_directories(const struct cache_entry *ce)
-{
-	static const char *last_directory;
-	struct strbuf sb = STRBUF_INIT;
-	const char *p = ce->name + prefix_len;
-	const char *sep;
-
-	if (last_directory) {
-		int len = strlen(last_directory);
-		if (!strncmp(ce->name, last_directory, len) &&
-		    ce->name[len] == '/')
-			p += len + 1;
-	}
-
-	while (*p && (sep = strchr(p, '/'))) {
-		struct strbuf sb2 = STRBUF_INIT;
-		strbuf_reset(&sb);
-		strbuf_add(&sb, ce->name, sep - ce->name);
-		p = sep + 1;
-		if (!match_pathspec(&pathspec, sb.buf, sb.len,
-				    prefix_len, NULL, 1))
-			continue;
-		write_name(&sb2, sb.buf);
-		if (want_color(use_color)) {
-			struct strbuf sb3 = STRBUF_INIT;
-			color_filename(&sb3, ce->name, sb2.buf, S_IFDIR, 1);
-			strbuf_release(&sb2);
-			sb2 = sb3;
-		}
-		if (show_tag)
-			strbuf_insert(&sb2, 0, tag_cached, strlen(tag_cached));
-		if (show_indicator)
-			append_indicator(&sb2, S_IFDIR);
-		last_directory = strbuf_detach(&sb, NULL);
-		strbuf_fputs(&sb2, last_directory, NULL);
-		strbuf_release(&sb2);
-	}
-}
-
 static void show_files_compact(struct dir_struct *dir)
 {
 	int i;
@@ -430,14 +437,13 @@ static void show_files_compact(struct dir_struct *dir)
 		if (show_killed)
 			show_killed_files(dir);
 	}
-	if (!(show_cached || show_stage || show_deleted || show_modified))
+	if (!(show_cached || show_unmerged || show_deleted ||
+	      show_modified || show_diff_cached))
 		return;
 	for (i = 0; i < active_nr; i++) {
 		const struct cache_entry *ce = active_cache[i];
 		struct stat st;
 		int err, shown = 0;
-		if (show_dirs)
-			show_directories(ce);
 		if ((dir->flags & DIR_SHOW_IGNORED) &&
 		    !ce_excluded(dir, ce))
 			continue;
@@ -452,6 +458,15 @@ static void show_files_compact(struct dir_struct *dir)
 			show_ce_entry(tag_removed, ce);
 			shown = 1;
 		}
+		if (show_diff_cached && (ce->ce_flags & CE_MATCHED)) {
+			show_ce_entry(tag_diff_cached, ce);
+			shown = 1;
+			/*
+			 * if we don't clear, it'll confuse write_ce_name()
+			 * when show_ce_entry(tag_modified, ce) is called
+			 */
+			active_cache[i]->ce_flags &= ~CE_MATCHED;
+		}
 		if (show_modified && (err || ce_modified(ce, &st, 0))) {
 			show_ce_entry(tag_modified, ce);
 			shown = 1;
@@ -817,7 +832,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		use_color = -1;
 		max_depth = 0;
 		show_tag = -1;
-		show_dirs = 1;
 		git_config(git_ls_config, NULL);
 	} else
 		git_config(git_default_config, NULL);
@@ -866,6 +880,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		       prefix, argv);
 	pathspec.max_depth = max_depth;
 	pathspec.recursive = 1;
+	show_dirs = porcelain && max_depth != -1;
+
 
 	/* Find common prefix for all pathspec's */
 	max_prefix = common_prefix(&pathspec);
@@ -911,7 +927,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		overlay_tree_on_cache(with_tree, max_prefix);
 	}
 	if (porcelain) {
-		refresh_index(&the_index, REFRESH_QUIET, &pathspec, NULL, NULL);
+		refresh_index(&the_index, REFRESH_QUIET | REFRESH_UNMERGED, &pathspec, NULL, NULL);
 		setup_pager();
 	}
 	if (show_diff_cached)
diff --git a/config.c b/config.c
index 15a2983..16209c6 100644
--- a/config.c
+++ b/config.c
@@ -40,6 +40,10 @@ static struct config_source *cf;
 
 static int zlib_compression_seen;
 
+static const char *builtin_config =
+	"[alias]\n"
+	"	ls = list-files\n";
+
 /*
  * Default config_set that contains key-value pairs from the usual set of config
  * config files (i.e repo specific .git/config, user wide ~/.gitconfig, XDG
@@ -1175,6 +1179,10 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
 
 	home_config_paths(&user_config, &xdg_config, "config");
 
+	if (git_config_system())
+		git_config_from_buf(fn, "<builtin>", builtin_config,
+				    strlen(builtin_config), data);
+
 	if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) {
 		ret += git_config_from_file(fn, git_etc_gitconfig(),
 					    data);
diff --git a/t/t3080-list-files.sh b/t/t3080-list-files.sh
new file mode 100755
index 0000000..6313dd9
--- /dev/null
+++ b/t/t3080-list-files.sh
@@ -0,0 +1,122 @@
+#!/bin/sh
+
+test_description='git list-files test'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	mkdir dir &&
+	touch file dir/file &&
+	git init gitlink &&
+	( cd gitlink && test_commit foo ) &&
+	git add file dir/file gitlink &&
+	git commit -qm1
+'
+
+test_expect_success 'LS_COLORS env variable' '
+	LS_COLORS="rs=0:fi=31:di=32" \
+		git list-files --color=always | grep -v gitlink >actual &&
+	test_cmp "$TEST_DIRECTORY"/t3080/ls_colors actual
+'
+
+test_expect_success 'color.ls.*' '
+	test_config color.ls.file red &&
+	test_config color.ls.directory green &&
+	test_config color.ls.submodule yellow &&
+	git list-files --color=always >actual &&
+	test_cmp "$TEST_DIRECTORY"/t3080/color_ls actual
+'
+
+test_expect_success 'column output' '
+	COLUMNS=20 git list-files --column=always >actual &&
+	cat >expected <<-\EOF &&
+	dir      gitlink
+	file
+	EOF
+	test_cmp expected actual &&
+	git list-files -1 >actual &&
+	cat >expected <<-\EOF &&
+	dir
+	file
+	gitlink
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success '--max-depth' '
+	git list-files --max-depth=1 >actual &&
+	cat >expected <<-\EOF &&
+	dir/file
+	file
+	gitlink
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'recursive' '
+	git list-files -R >actual &&
+	cat >expected <<-\EOF &&
+	dir/file
+	file
+	gitlink
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'globbing' '
+	git list-files "f*" >actual &&
+	cat >expected <<-\EOF &&
+	file
+	EOF
+	test_cmp expected actual &&
+	git list-files "**/f*" >actual &&
+	cat >expected <<-\EOF &&
+	dir/file
+	file
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'no dups' '
+	echo dirty >>file &&
+	git list-files -m file >actual &&
+	echo "file" >expected &&
+	test_cmp expected actual &&
+	git list-files -cm file >actual &&
+	echo "C file" >expected &&
+	test_cmp expected actual &&
+	git list-files -tcm file >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '--classify' '
+	git list-files -F >actual &&
+	cat >expected <<-\EOF &&
+	dir/
+	file
+	gitlink&
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'diff-cached' '
+	echo dirty >>file &&
+	git add file &&
+	git list-files -M >actual &&
+	echo "file" >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'unmerged files' '
+	git ls-files --stage file >index-info &&
+	sed "s/ 0/ 2/;s/file/unmerged/" index-info | git update-index --index-info &&
+	sed "s/ 0/ 3/;s,file,dir/unmerged," index-info | git update-index --index-info &&
+	git list-files -u >actual &&
+	cat >expected <<-\EOF &&
+	dir
+	unmerged
+	EOF
+	test_cmp expected actual
+'
+
+test_done
diff --git a/t/t3080/color_ls b/t/t3080/color_ls
new file mode 100644
index 0000000..47f77ad
--- /dev/null
+++ b/t/t3080/color_ls
@@ -0,0 +1,3 @@
+^[[32mdir^[[m
+^[[31mfile^[[m
+^[[33mgitlink^[[m
diff --git a/t/t3080/ls_colors b/t/t3080/ls_colors
new file mode 100644
index 0000000..423c016
--- /dev/null
+++ b/t/t3080/ls_colors
@@ -0,0 +1,2 @@
+^[[32mdir^[[m
+^[[31mfile^[[m
-- 8< --
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 01/21] ls_colors.c: add $LS_COLORS parsing code
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 02/21] ls_colors.c: parse color.ls.* from config file Nguyễn Thái Ngọc Duy
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Reusing color settings from $LS_COLORS could give a native look and
feel on file coloring.

This code is basically from coreutils.git [1], rewritten to fit Git.

As this is from GNU ls, the environment variable CLICOLOR is not
tested. It is to be decided later whether we should ignore $LS_COLORS
if $CLICOLOR is not set on Mac or FreeBSD.

[1] commit 7326d1f1a67edf21947ae98194f98c38b6e9e527 file
    src/ls.c. This is the last GPL-2 commit before coreutils turns to
    GPL-3.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Makefile          |   1 +
 color.h           |   8 ++
 ls_colors.c (new) | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 407 insertions(+)
 create mode 100644 ls_colors.c

diff --git a/Makefile b/Makefile
index 827006b..459121d 100644
--- a/Makefile
+++ b/Makefile
@@ -703,6 +703,7 @@ LIB_OBJS += list-objects.o
 LIB_OBJS += ll-merge.o
 LIB_OBJS += lockfile.o
 LIB_OBJS += log-tree.o
+LIB_OBJS += ls_colors.o
 LIB_OBJS += mailmap.o
 LIB_OBJS += match-trees.o
 LIB_OBJS += merge.o
diff --git a/color.h b/color.h
index f5beab1..3eaa5bd 100644
--- a/color.h
+++ b/color.h
@@ -45,6 +45,12 @@ struct strbuf;
 #define GIT_COLOR_BG_MAGENTA	"\033[45m"
 #define GIT_COLOR_BG_CYAN	"\033[46m"
 
+#define GIT_COLOR_WHITE_ON_RED    "\033[37;41m"
+#define GIT_COLOR_WHITE_ON_BLUE   "\033[37;44m"
+#define GIT_COLOR_BLACK_ON_YELLOW "\033[30;43m"
+#define GIT_COLOR_BLUE_ON_GREEN   "\033[34;42m"
+#define GIT_COLOR_BLACK_ON_GREEN  "\033[30;42m"
+
 /* A special value meaning "no color selected" */
 #define GIT_COLOR_NIL "NIL"
 
@@ -87,4 +93,6 @@ void color_print_strbuf(FILE *fp, const char *color, const struct strbuf *sb);
 
 int color_is_nil(const char *color);
 
+void parse_ls_color(void);
+
 #endif /* COLOR_H */
diff --git a/ls_colors.c b/ls_colors.c
new file mode 100644
index 0000000..e743315
--- /dev/null
+++ b/ls_colors.c
@@ -0,0 +1,398 @@
+#include "cache.h"
+#include "color.h"
+
+enum color_ls {
+	LS_LC,			/* left, unused */
+	LS_RC,			/* right, unused */
+	LS_EC,			/* end color, unused */
+	LS_RS,			/* reset */
+	LS_NO,			/* normal */
+	LS_FL,			/* file, default */
+	LS_DI,			/* directory */
+	LS_LN,			/* symlink */
+
+	LS_PI,			/* pipe */
+	LS_SO,			/* socket */
+	LS_BD,			/* block device */
+	LS_CD,			/* char device */
+	LS_MI,			/* missing file */
+	LS_OR,			/* orphaned symlink */
+	LS_EX,			/* executable */
+	LS_DO,			/* Solaris door */
+
+	LS_SU,			/* setuid */
+	LS_SG,			/* setgid */
+	LS_ST,			/* sticky */
+	LS_OW,			/* other-writable */
+	LS_TW,			/* ow with sticky */
+	LS_CA,			/* cap */
+	LS_MH,			/* multi hardlink */
+	LS_CL,			/* clear end of line */
+
+	MAX_LS
+};
+
+static char ls_colors[MAX_LS][COLOR_MAXLEN] = {
+	"",
+	"",
+	"",
+	GIT_COLOR_RESET,
+	GIT_COLOR_NORMAL,
+	GIT_COLOR_NORMAL,
+	GIT_COLOR_BOLD_BLUE,
+	GIT_COLOR_BOLD_CYAN,
+
+	GIT_COLOR_YELLOW,
+	GIT_COLOR_BOLD_MAGENTA,
+	GIT_COLOR_BOLD_YELLOW,
+	GIT_COLOR_BOLD_YELLOW,
+	GIT_COLOR_NORMAL,
+	GIT_COLOR_NORMAL,
+	GIT_COLOR_BOLD_GREEN,
+	GIT_COLOR_BOLD_MAGENTA,
+
+	GIT_COLOR_WHITE_ON_RED,
+	GIT_COLOR_BLACK_ON_YELLOW,
+	GIT_COLOR_WHITE_ON_BLUE,
+	GIT_COLOR_BLUE_ON_GREEN,
+	GIT_COLOR_BLACK_ON_GREEN,
+	"",
+	"",
+	""
+};
+
+static const char *const indicator_name[] = {
+	"lc", "rc", "ec", "rs", "no", "fi", "di", "ln",
+	"pi", "so", "bd", "cd", "mi", "or", "ex", "do",
+	"su", "sg", "st", "ow", "tw", "ca", "mh", "cl",
+	NULL
+};
+
+struct bin_str {
+	size_t len;			/* Number of bytes */
+	const char *string;		/* Pointer to the same */
+};
+
+struct color_ext_type {
+	struct bin_str ext;		/* The extension we're looking for */
+	struct bin_str seq;		/* The sequence to output when we do */
+	struct color_ext_type *next;	/* Next in list */
+};
+
+static struct color_ext_type *color_ext_list;
+
+/*
+ * When true, in a color listing, color each symlink name according to the
+ * type of file it points to.  Otherwise, color them according to the `ln'
+ * directive in LS_COLORS.  Dangling (orphan) symlinks are treated specially,
+ * regardless.  This is set when `ln=target' appears in LS_COLORS.
+ */
+static int color_symlink_as_referent;
+
+/*
+ * Parse a string as part of the LS_COLORS variable; this may involve
+ * decoding all kinds of escape characters.  If equals_end is set an
+ * unescaped equal sign ends the string, otherwise only a : or \0
+ * does.  Set *OUTPUT_COUNT to the number of bytes output.  Return
+ * true if successful.
+ *
+ * The resulting string is *not* null-terminated, but may contain
+ * embedded nulls.
+ *
+ * Note that both dest and src are char **; on return they point to
+ * the first free byte after the array and the character that ended
+ * the input string, respectively.
+ */
+static int get_funky_string(char **dest, const char **src, int equals_end,
+			    size_t *output_count)
+{
+	char num;			/* For numerical codes */
+	size_t count;			/* Something to count with */
+	enum {
+		ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX,
+		ST_CARET, ST_END, ST_ERROR
+	} state;
+	const char *p;
+	char *q;
+
+	p = *src;			/* We don't want to double-indirect */
+	q = *dest;			/* the whole darn time.  */
+
+	count = 0;			/* No characters counted in yet.  */
+	num = 0;
+
+	state = ST_GND;		/* Start in ground state.  */
+	while (state < ST_END) {
+		switch (state) {
+		case ST_GND:		/* Ground state (no escapes) */
+			switch (*p) {
+			case ':':
+			case '\0':
+				state = ST_END;	/* End of string */
+				break;
+			case '\\':
+				state = ST_BACKSLASH; /* Backslash scape sequence */
+				++p;
+				break;
+			case '^':
+				state = ST_CARET; /* Caret escape */
+				++p;
+				break;
+			case '=':
+				if (equals_end) {
+					state = ST_END; /* End */
+					break;
+				}
+				/* else fall through */
+			default:
+				*(q++) = *(p++);
+				++count;
+				break;
+			}
+			break;
+
+		case ST_BACKSLASH:	/* Backslash escaped character */
+			switch (*p) {
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+				state = ST_OCTAL;	/* Octal sequence */
+				num = *p - '0';
+				break;
+			case 'x':
+			case 'X':
+				state = ST_HEX;	/* Hex sequence */
+				num = 0;
+				break;
+			case 'a':		/* Bell */
+				num = '\a';
+				break;
+			case 'b':		/* Backspace */
+				num = '\b';
+				break;
+			case 'e':		/* Escape */
+				num = 27;
+				break;
+			case 'f':		/* Form feed */
+				num = '\f';
+				break;
+			case 'n':		/* Newline */
+				num = '\n';
+				break;
+			case 'r':		/* Carriage return */
+				num = '\r';
+				break;
+			case 't':		/* Tab */
+				num = '\t';
+				break;
+			case 'v':		/* Vtab */
+				num = '\v';
+				break;
+			case '?':		/* Delete */
+				num = 127;
+				break;
+			case '_':		/* Space */
+				num = ' ';
+				break;
+			case '\0':		/* End of string */
+				state = ST_ERROR;	/* Error! */
+				break;
+			default:		/* Escaped character like \ ^ : = */
+				num = *p;
+				break;
+			}
+			if (state == ST_BACKSLASH) {
+				*(q++) = num;
+				++count;
+				state = ST_GND;
+			}
+			++p;
+			break;
+
+		case ST_OCTAL:		/* Octal sequence */
+			if (*p < '0' || *p > '7') {
+				*(q++) = num;
+				++count;
+				state = ST_GND;
+			} else
+				num = (num << 3) + (*(p++) - '0');
+			break;
+
+		case ST_HEX:		/* Hex sequence */
+			switch (*p) {
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+			case '8':
+			case '9':
+				num = (num << 4) + (*(p++) - '0');
+				break;
+			case 'a':
+			case 'b':
+			case 'c':
+			case 'd':
+			case 'e':
+			case 'f':
+				num = (num << 4) + (*(p++) - 'a') + 10;
+				break;
+			case 'A':
+			case 'B':
+			case 'C':
+			case 'D':
+			case 'E':
+			case 'F':
+				num = (num << 4) + (*(p++) - 'A') + 10;
+				break;
+			default:
+				*(q++) = num;
+				++count;
+				state = ST_GND;
+				break;
+			}
+			break;
+
+		case ST_CARET:		/* Caret escape */
+			state = ST_GND;	/* Should be the next state... */
+			if (*p >= '@' && *p <= '~') {
+				*(q++) = *(p++) & 037;
+				++count;
+			} else if (*p == '?') {
+				*(q++) = 127;
+				++count;
+			} else
+				state = ST_ERROR;
+			break;
+
+		default:
+			abort();
+		}
+	}
+
+	*dest = q;
+	*src = p;
+	*output_count = count;
+
+	return state != ST_ERROR;
+}
+
+void parse_ls_color(void)
+{
+	const char *p;			/* Pointer to character being parsed */
+	char *buf;			/* color_buf buffer pointer */
+	int state;			/* State of parser */
+	int ind_no;			/* Indicator number */
+	char label[3];			/* Indicator label */
+	struct color_ext_type *ext;	/* Extension we are working on */
+	static char *color_buf;
+	char *start;
+	size_t len;
+
+	if ((p = getenv("LS_COLORS")) == NULL || *p == '\0')
+		return;
+
+	ext = NULL;
+	strcpy(label, "??");
+
+	/*
+	 * This is an overly conservative estimate, but any possible
+	 * LS_COLORS string will *not* generate a color_buf longer
+	 * than itself, so it is a safe way of allocating a buffer in
+	 * advance.
+	 */
+	buf = color_buf = xstrdup(p);
+
+	state = 1;
+	while (state > 0) {
+		switch (state) {
+		case 1:		/* First label character */
+			switch (*p) {
+			case ':':
+				++p;
+				break;
+
+			case '*':
+				/*
+				 * Allocate new extension block and add to head of
+				 * linked list (this way a later definition will
+				 * override an earlier one, which can be useful for
+				 * having terminal-specific defs override global).
+				 */
+
+				ext = xmalloc(sizeof(*ext));
+				ext->next = color_ext_list;
+				color_ext_list = ext;
+
+				++p;
+				ext->ext.string = buf;
+
+				state = (get_funky_string(&buf, &p, 1, &ext->ext.len)
+					 ? 4 : -1);
+				break;
+
+			case '\0':
+				state = 0;	/* Done! */
+				break;
+
+			default:	/* Assume it is file type label */
+				label[0] = *(p++);
+				state = 2;
+				break;
+			}
+			break;
+
+		case 2:		/* Second label character */
+			if (*p) {
+				label[1] = *(p++);
+				state = 3;
+			} else
+				state = -1;	/* Error */
+			break;
+
+		case 3:		/* Equal sign after indicator label */
+			state = -1;	/* Assume failure...  */
+			if (*(p++) != '=')
+				break;
+			for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no) {
+				if (!strcmp(label, indicator_name[ind_no])) {
+					start = buf;
+					if (get_funky_string(&buf, &p, 0, &len))
+						state = 1;
+					else
+						state = -1;
+					break;
+				}
+			}
+			if (state == -1)
+				error(_("unrecognized prefix: %s"), label);
+			else if (ind_no == LS_LN && len == 6 &&
+				 starts_with(start, "target"))
+				color_symlink_as_referent = 1;
+			else
+				sprintf(ls_colors[ind_no], "\033[%.*sm",
+				       (int)len, start);
+			break;
+
+		case 4:		/* Equal sign after *.ext */
+			if (*(p++) == '=') {
+				ext->seq.string = buf;
+				state = (get_funky_string(&buf, &p, 0, &ext->seq.len)
+					 ? 1 : -1);
+			} else
+				state = -1;
+			break;
+		}
+	}
+
+	if (!strcmp(ls_colors[LS_LN], "target"))
+		color_symlink_as_referent = 1;
+}
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/21] ls_colors.c: parse color.ls.* from config file
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 01/21] ls_colors.c: add $LS_COLORS parsing code Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 03/21] ls_colors.c: add a function to color a file name Nguyễn Thái Ngọc Duy
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

This is the second (and preferred) source for color information. This
will override $LS_COLORS.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/config.txt | 11 +++++++++++
 ls_colors.c              | 26 ++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 9220725..2090866 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -940,6 +940,17 @@ color.status.<slot>::
 	to red). The values of these variables may be specified as in
 	color.branch.<slot>.
 
+color.ls.<slot>::
+	Use customized color for file name colorization. If not set
+	and the environment variable LS_COLORS is set, color settings
+	from $LS_COLORS are used. `<slot>` can be `normal`, `file`,
+	`directory`, `symlink`, `fifo`, `socket`, `block`, `char`,
+	`missing`, `orphan`, `executable`, `door`, `setuid`, `setgid`,
+	`sticky`, `otherwritable`, `stickyotherwritable`, `cap`,
+	`multihardlink`. The values of these variables may be
+	specified as in color.branch.<slot>.
+
+
 color.ui::
 	This variable determines the default value for variables such
 	as `color.diff` and `color.grep` that control the use of color
diff --git a/ls_colors.c b/ls_colors.c
index e743315..08e7068 100644
--- a/ls_colors.c
+++ b/ls_colors.c
@@ -68,6 +68,14 @@ static const char *const indicator_name[] = {
 	NULL
 };
 
+static const char * const config_name[] = {
+	"", "", "", "", "normal", "file", "directory", "symlink",
+	"fifo", "socket", "block", "char", "missing", "orphan", "executable",
+	"door", "setuid", "setgid", "sticky", "otherwritable",
+	"stickyotherwritable", "cap", "multihardlink", "",
+	NULL
+};
+
 struct bin_str {
 	size_t len;			/* Number of bytes */
 	const char *string;		/* Pointer to the same */
@@ -285,6 +293,23 @@ static int get_funky_string(char **dest, const char **src, int equals_end,
 	return state != ST_ERROR;
 }
 
+static int ls_colors_config(const char *var, const char *value, void *cb)
+{
+	int slot;
+	if (!starts_with(var, "color.ls."))
+		return 0;
+	var += 9;
+	for (slot = 0; config_name[slot]; slot++)
+		if (!strcasecmp(var, config_name[slot]))
+			break;
+	if (!config_name[slot])
+		return 0;
+	if (!value)
+		return config_error_nonbool(var);
+	color_parse(value, ls_colors[slot]);
+	return 0;
+}
+
 void parse_ls_color(void)
 {
 	const char *p;			/* Pointer to character being parsed */
@@ -395,4 +420,5 @@ void parse_ls_color(void)
 
 	if (!strcmp(ls_colors[LS_LN], "target"))
 		color_symlink_as_referent = 1;
+	git_config(ls_colors_config, NULL);
 }
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/21] ls_colors.c: add a function to color a file name
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 01/21] ls_colors.c: add $LS_COLORS parsing code Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 02/21] ls_colors.c: parse color.ls.* from config file Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 04/21] ls_colors.c: highlight submodules like directories Nguyễn Thái Ngọc Duy
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

The new function is based on print_color_indicator() from commit
7326d1f1a67edf21947ae98194f98c38b6e9e527 in coreutils.git.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 color.h     |  2 ++
 ls_colors.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/color.h b/color.h
index 3eaa5bd..b6904a3 100644
--- a/color.h
+++ b/color.h
@@ -94,5 +94,7 @@ void color_print_strbuf(FILE *fp, const char *color, const struct strbuf *sb);
 int color_is_nil(const char *color);
 
 void parse_ls_color(void);
+void color_filename(struct strbuf *sb, const char *name,
+		    const char *display_name, mode_t mode, int linkok);
 
 #endif /* COLOR_H */
diff --git a/ls_colors.c b/ls_colors.c
index 08e7068..7d2e2e0 100644
--- a/ls_colors.c
+++ b/ls_colors.c
@@ -422,3 +422,69 @@ void parse_ls_color(void)
 		color_symlink_as_referent = 1;
 	git_config(ls_colors_config, NULL);
 }
+
+void color_filename(struct strbuf *sb, const char *name,
+		    const char *display_name, mode_t mode, int linkok)
+{
+	int type;
+	struct color_ext_type *ext;	/* Color extension */
+
+	if (S_ISREG(mode)) {
+		type = LS_FL;
+		if ((mode & S_ISUID) != 0)
+			type = LS_SU;
+		else if ((mode & S_ISGID) != 0)
+			type = LS_SG;
+		else if ((mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)
+			type = LS_EX;
+	} else if (S_ISDIR(mode)) {
+		if ((mode & S_ISVTX) && (mode & S_IWOTH))
+			type = LS_TW;
+		else if ((mode & S_IWOTH) != 0)
+			type = LS_OW;
+		else if ((mode & S_ISVTX) != 0)
+			type = LS_ST;
+		else
+			type = LS_DI;
+	} else if (S_ISLNK(mode))
+		type = (!linkok && *ls_colors[LS_OR]) ? LS_OR : LS_LN;
+	else if (S_ISFIFO(mode))
+		type = LS_PI;
+	else if (S_ISSOCK(mode))
+		type = LS_SO;
+	else if (S_ISBLK(mode))
+		type = LS_BD;
+	else if (S_ISCHR(mode))
+		type = LS_CD;
+#ifdef S_ISDOOR
+	else if (S_ISDOOR(mode))
+		type = LS_DO;
+#endif
+	else
+		/* Classify a file of some other type as C_ORPHAN.  */
+		type = LS_OR;
+
+	/* Check the file's suffix only if still classified as C_FILE.  */
+	ext = NULL;
+	if (type == LS_FL) {
+		/* Test if NAME has a recognized suffix.  */
+		size_t len = strlen(name);
+		const char *p = name + len;		/* Pointer to final \0.  */
+		for (ext = color_ext_list; ext != NULL; ext = ext->next) {
+			if (ext->ext.len <= len &&
+			    !strncmp(p - ext->ext.len, ext->ext.string, ext->ext.len))
+				break;
+		}
+	}
+
+	if (display_name)
+		name = display_name;
+	if (ext)
+		strbuf_addf(sb, "\033[%.*sm%s%s",
+			    (int)ext->seq.len, ext->seq.string,
+			    name, GIT_COLOR_RESET);
+	else if (*ls_colors[type])
+		strbuf_addf(sb, "%s%s%s", ls_colors[type], name, GIT_COLOR_RESET);
+	else
+		strbuf_addstr(sb, name);
+}
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/21] ls_colors.c: highlight submodules like directories
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (2 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 03/21] ls_colors.c: add a function to color a file name Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 05/21] ls-files: buffer full item in strbuf before printing Nguyễn Thái Ngọc Duy
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/config.txt | 3 ++-
 ls_colors.c              | 8 +++++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 2090866..2290c47 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -944,7 +944,8 @@ color.ls.<slot>::
 	Use customized color for file name colorization. If not set
 	and the environment variable LS_COLORS is set, color settings
 	from $LS_COLORS are used. `<slot>` can be `normal`, `file`,
-	`directory`, `symlink`, `fifo`, `socket`, `block`, `char`,
+	`directory`, `submodule`,
+	`symlink`, `fifo`, `socket`, `block`, `char`,
 	`missing`, `orphan`, `executable`, `door`, `setuid`, `setgid`,
 	`sticky`, `otherwritable`, `stickyotherwritable`, `cap`,
 	`multihardlink`. The values of these variables may be
diff --git a/ls_colors.c b/ls_colors.c
index 7d2e2e0..9259ad3 100644
--- a/ls_colors.c
+++ b/ls_colors.c
@@ -29,6 +29,8 @@ enum color_ls {
 	LS_MH,			/* multi hardlink */
 	LS_CL,			/* clear end of line */
 
+	LS_SUBMODULE,
+
 	MAX_LS
 };
 
@@ -58,7 +60,8 @@ static char ls_colors[MAX_LS][COLOR_MAXLEN] = {
 	GIT_COLOR_BLACK_ON_GREEN,
 	"",
 	"",
-	""
+	"",
+	GIT_COLOR_BOLD_BLUE
 };
 
 static const char *const indicator_name[] = {
@@ -73,6 +76,7 @@ static const char * const config_name[] = {
 	"fifo", "socket", "block", "char", "missing", "orphan", "executable",
 	"door", "setuid", "setgid", "sticky", "otherwritable",
 	"stickyotherwritable", "cap", "multihardlink", "",
+	"submodule",
 	NULL
 };
 
@@ -448,6 +452,8 @@ void color_filename(struct strbuf *sb, const char *name,
 			type = LS_DI;
 	} else if (S_ISLNK(mode))
 		type = (!linkok && *ls_colors[LS_OR]) ? LS_OR : LS_LN;
+	else if (S_ISGITLINK(mode))
+		type = LS_SUBMODULE;
 	else if (S_ISFIFO(mode))
 		type = LS_PI;
 	else if (S_ISSOCK(mode))
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/21] ls-files: buffer full item in strbuf before printing
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (3 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 04/21] ls_colors.c: highlight submodules like directories Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 06/21] ls-files: add --color to highlight file names Nguyễn Thái Ngọc Duy
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Buffering so that we can manipulate the strings (e.g. coloring)
further before finally printing them.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/ls-files.c | 48 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 99cee20..b6f0d9f 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -47,18 +47,30 @@ static const char *tag_modified = "";
 static const char *tag_skip_worktree = "";
 static const char *tag_resolve_undo = "";
 
-static void write_name(const char *name)
+static void write_name(struct strbuf *sb, const char *name)
 {
 	/*
 	 * With "--full-name", prefix_len=0; this caller needs to pass
 	 * an empty string in that case (a NULL is good for "").
 	 */
-	write_name_quoted_relative(name, prefix_len ? prefix : NULL,
-				   stdout, line_terminator);
+	const char *real_prefix = prefix_len ? prefix : NULL;
+	if (!line_terminator) {
+		struct strbuf sb2 = STRBUF_INIT;
+		strbuf_addstr(sb, relative_path(name, real_prefix, &sb2));
+		strbuf_release(&sb2);
+	} else
+		quote_path_relative(name, real_prefix, sb);
+	strbuf_addch(sb, line_terminator);
+}
+
+static void strbuf_fputs(struct strbuf *sb, FILE *fp)
+{
+	fwrite(sb->buf, sb->len, 1, fp);
 }
 
 static void show_dir_entry(const char *tag, struct dir_entry *ent)
 {
+	static struct strbuf sb = STRBUF_INIT;
 	int len = max_prefix_len;
 
 	if (len >= ent->len)
@@ -67,8 +79,10 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
 	if (!dir_path_match(ent, &pathspec, len, ps_matched))
 		return;
 
-	fputs(tag, stdout);
-	write_name(ent->name);
+	strbuf_reset(&sb);
+	strbuf_addstr(&sb, tag);
+	write_name(&sb, ent->name);
+	strbuf_fputs(&sb, stdout);
 }
 
 static void show_other_files(struct dir_struct *dir)
@@ -134,6 +148,7 @@ static void show_killed_files(struct dir_struct *dir)
 
 static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
+	static struct strbuf sb = STRBUF_INIT;
 	int len = max_prefix_len;
 
 	if (len >= ce_namelen(ce))
@@ -161,16 +176,18 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 		tag = alttag;
 	}
 
+	strbuf_reset(&sb);
 	if (!show_stage) {
-		fputs(tag, stdout);
+		strbuf_addstr(&sb, tag);
 	} else {
-		printf("%s%06o %s %d\t",
-		       tag,
-		       ce->ce_mode,
-		       find_unique_abbrev(ce->sha1,abbrev),
-		       ce_stage(ce));
+		strbuf_addf(&sb, "%s%06o %s %d\t",
+			    tag,
+			    ce->ce_mode,
+			    find_unique_abbrev(ce->sha1, abbrev),
+			    ce_stage(ce));
 	}
-	write_name(ce->name);
+	write_name(&sb, ce->name);
+	strbuf_fputs(&sb, stdout);
 	if (debug_mode) {
 		const struct stat_data *sd = &ce->ce_stat_data;
 
@@ -206,7 +223,12 @@ 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);
-			write_name(path);
+			/*
+			 * With "--full-name", prefix_len=0; this caller needs to pass
+			 * an empty string in that case (a NULL is good for "").
+			 */
+			write_name_quoted_relative(path, prefix_len ? prefix : NULL,
+						   stdout, line_terminator);
 		}
 	}
 }
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/21] ls-files: add --color to highlight file names
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (4 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 05/21] ls-files: buffer full item in strbuf before printing Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 07/21] ls-files: add --column Nguyễn Thái Ngọc Duy
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-ls-files.txt |  7 +++++++
 builtin/ls-files.c             | 38 +++++++++++++++++++++++++++++++++++---
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index e26f01f..148f226 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -147,6 +147,13 @@ a space) at the start of each line:
 	possible for manual inspection; the exact format may change at
 	any time.
 
+--color[=<when>]::
+--no-color::
+	Color file names. The value must be `always`, `never`, or
+	`auto`. `--no-color` is equivalent to
+	`--color=never`. `--color` is equivalent to
+	`--color=auto`.
+
 \--::
 	Do not interpret any more arguments as options.
 
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index b6f0d9f..0ee4f19 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -14,6 +14,7 @@
 #include "resolve-undo.h"
 #include "string-list.h"
 #include "pathspec.h"
+#include "color.h"
 
 static int abbrev;
 static int show_deleted;
@@ -27,6 +28,7 @@ static int show_killed;
 static int show_valid_bit;
 static int line_terminator = '\n';
 static int debug_mode;
+static int use_color;
 
 static const char *prefix;
 static int max_prefix_len;
@@ -60,7 +62,6 @@ static void write_name(struct strbuf *sb, const char *name)
 		strbuf_release(&sb2);
 	} else
 		quote_path_relative(name, real_prefix, sb);
-	strbuf_addch(sb, line_terminator);
 }
 
 static void strbuf_fputs(struct strbuf *sb, FILE *fp)
@@ -68,6 +69,21 @@ static void strbuf_fputs(struct strbuf *sb, FILE *fp)
 	fwrite(sb->buf, sb->len, 1, fp);
 }
 
+static void write_dir_entry(struct strbuf *sb, const struct dir_entry *ent)
+{
+	struct strbuf quoted = STRBUF_INIT;
+	struct stat st;
+	if (stat(ent->name, &st))
+		st.st_mode = 0;
+	write_name(&quoted, ent->name);
+	if (want_color(use_color))
+		color_filename(sb, ent->name, quoted.buf, st.st_mode, 1);
+	else
+		strbuf_addbuf(sb, &quoted);
+	strbuf_addch(sb, line_terminator);
+	strbuf_release(&quoted);
+}
+
 static void show_dir_entry(const char *tag, struct dir_entry *ent)
 {
 	static struct strbuf sb = STRBUF_INIT;
@@ -81,7 +97,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
 
 	strbuf_reset(&sb);
 	strbuf_addstr(&sb, tag);
-	write_name(&sb, ent->name);
+	write_dir_entry(&sb, ent);
 	strbuf_fputs(&sb, stdout);
 }
 
@@ -146,6 +162,18 @@ static void show_killed_files(struct dir_struct *dir)
 	}
 }
 
+static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
+{
+	struct strbuf quoted = STRBUF_INIT;
+	write_name(&quoted, ce->name);
+	if (want_color(use_color))
+		color_filename(sb, ce->name, quoted.buf, ce->ce_mode, 1);
+	else
+		strbuf_addbuf(sb, &quoted);
+	strbuf_addch(sb, line_terminator);
+	strbuf_release(&quoted);
+}
+
 static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
 	static struct strbuf sb = STRBUF_INIT;
@@ -186,7 +214,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 			    find_unique_abbrev(ce->sha1, abbrev),
 			    ce_stage(ce));
 	}
-	write_name(&sb, ce->name);
+	write_ce_name(&sb, ce);
 	strbuf_fputs(&sb, stdout);
 	if (debug_mode) {
 		const struct stat_data *sd = &ce->ce_stat_data;
@@ -523,6 +551,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			N_("if any <file> is not in the index, treat this as an error")),
 		OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
 			N_("pretend that paths removed since <tree-ish> are still present")),
+		OPT__COLOR(&use_color, N_("show color")),
 		OPT__ABBREV(&abbrev),
 		OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
 		OPT_END()
@@ -570,6 +599,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	if (require_work_tree && !is_inside_work_tree())
 		setup_work_tree();
 
+	if (want_color(use_color))
+		parse_ls_color();
+
 	parse_pathspec(&pathspec, 0,
 		       PATHSPEC_PREFER_CWD |
 		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/21] ls-files: add --column
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (5 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 06/21] ls-files: add --color to highlight file names Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 08/21] ls-files: support --max-depth Nguyễn Thái Ngọc Duy
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-ls-files.txt |  6 ++++++
 builtin/ls-files.c             | 28 ++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 148f226..99328b9 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -154,6 +154,12 @@ a space) at the start of each line:
 	`--color=never`. `--color` is equivalent to
 	`--color=auto`.
 
+--column[=<options>]::
+--no-column::
+	Display files in columns. See configuration variable column.ui
+	for option syntax. `--column` and `--no-column` without options
+	are equivalent to 'always' and 'never' respectively.
+
 \--::
 	Do not interpret any more arguments as options.
 
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 0ee4f19..44e5628 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -15,6 +15,7 @@
 #include "string-list.h"
 #include "pathspec.h"
 #include "color.h"
+#include "column.h"
 
 static int abbrev;
 static int show_deleted;
@@ -29,6 +30,7 @@ static int show_valid_bit;
 static int line_terminator = '\n';
 static int debug_mode;
 static int use_color;
+static unsigned int colopts;
 
 static const char *prefix;
 static int max_prefix_len;
@@ -39,6 +41,7 @@ static char *ps_matched;
 static const char *with_tree;
 static int exc_given;
 static int exclude_args;
+static struct string_list output = STRING_LIST_INIT_NODUP;
 
 static const char *tag_cached = "";
 static const char *tag_unmerged = "";
@@ -66,6 +69,10 @@ static void write_name(struct strbuf *sb, const char *name)
 
 static void strbuf_fputs(struct strbuf *sb, FILE *fp)
 {
+	if (column_active(colopts)) {
+		string_list_append(&output, strbuf_detach(sb, NULL));
+		return;
+	}
 	fwrite(sb->buf, sb->len, 1, fp);
 }
 
@@ -552,6 +559,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
 			N_("pretend that paths removed since <tree-ish> are still present")),
 		OPT__COLOR(&use_color, N_("show color")),
+		OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
 		OPT__ABBREV(&abbrev),
 		OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
 		OPT_END()
@@ -596,6 +604,18 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	if (dir.exclude_per_dir)
 		exc_given = 1;
 
+	finalize_colopts(&colopts, -1);
+	if (explicitly_enable_column(colopts)) {
+		if (!line_terminator)
+			die(_("--column and -z are incompatible"));
+		if (show_resolve_undo)
+			die(_("--column and --resolve-undo are incompatible"));
+		if (debug_mode)
+			die(_("--column and --debug are incompatible"));
+	}
+	if (column_active(colopts))
+		line_terminator = 0;
+
 	if (require_work_tree && !is_inside_work_tree())
 		setup_work_tree();
 
@@ -638,6 +658,14 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	if (show_resolve_undo)
 		show_ru_info();
 
+	if (column_active(colopts)) {
+		struct column_options copts;
+		memset(&copts, 0, sizeof(copts));
+		copts.padding = 2;
+		print_columns(&output, colopts, &copts);
+		string_list_clear(&output, 0);
+	}
+
 	if (ps_matched) {
 		int bad;
 		bad = report_path_error(ps_matched, &pathspec, prefix);
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/21] ls-files: support --max-depth
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (6 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 07/21] ls-files: add --column Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 09/21] list-files: a user friendly version of ls-files and more Nguyễn Thái Ngọc Duy
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-ls-files.txt | 7 +++++++
 builtin/ls-files.c             | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 99328b9..3d921eb 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -160,6 +160,13 @@ a space) at the start of each line:
 	for option syntax. `--column` and `--no-column` without options
 	are equivalent to 'always' and 'never' respectively.
 
+--max-depth=<depth>::
+	For each <pathspec> given on command line, descend at most <depth>
+	levels of directories. A negative value means no limit (default).
+	This option is ignored if <pathspec> contains active wildcards.
+	In other words if "a*" matches a directory named "a*",
+	"*" is matched literally so --max-depth is still effective.
+
 \--::
 	Do not interpret any more arguments as options.
 
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 44e5628..09a6b8d 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -503,6 +503,7 @@ static int option_parse_exclude_standard(const struct option *opt,
 int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 {
 	int require_work_tree = 0, show_tag = 0, i;
+	int max_depth = -1;
 	const char *max_prefix;
 	struct dir_struct dir;
 	struct exclude_list *el;
@@ -560,6 +561,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			N_("pretend that paths removed since <tree-ish> are still present")),
 		OPT__COLOR(&use_color, N_("show color")),
 		OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
+		{ OPTION_INTEGER, 0, "max-depth", &max_depth, N_("depth"),
+			N_("descend at most <depth> levels"), PARSE_OPT_NONEG,
+			NULL, 1 },
 		OPT__ABBREV(&abbrev),
 		OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
 		OPT_END()
@@ -624,8 +628,11 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 
 	parse_pathspec(&pathspec, 0,
 		       PATHSPEC_PREFER_CWD |
+		       (max_depth != -1 ? PATHSPEC_MAXDEPTH_VALID : 0) |
 		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
 		       prefix, argv);
+	pathspec.max_depth = max_depth;
+	pathspec.recursive = 1;
 
 	/* Find common prefix for all pathspec's */
 	max_prefix = common_prefix(&pathspec);
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/21] list-files: a user friendly version of ls-files and more
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (7 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 08/21] ls-files: support --max-depth Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-27 20:30   ` Junio C Hamano
  2015-01-25 12:37 ` [PATCH 10/21] list-files: make alias 'ls' default to 'list-files' Nguyễn Thái Ngọc Duy
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

This is more user friendly version of ls-files:

 * it's automatically colored and columnized
 * it refreshes the index like all porcelain commands
 * it defaults to non-recursive behavior like ls
 * :(glob) is on by default so '*.c' means a.c but not a/b.c, use
   '**/*.c' for that.
 * auto pager

The name 'ls' is not taken. It is left for the user to make an alias
with better default options.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 .gitignore                             |  1 +
 Documentation/config.txt               | 10 +++++
 Documentation/git-list-files.txt (new) | 80 ++++++++++++++++++++++++++++++++++
 Makefile                               |  1 +
 builtin/ls-files.c                     | 69 +++++++++++++++++++++++++++--
 command-list.txt                       |  1 +
 git.c                                  |  1 +
 7 files changed, 159 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/git-list-files.txt

diff --git a/.gitignore b/.gitignore
index a052419..9727ecc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,6 +76,7 @@
 /git-init-db
 /git-interpret-trailers
 /git-instaweb
+/git-list-files
 /git-log
 /git-ls-files
 /git-ls-remote
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 2290c47..74da715 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -940,6 +940,12 @@ color.status.<slot>::
 	to red). The values of these variables may be specified as in
 	color.branch.<slot>.
 
+color.list-files::
+	A boolean to enable/disable color in the output of
+	linkgit:git-list-files[1]. May be set to `always`, `false` (or
+	`never`) or `auto` (or `true`), in which case colors are used
+	only when the output is to a terminal. Defaults to false.
+
 color.ls.<slot>::
 	Use customized color for file name colorization. If not set
 	and the environment variable LS_COLORS is set, color settings
@@ -1012,6 +1018,10 @@ column.clean::
 	Specify the layout when list items in `git clean -i`, which always
 	shows files and directories in columns. See `column.ui` for details.
 
+column.list-files::
+	Specify whether to output tag listing in `git list-files` in columns.
+	See `column.ui` for details.
+
 column.status::
 	Specify whether to output untracked files in `git status` in columns.
 	See `column.ui` for details.
diff --git a/Documentation/git-list-files.txt b/Documentation/git-list-files.txt
new file mode 100644
index 0000000..3039e1e
--- /dev/null
+++ b/Documentation/git-list-files.txt
@@ -0,0 +1,80 @@
+git-list-files(1)
+===============
+
+NAME
+----
+git-list-files - List files
+
+SYNOPSIS
+--------
+[verse]
+'git list-files [options] [<pathspec>...]
+
+DESCRIPTION
+-----------
+List files (by default in current working directory) that are in the
+index. Depending on the chosen options, maybe only modified files in
+working tree are shown, or untracked files...
+
+OPTIONS
+-------
+-c::
+--cached::
+	Show cached files (default)
+
+-d::
+--deleted::
+	Show cached files that are deleted on working directory
+
+-m::
+--modified::
+	Show cached files that have modification on working directory
+
+-o::
+--others::
+	Show untracked files (and only unignored ones unless -i is
+	specified)
+
+-i::
+--ignored::
+	Show only ignored files. When showing files in the index,
+	print only those matched by an exclude pattern. When showing
+	"other" files, show only those matched by an exclude pattern.
+
+-u::
+--unmerged::
+	Show unmerged files
+
+--color[=<when>]::
+--no-color::
+	Color file names. The value must be `always`, `never`, or
+	`auto`. `--no-color` is equivalent to
+	`--color=never`. `--color` is equivalent to
+	`--color=auto`. See configuration variable `color.list-files`
+	for the default settings.
+
+--column[=<options>]::
+--no-column::
+	Display files in columns. See configuration variable column.ui
+	for option syntax. `--column` and `--no-column` without options
+	are equivalent to 'always' and 'never' respectively.
+
+--max-depth=<depth>::
+	For each <pathspec> given on command line, descend at most <depth>
+	levels of directories. A negative value means no limit.
+	This option is ignored if <pathspec> contains active wildcards.
+	In other words if "a*" matches a directory named "a*",
+	"*" is matched literally so --max-depth is still effective.
+	The default is `--max-depth=0`.
+
+<pathspec>::
+	Files to show. :(glob) magic is enabled and recursion disabled
+	by default.
+
+SEE ALSO
+--------
+linkgit:git-ls-files[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Makefile b/Makefile
index 459121d..23a0751 100644
--- a/Makefile
+++ b/Makefile
@@ -587,6 +587,7 @@ BUILT_INS += git-cherry-pick$X
 BUILT_INS += git-format-patch$X
 BUILT_INS += git-fsck-objects$X
 BUILT_INS += git-init$X
+BUILT_INS += git-list-files$X
 BUILT_INS += git-merge-subtree$X
 BUILT_INS += git-show$X
 BUILT_INS += git-stage$X
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 09a6b8d..eca9407 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -31,6 +31,7 @@ static int line_terminator = '\n';
 static int debug_mode;
 static int use_color;
 static unsigned int colopts;
+static int porcelain;
 
 static const char *prefix;
 static int max_prefix_len;
@@ -459,6 +460,11 @@ static const char * const ls_files_usage[] = {
 	NULL
 };
 
+static const char * const ls_usage[] = {
+	N_("git list-files [options] [<file>...]"),
+	NULL
+};
+
 static int option_parse_z(const struct option *opt,
 			  const char *arg, int unset)
 {
@@ -500,6 +506,17 @@ static int option_parse_exclude_standard(const struct option *opt,
 	return 0;
 }
 
+static int git_ls_config(const char *var, const char *value, void *cb)
+{
+	if (starts_with(var, "column."))
+		return git_column_config(var, value, "list-files", &colopts);
+	if (!strcmp(var, "color.list-files")) {
+		use_color = git_config_colorbool(var, value);
+		return 0;
+	}
+	return git_color_default_config(var, value, cb);
+}
+
 int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 {
 	int require_work_tree = 0, show_tag = 0, i;
@@ -568,21 +585,61 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
 		OPT_END()
 	};
+	struct option builtin_ls_options[] = {
+		OPT_BOOL('c', "cached", &show_cached,
+			N_("show cached files (default)")),
+		OPT_BOOL('d', "deleted", &show_deleted,
+			N_("show cached files that are deleted on working directory")),
+		OPT_BOOL('m', "modified", &show_modified,
+			N_("show cached files that have modification on working directory")),
+		OPT_BOOL('o', "others", &show_others,
+			N_("show untracked files")),
+		OPT_BIT('i', "ignored", &dir.flags,
+			N_("show ignored files"),
+			DIR_SHOW_IGNORED),
+		OPT_BOOL('u', "unmerged", &show_unmerged,
+			N_("show unmerged files")),
+		OPT__COLOR(&use_color, N_("show color")),
+		OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
+		{ OPTION_INTEGER, 0, "max-depth", &max_depth, N_("depth"),
+			N_("descend at most <depth> levels"), PARSE_OPT_NONEG,
+			NULL, 1 },
+		OPT__ABBREV(&abbrev),
+		OPT_END()
+	};
+	struct option *options;
+	const char * const *help_usage;
 
+	if (!strcmp(argv[0], "list-files")) {
+		help_usage = ls_usage;
+		options = builtin_ls_options;
+		porcelain = 1;
+	} else {
+		help_usage = ls_files_usage;
+		options = builtin_ls_files_options;
+	}
 	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(ls_files_usage, builtin_ls_files_options);
+		usage_with_options(help_usage, options);
 
 	memset(&dir, 0, sizeof(dir));
 	prefix = cmd_prefix;
 	if (prefix)
 		prefix_len = strlen(prefix);
-	git_config(git_default_config, NULL);
+
+	if (porcelain) {
+		setenv(GIT_GLOB_PATHSPECS_ENVIRONMENT, "1", 1);
+		exc_given = 1;
+		setup_standard_excludes(&dir);
+		use_color = -1;
+		max_depth = 0;
+		git_config(git_ls_config, NULL);
+	} else
+		git_config(git_default_config, NULL);
 
 	if (read_cache() < 0)
 		die("index file corrupt");
 
-	argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
-			ls_files_usage, 0);
+	argc = parse_options(argc, argv, prefix, options, help_usage, 0);
 	el = add_exclude_list(&dir, EXC_CMDL, "--exclude option");
 	for (i = 0; i < exclude_list.nr; i++) {
 		add_exclude(exclude_list.items[i].string, "", 0, el, --exclude_args);
@@ -661,6 +718,10 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			die("ls-files --with-tree is incompatible with -s or -u");
 		overlay_tree_on_cache(with_tree, max_prefix);
 	}
+	if (porcelain) {
+		refresh_index(&the_index, REFRESH_QUIET | REFRESH_UNMERGED, &pathspec, NULL, NULL);
+		setup_pager();
+	}
 	show_files(&dir);
 	if (show_resolve_undo)
 		show_ru_info();
diff --git a/command-list.txt b/command-list.txt
index f1eae08..32101de 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -64,6 +64,7 @@ git-init                                mainporcelain common
 git-instaweb                            ancillaryinterrogators
 git-interpret-trailers                  purehelpers
 gitk                                    mainporcelain
+git-list-files                          mainporcelain
 git-log                                 mainporcelain common
 git-ls-files                            plumbinginterrogators
 git-ls-remote                           plumbinginterrogators
diff --git a/git.c b/git.c
index 18fbf79..617c083 100644
--- a/git.c
+++ b/git.c
@@ -418,6 +418,7 @@ static struct cmd_struct commands[] = {
 	{ "init", cmd_init_db, NO_SETUP },
 	{ "init-db", cmd_init_db, NO_SETUP },
 	{ "interpret-trailers", cmd_interpret_trailers, RUN_SETUP },
+	{ "list-files", cmd_ls_files, RUN_SETUP },
 	{ "log", cmd_log, RUN_SETUP },
 	{ "ls-files", cmd_ls_files, RUN_SETUP },
 	{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/21] list-files: make alias 'ls' default to 'list-files'
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (8 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 09/21] list-files: a user friendly version of ls-files and more Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 11/21] list-files: -u does not imply showing stages Nguyễn Thái Ngọc Duy
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-list-files.txt | 3 ++-
 config.c                         | 8 ++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-list-files.txt b/Documentation/git-list-files.txt
index 3039e1e..2182a38 100644
--- a/Documentation/git-list-files.txt
+++ b/Documentation/git-list-files.txt
@@ -14,7 +14,8 @@ DESCRIPTION
 -----------
 List files (by default in current working directory) that are in the
 index. Depending on the chosen options, maybe only modified files in
-working tree are shown, or untracked files...
+working tree are shown, or untracked files... The builtin alias "ls"
+is set to "list-files".
 
 OPTIONS
 -------
diff --git a/config.c b/config.c
index 15a2983..16209c6 100644
--- a/config.c
+++ b/config.c
@@ -40,6 +40,10 @@ static struct config_source *cf;
 
 static int zlib_compression_seen;
 
+static const char *builtin_config =
+	"[alias]\n"
+	"	ls = list-files\n";
+
 /*
  * Default config_set that contains key-value pairs from the usual set of config
  * config files (i.e repo specific .git/config, user wide ~/.gitconfig, XDG
@@ -1175,6 +1179,10 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
 
 	home_config_paths(&user_config, &xdg_config, "config");
 
+	if (git_config_system())
+		git_config_from_buf(fn, "<builtin>", builtin_config,
+				    strlen(builtin_config), data);
+
 	if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) {
 		ret += git_config_from_file(fn, git_etc_gitconfig(),
 					    data);
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/21] list-files: -u does not imply showing stages
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (9 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 10/21] list-files: make alias 'ls' default to 'list-files' Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 12/21] list-files: add -R/--recursive short for --max-depth=-1 Nguyễn Thái Ngọc Duy
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Showing full index entry information is something for ls-files
only. The users of "git list-files" may just want to know what entries
are not unmerged.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/ls-files.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index eca9407..f2c29ce 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -656,7 +656,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	}
 	if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
 		require_work_tree = 1;
-	if (show_unmerged)
+	if (show_unmerged && !porcelain)
 		/*
 		 * There's no point in showing unmerged unless
 		 * you also show the stage information.
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 12/21] list-files: add -R/--recursive short for --max-depth=-1
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (10 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 11/21] list-files: -u does not imply showing stages Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 13/21] list-files: add -1 short for --no-column Nguyễn Thái Ngọc Duy
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-list-files.txt | 4 ++++
 builtin/ls-files.c               | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/Documentation/git-list-files.txt b/Documentation/git-list-files.txt
index 2182a38..8d285c1 100644
--- a/Documentation/git-list-files.txt
+++ b/Documentation/git-list-files.txt
@@ -46,6 +46,10 @@ OPTIONS
 --unmerged::
 	Show unmerged files
 
+-R::
+--recursive::
+	Equivalent of `--max-depth=-1` (infinite recursion).
+
 --color[=<when>]::
 --no-color::
 	Color file names. The value must be `always`, `never`, or
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index f2c29ce..010291c 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -594,6 +594,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			N_("show cached files that have modification on working directory")),
 		OPT_BOOL('o', "others", &show_others,
 			N_("show untracked files")),
+		OPT_SET_INT('R', "recursive", &max_depth,
+			    N_("shortcut for --max-depth=-1"), -1),
 		OPT_BIT('i', "ignored", &dir.flags,
 			N_("show ignored files"),
 			DIR_SHOW_IGNORED),
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 13/21] list-files: add -1 short for --no-column
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (11 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 12/21] list-files: add -R/--recursive short for --max-depth=-1 Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 14/21] list-files: add -t back Nguyễn Thái Ngọc Duy
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-list-files.txt | 3 +++
 builtin/ls-files.c               | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/Documentation/git-list-files.txt b/Documentation/git-list-files.txt
index 8d285c1..1c0c877 100644
--- a/Documentation/git-list-files.txt
+++ b/Documentation/git-list-files.txt
@@ -50,6 +50,9 @@ OPTIONS
 --recursive::
 	Equivalent of `--max-depth=-1` (infinite recursion).
 
+-1::
+	Equivalent of --no-column.
+
 --color[=<when>]::
 --no-color::
 	Color file names. The value must be `always`, `never`, or
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 010291c..a80ac6a 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -603,6 +603,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			N_("show unmerged files")),
 		OPT__COLOR(&use_color, N_("show color")),
 		OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
+		OPT_SET_INT('1', NULL, &colopts,
+			    N_("shortcut for --no-column"), COL_PARSEOPT),
 		{ OPTION_INTEGER, 0, "max-depth", &max_depth, N_("depth"),
 			N_("descend at most <depth> levels"), PARSE_OPT_NONEG,
 			NULL, 1 },
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 14/21] list-files: add -t back
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (12 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 13/21] list-files: add -1 short for --no-column Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 15/21] list-files: sort output and remove duplicates Nguyễn Thái Ngọc Duy
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Tag "H" (cached) is not shown though because it's usually the majority
and becomes noise. Not showing it makes the other tags stand out. -t
is on by default if more than one file category is selected.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-list-files.txt |  6 ++++++
 builtin/ls-files.c               | 27 +++++++++++++++++----------
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-list-files.txt b/Documentation/git-list-files.txt
index 1c0c877..9d4c127 100644
--- a/Documentation/git-list-files.txt
+++ b/Documentation/git-list-files.txt
@@ -46,6 +46,12 @@ OPTIONS
 --unmerged::
 	Show unmerged files
 
+-t::
+--[no-]tag::
+	Show a tag to indicate file type. Automatically turned on with
+	multiple file selections. See linkgit::git-ls-files[1] option
+	`-t` for more information.
+
 -R::
 --recursive::
 	Equivalent of `--max-depth=-1` (infinite recursion).
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index a80ac6a..b4b24ef 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -596,6 +596,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			N_("show untracked files")),
 		OPT_SET_INT('R', "recursive", &max_depth,
 			    N_("shortcut for --max-depth=-1"), -1),
+		OPT_BOOL('t', "tag", &show_tag,
+			N_("identify the file status with tags")),
 		OPT_BIT('i', "ignored", &dir.flags,
 			N_("show ignored files"),
 			DIR_SHOW_IGNORED),
@@ -636,6 +638,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		setup_standard_excludes(&dir);
 		use_color = -1;
 		max_depth = 0;
+		show_tag = -1;
 		git_config(git_ls_config, NULL);
 	} else
 		git_config(git_default_config, NULL);
@@ -648,16 +651,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	for (i = 0; i < exclude_list.nr; i++) {
 		add_exclude(exclude_list.items[i].string, "", 0, el, --exclude_args);
 	}
-	if (show_tag || show_valid_bit) {
-		tag_cached = "H ";
-		tag_unmerged = "M ";
-		tag_removed = "R ";
-		tag_modified = "C ";
-		tag_other = "? ";
-		tag_killed = "K ";
-		tag_skip_worktree = "S ";
-		tag_resolve_undo = "U ";
-	}
 	if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
 		require_work_tree = 1;
 	if (show_unmerged && !porcelain)
@@ -711,6 +704,20 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	      show_killed || show_modified || show_resolve_undo))
 		show_cached = 1;
 
+	if (show_tag == -1)
+		show_tag = (show_cached + show_deleted + show_others +
+			    show_unmerged + show_killed + show_modified) > 1;
+	if (show_tag || show_valid_bit) {
+		tag_cached = porcelain ? "  " : "H ";
+		tag_unmerged = "M ";
+		tag_removed = "R ";
+		tag_modified = "C ";
+		tag_other = "? ";
+		tag_killed = "K ";
+		tag_skip_worktree = "S ";
+		tag_resolve_undo = "U ";
+	}
+
 	if (max_prefix)
 		prune_cache(max_prefix);
 	if (with_tree) {
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 15/21] list-files: sort output and remove duplicates
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (13 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 14/21] list-files: add -t back Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 16/21] list-files: do not show duplicate cached entries Nguyễn Thái Ngọc Duy
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

When you mix different file types, with ls-files you may get separate
listing. For example, "ls-files -cm" will show file "abc" twice: one
as part of cached list, one of modified list. With "ls" (and this
patch) they will be in a single sorted list (easier for the eye).

Duplicate entries are also removed. Note that display content is
compared, so if you have "-t" on, or you color file types differently,
you will get duplicate textual entries. This is good imo.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/ls-files.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index b4b24ef..154dd9d 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -53,6 +53,13 @@ static const char *tag_modified = "";
 static const char *tag_skip_worktree = "";
 static const char *tag_resolve_undo = "";
 
+static int compare_output(const void *a_, const void *b_)
+{
+	const struct string_list_item *a = a_;
+	const struct string_list_item *b = b_;
+	return strcmp(a->util, b->util);
+}
+
 static void write_name(struct strbuf *sb, const char *name)
 {
 	/*
@@ -68,10 +75,12 @@ static void write_name(struct strbuf *sb, const char *name)
 		quote_path_relative(name, real_prefix, sb);
 }
 
-static void strbuf_fputs(struct strbuf *sb, FILE *fp)
+static void strbuf_fputs(struct strbuf *sb, const char *full_name, FILE *fp)
 {
-	if (column_active(colopts)) {
-		string_list_append(&output, strbuf_detach(sb, NULL));
+	if (column_active(colopts) || porcelain) {
+		struct string_list_item *it;
+		it = string_list_append(&output, strbuf_detach(sb, NULL));
+		it->util = (void *)full_name;
 		return;
 	}
 	fwrite(sb->buf, sb->len, 1, fp);
@@ -106,7 +115,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
 	strbuf_reset(&sb);
 	strbuf_addstr(&sb, tag);
 	write_dir_entry(&sb, ent);
-	strbuf_fputs(&sb, stdout);
+	strbuf_fputs(&sb, ent->name, stdout);
 }
 
 static void show_other_files(struct dir_struct *dir)
@@ -223,7 +232,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 			    ce_stage(ce));
 	}
 	write_ce_name(&sb, ce);
-	strbuf_fputs(&sb, stdout);
+	strbuf_fputs(&sb, ce->name, stdout);
 	if (debug_mode) {
 		const struct stat_data *sd = &ce->ce_stat_data;
 
@@ -524,6 +533,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	const char *max_prefix;
 	struct dir_struct dir;
 	struct exclude_list *el;
+	struct column_options copts;
 	struct string_list exclude_list = STRING_LIST_INIT_NODUP;
 	struct option builtin_ls_files_options[] = {
 		{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
@@ -671,7 +681,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		if (debug_mode)
 			die(_("--column and --debug are incompatible"));
 	}
-	if (column_active(colopts))
+	if (column_active(colopts) || porcelain)
 		line_terminator = 0;
 
 	if (require_work_tree && !is_inside_work_tree())
@@ -737,13 +747,15 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	if (show_resolve_undo)
 		show_ru_info();
 
-	if (column_active(colopts)) {
-		struct column_options copts;
-		memset(&copts, 0, sizeof(copts));
-		copts.padding = 2;
-		print_columns(&output, colopts, &copts);
-		string_list_clear(&output, 0);
+	memset(&copts, 0, sizeof(copts));
+	copts.padding = 2;
+	if (porcelain) {
+		qsort(output.items, output.nr, sizeof(*output.items),
+		      compare_output);
+		string_list_remove_duplicates(&output, 0);
 	}
+	print_columns(&output, colopts, &copts);
+	string_list_clear(&output, 0);
 
 	if (ps_matched) {
 		int bad;
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 16/21] list-files: do not show duplicate cached entries
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (14 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 15/21] list-files: sort output and remove duplicates Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 17/21] list-files: show directories as well as files Nguyễn Thái Ngọc Duy
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

With the current show_files() "list-files -tcm" will show

  foo.c
M foo.c

The first item is redundant. If "foo.c" is modified, we know it's in
the cache. Introduce show_files_compact to do that because ls-files is
plumbing and scripts may already depend on current display behavior.

Another difference in show_files_compact() is it does not show
skip-worktree (aka outside sparse checkout) entries anymore, which
makes sense in porcelain context.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/ls-files.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 154dd9d..1a1c9c8 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -333,6 +333,53 @@ static void show_files(struct dir_struct *dir)
 	}
 }
 
+static void show_files_compact(struct dir_struct *dir)
+{
+	int i;
+
+	/* For cached/deleted files we don't need to even do the readdir */
+	if (show_others || show_killed) {
+		if (!show_others)
+			dir->flags |= DIR_COLLECT_KILLED_ONLY;
+		fill_directory(dir, &pathspec);
+		if (show_others)
+			show_other_files(dir);
+		if (show_killed)
+			show_killed_files(dir);
+	}
+	if (!(show_cached || show_unmerged || show_deleted || show_modified))
+		return;
+	for (i = 0; i < active_nr; i++) {
+		const struct cache_entry *ce = active_cache[i];
+		struct stat st;
+		int err, shown = 0;
+		if ((dir->flags & DIR_SHOW_IGNORED) &&
+		    !ce_excluded(dir, ce))
+			continue;
+		if (show_unmerged && !ce_stage(ce))
+			continue;
+		if (ce->ce_flags & CE_UPDATE)
+			continue;
+		if (ce_skip_worktree(ce))
+			continue;
+		err = lstat(ce->name, &st);
+		if (show_deleted && err) {
+			show_ce_entry(tag_removed, ce);
+			shown = 1;
+		}
+		if (show_modified && (err || ce_modified(ce, &st, 0))) {
+			show_ce_entry(tag_modified, ce);
+			shown = 1;
+		}
+		if (ce_stage(ce)) {
+			show_ce_entry(tag_unmerged, ce);
+			shown = 1;
+		}
+		if (!shown && show_cached)
+			show_ce_entry(tag_cached, ce);
+	}
+}
+
 /*
  * Prune the index to only contain stuff starting with "prefix"
  */
@@ -743,7 +790,10 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		refresh_index(&the_index, REFRESH_QUIET | REFRESH_UNMERGED, &pathspec, NULL, NULL);
 		setup_pager();
 	}
-	show_files(&dir);
+	if (porcelain)
+		show_files_compact(&dir);
+	else
+		show_files(&dir);
 	if (show_resolve_undo)
 		show_ru_info();
 
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 17/21] list-files: show directories as well as files
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (15 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 16/21] list-files: do not show duplicate cached entries Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 19:16   ` Eric Sunshine
  2015-01-27 21:51   ` Junio C Hamano
  2015-01-25 12:37 ` [PATCH 18/21] list-files: add -F/--classify Nguyễn Thái Ngọc Duy
                   ` (3 subsequent siblings)
  20 siblings, 2 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

The index does not store directories explicitly (except submodules) so
we have to figure them out from file list when output lis depth-limited.

The function show_as_directory() deliberately generates duplicate
directories and expects the previous patch to remove duplicates.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/ls-files.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 1a1c9c8..29b5c2e 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -27,6 +27,8 @@ static int show_resolve_undo;
 static int show_modified;
 static int show_killed;
 static int show_valid_bit;
+static int show_tag;
+static int show_dirs;
 static int line_terminator = '\n';
 static int debug_mode;
 static int use_color;
@@ -179,6 +181,35 @@ static void show_killed_files(struct dir_struct *dir)
 	}
 }
 
+static int show_as_directory(const struct cache_entry *ce)
+{
+	struct strbuf sb = STRBUF_INIT;
+	const char *p;
+
+	strbuf_add(&sb, ce->name, ce_namelen(ce));
+	while (sb.len && (p = strrchr(sb.buf, '/')) != NULL) {
+		struct strbuf sb2 = STRBUF_INIT;
+		strbuf_setlen(&sb, p - sb.buf);
+		if (!match_pathspec(&pathspec, sb.buf, sb.len,
+				    max_prefix_len, NULL, 1))
+			continue;
+		write_name(&sb2, sb.buf);
+		if (want_color(use_color)) {
+			struct strbuf sb3 = STRBUF_INIT;
+			color_filename(&sb3, ce->name, sb2.buf, S_IFDIR, 1);
+			strbuf_release(&sb2);
+			sb2 = sb3;
+		}
+		if (show_tag)
+			strbuf_insert(&sb2, 0, tag_cached, strlen(tag_cached));
+		strbuf_fputs(&sb2, strbuf_detach(&sb, NULL), NULL);
+		strbuf_release(&sb2);
+		return 1;
+	}
+	strbuf_release(&sb);
+	return 0;
+}
+
 static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
 {
 	struct strbuf quoted = STRBUF_INIT;
@@ -194,16 +225,31 @@ static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
 static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
 	static struct strbuf sb = STRBUF_INIT;
-	int len = max_prefix_len;
+	int len = max_prefix_len, saved_max_depth;
 
 	if (len >= ce_namelen(ce))
 		die("git ls-files: internal error - cache entry not superset of prefix");
 
+	if (show_dirs) {
+		/* ignore depth to catch dirs that contain matched entries */
+		saved_max_depth = pathspec.max_depth;
+		pathspec.max_depth = -1;
+	}
+
 	if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce),
 			    len, ps_matched,
 			    S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode)))
 		return;
 
+	if (show_dirs) {
+		pathspec.max_depth = saved_max_depth;
+		if (strchr(ce->name, '/') &&
+		    !match_pathspec(&pathspec, ce->name, ce_namelen(ce),
+				    prefix_len, NULL, 1) &&
+		    show_as_directory(ce))
+			return;
+	}
+
 	if (tag && *tag && show_valid_bit &&
 	    (ce->ce_flags & CE_VALID)) {
 		static char alttag[4];
@@ -575,7 +621,7 @@ static int git_ls_config(const char *var, const char *value, void *cb)
 
 int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 {
-	int require_work_tree = 0, show_tag = 0, i;
+	int require_work_tree = 0, i;
 	int max_depth = -1;
 	const char *max_prefix;
 	struct dir_struct dir;
@@ -744,6 +790,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		       prefix, argv);
 	pathspec.max_depth = max_depth;
 	pathspec.recursive = 1;
+	show_dirs = porcelain && max_depth != -1;
+
 
 	/* Find common prefix for all pathspec's */
 	max_prefix = common_prefix(&pathspec);
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 18/21] list-files: add -F/--classify
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (16 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 17/21] list-files: show directories as well as files Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 19/21] list-files -F: show submodules with the new indicator '&' Nguyễn Thái Ngọc Duy
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

This appends an indicator after the file name if it's executable, a
directory and so on, like in GNU ls. In fact append_indicator() is a
rewrite from get_type_indicator() in coreutils.git commit
7326d1f1a67edf21947ae98194f98c38b6e9e527.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-list-files.txt |  6 ++++++
 builtin/ls-files.c               | 31 +++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/Documentation/git-list-files.txt b/Documentation/git-list-files.txt
index 9d4c127..475c6da 100644
--- a/Documentation/git-list-files.txt
+++ b/Documentation/git-list-files.txt
@@ -52,6 +52,12 @@ OPTIONS
 	multiple file selections. See linkgit::git-ls-files[1] option
 	`-t` for more information.
 
+-F::
+--classify::
+	Append indicator (one of `*/=>@|`, which is executable,
+	directory, socket, Solaris door, symlink, or fifo
+	respectively) to entries.
+
 -R::
 --recursive::
 	Equivalent of `--max-depth=-1` (infinite recursion).
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 29b5c2e..bbeb4ce 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -29,6 +29,7 @@ static int show_killed;
 static int show_valid_bit;
 static int show_tag;
 static int show_dirs;
+static int show_indicator;
 static int line_terminator = '\n';
 static int debug_mode;
 static int use_color;
@@ -77,6 +78,28 @@ static void write_name(struct strbuf *sb, const char *name)
 		quote_path_relative(name, real_prefix, sb);
 }
 
+static void append_indicator(struct strbuf *sb, mode_t mode)
+{
+	char c = 0;
+	if (S_ISREG(mode)) {
+		if (mode & (S_IXUSR | S_IXGRP | S_IXOTH))
+			c = '*';
+	} else if (S_ISDIR(mode))
+		c = '/';
+	else if (S_ISLNK(mode))
+		c = '@';
+	else if (S_ISFIFO(mode))
+		c = '|';
+	else if (S_ISSOCK(mode))
+		c = '=';
+#ifdef S_ISDOOR
+	else if (S_ISDOOR(mode))
+		c = '>';
+#endif
+	if (c)
+		strbuf_addch(sb, c);
+}
+
 static void strbuf_fputs(struct strbuf *sb, const char *full_name, FILE *fp)
 {
 	if (column_active(colopts) || porcelain) {
@@ -99,6 +122,8 @@ static void write_dir_entry(struct strbuf *sb, const struct dir_entry *ent)
 		color_filename(sb, ent->name, quoted.buf, st.st_mode, 1);
 	else
 		strbuf_addbuf(sb, &quoted);
+	if (show_indicator && st.st_mode)
+		append_indicator(sb, st.st_mode);
 	strbuf_addch(sb, line_terminator);
 	strbuf_release(&quoted);
 }
@@ -202,6 +227,8 @@ static int show_as_directory(const struct cache_entry *ce)
 		}
 		if (show_tag)
 			strbuf_insert(&sb2, 0, tag_cached, strlen(tag_cached));
+		if (show_indicator)
+			append_indicator(&sb2, S_IFDIR);
 		strbuf_fputs(&sb2, strbuf_detach(&sb, NULL), NULL);
 		strbuf_release(&sb2);
 		return 1;
@@ -218,6 +245,8 @@ static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
 		color_filename(sb, ce->name, quoted.buf, ce->ce_mode, 1);
 	else
 		strbuf_addbuf(sb, &quoted);
+	if (show_indicator)
+		append_indicator(sb, ce->ce_mode);
 	strbuf_addch(sb, line_terminator);
 	strbuf_release(&quoted);
 }
@@ -706,6 +735,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			DIR_SHOW_IGNORED),
 		OPT_BOOL('u', "unmerged", &show_unmerged,
 			N_("show unmerged files")),
+		OPT_BOOL('F', "classify", &show_indicator,
+			 N_("append indicator (one of */=>@|) to entries")),
 		OPT__COLOR(&use_color, N_("show color")),
 		OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
 		OPT_SET_INT('1', NULL, &colopts,
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 19/21] list-files -F: show submodules with the new indicator '&'
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (17 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 18/21] list-files: add -F/--classify Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 20/21] list-files: -M aka diff-cached Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 21/21] t3080: tests for git-list-files Nguyễn Thái Ngọc Duy
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-list-files.txt | 4 ++--
 builtin/ls-files.c               | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-list-files.txt b/Documentation/git-list-files.txt
index 475c6da..223f6fd 100644
--- a/Documentation/git-list-files.txt
+++ b/Documentation/git-list-files.txt
@@ -54,8 +54,8 @@ OPTIONS
 
 -F::
 --classify::
-	Append indicator (one of `*/=>@|`, which is executable,
-	directory, socket, Solaris door, symlink, or fifo
+	Append indicator (one of `*/=>@|&`, which is executable,
+	directory, socket, Solaris door, symlink, fifo, or submodule
 	respectively) to entries.
 
 -R::
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index bbeb4ce..697a307 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -92,6 +92,8 @@ static void append_indicator(struct strbuf *sb, mode_t mode)
 		c = '|';
 	else if (S_ISSOCK(mode))
 		c = '=';
+	else if (S_ISGITLINK(mode))
+		c = '&';
 #ifdef S_ISDOOR
 	else if (S_ISDOOR(mode))
 		c = '>';
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 20/21] list-files: -M aka diff-cached
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (18 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 19/21] list-files -F: show submodules with the new indicator '&' Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 12:37 ` [PATCH 21/21] t3080: tests for git-list-files Nguyễn Thái Ngọc Duy
  20 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/ls-files.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 64 insertions(+), 3 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 697a307..b04c712 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -16,6 +16,9 @@
 #include "pathspec.h"
 #include "color.h"
 #include "column.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "revision.h"
 
 static int abbrev;
 static int show_deleted;
@@ -25,6 +28,7 @@ static int show_stage;
 static int show_unmerged;
 static int show_resolve_undo;
 static int show_modified;
+static int show_diff_cached;
 static int show_killed;
 static int show_valid_bit;
 static int show_tag;
@@ -53,6 +57,7 @@ static const char *tag_removed = "";
 static const char *tag_other = "";
 static const char *tag_killed = "";
 static const char *tag_modified = "";
+static const char *tag_diff_cached = "";
 static const char *tag_skip_worktree = "";
 static const char *tag_resolve_undo = "";
 
@@ -404,7 +409,15 @@ static void show_files(struct dir_struct *dir)
 			err = lstat(ce->name, &st);
 			if (show_deleted && err)
 				show_ce_entry(tag_removed, ce);
-			if (show_modified && ce_modified(ce, &st, 0))
+			if (show_diff_cached && (ce->ce_flags & CE_MATCHED)) {
+				show_ce_entry(tag_diff_cached, ce);
+				/*
+				 * if we don't clear, it'll confuse write_ce_name()
+				 * when show_ce_entry(tag_modified, ce) is called
+				 */
+				active_cache[i]->ce_flags &= ~CE_MATCHED;
+			}
+			if (show_modified && (err || ce_modified(ce, &st, 0)))
 				show_ce_entry(tag_modified, ce);
 		}
 	}
@@ -424,7 +437,8 @@ static void show_files_compact(struct dir_struct *dir)
 		if (show_killed)
 			show_killed_files(dir);
 	}
-	if (!(show_cached || show_unmerged || show_deleted || show_modified))
+	if (!(show_cached || show_unmerged || show_deleted ||
+	      show_modified || show_diff_cached))
 		return;
 	for (i = 0; i < active_nr; i++) {
 		const struct cache_entry *ce = active_cache[i];
@@ -444,6 +458,15 @@ static void show_files_compact(struct dir_struct *dir)
 			show_ce_entry(tag_removed, ce);
 			shown = 1;
 		}
+		if (show_diff_cached && (ce->ce_flags & CE_MATCHED)) {
+			show_ce_entry(tag_diff_cached, ce);
+			shown = 1;
+			/*
+			 * if we don't clear, it'll confuse write_ce_name()
+			 * when show_ce_entry(tag_modified, ce) is called
+			 */
+			active_cache[i]->ce_flags &= ~CE_MATCHED;
+		}
 		if (show_modified && (err || ce_modified(ce, &st, 0))) {
 			show_ce_entry(tag_modified, ce);
 			shown = 1;
@@ -457,6 +480,38 @@ static void show_files_compact(struct dir_struct *dir)
 	}
 }
 
+static void mark_diff_cached(struct diff_queue_struct *q,
+			     struct diff_options *options,
+			     void *data)
+{
+	int i;
+
+	for (i = 0; i < q->nr; i++) {
+		struct diff_filepair *p = q->queue[i];
+		int pos = cache_name_pos(p->two->path, strlen(p->two->path));
+		if (pos < 0)
+			continue;
+		active_cache[pos]->ce_flags |= CE_MATCHED;
+	}
+}
+
+static void diff_cached(struct pathspec *pathspec)
+{
+	struct rev_info rev;
+	const char *argv[] = { "ls-files", "HEAD", NULL };
+
+	init_revisions(&rev, NULL);
+	setup_revisions(2, argv, &rev, NULL);
+
+	rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
+	rev.diffopt.format_callback = mark_diff_cached;
+	rev.diffopt.detect_rename = 1;
+	rev.diffopt.rename_limit = 200;
+	rev.diffopt.break_opt = 0;
+	copy_pathspec(&rev.prune_data, pathspec);
+	run_diff_index(&rev, 1);
+}
+
 /*
  * Prune the index to only contain stuff starting with "prefix"
  */
@@ -726,6 +781,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			N_("show cached files that are deleted on working directory")),
 		OPT_BOOL('m', "modified", &show_modified,
 			N_("show cached files that have modification on working directory")),
+		OPT_BOOL('M', "modified", &show_diff_cached,
+			N_("show modified files in the cache")),
 		OPT_BOOL('o', "others", &show_others,
 			N_("show untracked files")),
 		OPT_SET_INT('R', "recursive", &max_depth,
@@ -839,11 +896,12 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 
 	/* With no flags, we default to showing the cached files */
 	if (!(show_stage || show_deleted || show_others || show_unmerged ||
-	      show_killed || show_modified || show_resolve_undo))
+	      show_killed || show_modified || show_resolve_undo || show_diff_cached))
 		show_cached = 1;
 
 	if (show_tag == -1)
 		show_tag = (show_cached + show_deleted + show_others +
+			    show_diff_cached +
 			    show_unmerged + show_killed + show_modified) > 1;
 	if (show_tag || show_valid_bit) {
 		tag_cached = porcelain ? "  " : "H ";
@@ -851,6 +909,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		tag_removed = "R ";
 		tag_modified = "C ";
 		tag_other = "? ";
+		tag_diff_cached = "X ";
 		tag_killed = "K ";
 		tag_skip_worktree = "S ";
 		tag_resolve_undo = "U ";
@@ -871,6 +930,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		refresh_index(&the_index, REFRESH_QUIET | REFRESH_UNMERGED, &pathspec, NULL, NULL);
 		setup_pager();
 	}
+	if (show_diff_cached)
+		diff_cached(&pathspec);
 	if (porcelain)
 		show_files_compact(&dir);
 	else
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 21/21] t3080: tests for git-list-files
  2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
                   ` (19 preceding siblings ...)
  2015-01-25 12:37 ` [PATCH 20/21] list-files: -M aka diff-cached Nguyễn Thái Ngọc Duy
@ 2015-01-25 12:37 ` Nguyễn Thái Ngọc Duy
  2015-01-25 19:20   ` Eric Sunshine
  20 siblings, 1 reply; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-01-25 12:37 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 t/t3080-list-files.sh (new +x) | 122 +++++++++++++++++++++++++++++++++++++++++
 t/t3080/color_ls (new)         |   3 +
 t/t3080/ls_colors (new)        |   2 +
 3 files changed, 127 insertions(+)
 create mode 100755 t/t3080-list-files.sh
 create mode 100644 t/t3080/color_ls
 create mode 100644 t/t3080/ls_colors

diff --git a/t/t3080-list-files.sh b/t/t3080-list-files.sh
new file mode 100755
index 0000000..6313dd9
--- /dev/null
+++ b/t/t3080-list-files.sh
@@ -0,0 +1,122 @@
+#!/bin/sh
+
+test_description='git list-files test'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	mkdir dir &&
+	touch file dir/file &&
+	git init gitlink &&
+	( cd gitlink && test_commit foo ) &&
+	git add file dir/file gitlink &&
+	git commit -qm1
+'
+
+test_expect_success 'LS_COLORS env variable' '
+	LS_COLORS="rs=0:fi=31:di=32" \
+		git list-files --color=always | grep -v gitlink >actual &&
+	test_cmp "$TEST_DIRECTORY"/t3080/ls_colors actual
+'
+
+test_expect_success 'color.ls.*' '
+	test_config color.ls.file red &&
+	test_config color.ls.directory green &&
+	test_config color.ls.submodule yellow &&
+	git list-files --color=always >actual &&
+	test_cmp "$TEST_DIRECTORY"/t3080/color_ls actual
+'
+
+test_expect_success 'column output' '
+	COLUMNS=20 git list-files --column=always >actual &&
+	cat >expected <<-\EOF &&
+	dir      gitlink
+	file
+	EOF
+	test_cmp expected actual &&
+	git list-files -1 >actual &&
+	cat >expected <<-\EOF &&
+	dir
+	file
+	gitlink
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success '--max-depth' '
+	git list-files --max-depth=1 >actual &&
+	cat >expected <<-\EOF &&
+	dir/file
+	file
+	gitlink
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'recursive' '
+	git list-files -R >actual &&
+	cat >expected <<-\EOF &&
+	dir/file
+	file
+	gitlink
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'globbing' '
+	git list-files "f*" >actual &&
+	cat >expected <<-\EOF &&
+	file
+	EOF
+	test_cmp expected actual &&
+	git list-files "**/f*" >actual &&
+	cat >expected <<-\EOF &&
+	dir/file
+	file
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'no dups' '
+	echo dirty >>file &&
+	git list-files -m file >actual &&
+	echo "file" >expected &&
+	test_cmp expected actual &&
+	git list-files -cm file >actual &&
+	echo "C file" >expected &&
+	test_cmp expected actual &&
+	git list-files -tcm file >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success '--classify' '
+	git list-files -F >actual &&
+	cat >expected <<-\EOF &&
+	dir/
+	file
+	gitlink&
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'diff-cached' '
+	echo dirty >>file &&
+	git add file &&
+	git list-files -M >actual &&
+	echo "file" >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'unmerged files' '
+	git ls-files --stage file >index-info &&
+	sed "s/ 0/ 2/;s/file/unmerged/" index-info | git update-index --index-info &&
+	sed "s/ 0/ 3/;s,file,dir/unmerged," index-info | git update-index --index-info &&
+	git list-files -u >actual &&
+	cat >expected <<-\EOF &&
+	dir
+	unmerged
+	EOF
+	test_cmp expected actual
+'
+
+test_done
diff --git a/t/t3080/color_ls b/t/t3080/color_ls
new file mode 100644
index 0000000..47f77ad
--- /dev/null
+++ b/t/t3080/color_ls
@@ -0,0 +1,3 @@
+^[[32mdir^[[m
+^[[31mfile^[[m
+^[[33mgitlink^[[m
diff --git a/t/t3080/ls_colors b/t/t3080/ls_colors
new file mode 100644
index 0000000..423c016
--- /dev/null
+++ b/t/t3080/ls_colors
@@ -0,0 +1,2 @@
+^[[32mdir^[[m
+^[[31mfile^[[m
-- 
2.2.0.84.ge9c7a8a

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 17/21] list-files: show directories as well as files
  2015-01-25 12:37 ` [PATCH 17/21] list-files: show directories as well as files Nguyễn Thái Ngọc Duy
@ 2015-01-25 19:16   ` Eric Sunshine
  2015-01-27 21:51   ` Junio C Hamano
  1 sibling, 0 replies; 31+ messages in thread
From: Eric Sunshine @ 2015-01-25 19:16 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: Git List

On Sun, Jan 25, 2015 at 7:37 AM, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:
> The index does not store directories explicitly (except submodules) so
> we have to figure them out from file list when output lis depth-limited.
>
> The function show_as_directory() deliberately generates duplicate
> directories and expects the previous patch to remove duplicates.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
> diff --git a/builtin/ls-files.c b/builtin/ls-files.c
> index 1a1c9c8..29b5c2e 100644
> --- a/builtin/ls-files.c
> +++ b/builtin/ls-files.c
> @@ -179,6 +181,35 @@ static void show_killed_files(struct dir_struct *dir)
>         }
>  }
>
> +static int show_as_directory(const struct cache_entry *ce)
> +{
> +       struct strbuf sb = STRBUF_INIT;
> +       const char *p;
> +
> +       strbuf_add(&sb, ce->name, ce_namelen(ce));
> +       while (sb.len && (p = strrchr(sb.buf, '/')) != NULL) {
> +               struct strbuf sb2 = STRBUF_INIT;
> +               strbuf_setlen(&sb, p - sb.buf);
> +               if (!match_pathspec(&pathspec, sb.buf, sb.len,
> +                                   max_prefix_len, NULL, 1))
> +                       continue;
> +               write_name(&sb2, sb.buf);
> +               if (want_color(use_color)) {
> +                       struct strbuf sb3 = STRBUF_INIT;
> +                       color_filename(&sb3, ce->name, sb2.buf, S_IFDIR, 1);
> +                       strbuf_release(&sb2);
> +                       sb2 = sb3;

Although more expensive, would it be a bit more idiomatic and obvious
to phrase this as

    strbuf_swap(&sb2, &sb3);
    strbuf_release(&sb3);

or is it not worth it?

> +               }
> +               if (show_tag)
> +                       strbuf_insert(&sb2, 0, tag_cached, strlen(tag_cached));
> +               strbuf_fputs(&sb2, strbuf_detach(&sb, NULL), NULL);

The detached strbuf content gets assigned to the 'util' field of the
'struct string_list output' item and is eventually leaked, however,
the program exits soon after. Okay.

> +               strbuf_release(&sb2);
> +               return 1;
> +       }
> +       strbuf_release(&sb);
> +       return 0;
> +}
> +
>  static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
>  {
>         struct strbuf quoted = STRBUF_INIT;

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 21/21] t3080: tests for git-list-files
  2015-01-25 12:37 ` [PATCH 21/21] t3080: tests for git-list-files Nguyễn Thái Ngọc Duy
@ 2015-01-25 19:20   ` Eric Sunshine
  2015-01-28  4:44     ` Michael Blume
  0 siblings, 1 reply; 31+ messages in thread
From: Eric Sunshine @ 2015-01-25 19:20 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: Git List

On Sun, Jan 25, 2015 at 7:37 AM, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
> diff --git a/t/t3080-list-files.sh b/t/t3080-list-files.sh
> new file mode 100755
> index 0000000..6313dd9
> --- /dev/null
> +++ b/t/t3080-list-files.sh
> +test_expect_success 'no dups' '
> +       echo dirty >>file &&

To leave a clean slate for subsequent tests, would it make sense to
restore 'file' to a clean state via test_when_finished()?

> +       git list-files -m file >actual &&
> +       echo "file" >expected &&
> +       test_cmp expected actual &&
> +       git list-files -cm file >actual &&
> +       echo "C file" >expected &&
> +       test_cmp expected actual &&
> +       git list-files -tcm file >actual &&
> +       test_cmp expected actual
> +'
> +
> +test_expect_success 'diff-cached' '
> +       echo dirty >>file &&
> +       git add file &&

Ditto here?

> +       git list-files -M >actual &&
> +       echo "file" >expected &&
> +       test_cmp expected actual
> +'

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 09/21] list-files: a user friendly version of ls-files and more
  2015-01-25 12:37 ` [PATCH 09/21] list-files: a user friendly version of ls-files and more Nguyễn Thái Ngọc Duy
@ 2015-01-27 20:30   ` Junio C Hamano
  0 siblings, 0 replies; 31+ messages in thread
From: Junio C Hamano @ 2015-01-27 20:30 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> +color.list-files::
> +	A boolean to enable/disable color in the output of
> +	linkgit:git-list-files[1]. May be set to `always`, `false` (or
> +	`never`) or `auto` (or `true`), in which case colors are used
> +	only when the output is to a terminal. Defaults to false.

This violates the configuration variable naming rules; perhaps
rename it to color.listFiles or something?

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 17/21] list-files: show directories as well as files
  2015-01-25 12:37 ` [PATCH 17/21] list-files: show directories as well as files Nguyễn Thái Ngọc Duy
  2015-01-25 19:16   ` Eric Sunshine
@ 2015-01-27 21:51   ` Junio C Hamano
  1 sibling, 0 replies; 31+ messages in thread
From: Junio C Hamano @ 2015-01-27 21:51 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> @@ -194,16 +225,31 @@ static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
>  static void show_ce_entry(const char *tag, const struct cache_entry *ce)
>  {
>  	static struct strbuf sb = STRBUF_INIT;
> -	int len = max_prefix_len;
> +	int len = max_prefix_len, saved_max_depth;
>  
>  	if (len >= ce_namelen(ce))
>  		die("git ls-files: internal error - cache entry not superset of prefix");
>  
> +	if (show_dirs) {
> +		/* ignore depth to catch dirs that contain matched entries */
> +		saved_max_depth = pathspec.max_depth;
> +		pathspec.max_depth = -1;
> +	}
> +
>  	if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce),
>  			    len, ps_matched,
>  			    S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode)))
>  		return;
>  
> +	if (show_dirs) {
> +		pathspec.max_depth = saved_max_depth;
> +		if (strchr(ce->name, '/') &&
> +		    !match_pathspec(&pathspec, ce->name, ce_namelen(ce),
> +				    prefix_len, NULL, 1) &&
> +		    show_as_directory(ce))
> +			return;
> +	}
> +

My compiler seems to be too stupid to notice that saved_max_depth is
always set before it is used, if it gets used and complains.  Sigh.

For now I am tempted to squash this in.  Note that the original does
not seem to restore saved_max_depath when the pathspec does not match
and function returns in the call to match_pathspec() we have in the
code before your patch, which smells like a bug, and the attached
would fix it.

 builtin/ls-files.c | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 29b5c2e..f28b7e9 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -222,27 +222,38 @@ static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
 	strbuf_release(&quoted);
 }
 
+static int match_pathspec_with_depth(struct pathspec *ps,
+				     const char *name, int namelen,
+				     int prefix, char *seen, int is_dir,
+				     const int *custom_depth)
+{
+	int saved_depth = ps->max_depth;
+	int result;
+
+	if (custom_depth)
+		ps->max_depth = *custom_depth;
+	result = match_pathspec(ps, name, namelen, prefix, seen, is_dir);
+	if (custom_depth)
+		ps->max_depth = saved_depth;
+	return result;
+}
+
 static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
 	static struct strbuf sb = STRBUF_INIT;
-	int len = max_prefix_len, saved_max_depth;
+	int len = max_prefix_len;
+	static const int infinite_depth = -1;
 
 	if (len >= ce_namelen(ce))
 		die("git ls-files: internal error - cache entry not superset of prefix");
 
-	if (show_dirs) {
-		/* ignore depth to catch dirs that contain matched entries */
-		saved_max_depth = pathspec.max_depth;
-		pathspec.max_depth = -1;
-	}
-
-	if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce),
-			    len, ps_matched,
-			    S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode)))
+	if (!match_pathspec_with_depth(&pathspec, ce->name, ce_namelen(ce),
+				       len, ps_matched,
+				       S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode),
+				       show_dirs ? &infinite_depth : NULL))
 		return;
 
 	if (show_dirs) {
-		pathspec.max_depth = saved_max_depth;
 		if (strchr(ce->name, '/') &&
 		    !match_pathspec(&pathspec, ce->name, ce_namelen(ce),
 				    prefix_len, NULL, 1) &&

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 21/21] t3080: tests for git-list-files
  2015-01-25 19:20   ` Eric Sunshine
@ 2015-01-28  4:44     ` Michael Blume
  2015-01-28 10:19       ` Duy Nguyen
  2015-01-28 19:03       ` Junio C Hamano
  0 siblings, 2 replies; 31+ messages in thread
From: Michael Blume @ 2015-01-28  4:44 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: Nguyễn Thái Ngọc Duy, Git List

Test 3 is failing on my mac:

expecting success:
test_config color.ls.file red &&
test_config color.ls.directory green &&
test_config color.ls.submodule yellow &&
git list-files --color=always >actual &&
test_cmp "$TEST_DIRECTORY"/t3080/color_ls actual

--- /Users/michael.blume/workspace/git/t/t3080/color_ls 2015-01-28
04:40:23.000000000 +0000
+++ actual 2015-01-28 04:42:59.000000000 +0000
@@ -1,3 +1,3 @@
-dir
-file
-gitlink
+dir
+file
+gitlink
not ok 3 - color.ls.*
#
# test_config color.ls.file red &&
# test_config color.ls.directory green &&
# test_config color.ls.submodule yellow &&
# git list-files --color=always >actual &&
# test_cmp "$TEST_DIRECTORY"/t3080/color_ls actual
#

On Sun, Jan 25, 2015 at 11:20 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:
> On Sun, Jan 25, 2015 at 7:37 AM, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:
>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
>> ---
>> diff --git a/t/t3080-list-files.sh b/t/t3080-list-files.sh
>> new file mode 100755
>> index 0000000..6313dd9
>> --- /dev/null
>> +++ b/t/t3080-list-files.sh
>> +test_expect_success 'no dups' '
>> +       echo dirty >>file &&
>
> To leave a clean slate for subsequent tests, would it make sense to
> restore 'file' to a clean state via test_when_finished()?
>
>> +       git list-files -m file >actual &&
>> +       echo "file" >expected &&
>> +       test_cmp expected actual &&
>> +       git list-files -cm file >actual &&
>> +       echo "C file" >expected &&
>> +       test_cmp expected actual &&
>> +       git list-files -tcm file >actual &&
>> +       test_cmp expected actual
>> +'
>> +
>> +test_expect_success 'diff-cached' '
>> +       echo dirty >>file &&
>> +       git add file &&
>
> Ditto here?
>
>> +       git list-files -M >actual &&
>> +       echo "file" >expected &&
>> +       test_cmp expected actual
>> +'
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 21/21] t3080: tests for git-list-files
  2015-01-28  4:44     ` Michael Blume
@ 2015-01-28 10:19       ` Duy Nguyen
  2015-01-28 17:49         ` Michael Blume
  2015-01-28 19:03       ` Junio C Hamano
  1 sibling, 1 reply; 31+ messages in thread
From: Duy Nguyen @ 2015-01-28 10:19 UTC (permalink / raw)
  To: Michael Blume; +Cc: Eric Sunshine, Git List

On Wed, Jan 28, 2015 at 11:44 AM, Michael Blume <blume.mike@gmail.com> wrote:
> Test 3 is failing on my mac:
>
> expecting success:
> test_config color.ls.file red &&
> test_config color.ls.directory green &&
> test_config color.ls.submodule yellow &&
> git list-files --color=always >actual &&
> test_cmp "$TEST_DIRECTORY"/t3080/color_ls actual
>
> --- /Users/michael.blume/workspace/git/t/t3080/color_ls 2015-01-28
> 04:40:23.000000000 +0000
> +++ actual 2015-01-28 04:42:59.000000000 +0000
> @@ -1,3 +1,3 @@
> -dir
> -file
> -gitlink
> +dir
> +file
> +gitlink

Urgh.. colors do not send well over plain text.. I just realized we
have test_decode_color to convert colors to text descriptions.. will
fix..

Anyway, I think i may know why it fails. I suppose  the env variable
LS_COLORS is not defined, or defined as empty in your shell?
-- 
Duy

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 21/21] t3080: tests for git-list-files
  2015-01-28 10:19       ` Duy Nguyen
@ 2015-01-28 17:49         ` Michael Blume
  0 siblings, 0 replies; 31+ messages in thread
From: Michael Blume @ 2015-01-28 17:49 UTC (permalink / raw)
  To: Duy Nguyen; +Cc: Eric Sunshine, Git List

On Wed, Jan 28, 2015 at 2:19 AM, Duy Nguyen <pclouds@gmail.com> wrote:
> On Wed, Jan 28, 2015 at 11:44 AM, Michael Blume <blume.mike@gmail.com> wrote:
>> Test 3 is failing on my mac:
>>
>> expecting success:
>> test_config color.ls.file red &&
>> test_config color.ls.directory green &&
>> test_config color.ls.submodule yellow &&
>> git list-files --color=always >actual &&
>> test_cmp "$TEST_DIRECTORY"/t3080/color_ls actual
>>
>> --- /Users/michael.blume/workspace/git/t/t3080/color_ls 2015-01-28
>> 04:40:23.000000000 +0000
>> +++ actual 2015-01-28 04:42:59.000000000 +0000
>> @@ -1,3 +1,3 @@
>> -dir
>> -file
>> -gitlink
>> +dir
>> +file
>> +gitlink
>
> Urgh.. colors do not send well over plain text.. I just realized we
> have test_decode_color to convert colors to text descriptions.. will
> fix..
>
> Anyway, I think i may know why it fails. I suppose  the env variable
> LS_COLORS is not defined, or defined as empty in your shell?
> --
> Duy


In case it helps:
https://www.dropbox.com/s/zsm3xgulmsl3rqm/Screenshot%202015-01-28%2009.46.57.png?dl=0

Also no, LS_COLORS is not defined

$ echo $LS_COLORS

$

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 21/21] t3080: tests for git-list-files
  2015-01-28  4:44     ` Michael Blume
  2015-01-28 10:19       ` Duy Nguyen
@ 2015-01-28 19:03       ` Junio C Hamano
  1 sibling, 0 replies; 31+ messages in thread
From: Junio C Hamano @ 2015-01-28 19:03 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: Michael Blume, Eric Sunshine, Git List

Michael Blume <blume.mike@gmail.com> writes:

> Test 3 is failing on my mac:
>
> expecting success:
> test_config color.ls.file red &&
> test_config color.ls.directory green &&
> test_config color.ls.submodule yellow &&
> git list-files --color=always >actual &&
> test_cmp "$TEST_DIRECTORY"/t3080/color_ls actual
>
> --- /Users/michael.blume/workspace/git/t/t3080/color_ls 2015-01-28
> 04:40:23.000000000 +0000
> +++ actual 2015-01-28 04:42:59.000000000 +0000
> @@ -1,3 +1,3 @@
> -dir
> -file
> -gitlink
> +dir
> +file
> +gitlink
> not ok 3 - color.ls.*

Same here on Ubuntu.

Regardless of the breakage in the code that violates the expectation
of this test, I do not think you would want to have test_cmp compare
coloured output directly without using test_decode_color.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 14/21] list-files: add -t back
  2015-02-08  9:01 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
@ 2015-02-08  9:01 ` Nguyễn Thái Ngọc Duy
  0 siblings, 0 replies; 31+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2015-02-08  9:01 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy, Junio C Hamano

Tag "H" (cached) is not shown though because it's usually the majority
and becomes noise. Not showing it makes the other tags stand out. -t
is on by default if more than one file category is selected.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-list-files.txt |  6 ++++++
 builtin/ls-files.c               | 27 +++++++++++++++++----------
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-list-files.txt b/Documentation/git-list-files.txt
index 1c0c877..9d4c127 100644
--- a/Documentation/git-list-files.txt
+++ b/Documentation/git-list-files.txt
@@ -46,6 +46,12 @@ OPTIONS
 --unmerged::
 	Show unmerged files
 
+-t::
+--[no-]tag::
+	Show a tag to indicate file type. Automatically turned on with
+	multiple file selections. See linkgit::git-ls-files[1] option
+	`-t` for more information.
+
 -R::
 --recursive::
 	Equivalent of `--max-depth=-1` (infinite recursion).
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 62aa64f..0e7cbb9 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -596,6 +596,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			N_("show untracked files")),
 		OPT_SET_INT('R', "recursive", &max_depth,
 			    N_("shortcut for --max-depth=-1"), -1),
+		OPT_BOOL('t', "tag", &show_tag,
+			N_("identify the file status with tags")),
 		OPT_BIT('i', "ignored", &dir.flags,
 			N_("show ignored files"),
 			DIR_SHOW_IGNORED),
@@ -636,6 +638,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		setup_standard_excludes(&dir);
 		use_color = -1;
 		max_depth = 0;
+		show_tag = -1;
 		git_config(git_ls_config, NULL);
 	} else
 		git_config(git_default_config, NULL);
@@ -648,16 +651,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	for (i = 0; i < exclude_list.nr; i++) {
 		add_exclude(exclude_list.items[i].string, "", 0, el, --exclude_args);
 	}
-	if (show_tag || show_valid_bit) {
-		tag_cached = "H ";
-		tag_unmerged = "M ";
-		tag_removed = "R ";
-		tag_modified = "C ";
-		tag_other = "? ";
-		tag_killed = "K ";
-		tag_skip_worktree = "S ";
-		tag_resolve_undo = "U ";
-	}
 	if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
 		require_work_tree = 1;
 	if (show_unmerged && !porcelain)
@@ -711,6 +704,20 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	      show_killed || show_modified || show_resolve_undo))
 		show_cached = 1;
 
+	if (show_tag == -1)
+		show_tag = (show_cached + show_deleted + show_others +
+			    show_unmerged + show_killed + show_modified) > 1;
+	if (show_tag || show_valid_bit) {
+		tag_cached = porcelain ? "  " : "H ";
+		tag_unmerged = "M ";
+		tag_removed = "R ";
+		tag_modified = "C ";
+		tag_other = "? ";
+		tag_killed = "K ";
+		tag_skip_worktree = "S ";
+		tag_resolve_undo = "U ";
+	}
+
 	if (max_prefix)
 		prune_cache(max_prefix);
 	if (with_tree) {
-- 
2.3.0.rc1.137.g477eb31

^ permalink raw reply related	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2015-02-08  9:03 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-25 12:37 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 01/21] ls_colors.c: add $LS_COLORS parsing code Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 02/21] ls_colors.c: parse color.ls.* from config file Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 03/21] ls_colors.c: add a function to color a file name Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 04/21] ls_colors.c: highlight submodules like directories Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 05/21] ls-files: buffer full item in strbuf before printing Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 06/21] ls-files: add --color to highlight file names Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 07/21] ls-files: add --column Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 08/21] ls-files: support --max-depth Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 09/21] list-files: a user friendly version of ls-files and more Nguyễn Thái Ngọc Duy
2015-01-27 20:30   ` Junio C Hamano
2015-01-25 12:37 ` [PATCH 10/21] list-files: make alias 'ls' default to 'list-files' Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 11/21] list-files: -u does not imply showing stages Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 12/21] list-files: add -R/--recursive short for --max-depth=-1 Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 13/21] list-files: add -1 short for --no-column Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 14/21] list-files: add -t back Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 15/21] list-files: sort output and remove duplicates Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 16/21] list-files: do not show duplicate cached entries Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 17/21] list-files: show directories as well as files Nguyễn Thái Ngọc Duy
2015-01-25 19:16   ` Eric Sunshine
2015-01-27 21:51   ` Junio C Hamano
2015-01-25 12:37 ` [PATCH 18/21] list-files: add -F/--classify Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 19/21] list-files -F: show submodules with the new indicator '&' Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 20/21] list-files: -M aka diff-cached Nguyễn Thái Ngọc Duy
2015-01-25 12:37 ` [PATCH 21/21] t3080: tests for git-list-files Nguyễn Thái Ngọc Duy
2015-01-25 19:20   ` Eric Sunshine
2015-01-28  4:44     ` Michael Blume
2015-01-28 10:19       ` Duy Nguyen
2015-01-28 17:49         ` Michael Blume
2015-01-28 19:03       ` Junio C Hamano
  -- strict thread matches above, loose matches on Subject: below --
2015-02-08  9:01 [PATCH 00/21] nd/list-files updates Nguyễn Thái Ngọc Duy
2015-02-08  9:01 ` [PATCH 14/21] list-files: add -t back Nguyễn Thái Ngọc Duy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).