threads / patch / 13050

v2, 3 partsgit-submodule summary: --for-status option

Subject: [PATCH v2 1/3] git-submodule summary: --for-status option

## tl;dr

8 messages between Apr 10, 2008 and Apr 12, 2008. Diffs are folded; open one to read it.

replies: 7people: 3as markdown or json

Ping Yin· Apr 10, 2008, 15:35 UTC · re: Ping Yin · lore

The --for-status option is mainly used by builtin-status/commit. It adds 'Modified submodules:' line at top and '# ' prefix to all following lines.

Signed-off-by: Ping Yin <pkufranky@gmail.com>
---
 git-submodule.sh             |   17 ++++++++++++++++-
 t/t7401-submodule-summary.sh |   13 +++++++++++++
 2 files changed, 29 insertions(+), 1 deletions(-)
Show changes to 2 files +29 −1

git-submodule.sh, t/t7401-submodule-summary.sh

diff --git a/git-submodule.sh b/git-submodule.sh
index 56ec353..d7937a5 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -342,6 +342,7 @@ set_name_rev () {
 #
 cmd_summary() {
 	summary_limit=-1
+	for_status=
 
 	# parse $args after "submodule ... summary".
 	while test $# -ne 0
@@ -350,6 +351,9 @@ cmd_summary() {
 		--cached)
 			cached="$1"
 			;;
+		--for-status)
+			for_status="$1"
+			;;
 		-n|--summary-limit)
 			if summary_limit=$(($2 + 0)) 2>/dev/null && test "$summary_limit" = "$2"
 			then
@@ -398,6 +402,12 @@ cmd_summary() {
 	)
 
 	test -n "$modules" &&
+	if test -n "$for_status"; then
+		echo "# Modified submodules:"
+		echo "#"
+	else
+		true
+	fi &&
 	git diff-index $cached --raw $head -- $modules |
 	grep -e '^:160000' -e '^:[0-7]* 160000' |
 	cut -c2- |
@@ -499,7 +509,12 @@ cmd_summary() {
 			echo
 		fi
 		echo
-	done
+	done |
+	if test -n "$for_status"; then
+		sed -e "s|^|# |" -e 's|^# $|#|'
+	else
+		cat
+	fi
 }
 #
 # List all submodules, prefixed with:
diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index 0f3c42a..1dbb39d 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -192,4 +192,17 @@ test_expect_success 'given commit' "
 EOF
 "
 
+test_expect_success '--for-status' "
+    git submodule summary --for-status HEAD^ >actual &&
+    diff actual - <<-EOF
+# Modified submodules:
+#
+# * sm1 $head6...0000000:
+#
+# * sm2 0000000...$head7 (2):
+#   > Add foo9
+#
+EOF
+"
+
 test_done
-- 
1.5.5.23.g2a5f
Ping Yin· Apr 10, 2008, 15:35 UTC · re: Ping Yin · lore

[PATCH v2 2/3] builtin-status: submodule summary support

This commit teaches 'git commit/status' show 'Modified submodules' section given by

git submodule summary --cached --for-status --summary-limit <limit>
just before 'Untracked files' section.

The <limit> is given by the config variable status.submodulesummary to limit the submodule summary size. status.submodulesummary is 0 by default which disables the summary.

Also mention status.submodulesummary in the documentation.
Signed-off-by: Ping Yin <pkufranky@gmail.com>
---
 Documentation/git-status.txt |    4 ++++
 wt-status.c                  |   39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 0 deletions(-)
Show changes to 2 files +43 −0

Documentation/git-status.txt, wt-status.c

diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index 3ea269a..32b6660 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -52,6 +52,10 @@ If the config variable `status.relativePaths` is set to false, then all
 paths shown are relative to the repository root, not to the current
 directory.
 
+If 'status.submodulesummary' is set to a non zero number, the submodule
+summary will be enabled and a summary of commits for modified submodules
+will be shown (see --summary-limit option of linkgit:git-submodule[1]).
+
 See Also
 --------
 linkgit:gitignore[5]
diff --git a/wt-status.c b/wt-status.c
index b3fd57b..369c519 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -8,9 +8,11 @@
 #include "revision.h"
 #include "diffcore.h"
 #include "quote.h"
