* [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("ed, ent->name);
+ if (want_color(use_color))
+ color_filename(sb, ent->name, quoted.buf, st.st_mode, 1);
+ else
+ strbuf_addbuf(sb, "ed);
+ strbuf_addch(sb, line_terminator);
+ strbuf_release("ed);
+}
+
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("ed, ce->name);
+ if (want_color(use_color))
+ color_filename(sb, ce->name, quoted.buf, ce->ce_mode, 1);
+ else
+ strbuf_addbuf(sb, "ed);
+ strbuf_addch(sb, line_terminator);
+ strbuf_release("ed);
+}
+
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
* 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 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("ed);
}
+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
* [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, "ed);
+ if (show_indicator && st.st_mode)
+ append_indicator(sb, st.st_mode);
strbuf_addch(sb, line_terminator);
strbuf_release("ed);
}
@@ -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, "ed);
+ if (show_indicator)
+ append_indicator(sb, ce->ce_mode);
strbuf_addch(sb, line_terminator);
strbuf_release("ed);
}
@@ -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 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 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