git@vger.kernel.org mailing list mirror (one of many)
 help / Atom feed
* [PATCH/RFC] diff: add --compact-summary option to complement --stat
@ 2018-01-13 13:22 Nguyễn Thái Ngọc Duy
  2018-01-13 18:37 ` Philip Oakley
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2018-01-13 13:22 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

This is partly inspired by gerrit web interface which shows diffstat
like this, e.g. with commit 0433d533f1 (notice the "A" column on the
third line):

     Documentation/merge-config.txt     |  4 +
     builtin/merge.c                    |  2 +
   A t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++
     t/t7612-merge-verify-signatures.sh | 45 ++++++++++
   4 files changed, 132 insertions(+)

In other words, certain information currently shown with --summary is
embedded in the diffstat. This helps reading (all information of the
same file in the same line instead of two) and can reduce the number of
lines if you add/delete a lot of files.

The new option --compact-summary implements this with a tweak to support
mode change, which is shown in --summary too.

For mode changes, executable bit is denoted as "(+x)" or "(-x)" when
it's added or removed respectively. The same for when a regular file is
replaced with a symlink "(+l)" or the other way "(-l)". This also
applies to new files. New regulare files are "A", while new executable
files or symlinks are "A+x" or "A+l".

Note, there is still one piece of information missing from --summary,
the rename/copy percentage. That could probably be added later. It's not
as useful as the others anyway.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 I have had something similar for years but the data is shown after
 the path name instead (it's incidentally shown in the diffstat right
 below). I was going to clean it up and submit it again, but my recent
 experience with Gerrit changed my mind a bit about the output.

 Documentation/diff-options.txt                     | 11 ++++
 diff.c                                             | 64 +++++++++++++++++++++-
 diff.h                                             |  1 +
 t/t4013-diff-various.sh                            |  5 ++
 ...y_--root_--stat_--compact-summary_initial (new) | 12 ++++
 ...R_--root_--stat_--compact-summary_initial (new) | 12 ++++
 ...ree_--stat_--compact-summary_initial_mode (new) |  4 ++
 ..._-R_--stat_--compact-summary_initial_mode (new) |  4 ++
 8 files changed, 110 insertions(+), 3 deletions(-)
 create mode 100644 t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial
 create mode 100644 t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial
 create mode 100644 t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode
 create mode 100644 t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode

diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 9d1586b956..ff93ff74d0 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -188,6 +188,17 @@ and accumulating child directory counts in the parent directories:
 	Output a condensed summary of extended header information
 	such as creations, renames and mode changes.
 
+--compact-summary::
+	Output a condensed summary of extended header information in
+	front of the file name part of diffstat. This option is
+	ignored if --stat is not specified.
++
+Fle creations or deletions are denoted with "A" or "D" respectively,
+optionally "+l" if it's a symlink, or "+x" if it's executable.
+Mode changes are put in brackets, e.g. "+x" or "-x" for adding or
+removing executable bit respectively, "+l" or "-l" for becoming a
+symlink or a regular file.
+
 ifndef::git-format-patch[]
 --patch-with-stat::
 	Synonym for `-p --stat`.
diff --git a/diff.c b/diff.c
index fb22b19f09..3f6767777d 100644
--- a/diff.c
+++ b/diff.c
@@ -2131,6 +2131,7 @@ struct diffstat_t {
 		char *from_name;
 		char *name;
 		char *print_name;
+		const char *status_code;
 		unsigned is_unmerged:1;
 		unsigned is_binary:1;
 		unsigned is_renamed:1;
@@ -2271,6 +2272,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 {
 	int i, len, add, del, adds = 0, dels = 0;
 	uintmax_t max_change = 0, max_len = 0;
+	int max_status_len = 0;
 	int total_files = data->nr, count;
 	int width, name_width, graph_width, number_width = 0, bin_width = 0;
 	const char *reset, *add_c, *del_c;
@@ -2287,6 +2289,18 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 	add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
 	del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
 
+	for (i = 0; (i < count) && (i < data->nr); i++) {
+		const struct diffstat_file *file = data->files[i];
+		int len;
+
+		if (!file->status_code)
+			continue;
+		len = strlen(file->status_code) + 1;
+
+		if (len > max_status_len)
+			max_status_len = len;
+	}
+
 	/*
 	 * Find the longest filename and max number of changes
 	 */
@@ -2383,6 +2397,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		      options->stat_name_width < max_len) ?
 		options->stat_name_width : max_len;
 
+	name_width += max_status_len;
+
 	/*
 	 * Adjust adjustable widths not to exceed maximum width
 	 */
@@ -2402,6 +2418,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 			graph_width = width - number_width - 6 - name_width;
 	}
 
+	name_width -= max_status_len;
+
 	/*
 	 * From here name_width is the width of the name area,
 	 * and graph_width is the width of the graph area.
@@ -2409,6 +2427,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 	 */
 	for (i = 0; i < count; i++) {
 		const char *prefix = "";
+		const char *status_code = "";
 		struct diffstat_file *file = data->files[i];
 		char *name = file->print_name;
 		uintmax_t added = file->added;
@@ -2418,6 +2437,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		if (!file->is_interesting && (added + deleted == 0))
 			continue;
 
+		if (file->status_code)
+			status_code = file->status_code;
+
 		/*
 		 * "scale" the filename
 		 */
@@ -2434,7 +2456,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		}
 
 		if (file->is_binary) {
-			strbuf_addf(&out, " %s%-*s |", prefix, len, name);
+			strbuf_addf(&out, " %-*s%s%-*s |",
+				    max_status_len, status_code,
+				    prefix, len, name);
 			strbuf_addf(&out, " %*s", number_width, "Bin");
 			if (!added && !deleted) {
 				strbuf_addch(&out, '\n');
@@ -2455,7 +2479,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 			continue;
 		}
 		else if (file->is_unmerged) {
-			strbuf_addf(&out, " %s%-*s |", prefix, len, name);
+			strbuf_addf(&out, " %-*s%s%-*s |",
+				    max_status_len, status_code,
+				    prefix, len, name);
 			strbuf_addstr(&out, " Unmerged\n");
 			emit_diff_symbol(options, DIFF_SYMBOL_STATS_LINE,
 					 out.buf, out.len, 0);
@@ -2482,7 +2508,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 				add = total - del;
 			}
 		}
-		strbuf_addf(&out, " %s%-*s |", prefix, len, name);
+		strbuf_addf(&out, " %-*s%s%-*s |",
+			    max_status_len, status_code,
+			    prefix, len, name);
 		strbuf_addf(&out, " %*"PRIuMAX"%s",
 			number_width, added + deleted,
 			added + deleted ? " " : "");
@@ -3248,6 +3276,32 @@ static void builtin_diff(const char *name_a,
 	return;
 }
 
+static const char *get_compact_summary(const struct diff_filepair *p, int is_renamed)
+{
+	if (!is_renamed) {
+		if (p->status == DIFF_STATUS_ADDED) {
+			if (S_ISLNK(p->two->mode))
+				return "A+l";
+			else if ((p->two->mode & 0777) == 0755)
+				return "A+x";
+			else
+				return "A";
+		} else if (p->status == DIFF_STATUS_DELETED)
+			return "D";
+	}
+	if (S_ISLNK(p->one->mode) && !S_ISLNK(p->two->mode))
+		return "(-l)";
+	else if (!S_ISLNK(p->one->mode) && S_ISLNK(p->two->mode))
+		return "(+l)";
+	else if ((p->one->mode & 0777) == 0644 &&
+		 (p->two->mode & 0777) == 0755)
+		return "(+x)";
+	else if ((p->one->mode & 0777) == 0755 &&
+		 (p->two->mode & 0777) == 0644)
+		return "(-x)";
+	return NULL;
+}
+
 static void builtin_diffstat(const char *name_a, const char *name_b,
 			     struct diff_filespec *one,
 			     struct diff_filespec *two,
@@ -3267,6 +3321,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
 
 	data = diffstat_add(diffstat, name_a, name_b);
 	data->is_interesting = p->status != DIFF_STATUS_UNKNOWN;
+	if (o->flags.compact_summary)
+		data->status_code = get_compact_summary(p, data->is_renamed);
 
 	if (!one || !two) {
 		data->is_unmerged = 1;
@@ -4537,6 +4593,8 @@ int diff_opt_parse(struct diff_options *options,
 	else if (starts_with(arg, "--stat"))
 		/* --stat, --stat-width, --stat-name-width, or --stat-count */
 		return stat_opt(options, av);
+	else if (!strcmp(arg, "--compact-summary"))
+		options->flags.compact_summary = 1;
 
 	/* renames options */
 	else if (starts_with(arg, "-B") ||
diff --git a/diff.h b/diff.h
index 7cf276f077..843276196c 100644
--- a/diff.h
+++ b/diff.h
@@ -93,6 +93,7 @@ struct diff_flags {
 	unsigned funccontext:1;
 	unsigned pickaxe_ignore_case:1;
 	unsigned default_follow_renames:1;
+	unsigned compact_summary:1;
 };
 
 static inline void diff_flags_or(struct diff_flags *a,
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index f10798b2df..3f9a24fd56 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -361,6 +361,11 @@ diff --no-index --raw dir2 dir
 diff --no-index --raw --abbrev=4 dir2 dir
 :noellipses diff --no-index --raw --abbrev=4 dir2 dir
 diff --no-index --raw --no-abbrev dir2 dir
+
+diff-tree --pretty --root --stat --compact-summary initial
+diff-tree --pretty -R --root --stat --compact-summary initial
+diff-tree --stat --compact-summary initial mode
+diff-tree -R --stat --compact-summary initial mode
 EOF
 
 test_expect_success 'log -S requires an argument' '
diff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial
new file mode 100644
index 0000000000..0f086907fc
--- /dev/null
+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial
@@ -0,0 +1,12 @@
+$ git diff-tree --pretty --root --stat --compact-summary initial
+commit 444ac553ac7612cc88969031b02b3767fb8a353a
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:00:00 2006 +0000
+
+    Initial
+
+ A dir/sub | 2 ++
+ A file0   | 3 +++
+ A file2   | 3 +++
+ 3 files changed, 8 insertions(+)
+$
diff --git a/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial
new file mode 100644
index 0000000000..eeed5872e0
--- /dev/null
+++ b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial
@@ -0,0 +1,12 @@
+$ git diff-tree --pretty -R --root --stat --compact-summary initial
+commit 444ac553ac7612cc88969031b02b3767fb8a353a
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:00:00 2006 +0000
+
+    Initial
+
+ D dir/sub | 2 --
+ D file0   | 3 ---
+ D file2   | 3 ---
+ 3 files changed, 8 deletions(-)
+$
diff --git a/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode
new file mode 100644
index 0000000000..b674ef9c31
--- /dev/null
+++ b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode
@@ -0,0 +1,4 @@
+$ git diff-tree --stat --compact-summary initial mode
+ (+x) file0 | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+$
diff --git a/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode
new file mode 100644
index 0000000000..877e9ae19d
--- /dev/null
+++ b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode
@@ -0,0 +1,4 @@
+$ git diff-tree -R --stat --compact-summary initial mode
+ (-x) file0 | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+$
-- 
2.15.1.600.g899a5f85c6


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

* Re: [PATCH/RFC] diff: add --compact-summary option to complement --stat
  2018-01-13 13:22 [PATCH/RFC] diff: add --compact-summary option to complement --stat Nguyễn Thái Ngọc Duy
@ 2018-01-13 18:37 ` Philip Oakley
  2018-01-14  9:37 ` Simon Ruderich
  2018-01-18 10:05 ` [PATCH v2] " Nguyễn Thái Ngọc Duy
  2 siblings, 0 replies; 14+ messages in thread