+#include "run-command.h"
 
 int wt_status_relative_paths = 1;
 int wt_status_use_color = -1;
+int wt_status_submodule_summary = 0;
 static char wt_status_colors[][COLOR_MAXLEN] = {
 	"",         /* WT_STATUS_HEADER: normal */
 	"\033[32m", /* WT_STATUS_UPDATED: green */
@@ -219,6 +221,38 @@ static void wt_status_print_changed(struct wt_status *s)
 	rev.diffopt.format_callback_data = s;
 	run_diff_files(&rev, 0);
 }
+static void wt_status_print_submodule_summary(struct wt_status *s)
+{
+	struct child_process sm_summary;
+	char summary_limit[64];
+	char index[PATH_MAX];
+	const char *env[] = { index, NULL };
+	const char *argv[] = {
+		"submodule",
+		"summary",
+		"--cached",
+		"--for-status",
+		"--summary-limit",
+		summary_limit,
+		s->amend ? "HEAD^" : "HEAD",
+		NULL
+	};
+
+	if (!wt_status_submodule_summary)
+		return;
+
+	sprintf(summary_limit, "%d", wt_status_submodule_summary);
+	snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", s->index_file);
+
+	memset(&sm_summary, 0, sizeof(sm_summary));
+	sm_summary.argv = argv;
+	sm_summary.env = env;
+	sm_summary.git_cmd = 1;
+	sm_summary.no_stdin = 1;
+	fflush(s->fp);
+	sm_summary.out = dup(fileno(s->fp));    /* run_command closes it */
+	run_command(&sm_summary);
+}
 
 static void wt_status_print_untracked(struct wt_status *s)
 {
@@ -308,6 +342,7 @@ void wt_status_print(struct wt_status *s)
 	}
 
 	wt_status_print_changed(s);
+	wt_status_print_submodule_summary(s);
 	wt_status_print_untracked(s);
 
 	if (s->verbose && !s->is_initial)
