Re: [PATCH 17/21] list-files: show directories as well as files

2015-02-09 Thread Junio C Hamano
Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

 + if (show_dirs strchr(ce-name, '/') 

Oops.  Will fix it up locally.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 17/21] list-files: show directories as well as files

2015-02-08 Thread 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.

Helped-by: Eric Sunshine sunsh...@sunshineco.com
Helped-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 builtin/ls-files.c | 64 ++
 1 file changed, 60 insertions(+), 4 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 457d067..6be08fb 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_swap(sb2, sb3);
+   strbuf_release(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;
@@ -191,17 +222,40 @@ static void write_ce_name(struct strbuf *sb, const struct 
cache_entry *ce)
strbuf_release(quoted);
 }
 
+static int match_pathspec_with_depth(struct pathspec *ps,
+const char *name, int namelen,
+int prefix, char *seen, int is_dir,
+const int *custom_depth)
+{
+   int saved_depth = ps-max_depth;
+   int result;
+
+   if (custom_depth)
+   ps-max_depth = *custom_depth;
+   result = match_pathspec(ps, name, namelen, prefix, seen, is_dir);
+   if (custom_depth)
+   ps-max_depth = saved_depth;
+   return result;
+}
+
 static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
static struct strbuf sb = STRBUF_INIT;
+   static const int infinite_depth = -1;
int len = max_prefix_len;
 
if (len = ce_namelen(ce))
die(git ls-files: internal error - cache entry not superset of 
prefix);
 
-   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 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 
@@ -575,7 +629,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 +798,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.3.0.rc1.137.g477eb31

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 17/21] list-files: show directories as well as files

2015-01-27 Thread Junio C Hamano
Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

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

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

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

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

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


Re: [PATCH 17/21] list-files: show directories as well as files

2015-01-25 Thread Eric Sunshine
On Sun, Jan 25, 2015 at 7:37 AM, Nguyễn Thái Ngọc Duy pclo...@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 pclo...@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;
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 17/21] list-files: show directories as well as files

2015-01-25 Thread 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 pclo...@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

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html