From: Philip Oakley @ 2018-01-13 18:37 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy, git
  Cc: Nguyễn Thái Ngọc Duy

(one spelling spotted)..
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
> This is partly inspired by gerrit web interface which shows diffstat
> like this, e.g. with commit 0433d533f1 (notice the "A" column on the
> third line):
>
>     Documentation/merge-config.txt     |  4 +
>     builtin/merge.c                    |  2 +
>   A t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++
>     t/t7612-merge-verify-signatures.sh | 45 ++++++++++
>   4 files changed, 132 insertions(+)
>
> In other words, certain information currently shown with --summary is
> embedded in the diffstat. This helps reading (all information of the
> same file in the same line instead of two) and can reduce the number of
> lines if you add/delete a lot of files.
>
> The new option --compact-summary implements this with a tweak to support
> mode change, which is shown in --summary too.
>
> For mode changes, executable bit is denoted as "(+x)" or "(-x)" when
> it's added or removed respectively. The same for when a regular file is
> replaced with a symlink "(+l)" or the other way "(-l)". This also
> applies to new files. New regulare files are "A", while new executable
> files or symlinks are "A+x" or "A+l".
>
> Note, there is still one piece of information missing from --summary,
> the rename/copy percentage. That could probably be added later. It's not
> as useful as the others anyway.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
> I have had something similar for years but the data is shown after
> the path name instead (it's incidentally shown in the diffstat right
> below). I was going to clean it up and submit it again, but my recent
> experience with Gerrit changed my mind a bit about the output.
>
> Documentation/diff-options.txt                     | 11 ++++
> diff.c                                             | 64 
> +++++++++++++++++++++-
> diff.h                                             |  1 +
> t/t4013-diff-various.sh                            |  5 ++
> ...y_--root_--stat_--compact-summary_initial (new) | 12 ++++
> ...R_--root_--stat_--compact-summary_initial (new) | 12 ++++
> ...ree_--stat_--compact-summary_initial_mode (new) |  4 ++
> ..._-R_--stat_--compact-summary_initial_mode (new) |  4 ++
> 8 files changed, 110 insertions(+), 3 deletions(-)
> create mode 100644 
> t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial
> create mode 100644 
> t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial
> create mode 100644 
> t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode
> create mode 100644 
> t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode
>
> diff --git a/Documentation/diff-options.txt 
> b/Documentation/diff-options.txt
> index 9d1586b956..ff93ff74d0 100644
> --- a/Documentation/diff-options.txt
> +++ b/Documentation/diff-options.txt
> @@ -188,6 +188,17 @@ and accumulating child directory counts in the parent 
> directories:
>  Output a condensed summary of extended header information
>  such as creations, renames and mode changes.
>
> +--compact-summary::
> + Output a condensed summary of extended header information in
> + front of the file name part of diffstat. This option is
> + ignored if --stat is not specified.
> ++
> +Fle creations or deletions are denoted with "A" or "D" respectively,

s/Fle/File/ ?