@@ -330,6 +365,10 @@ void wt_status_print(struct wt_status *s)
 
 int git_status_config(const char *k, const char *v)
 {
+	if (!strcmp(k, "status.submodulesummary")) {
+		wt_status_submodule_summary = atoi(v);
+		return 0;
+	}
 	if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
 		wt_status_use_color = git_config_colorbool(k, v, -1);
 		return 0;
-- 
1.5.5.23.g2a5f
Ping Yin· Apr 10, 2008, 15:35 UTC · re: Ping Yin · lore

[PATCH v2 3/3] buitin-status: Add tests for submodule summary

Signed-off-by: Ping Yin <pkufranky@gmail.com>
---
 t/t7502-status.sh |  134 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 134 insertions(+), 0 deletions(-)
Show changes to t/t7502-status.sh +134 −0
diff --git a/t/t7502-status.sh b/t/t7502-status.sh
index cd08516..33882c9 100755
--- a/t/t7502-status.sh
+++ b/t/t7502-status.sh
@@ -149,4 +149,138 @@ test_expect_success 'status of partial commit excluding new file in index' '
 	test_cmp expect output
 '
 
+test_expect_success "setup status submodule summary" '
+	test_create_repo sm &&
+	cd sm &&
+	: >foo &&
+	git add foo &&
+	git commit -m "Add foo" &&
+	cd .. &&
+	git add sm
+'
+
+cat > expect <<EOF
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD <file>..." to unstage)
+#
+#	new file:   dir2/added
+#	new file:   sm
+#
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#	modified:   dir1/modified
+#
+# Untracked files:
+#   (use "git add <file>..." to include in what will be committed)
+#
+#	dir1/untracked
+#	dir2/modified
+#	dir2/untracked
+#	expect
+#	output
+#	untracked
+EOF
+test_expect_success "status submodule summary is disabled by default" '
+	git status > output &&
+	git diff expect output
+'
+
+head=$(cd sm && git rev-parse --short=7 --verify HEAD)
+
+cat > expect <<EOF
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD <file>..." to unstage)
+#
+#	new file:   dir2/added
+#	new file:   sm
+#
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#	modified:   dir1/modified
+#
+# Modified submodules:
+#
+# * sm 0000000...$head (1):
+#   > Add foo
+#
+# Untracked files:
+#   (use "git add <file>..." to include in what will be committed)
+#
+#	dir1/untracked
+#	dir2/modified
+#	dir2/untracked
+#	expect
+#	output
+#	untracked
+EOF
+test_expect_success "status submodule summary" '
+	git config status.submodulesummary 10 &&
+	git status > output &&
+	git diff expect output
+'
+
+
+cat > expect <<EOF
+# On branch master
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#	modified:   dir1/modified
+#
+# Untracked files:
+#   (use "git add <file>..." to include in what will be committed)
+#
+#	dir1/untracked
+#	dir2/modified
+#	dir2/untracked
+#	expect
+#	output
+#	untracked
+no changes added to commit (use "git add" and/or "git commit -a")
+EOF
+test_expect_success "status submodule summary (clean submodule)" '
+	git commit -m "commit submodule" &&
+	git config status.submodulesummary 10 &&
+	! git status > output &&
+	git diff expect output
+'
+
+cat > expect <<EOF
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD^1 <file>..." to unstage)
+#
+#	new file:   dir2/added
+#	new file:   sm
+#
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#	modified:   dir1/modified
+#
+# Modified submodules:
+#
+# * sm 0000000...$head (1):
+#   > Add foo
+#
+# Untracked files:
+#   (use "git add <file>..." to include in what will be committed)
+#
+#	dir1/untracked
+#	dir2/modified
+#	dir2/untracked
+#	expect
+#	output
+#	untracked
+EOF
+test_expect_success "status submodule summary (--amend)" '
+	git config status.submodulesummary 10 &&
+	git status --amend > output &&
+	git diff expect output
+'
+
 test_done
-- 
1.5.5.23.g2a5f
Junio C Hamano· Apr 11, 2008, 22:31 UTC · re: Ping Yin · lore

Re: [PATCH v2 2/3] builtin-status: submodule summary support

Ping Yin <pkufranky@gmail.com> writes:
Show 10 quoted lines
> This commit teaches 'git commit/status' show 'Modified submodules'
> section given by
>
> git submodule summary --cached --for-status --summary-limit <limit>
>
> just before 'Untracked files' section.
>
> The <limit> is given by the config variable status.submodulesummary
> to limit the submodule summary size. status.submodulesummary is 0 by
> default which disables the summary.

This begs an obvious question "What if I want to have an unlimited summary in the status output?"

Show 12 quoted lines
> diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
> index 3ea269a..32b6660 100644
> --- a/Documentation/git-status.txt
> +++ b/Documentation/git-status.txt
> @@ -52,6 +52,10 @@ If the config variable `status.relativePaths` is set to false, then all
>  paths shown are relative to the repository root, not to the current
>  directory.
>  
> +If 'status.submodulesummary' is set to a non zero number, the submodule
> +summary will be enabled and a summary of commits for modified submodules
> +will be shown (see --summary-limit option of linkgit:git-submodule[1]).
> +

The docs quote configuration variables in typewriter face by using backticks (pay attention to how status.relativePaths is quoted in your hunk header comment).

Show 13 quoted lines
> diff --git a/wt-status.c b/wt-status.c
> index b3fd57b..369c519 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -8,9 +8,11 @@
>  #include "revision.h"
>  #include "diffcore.h"
>  #include "quote.h"
> +#include "run-command.h"
>  
>  int wt_status_relative_paths = 1;
>  int wt_status_use_color = -1;
> +int wt_status_submodule_summary = 0;
Don't initialize to 0.  BSS takes care of it.
Show 18 quoted lines
>  static char wt_status_colors[][COLOR_MAXLEN] = {
>  	"",         /* WT_STATUS_HEADER: normal */
>  	"\033[32m", /* WT_STATUS_UPDATED: green */
> @@ -219,6 +221,38 @@ static void wt_status_print_changed(struct wt_status *s)
>  	rev.diffopt.format_callback_data = s;
>  	run_diff_files(&rev, 0);
>  }
> +static void wt_status_print_submodule_summary(struct wt_status *s)
> +{
> ...
> +	memset(&sm_summary, 0, sizeof(sm_summary));
> +	sm_summary.argv = argv;
> +	sm_summary.env = env;
> +	sm_summary.git_cmd = 1;
> +	sm_summary.no_stdin = 1;
> +	fflush(s->fp);
> +	sm_summary.out = dup(fileno(s->fp));    /* run_command closes it */
> +	run_command(&sm_summary);

I recall we had some clean-up on how file descriptors are inherited and duped around when run_command() runs a subprocess. Hannes, is this dup() consistent with how the things ought to be these days?

Show 6 quoted lines
> @@ -330,6 +365,10 @@ void wt_status_print(struct wt_status *s)
>  
>  int git_status_config(const char *k, const char *v)
>  {
> +	if (!strcmp(k, "status.submodulesummary")) {
> +		wt_status_submodule_summary = atoi(v);
With this code, you would feed a NULL to atoi() with:
        [status]
                submoduleSummary

How about making this a bool-or-number, and boolean true gives whatever the default limit (may be unlimited) when no --summary-limit is given?

We may want to have git_config_bool_or_int() in config.c so that the caller can tell if the value is boolean true or integer 1, which would be a reasonable improvement independent from this submodule summary codepath.

int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
{
        *is_bool = 1;
	if (!value)
		return 1;
	if (!*value)
		return 0;
	if (!strcasecmp(value, "true") || !strcasecmp(value, "yes"))
		return 1;
	if (!strcasecmp(value, "false") || !strcasecmp(value, "no"))
		return 0;
	*is_bool = 0;
	return git_config_int(name, value) != 0;
}
With that, your configuration parser can do something like:
	if (!strcmp(k, "status.submodulesummary")) {
		int is_bool, val;
		val = git_config_bool_or_int(k, v, &b);
		if (is_bool || val <= 0) {
                	wt_status_submodule_summary_enabled = val;
		} else {
                	wt_status_submodule_summary = val;
                	wt_status_submodule_summary_enabled = 1;
		}
	}

and skip the call to wt_status_print_submodule_summary() when not enabled.

>  int wt_status_relative_paths = 1;
>  int wt_status_use_color = -1;
> +int wt_status_submodule_summary = -1; /* unspecified */
  +int wt_status_submodule_summary_enabled;
The call site in wt_status_print() would look like: 
	...
 	wt_status_print_changed(s);
	if (wt_status_submodule_summary_enabled > 0)
		wt_status_print_submodule_summary(s);
 	wt_status_print_untracked(s);
	...

and the wt_status_print_submodule_summary() would not add --summary-limit parameter if wt_status_submodule_summary is left unspecified (i.e. -1).

Ping Yin· Apr 12, 2008, 05:28 UTC · re: Junio C Hamano · lore

Re: [PATCH v2 2/3] builtin-status: submodule summary support

On Sat, Apr 12, 2008 at 6:31 AM, Junio C Hamano <junio@pobox.com> wrote:
Show 49 quoted lines
>  int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
>  {
>         *is_bool = 1;
>         if (!value)
>                 return 1;
>         if (!*value)
>                 return 0;
>         if (!strcasecmp(value, "true") || !strcasecmp(value, "yes"))
>                 return 1;
>         if (!strcasecmp(value, "false") || !strcasecmp(value, "no"))
>                 return 0;
>         *is_bool = 0;
>         return git_config_int(name, value) != 0;
>  }
>
>  With that, your configuration parser can do something like:
>
>
>         if (!strcmp(k, "status.submodulesummary")) {
>                 int is_bool, val;
>                 val = git_config_bool_or_int(k, v, &b);
>                 if (is_bool || val <= 0) {
>                         wt_status_submodule_summary_enabled = val;
>                 } else {
>                         wt_status_submodule_summary = val;
>                         wt_status_submodule_summary_enabled = 1;
>                 }
>         }
>
>  and skip the call to wt_status_print_submodule_summary() when not
>  enabled.
>
>
>  >  int wt_status_relative_paths = 1;
>  >  int wt_status_use_color = -1;
>  > +int wt_status_submodule_summary = -1; /* unspecified */
>   +int wt_status_submodule_summary_enabled;
>
>  The call site in wt_status_print() would look like:
>
>         ...
>
>         wt_status_print_changed(s);
>         if (wt_status_submodule_summary_enabled > 0)
>
>                 wt_status_print_submodule_summary(s);
>         wt_status_print_untracked(s);
>         ...
>
How about the following?
Show changes to 2 files +19 −1

config.c, wt-status.c

diff --git a/config.c b/config.c
index 0624494..e614456 100644
--- a/config.c
+++ b/config.c
@@ -316,6 +316,21 @@ int git_config_bool(const char *name, const char *value)
 	return git_config_int(name, value) != 0;
 }

+int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
+{
+	*is_bool = 1;
+	if (!value)
+		return 1;
+	if (!*value)
+		return 0;
+	if (!strcasecmp(value, "true") || !strcasecmp(value, "yes"))
+		return 1;
+	if (!strcasecmp(value, "false") || !strcasecmp(value, "no"))
+		return 0;
+	*is_bool = 0;
+	return git_config_int(name, value);
+}
+
 int git_config_string(const char **dest, const char *var, const char *value)
 {
 	if (!value)
diff --git a/wt-status.c b/wt-status.c
index 22385f5..3baa128 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -366,7 +366,10 @@ void wt_status_print(struct wt_status *s)
 int git_status_config(const char *k, const char *v)
 {
 	if (!strcmp(k, "status.submodulesummary")) {
-		wt_status_submodule_summary = atoi(v);
+		int is_bool;
+		wt_status_submodule_summary = git_config_bool_or_int(k, v, &is_bool);
+		if (is_bool && wt_status_submodule_summary)
+			wt_status_submodule_summary = -1;
 		return 0;
 	}
 	if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
-- 
Ping Yin
Ping Yin· Apr 12, 2008, 14:47 UTC · re: Junio C Hamano · lore

Re: [PATCH v2 2/3] builtin-status: submodule summary support

On Sat, Apr 12, 2008 at 6:31 AM, Junio C Hamano <junio@pobox.com> wrote:
Show 16 quoted lines
>  > +static void wt_status_print_submodule_summary(struct wt_status *s)
>  > +{
>  > ...
>
> > +     memset(&sm_summary, 0, sizeof(sm_summary));
>  > +     sm_summary.argv = argv;
>  > +     sm_summary.env = env;
>  > +     sm_summary.git_cmd = 1;
>  > +     sm_summary.no_stdin = 1;
>  > +     fflush(s->fp);
>  > +     sm_summary.out = dup(fileno(s->fp));    /* run_command closes it */
>  > +     run_command(&sm_summary);
>
>  I recall we had some clean-up on how file descriptors are inherited and
>  duped around when run_command() runs a subprocess.  Hannes, is this dup()
>  consistent with how the things ought to be these days?

I think dup is needed, as commit c20181e3a3 says, run_command still will close passed in positive descripors.

    start_command(), if .in/.out > 0, closes file descriptors, not the callers
    Callers of start_command() can set the members .in and .out of struct
    child_process to a value > 0 to specify that this descriptor is used as
    the stdin or stdout of the child process.
    Previously, if start_command() was successful, this descriptor was closed
    upon return. Here we now make sure that the descriptor is also closed in
    case of failures. All callers are updated not to close the file descriptor
    themselves after start_command() was called.
-- 
Ping Yin
Johannes Sixt· Apr 12, 2008, 16:13 UTC · re: Junio C Hamano · lore

Re: [PATCH v2 2/3] builtin-status: submodule summary support

On Saturday 12 April 2008 00:31, Junio C Hamano wrote:
Show 16 quoted lines
> Ping Yin <pkufranky@gmail.com> writes:
> > +static void wt_status_print_submodule_summary(struct wt_status *s)
> > +{
> > ...
> > +	memset(&sm_summary, 0, sizeof(sm_summary));
> > +	sm_summary.argv = argv;
> > +	sm_summary.env = env;
> > +	sm_summary.git_cmd = 1;
> > +	sm_summary.no_stdin = 1;
> > +	fflush(s->fp);
> > +	sm_summary.out = dup(fileno(s->fp));    /* run_command closes it */
> > +	run_command(&sm_summary);
>
> I recall we had some clean-up on how file descriptors are inherited and
> duped around when run_command() runs a subprocess.  Hannes, is this dup()
> consistent with how the things ought to be these days?
Yes, this dup() is required and correct.
-- Hannes

← back to recent threads