> +optionally "+l" if it's a symlink, or "+x" if it's executable.
> +Mode changes are put in brackets, e.g. "+x" or "-x" for adding or
> +removing executable bit respectively, "+l" or "-l" for becoming a
> +symlink or a regular file.
> +
> ifndef::git-format-patch[]
> --patch-with-stat::
>  Synonym for `-p --stat`.
> diff --git a/diff.c b/diff.c
> index fb22b19f09..3f6767777d 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -2131,6 +2131,7 @@ struct diffstat_t {
>  char *from_name;
>  char *name;
>  char *print_name;
> + const char *status_code;
>  unsigned is_unmerged:1;
>  unsigned is_binary:1;
>  unsigned is_renamed:1;
> @@ -2271,6 +2272,7 @@ static void show_stats(struct diffstat_t *data, 
> struct diff_options *options)
> {
>  int i, len, add, del, adds = 0, dels = 0;
>  uintmax_t max_change = 0, max_len = 0;
> + int max_status_len = 0;
>  int total_files = data->nr, count;
>  int width, name_width, graph_width, number_width = 0, bin_width = 0;
>  const char *reset, *add_c, *del_c;
> @@ -2287,6 +2289,18 @@ static void show_stats(struct diffstat_t *data, 
> struct diff_options *options)
>  add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
>  del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
>
> + for (i = 0; (i < count) && (i < data->nr); i++) {
> + const struct diffstat_file *file = data->files[i];
> + int len;
> +
> + if (!file->status_code)
> + continue;
> + len = strlen(file->status_code) + 1;
> +
> + if (len > max_status_len)
> + max_status_len = len;
> + }
> +
>  /*
>  * Find the longest filename and max number of changes
>  */
> @@ -2383,6 +2397,8 @@ static void show_stats(struct diffstat_t *data, 
> struct diff_options *options)
>        options->stat_name_width < max_len) ?
>  options->stat_name_width : max_len;
>
> + name_width += max_status_len;
> +
>  /*
>  * Adjust adjustable widths not to exceed maximum width
>  */
> @@ -2402,6 +2418,8 @@ static void show_stats(struct diffstat_t *data, 
> struct diff_options *options)
>  graph_width = width - number_width - 6 - name_width;
>  }
>
> + name_width -= max_status_len;
> +
>  /*
>  * From here name_width is the width of the name area,
>  * and graph_width is the width of the graph area.
> @@ -2409,6 +2427,7 @@ static void show_stats(struct diffstat_t *data, 
> struct diff_options *options)
>  */
>  for (i = 0; i < count; i++) {
>  const char *prefix = "";
> + const char *status_code = "";
>  struct diffstat_file *file = data->files[i];
>  char *name = file->print_name;
>  uintmax_t added = file->added;
> @@ -2418,6 +2437,9 @@ static void show_stats(struct diffstat_t *data, 
> struct diff_options *options)
>  if (!file->is_interesting && (added + deleted == 0))
>  continue;
>
> + if (file->status_code)
> + status_code = file->status_code;
> +
>  /*
>  * "scale" the filename
>  */
> @@ -2434,7 +2456,9 @@ static void show_stats(struct diffstat_t *data, 
> struct diff_options *options)
>  }
>
>  if (file->is_binary) {
> - strbuf_addf(&out, " %s%-*s |", prefix, len, name);
> + strbuf_addf(&out, " %-*s%s%-*s |",
> +     max_status_len, status_code,
> +     prefix, len, name);
>  strbuf_addf(&out, " %*s", number_width, "Bin");
>  if (!added && !deleted) {
>  strbuf_addch(&out, '\n');
> @@ -2455,7 +2479,9 @@ static void show_stats(struct diffstat_t *data, 
> struct diff_options *options)
>  continue;
>  }
>  else if (file->is_unmerged) {
> - strbuf_addf(&out, " %s%-*s |", prefix, len, name);
> + strbuf_addf(&out, " %-*s%s%-*s |",
> +     max_status_len, status_code,
> +     prefix, len, name);
>  strbuf_addstr(&out, " Unmerged\n");
>  emit_diff_symbol(options, DIFF_SYMBOL_STATS_LINE,
>  out.buf, out.len, 0);
> @@ -2482,7 +2508,9 @@ static void show_stats(struct diffstat_t *data, 
> struct diff_options *options)
>  add = total - del;
>  }
>  }
> - strbuf_addf(&out, " %s%-*s |", prefix, len, name);
> + strbuf_addf(&out, " %-*s%s%-*s |",
> +     max_status_len, status_code,
> +     prefix, len, name);
>  strbuf_addf(&out, " %*"PRIuMAX"%s",
>  number_width, added + deleted,
>  added + deleted ? " " : "");
> @@ -3248,6 +3276,32 @@ static void builtin_diff(const char *name_a,
>  return;
> }
>
> +static const char *get_compact_summary(const struct diff_filepair *p, int 
> is_renamed)
> +{
> + if (!is_renamed) {
> + if (p->status == DIFF_STATUS_ADDED) {
> + if (S_ISLNK(p->two->mode))
> + return "A+l";
> + else if ((p->two->mode & 0777) == 0755)
> + return "A+x";
> + else
> + return "A";
> + } else if (p->status == DIFF_STATUS_DELETED)
> + return "D";
> + }
> + if (S_ISLNK(p->one->mode) && !S_ISLNK(p->two->mode))
> + return "(-l)";
> + else if (!S_ISLNK(p->one->mode) && S_ISLNK(p->two->mode))
> + return "(+l)";
> + else if ((p->one->mode & 0777) == 0644 &&
> + (p->two->mode & 0777) == 0755)
> + return "(+x)";
> + else if ((p->one->mode & 0777) == 0755 &&
> + (p->two->mode & 0777) == 0644)
> + return "(-x)";
> + return NULL;
> +}
> +
> static void builtin_diffstat(const char *name_a, const char *name_b,
>       struct diff_filespec *one,
>       struct diff_filespec *two,
> @@ -3267,6 +3321,8 @@ static void builtin_diffstat(const char *name_a, 
> const char *name_b,
>
>  data = diffstat_add(diffstat, name_a, name_b);
>  data->is_interesting = p->status != DIFF_STATUS_UNKNOWN;
> + if (o->flags.compact_summary)
> + data->status_code = get_compact_summary(p, data->is_renamed);
>
>  if (!one || !two) {
>  data->is_unmerged = 1;
> @@ -4537,6 +4593,8 @@ int diff_opt_parse(struct diff_options *options,
>  else if (starts_with(arg, "--stat"))
>  /* --stat, --stat-width, --stat-name-width, or --stat-count */
>  return stat_opt(options, av);
> + else if (!strcmp(arg, "--compact-summary"))
> + options->flags.compact_summary = 1;
>
>  /* renames options */
>  else if (starts_with(arg, "-B") ||
> diff --git a/diff.h b/diff.h
> index 7cf276f077..843276196c 100644
> --- a/diff.h
> +++ b/diff.h
> @@ -93,6 +93,7 @@ struct diff_flags {
>  unsigned funccontext:1;
>  unsigned pickaxe_ignore_case:1;
>  unsigned default_follow_renames:1;
> + unsigned compact_summary:1;
> };
>
> static inline void diff_flags_or(struct diff_flags *a,
> diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
> index f10798b2df..3f9a24fd56 100755
> --- a/t/t4013-diff-various.sh
> +++ b/t/t4013-diff-various.sh
> @@ -361,6 +361,11 @@ diff --no-index --raw dir2 dir
> diff --no-index --raw --abbrev=4 dir2 dir
> :noellipses diff --no-index --raw --abbrev=4 dir2 dir
> diff --no-index --raw --no-abbrev dir2 dir
> +
> +diff-tree --pretty --root --stat --compact-summary initial
> +diff-tree --pretty -R --root --stat --compact-summary initial
> +diff-tree --stat --compact-summary initial mode
> +diff-tree -R --stat --compact-summary initial mode
> EOF
>
> test_expect_success 'log -S requires an argument' '
> diff --git 
> a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial 
> b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial
> new file mode 100644
> index 0000000000..0f086907fc
> --- /dev/null
> +++ 
> b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial
> @@ -0,0 +1,12 @@
> +$ git diff-tree --pretty --root --stat --compact-summary initial
> +commit 444ac553ac7612cc88969031b02b3767fb8a353a
> +Author: A U Thor <author@example.com>
> +Date:   Mon Jun 26 00:00:00 2006 +0000
> +
> +    Initial
> +
> + A dir/sub | 2 ++
> + A file0   | 3 +++
> + A file2   | 3 +++
> + 3 files changed, 8 insertions(+)
> +$
> diff --git 
> a/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial 
> b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial
> new file mode 100644
> index 0000000000..eeed5872e0
> --- /dev/null
> +++ 
> b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial
> @@ -0,0 +1,12 @@
> +$ git diff-tree --pretty -R --root --stat --compact-summary initial
> +commit 444ac553ac7612cc88969031b02b3767fb8a353a
> +Author: A U Thor <author@example.com>
> +Date:   Mon Jun 26 00:00:00 2006 +0000
> +
> +    Initial
> +
> + D dir/sub | 2 --
> + D file0   | 3 ---
> + D file2   | 3 ---
> + 3 files changed, 8 deletions(-)
> +$
> diff --git a/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode 
> b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode
> new file mode 100644
> index 0000000000..b674ef9c31
> --- /dev/null
> +++ b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode
> @@ -0,0 +1,4 @@
> +$ git diff-tree --stat --compact-summary initial mode
> + (+x) file0 | 0
> + 1 file changed, 0 insertions(+), 0 deletions(-)
> +$
> diff --git 
> a/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode 
> b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode
> new file mode 100644
> index 0000000000..877e9ae19d
> --- /dev/null
> +++ b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode
> @@ -0,0 +1,4 @@
> +$ git diff-tree -R --stat --compact-summary initial mode
> + (-x) file0 | 0
> + 1 file changed, 0 insertions(+), 0 deletions(-)
> +$
> -- 
> 2.15.1.600.g899a5f85c6
> 


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

* Re: [PATCH/RFC] diff: add --compact-summary option to complement --stat
  2018-01-13 13:22 [PATCH/RFC] diff: add --compact-summary option to complement --stat Nguyễn Thái Ngọc Duy
  2018-01-13 18:37 ` Philip Oakley
@ 2018-01-14  9:37 ` Simon Ruderich
  2018-01-14 10:24   ` Duy Nguyen
  2018-01-18 10:05 ` [PATCH v2] " Nguyễn Thái Ngọc Duy
  2 siblings, 1 reply; 14+ messages in thread
From: Simon Ruderich @ 2018-01-14  9:37 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

On Sat, Jan 13, 2018 at 08:22:11PM +0700, Nguyễn Thái Ngọc Duy wrote:
> [snip]
>
> For mode changes, executable bit is denoted as "(+x)" or "(-x)" when
> it's added or removed respectively. The same for when a regular file is
> replaced with a symlink "(+l)" or the other way "(-l)". This also
> applies to new files. New regulare files are "A", while new executable
> files or symlinks are "A+x" or "A+l".

I like the short summary. However I find the use of parentheses
inconsistent. Why not use them either always (also for "(A+l)")
or never? Was there a specific reason why you added them just in
one place?

Regards
Simon
-- 
+ privacy is necessary
+ using gnupg http://gnupg.org
+ public key id: 0x92FEFDB7E44C32F9

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

* Re: [PATCH/RFC] diff: add --compact-summary option to complement --stat
  2018-01-14  9:37 ` Simon Ruderich
@ 2018-01-14 10:24   ` Duy Nguyen
  0 siblings, 0 replies; 14+ messages in thread
From: Duy Nguyen @ 2018-01-14 10:24 UTC (permalink / raw)
  To: Simon Ruderich; +Cc: Git Mailing List

On Sun, Jan 14, 2018 at 4:37 PM, Simon Ruderich <simon@ruderich.org> wrote:
> On Sat, Jan 13, 2018 at 08:22:11PM +0700, Nguyễn Thái Ngọc Duy wrote:
>> [snip]
>>
>> For mode changes, executable bit is denoted as "(+x)" or "(-x)" when
>> it's added or removed respectively. The same for when a regular file is
>> replaced with a symlink "(+l)" or the other way "(-l)". This also
>> applies to new files. New regulare files are "A", while new executable
>> files or symlinks are "A+x" or "A+l".
>
> I like the short summary. However I find the use of parentheses
> inconsistent.

I agree. I put them in parentheses because somehow to me plain "+x"
looks weird to me.

> Why not use them either always (also for "(A+l)")
> or never? Was there a specific reason why you added them just in
> one place?

Actually shortly after I sent the mail, I realized I could do better.
Since this is a mode _modification_, we could denote it with "M" (most
files in diffstat are "M" for obvious reasons, we just don't print it
because it adds no value), so here we could print "M+x" or "M-x". This
aligns well with "A+l" or "A+x" for example and is one character
shorter than my old way.
-- 
Duy

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

* [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-13 13:22 [PATCH/RFC] diff: add --compact-summary option to complement --stat Nguyễn Thái Ngọc Duy
  2018-01-13 18:37 ` Philip Oakley
  2018-01-14  9:37 ` Simon Ruderich
@ 2018-01-18 10:05 ` " Nguyễn Thái Ngọc Duy
  2018-01-18 18:57   ` Eric Sunshine
                     ` (3 more replies)
  2 siblings, 4 replies; 14+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2018-01-18 10:05 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

This is partly inspired by gerrit web interface which shows diffstat
like this, e.g. with commit 0433d533f1 (notice the "A" column on the
third line):

     Documentation/merge-config.txt     |  4 +
     builtin/merge.c                    |  2 +
   A t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++
     t/t7612-merge-verify-signatures.sh | 45 ++++++++++
   4 files changed, 132 insertions(+)

In other words, certain information currently shown with --summary is
embedded in the diffstat. This helps reading (all information of the
same file in the same line instead of two) and can reduce the number of
lines if you add/delete a lot of files.

The new option --compact-summary implements this with a tweak to support
mode change, which is shown in --summary too.

For mode changes, executable bit is denoted as "M+x" or "M-x" when it's
added or removed respectively. The same for when a regular file is
replaced with a symlink "M+l" or the other way "M-l". This also applies
to new files. New regulare files are "A", while new executable files or
symlinks are "A+x" or "A+l".

With this tweak, the actual printout is like this

     Documentation/merge-config.txt     |  4 ++
     builtin/merge.c                    |  2 +
 A+x t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++++++++
     t/t7612-merge-verify-signatures.sh | 45 +++++++++++++
 4 files changed, 132 insertions(+)

Note, there is still one piece of information missing from --summary,
the rename/copy percentage. That could probably be added later. It's not
as useful as the others anyway.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 v2 changes "(+x)" and friends to "M+x" and fixes the "Fle" typo.

 Documentation/diff-options.txt                     | 11 ++++
 diff.c                                             | 64 +++++++++++++++++++++-
 diff.h                                             |  1 +
 t/t4013-diff-various.sh                            |  5 ++
 ...y_--root_--stat_--compact-summary_initial (new) | 12 ++++
 ...R_--root_--stat_--compact-summary_initial (new) | 12 ++++
 ...ree_--stat_--compact-summary_initial_mode (new) |  4 ++
 ..._-R_--stat_--compact-summary_initial_mode (new) |  4 ++
 8 files changed, 110 insertions(+), 3 deletions(-)
 create mode 100644 t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial
 create mode 100644 t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial
 create mode 100644 t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode
 create mode 100644 t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode

diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 743af97b06..92cbf7696f 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -188,6 +188,17 @@ and accumulating child directory counts in the parent directories:
 	Output a condensed summary of extended header information
 	such as creations, renames and mode changes.
 
+--compact-summary::
+	Output a condensed summary of extended header information in
+	front of the file name part of diffstat. This option is
+	ignored if --stat is not specified.
++
+File creations or deletions are denoted wigth "A" or "D" respectively,
+optionally "+l" if it's a symlink, or "+x" if it's executable.
+Mode changes are shown "M+x" or "M-x" for adding or removing
+executable bit respectively, "M+l" or "M-l" for becoming a symlink or
+a regular file.
+
 ifndef::git-format-patch[]
 --patch-with-stat::
 	Synonym for `-p --stat`.
diff --git a/diff.c b/diff.c
index fb22b19f09..ce1d24b417 100644
--- a/diff.c
+++ b/diff.c
@@ -2131,6 +2131,7 @@ struct diffstat_t {
 		char *from_name;
 		char *name;
 		char *print_name;
+		const char *status_code;
 		unsigned is_unmerged:1;
 		unsigned is_binary:1;
 		unsigned is_renamed:1;
@@ -2271,6 +2272,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 {
 	int i, len, add, del, adds = 0, dels = 0;
 	uintmax_t max_change = 0, max_len = 0;
+	int max_status_len = 0;
 	int total_files = data->nr, count;
 	int width, name_width, graph_width, number_width = 0, bin_width = 0;
 	const char *reset, *add_c, *del_c;
@@ -2287,6 +2289,18 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 	add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
 	del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
 
+	for (i = 0; (i < count) && (i < data->nr); i++) {
+		const struct diffstat_file *file = data->files[i];
+		int len;
+
+		if (!file->status_code)
+			continue;
+		len = strlen(file->status_code) + 1;
+
+		if (len > max_status_len)
+			max_status_len = len;
+	}
+
 	/*
 	 * Find the longest filename and max number of changes
 	 */
@@ -2383,6 +2397,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		      options->stat_name_width < max_len) ?
 		options->stat_name_width : max_len;
 
+	name_width += max_status_len;
+
 	/*
 	 * Adjust adjustable widths not to exceed maximum width
 	 */
@@ -2402,6 +2418,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 			graph_width = width - number_width - 6 - name_width;
 	}
 
+	name_width -= max_status_len;
+
 	/*
 	 * From here name_width is the width of the name area,
 	 * and graph_width is the width of the graph area.
@@ -2409,6 +2427,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 	 */
 	for (i = 0; i < count; i++) {
 		const char *prefix = "";
+		const char *status_code = "";
 		struct diffstat_file *file = data->files[i];
 		char *name = file->print_name;
 		uintmax_t added = file->added;
@@ -2418,6 +2437,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		if (!file->is_interesting && (added + deleted == 0))
 			continue;
 
+		if (file->status_code)
+			status_code = file->status_code;
+
 		/*
 		 * "scale" the filename
 		 */
@@ -2434,7 +2456,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		}
 
 		if (file->is_binary) {
-			strbuf_addf(&out, " %s%-*s |", prefix, len, name);
+			strbuf_addf(&out, " %-*s%s%-*s |",
+				    max_status_len, status_code,
+				    prefix, len, name);
 			strbuf_addf(&out, " %*s", number_width, "Bin");
 			if (!added && !deleted) {
 				strbuf_addch(&out, '\n');
@@ -2455,7 +2479,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 			continue;
 		}
 		else if (file->is_unmerged) {
-			strbuf_addf(&out, " %s%-*s |", prefix, len, name);
+			strbuf_addf(&out, " %-*s%s%-*s |",
+				    max_status_len, status_code,
+				    prefix, len, name);
 			strbuf_addstr(&out, " Unmerged\n");
 			emit_diff_symbol(options, DIFF_SYMBOL_STATS_LINE,
 					 out.buf, out.len, 0);
@@ -2482,7 +2508,9 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 				add = total - del;
 			}
 		}
-		strbuf_addf(&out, " %s%-*s |", prefix, len, name);
+		strbuf_addf(&out, " %-*s%s%-*s |",
+			    max_status_len, status_code,
+			    prefix, len, name);
 		strbuf_addf(&out, " %*"PRIuMAX"%s",
 			number_width, added + deleted,
 			added + deleted ? " " : "");
@@ -3248,6 +3276,32 @@ static void builtin_diff(const char *name_a,
 	return;
 }
 
+static const char *get_compact_summary(const struct diff_filepair *p, int is_renamed)
+{
+	if (!is_renamed) {
+		if (p->status == DIFF_STATUS_ADDED) {
+			if (S_ISLNK(p->two->mode))
+				return "A+l";
+			else if ((p->two->mode & 0777) == 0755)
+				return "A+x";
+			else
+				return "A";
+		} else if (p->status == DIFF_STATUS_DELETED)
+			return "D";
+	}
+	if (S_ISLNK(p->one->mode) && !S_ISLNK(p->two->mode))
+		return "M-l";
+	else if (!S_ISLNK(p->one->mode) && S_ISLNK(p->two->mode))
+		return "M+l";
+	else if ((p->one->mode & 0777) == 0644 &&
+		 (p->two->mode & 0777) == 0755)
+		return "M+x";
+	else if ((p->one->mode & 0777) == 0755 &&
+		 (p->two->mode & 0777) == 0644)
+		return "M-x";
+	return NULL;
+}
+
 static void builtin_diffstat(const char *name_a, const char *name_b,
 			     struct diff_filespec *one,
 			     struct diff_filespec *two,
@@ -3267,6 +3321,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
 
 	data = diffstat_add(diffstat, name_a, name_b);
 	data->is_interesting = p->status != DIFF_STATUS_UNKNOWN;
+	if (o->flags.compact_summary)
+		data->status_code = get_compact_summary(p, data->is_renamed);
 
 	if (!one || !two) {
 		data->is_unmerged = 1;
@@ -4537,6 +4593,8 @@ int diff_opt_parse(struct diff_options *options,
 	else if (starts_with(arg, "--stat"))
 		/* --stat, --stat-width, --stat-name-width, or --stat-count */
 		return stat_opt(options, av);
+	else if (!strcmp(arg, "--compact-summary"))
+		options->flags.compact_summary = 1;
 
 	/* renames options */
 	else if (starts_with(arg, "-B") ||
diff --git a/diff.h b/diff.h
index 7cf276f077..843276196c 100644
--- a/diff.h
+++ b/diff.h
@@ -93,6 +93,7 @@ struct diff_flags {
 	unsigned funccontext:1;
 	unsigned pickaxe_ignore_case:1;
 	unsigned default_follow_renames:1;
+	unsigned compact_summary:1;
 };
 
 static inline void diff_flags_or(struct diff_flags *a,
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index f10798b2df..3f9a24fd56 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -361,6 +361,11 @@ diff --no-index --raw dir2 dir
 diff --no-index --raw --abbrev=4 dir2 dir
 :noellipses diff --no-index --raw --abbrev=4 dir2 dir
 diff --no-index --raw --no-abbrev dir2 dir
+
+diff-tree --pretty --root --stat --compact-summary initial
+diff-tree --pretty -R --root --stat --compact-summary initial
+diff-tree --stat --compact-summary initial mode
+diff-tree -R --stat --compact-summary initial mode
 EOF
 
 test_expect_success 'log -S requires an argument' '
diff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial
new file mode 100644
index 0000000000..0f086907fc
--- /dev/null
+++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--compact-summary_initial
@@ -0,0 +1,12 @@
+$ git diff-tree --pretty --root --stat --compact-summary initial
+commit 444ac553ac7612cc88969031b02b3767fb8a353a
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:00:00 2006 +0000
+
+    Initial
+
+ A dir/sub | 2 ++
+ A file0   | 3 +++
+ A file2   | 3 +++
+ 3 files changed, 8 insertions(+)
+$
diff --git a/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial
new file mode 100644
index 0000000000..eeed5872e0
--- /dev/null
+++ b/t/t4013/diff.diff-tree_--pretty_-R_--root_--stat_--compact-summary_initial
@@ -0,0 +1,12 @@
+$ git diff-tree --pretty -R --root --stat --compact-summary initial
+commit 444ac553ac7612cc88969031b02b3767fb8a353a
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:00:00 2006 +0000
+
+    Initial
+
+ D dir/sub | 2 --
+ D file0   | 3 ---
+ D file2   | 3 ---
+ 3 files changed, 8 deletions(-)
+$
diff --git a/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode
new file mode 100644
index 0000000000..5d4d511dd5
--- /dev/null
+++ b/t/t4013/diff.diff-tree_--stat_--compact-summary_initial_mode
@@ -0,0 +1,4 @@
+$ git diff-tree --stat --compact-summary initial mode
+ M+x file0 | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+$
diff --git a/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode
new file mode 100644
index 0000000000..6b8c4531b4
--- /dev/null
+++ b/t/t4013/diff.diff-tree_-R_--stat_--compact-summary_initial_mode
@@ -0,0 +1,4 @@
+$ git diff-tree -R --stat --compact-summary initial mode
+ M-x file0 | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+$
-- 
2.15.1.600.g899a5f85c6


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

* Re: [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-18 10:05 ` [PATCH v2] " Nguyễn Thái Ngọc Duy
@ 2018-01-18 18:57   ` Eric Sunshine
  2018-01-19  0:01     ` Duy Nguyen
  2018-01-18 21:23   ` Ævar Arnfjörð Bjarmason
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: Eric Sunshine @ 2018-01-18 18:57 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: Git List

On Thu, Jan 18, 2018 at 5:05 AM, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:
> [...]
> The new option --compact-summary implements this with a tweak to support
> mode change, which is shown in --summary too.
>
> For mode changes, executable bit is denoted as "M+x" or "M-x" when it's
> added or removed respectively. The same for when a regular file is
> replaced with a symlink "M+l" or the other way "M-l". This also applies
> to new files. New regulare files are "A", while new executable files or

s/regulare/regular/

> symlinks are "A+x" or "A+l".
> [...]
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
> diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
> @@ -188,6 +188,17 @@ and accumulating child directory counts in the parent directories:
> +--compact-summary::
> +       Output a condensed summary of extended header information in
> +       front of the file name part of diffstat. This option is
> +       ignored if --stat is not specified.

Rather than ignoring this option if --stat is not specified, a
different approach would be for --compact-summary to imply --stat.

Also, per documentation:

    --stat[=<width>[,<name-width>[,<count>]]]::

    These parameters can also be set individually with `--stat-width=<width>`,
    `--stat-name-width=<name-width>` and `--stat-count=<count>`.

One wonders if "compact" could be another modifier recognized by --stat.

(Genuine questions/observations; I haven't formed strong opinions either way.)

> diff --git a/diff.c b/diff.c
> @@ -2287,6 +2289,18 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
> +       for (i = 0; (i < count) && (i < data->nr); i++) {

Noisy extra parentheses...

    for (i = 0; i < count && i < data->nr; i++) {

perhaps? (Not at all worth a re-roll.)

> +               const struct diffstat_file *file = data->files[i];
> +               int len;
> +
> +               if (!file->status_code)
> +                       continue;
> +               len = strlen(file->status_code) + 1;

The +1 is for the space following the status code? (Reading ahead,
that seems to be the case.)

    len = strlen(file->status_code) + strlen(" ");

perhaps? (Probably not worth a re-roll.)

> +               if (len > max_status_len)
> +                       max_status_len = len;
> +       }
> +
> @@ -2383,6 +2397,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
>                       options->stat_name_width < max_len) ?
>                 options->stat_name_width : max_len;
>
> +       name_width += max_status_len;

I wonder if it would be clearer to account for the space after the the
status code here rather than above when it was not obvious what +1 was
for.

    name_width += max_status_len + strlen(" ");

(and drop the earlier +1)

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

* Re: [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-18 10:05 ` [PATCH v2] " Nguyễn Thái Ngọc Duy
  2018-01-18 18:57   ` Eric Sunshine
@ 2018-01-18 21:23   ` Ævar Arnfjörð Bjarmason
  2018-01-19  0:06     ` Duy Nguyen
  2018-01-18 22:48   ` Jeff King
  2018-01-19 21:20   ` Junio C Hamano
  3 siblings, 1 reply; 14+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2018-01-18 21:23 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git


On Thu, Jan 18 2018, Nguyễn Thái Ngọc Duy jotted:

> This is partly inspired by gerrit web interface which shows diffstat
> like this, e.g. with commit 0433d533f1 (notice the "A" column on the
> third line):
>
>
>      Documentation/merge-config.txt     |  4 +
>      builtin/merge.c                    |  2 +
>    A t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++
>      t/t7612-merge-verify-signatures.sh | 45 ++++++++++
>    4 files changed, 132 insertions(+)

This feature is awesome. This has bothered me about --stat, but I
haven't done anything about it.

> In other words, certain information currently shown with --summary is
> embedded in the diffstat. This helps reading (all information of the
> same file in the same line instead of two) and can reduce the number of
> lines if you add/delete a lot of files.

Wait, isn't there a bug here in the existing --summary code, its
documentation says it'll show information "such as creations, renames
and mode changes".

But even though your --compact-summary shows that the file is being
added and its mode changed:

    $ diff -ru <(./git-show --stat 0433d533f1) <(./git-show --stat --compact-summary 0433d533f1)
    --- /dev/fd/63  2018-01-18 21:11:51.186570555 +0000
    +++ /dev/fd/62  2018-01-18 21:11:51.186570555 +0000
    @@ -14,8 +14,8 @@
           t: add tests for pull --verify-signatures
           merge: add config option for verifySignatures

    - Documentation/merge-config.txt     |  4 ++
    - builtin/merge.c                    |  2 +
    - t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++++++++++++++++++++++
    - t/t7612-merge-verify-signatures.sh | 45 +++++++++++++++++++++
    +     Documentation/merge-config.txt     |  4 ++
    +     builtin/merge.c                    |  2 +
    + A+x t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++++++++++++++++++
    +     t/t7612-merge-verify-signatures.sh | 45 +++++++++++++++++++
      4 files changed, 132 insertions(+)

There is no difference between --stat with and without --summary on the
same commit, shouldn't it show "create mode [...]" ?

E.g. 95450bbbaa will do the trick for both:

    $ diff -ru <(./git-show --stat 95450bbbaa) <(./git-show --stat --summary 95450bbbaa)
    --- /dev/fd/63  2018-01-18 21:14:20.770050599 +0000
    +++ /dev/fd/62  2018-01-18 21:14:20.770050599 +0000
    @@ -14,3 +14,4 @@
      git-svn.perl                    |  1 +
      t/t9169-git-svn-dcommit-crlf.sh | 27 +++++++++++++++++++++++++++
      2 files changed, 28 insertions(+)
    + create mode 100755 t/t9169-git-svn-dcommit-crlf.sh

    $ diff -ru <(./git-show --stat --summary 95450bbbaa) <(./git-show --stat --compact-summary 95450bbbaa)
    --- /dev/fd/63  2018-01-18 21:14:30.646016210 +0000
    +++ /dev/fd/62  2018-01-18 21:14:30.646016210 +0000
    @@ -11,7 +11,6 @@
         Reported-by: Brian Bennett <Brian.Bennett@Transamerica.com>
         Signed-off-by: Eric Wong <e@80x24.org>

    - git-svn.perl                    |  1 +
    - t/t9169-git-svn-dcommit-crlf.sh | 27 +++++++++++++++++++++++++++
    +     git-svn.perl                    |  1 +
    + A+x t/t9169-git-svn-dcommit-crlf.sh | 27 +++++++++++++++++++++++++++
      2 files changed, 28 insertions(+)
    - create mode 100755 t/t9169-git-svn-dcommit-crlf.sh

> +--compact-summary::
> +	Output a condensed summary of extended header information in
> +	front of the file name part of diffstat. This option is
> +	ignored if --stat is not specified.
> ++

If for some reason the lack of information about the commit under
--summary isn't a bug/fixable it makes sense to document the differences
here.

> +File creations or deletions are denoted wigth "A" or "D" respectively,

s/wigth/with/

> +optionally "+l" if it's a symlink, or "+x" if it's executable.
> +Mode changes are shown "M+x" or "M-x" for adding or removing

"Mode changes are shown as" is better worded.

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

* Re: [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-18 10:05 ` [PATCH v2] " Nguyễn Thái Ngọc Duy
  2018-01-18 18:57   ` Eric Sunshine
  2018-01-18 21:23   ` Ævar Arnfjörð Bjarmason
@ 2018-01-18 22:48   ` Jeff King
  2018-01-19  0:26     ` Duy Nguyen
  2018-01-19 21:20   ` Junio C Hamano
  3 siblings, 1 reply; 14+ messages in thread
From: Jeff King @ 2018-01-18 22:48 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

On Thu, Jan 18, 2018 at 05:05:46PM +0700, Nguyễn Thái Ngọc Duy wrote:

> This is partly inspired by gerrit web interface which shows diffstat
> like this, e.g. with commit 0433d533f1 (notice the "A" column on the
> third line):
> 
>      Documentation/merge-config.txt     |  4 +
>      builtin/merge.c                    |  2 +
>    A t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++
>      t/t7612-merge-verify-signatures.sh | 45 ++++++++++
>    4 files changed, 132 insertions(+)

I like the general concept. Perusing "git log" output, though, it felt
like the summary column was very close to the filenames. What do you
think of putting it after the "|", where it is only close to a number?

Something like the patch below (on top of yours, but it probably needs
tweaked further for graph_width), which gives:

   t/t5573-pull-verify-signatures.sh | A+x  78 ++++++++++++++++++++++++++++

(I know this is a bikeshed, so I'm perfectly willing to take "yuck, I
don't like that as well" as a response).

> The new option --compact-summary implements this with a tweak to support
> mode change, which is shown in --summary too.

One thing I noticed is that --compact-summary by itself does nothing.
Should it imply --stat?

-Peff

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

* Re: [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-18 18:57   ` Eric Sunshine
@ 2018-01-19  0:01     ` Duy Nguyen
  0 siblings, 0 replies; 14+ messages in thread
From: Duy Nguyen @ 2018-01-19  0:01 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: Git List

On Fri, Jan 19, 2018 at 1:57 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:
>> diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
>> @@ -188,6 +188,17 @@ and accumulating child directory counts in the parent directories:
>> +--compact-summary::
>> +       Output a condensed summary of extended header information in
>> +       front of the file name part of diffstat. This option is
>> +       ignored if --stat is not specified.
>
> Rather than ignoring this option if --stat is not specified, a
> different approach would be for --compact-summary to imply --stat.
>
> Also, per documentation:
>
>     --stat[=<width>[,<name-width>[,<count>]]]::
>
>     These parameters can also be set individually with `--stat-width=<width>`,
>     `--stat-name-width=<name-width>` and `--stat-count=<count>`.
>
> One wonders if "compact" could be another modifier recognized by --stat.
>
> (Genuine questions/observations; I haven't formed strong opinions either way.)

I left open an option to combine this with other --*stat like numstat
(or unlikely, dirstat). I haven't really thought about this. Yeah
perhaps putting this in --stat would be a better move.
--
Duy

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

* Re: [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-18 21:23   ` Ævar Arnfjörð Bjarmason
@ 2018-01-19  0:06     ` Duy Nguyen
  0 siblings, 0 replies; 14+ messages in thread
From: Duy Nguyen @ 2018-01-19  0:06 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: Git Mailing List

On Fri, Jan 19, 2018 at 4:23 AM, Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
> Wait, isn't there a bug here in the existing --summary code, its
> documentation says it'll show information "such as creations, renames
> and mode changes".
>
> But even though your --compact-summary shows that the file is being
> added and its mode changed:
>
>     $ diff -ru <(./git-show --stat 0433d533f1) <(./git-show --stat --compact-summary 0433d533f1)
>     --- /dev/fd/63  2018-01-18 21:11:51.186570555 +0000
>     +++ /dev/fd/62  2018-01-18 21:11:51.186570555 +0000
>     @@ -14,8 +14,8 @@
>            t: add tests for pull --verify-signatures
>            merge: add config option for verifySignatures
>
>     - Documentation/merge-config.txt     |  4 ++
>     - builtin/merge.c                    |  2 +
>     - t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++++++++++++++++++++++
>     - t/t7612-merge-verify-signatures.sh | 45 +++++++++++++++++++++
>     +     Documentation/merge-config.txt     |  4 ++
>     +     builtin/merge.c                    |  2 +
>     + A+x t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++++++++++++++++++
>     +     t/t7612-merge-verify-signatures.sh | 45 +++++++++++++++++++
>       4 files changed, 132 insertions(+)
>
> There is no difference between --stat with and without --summary on the
> same commit, shouldn't it show "create mode [...]" ?
>
> E.g. 95450bbbaa will do the trick for both:
>
>     $ diff -ru <(./git-show --stat 95450bbbaa) <(./git-show --stat --summary 95450bbbaa)
>     --- /dev/fd/63  2018-01-18 21:14:20.770050599 +0000
>     +++ /dev/fd/62  2018-01-18 21:14:20.770050599 +0000
>     @@ -14,3 +14,4 @@
>       git-svn.perl                    |  1 +
>       t/t9169-git-svn-dcommit-crlf.sh | 27 +++++++++++++++++++++++++++
>       2 files changed, 28 insertions(+)
>     + create mode 100755 t/t9169-git-svn-dcommit-crlf.sh
>
>     $ diff -ru <(./git-show --stat --summary 95450bbbaa) <(./git-show --stat --compact-summary 95450bbbaa)
>     --- /dev/fd/63  2018-01-18 21:14:30.646016210 +0000
>     +++ /dev/fd/62  2018-01-18 21:14:30.646016210 +0000
>     @@ -11,7 +11,6 @@
>          Reported-by: Brian Bennett <Brian.Bennett@Transamerica.com>
>          Signed-off-by: Eric Wong <e@80x24.org>
>
>     - git-svn.perl                    |  1 +
>     - t/t9169-git-svn-dcommit-crlf.sh | 27 +++++++++++++++++++++++++++
>     +     git-svn.perl                    |  1 +
>     + A+x t/t9169-git-svn-dcommit-crlf.sh | 27 +++++++++++++++++++++++++++
>       2 files changed, 28 insertions(+)
>     - create mode 100755 t/t9169-git-svn-dcommit-crlf.sh

Interesting. 0433d533f1 is a merge commit, perhaps that has something
to do with this. Adding --first-parent does show "create mode" line.
I'll check this later.
-- 
Duy

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

* Re: [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-18 22:48   ` Jeff King
@ 2018-01-19  0:26     ` Duy Nguyen
  2018-01-19 21:52       ` Jeff King
  0 siblings, 1 reply; 14+ messages in thread
From: Duy Nguyen @ 2018-01-19  0:26 UTC (permalink / raw)
  To: Jeff King; +Cc: Git Mailing List

On Fri, Jan 19, 2018 at 5:48 AM, Jeff King <peff@peff.net> wrote:
> On Thu, Jan 18, 2018 at 05:05:46PM +0700, Nguyễn Thái Ngọc Duy wrote:
>
>> This is partly inspired by gerrit web interface which shows diffstat
>> like this, e.g. with commit 0433d533f1 (notice the "A" column on the
>> third line):
>>
>>      Documentation/merge-config.txt     |  4 +
>>      builtin/merge.c                    |  2 +
>>    A t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++
>>      t/t7612-merge-verify-signatures.sh | 45 ++++++++++
>>    4 files changed, 132 insertions(+)
>
> I like the general concept. Perusing "git log" output, though, it felt
> like the summary column was very close to the filenames. What do you
> think of putting it after the "|", where it is only close to a number?
>
> Something like the patch below (on top of yours, but it probably needs
> tweaked further for graph_width), which gives:
>
>    t/t5573-pull-verify-signatures.sh | A+x  78 ++++++++++++++++++++++++++++
>
> (I know this is a bikeshed, so I'm perfectly willing to take "yuck, I
> don't like that as well" as a response).

The position of A+x column is exactly where gerrit put it. Though web
pages have more flexibility than our terminal console so its position
does not have to be the same. I'm just throwing options out there

For many years I have this instead

 t/t5573-pull-verify-signatures.sh (new +x) | 81 ++++++++++++++++++++

Another option is just wrap the code in [] to make it look like check
boxes. But that wastes two more columns

       builtin/merge.c                    |  2 +
 [A+x] t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++++++++
       t/t7612-merge-verify-signatures.sh | 45 +++++++++++++

Back to your suggestion, I kinda like the closeness between the +/-
count and "|" though. The output on 10c78a162f is like this, which
makes "A" looks a bit umm.. disconnected from the path name?

  Documentation/RelNotes/2.14.0.txt | A  97 +++++++++++++++++++++++++++
  GIT-VERSION-GEN                   |     2 +-
  RelNotes                          |     2 +-

Another way is just separate the status code from file name

 A | Documentation/RelNotes/2.14.0.txt | 97 +++++++++++++++++++++++++++
   | GIT-VERSION-GEN                   |  2 +-
   | RelNotes                          |  2 +-

Last note. With colored diffstat, we should be able to use a separate
color (or something in the +/- part) to denote new/deleted files. I
didn't think about this...

>> The new option --compact-summary implements this with a tweak to support
>> mode change, which is shown in --summary too.
>
> One thing I noticed is that --compact-summary by itself does nothing.
> Should it imply --stat?

It might go with --numstat or --dirstat in future too. Didn't really
think hard about this yet. But I probably will go with Eric suggestion
and keep this in --stat=.... unless it really makes sense to have
something like this in --numstat or --dirstat.
-- 
Duy

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

* Re: [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-18 10:05 ` [PATCH v2] " Nguyễn Thái Ngọc Duy
                     ` (2 preceding siblings ...)
  2018-01-18 22:48   ` Jeff King
@ 2018-01-19 21:20   ` Junio C Hamano
  2018-01-19 21:53     ` Jeff King
  3 siblings, 1 reply; 14+ messages in thread
From: Junio C Hamano @ 2018-01-19 21:20 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

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

>      Documentation/merge-config.txt     |  4 +
>      builtin/merge.c                    |  2 +
>    A t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++
>      t/t7612-merge-verify-signatures.sh | 45 ++++++++++
>    4 files changed, 132 insertions(+)
> ...
> With this tweak, the actual printout is like this
>
>      Documentation/merge-config.txt     |  4 ++
>      builtin/merge.c                    |  2 +
>  A+x t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++++++++
>      t/t7612-merge-verify-signatures.sh | 45 +++++++++++++
>  4 files changed, 132 insertions(+)

I like the concept but given that additions and mode changes are
rare events, I am not so sure if it is worth always wasting three
columns like the above.  Assuming that this is solely meant for
human consumption and machine parsability is of no concern, I
actually prefer the output format you said you've been using your
personal fork, e.g.

 Documentation/merge-config.txt              |  4 ++
 builtin/merge.c                             |  2 +
 t/t5573-pull-verify-signatures.sh (new, +x) | 81 ++++++++++++++++++++++++
 t/t7612-merge-verify-signatures.sh          | 45 +++++++++++++

That is

 (1) do not change the starting column at the leftmost end, and
 (2) do not permanently allocate the columns for "compact" summary.

Instead, the above may be (a) just stealing the columns needed for
"(new, +x)" from the pathname portion of the output, and/or (2)
widening the pathname portion of the output for the whole thing
while doing so.


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

* Re: [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-19  0:26     ` Duy Nguyen
@ 2018-01-19 21:52       ` Jeff King
  0 siblings, 0 replies; 14+ messages in thread
From: Jeff King @ 2018-01-19 21:52 UTC (permalink / raw)
  To: Duy Nguyen; +Cc: Git Mailing List

On Fri, Jan 19, 2018 at 07:26:28AM +0700, Duy Nguyen wrote:

> > (I know this is a bikeshed, so I'm perfectly willing to take "yuck, I
> > don't like that as well" as a response).
> 
> The position of A+x column is exactly where gerrit put it. Though web
> pages have more flexibility than our terminal console so its position
> does not have to be the same. I'm just throwing options out there
> 
> For many years I have this instead
> 
>  t/t5573-pull-verify-signatures.sh (new +x) | 81 ++++++++++++++++++++
> 
> Another option is just wrap the code in [] to make it look like check
> boxes. But that wastes two more columns
> 
>        builtin/merge.c                    |  2 +
>  [A+x] t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++++++++
>        t/t7612-merge-verify-signatures.sh | 45 +++++++++++++

Yeah, I almost suggested brackets, but wasn't sure if people would balk
at the extra 2 columns. But they do help it stand out more. Colors would
help, too, as you noted. Though they would not transfer over email, and
I wonder if people would want to use this for format-patch.

> Back to your suggestion, I kinda like the closeness between the +/-
> count and "|" though. The output on 10c78a162f is like this, which
> makes "A" looks a bit umm.. disconnected from the path name?
> 
>   Documentation/RelNotes/2.14.0.txt | A  97 +++++++++++++++++++++++++++
>   GIT-VERSION-GEN                   |     2 +-
>   RelNotes                          |     2 +-

Yeah, I was trying to get it away from the pathname, since it doesn't
stand out as much. I guess it depends how you think of the "A". To me it
is sensible as a modifier for the line-count change. I.e., My read on
the output above is "here is a path; it was added with 97 lines".

> > One thing I noticed is that --compact-summary by itself does nothing.
> > Should it imply --stat?
> 
> It might go with --numstat or --dirstat in future too. Didn't really
> think hard about this yet. But I probably will go with Eric suggestion
> and keep this in --stat=.... unless it really makes sense to have
> something like this in --numstat or --dirstat.

I'd think that most consumers of --numstat are not human, and would
just use "--numstat --raw" to get all the information. But I also have
not thought hard about it.

Anyway, thanks for listening. :)

-Peff

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

* Re: [PATCH v2] diff: add --compact-summary option to complement --stat
  2018-01-19 21:20   ` Junio C Hamano
@ 2018-01-19 21:53     ` Jeff King
  0 siblings, 0 replies; 14+ messages in thread
From: Jeff King @ 2018-01-19 21:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy, git

On Fri, Jan 19, 2018 at 01:20:41PM -0800, Junio C Hamano wrote:

> >      Documentation/merge-config.txt     |  4 ++
> >      builtin/merge.c                    |  2 +
> >  A+x t/t5573-pull-verify-signatures.sh  | 81 ++++++++++++++++++++++++
> >      t/t7612-merge-verify-signatures.sh | 45 +++++++++++++
> >  4 files changed, 132 insertions(+)
> 
> I like the concept but given that additions and mode changes are
> rare events, I am not so sure if it is worth always wasting three
> columns like the above.  Assuming that this is solely meant for
> human consumption and machine parsability is of no concern, I
> actually prefer the output format you said you've been using your
> personal fork, e.g.
> 
>  Documentation/merge-config.txt              |  4 ++
>  builtin/merge.c                             |  2 +
>  t/t5573-pull-verify-signatures.sh (new, +x) | 81 ++++++++++++++++++++++++
>  t/t7612-merge-verify-signatures.sh          | 45 +++++++++++++
> 
> That is
> 
>  (1) do not change the starting column at the leftmost end, and
>  (2) do not permanently allocate the columns for "compact" summary.

I think the patch already does (2). In fact, it computes the max
compact-status size (so if you only have "A" and not "A+x", it wastes
only the one column).

I agree that (1) would save space in some cases, though IMHO it's a
little hard to notice.

-Peff

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

end of thread, back to index

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-13 13:22 [PATCH/RFC] diff: add --compact-summary option to complement --stat Nguyễn Thái Ngọc Duy
2018-01-13 18:37 ` Philip Oakley
2018-01-14  9:37 ` Simon Ruderich
2018-01-14 10:24   ` Duy Nguyen
2018-01-18 10:05 ` [PATCH v2] " Nguyễn Thái Ngọc Duy
2018-01-18 18:57   ` Eric Sunshine
2018-01-19  0:01     ` Duy Nguyen
2018-01-18 21:23   ` Ævar Arnfjörð Bjarmason
2018-01-19  0:06     ` Duy Nguyen
2018-01-18 22:48   ` Jeff King
2018-01-19  0:26     ` Duy Nguyen
2018-01-19 21:52       ` Jeff King
2018-01-19 21:20   ` Junio C Hamano
2018-01-19 21:53     ` Jeff King

git@vger.kernel.org mailing list mirror (one of many)

Archives are clonable:
	git clone --mirror https://public-inbox.org/git
	git clone --mirror http://ou63pmih66umazou.onion/git
	git clone --mirror http://czquwvybam4bgbro.onion/git
	git clone --mirror http://hjrcffqmbrq6wope.onion/git

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.version-control.git
	nntp://ou63pmih66umazou.onion/inbox.comp.version-control.git
	nntp://czquwvybam4bgbro.onion/inbox.comp.version-control.git
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.version-control.git
	nntp://news.gmane.org/gmane.comp.version-control.git

 note: .onion URLs require Tor: https://www.torproject.org/
       or Tor2web: https://www.tor2web.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox