git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH/RFC] t7512-status-warnings.sh : better advices for git status
@ 2012-05-24  9:37 Kong Lucien
  2012-05-24 17:31 ` Matthieu Moy
  2012-05-26 12:38 ` [PATCHv2 1/2] wt-status: " Kong Lucien
  0 siblings, 2 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-24  9:37 UTC (permalink / raw)
  To: git; +Cc: Matthieu.Moy, Kong Lucien

Tests for the display of 'git status' before and after a conflict
resolved, and after a conflict warning during a rebase.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
---
The three following tests are supposed to be successful
but are not currently as we are not sure about the implementation.
For example, should the warning messages be in the top header of 'git status' or after that ?
If the warning messages are put as in the following tests,
we will have to code the messages in remote.c, and not in wt-status.c.

We are also working on the same kind of messages for git am and bisect.

 git/t/t7512-status-warnings.sh |   96 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 96 insertions(+), 0 deletions(-)
 create mode 100755 git/t/t7512-status-warnings.sh

diff --git a/git/t/t7512-status-warnings.sh b/git/t/t7512-status-warnings.sh
new file mode 100755
index 0000000..0214348
--- /dev/null
+++ b/git/t/t7512-status-warnings.sh
@@ -0,0 +1,96 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+test_expect_success 'status when conflicts unresolved' '
+	git init --shared --bare conflict_test.git &&
+	git clone conflict_test.git test1 &&
+	git clone conflict_test.git test2 &&
+	cd ./test1 &&
+	test_commit A main.txt toto &&
+	cd ../test2 &&
+	test_commit B main.txt tata &&
+	git push --all &&
+	cd ../test1 &&
+	test_must_fail git pull &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# Your branch and '\''origin/master'\'' have diverged,
+	# and have 1 and 1 different commit each, respectively.
+	# You have unmerged paths : fix conflicts and then commit the result.
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both added:         main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	echo toto > main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# Your branch and '\''origin/master'\'' have diverged,
+	# and have 1 and 1 different commit each, respectively.
+	# You are still merging, commit to end merge.
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+
+test_expect_success 'status when rebase in progress' '
+	git commit -m "one" &&
+	test_commit two main.txt tata &&
+	test_commit three main.txt titi &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing : fix conflicts and then run "git rebase -- continue".
+	# If you would prefer to skip this patch, instead run "git rebase --skip".
+	# To check out  the original branch and stop rebasing run "git rebase --abort".
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+test_done
-- 
1.7.8

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

* Re: [PATCH/RFC] t7512-status-warnings.sh : better advices for git status
  2012-05-24  9:37 [PATCH/RFC] t7512-status-warnings.sh : better advices for git status Kong Lucien
@ 2012-05-24 17:31 ` Matthieu Moy
  2012-05-26 12:38 ` [PATCHv2 1/2] wt-status: " Kong Lucien
  1 sibling, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-05-24 17:31 UTC (permalink / raw)
  To: Kong Lucien; +Cc: git

(We met off-list and already did a few fixes, but here are a few more)

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> +test_expect_success 'status when conflicts unresolved' '
> +	git init --shared --bare conflict_test.git &&
> +	git clone conflict_test.git test1 &&
> +	git clone conflict_test.git test2 &&

You don't need to clone to get conflicts. Just create local branches and
use "git merge".

> +test_expect_success 'status when conflicts resolved before commit' '
> +	echo toto > main.txt &&

"toto" would usually be "foo" in english ;-).

We usually write >main, not > main.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* [PATCHv2 1/2] wt-status: better advices for git status
  2012-05-24  9:37 [PATCH/RFC] t7512-status-warnings.sh : better advices for git status Kong Lucien
  2012-05-24 17:31 ` Matthieu Moy
@ 2012-05-26 12:38 ` Kong Lucien
  2012-05-26 12:38   ` [PATCHv2 2/2] t7512-status-warnings.sh: " Kong Lucien
                     ` (4 more replies)
  1 sibling, 5 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-26 12:38 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

This patch provides more information about your current state after a git status command (in the cases of conflicts, before and after they are resolved, a rebase or a bisect process).
This would help users to know what they are currently doing, in a more accurate way.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen Lucien <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
 wt-status.c |   89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.h |    1 +
 2 files changed, 90 insertions(+), 0 deletions(-)

diff --git a/wt-status.c b/wt-status.c
index dd6d8c4..9839280 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -15,6 +15,7 @@
 
 static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
+	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
 	GIT_COLOR_GREEN,  /* WT_STATUS_UPDATED */
 	GIT_COLOR_RED,    /* WT_STATUS_CHANGED */
 	GIT_COLOR_RED,    /* WT_STATUS_UNTRACKED */
@@ -728,6 +729,92 @@ static void wt_status_print_tracking(struct wt_status *s)
 	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
 }
 
+static void wt_status_print_in_progress(struct wt_status *s)
+{
+	int i;
+	const char *c = color(WT_STATUS_IN_PROGRESS, s);
+	const char *git_dir = getenv(GIT_DIR_ENVIRONMENT);
+	const char* path;
+	int unmerged_state = 0;
+	int rebase_state = 0;
+	int rebase_interactive_state = 0;
+	int am_state = 0;
+	int bisect_state = 0;
+	int conflict = 0;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		struct string_list_item *it;
+		it = &(s->change.items[i]);
+		d = it->util;
+		if (d->stagemask) {
+			conflict = 1;
+			continue;
+		}
+	}
+
+	path = mkpath("%s/MERGE_HEAD", git_dir);
+	if (!access(path, R_OK))
+		unmerged_state = 1;
+
+	path = mkpath("%s/rebase-apply", git_dir);
+	if (!access(path, R_OK)) {
+		path = mkpath("%s/rebase-apply/applying", git_dir);
+		if (!access(path, R_OK))
+			am_state = 1;
+		else
+			rebase_state = 1;
+	}
+	else {
+		path = mkpath("%s/rebase-merge", git_dir);
+		if (!access(path, R_OK)) {
+			path = mkpath("%s/rebase-merge/interactive", git_dir);
+			if (!access(path, R_OK))
+				rebase_interactive_state = 1;
+			else
+				rebase_state = 1;
+		}
+	}
+
+	path = mkpath("%s/BISECT_LOG", git_dir);
+	if (!access(path, R_OK))
+		bisect_state = 1;
+
+	if(bisect_state) {
+		status_printf_ln(s, c, _("You are currently bisecting."));
+		status_printf_ln(s, c, _("To get back to the original branch run \"git bisect reset\""));
+		wt_status_print_trailer(s);
+	}
+
+	if(unmerged_state) {
+		if (conflict)
+			status_printf_ln(s, c, _("You have unmerged paths: fix conflicts and then commit the result."));
+		else
+			status_printf_ln(s, c, _("You are still merging, run \"git commit\" to conclude merge."));
+		wt_status_print_trailer(s);
+	}
+
+	if(rebase_state || rebase_interactive_state) {
+		if (conflict) {
+			status_printf_ln(s, c, _("You are currently rebasing: fix conflicts and then run \"git rebase -- continue\"."));
+			status_printf_ln(s, c, _("If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
+			status_printf_ln(s, c, _("To check out  the original branch and stop rebasing run \"git rebase --abort\"."));
+		}
+		else {
+			if (rebase_state)
+				status_printf_ln(s, c, _("You are currently rebasing: all conflicts fixed; run \"git rebase --continue\"."));
+			else {
+				status_printf_ln(s, c, _("You are currently editing in a rebase progress."));
+				status_printf_ln(s, c, _("You can amend the commit with"));
+				status_printf_ln(s, c, _("	git commit --amend"));
+				status_printf_ln(s, c, _("Once you are satisfied with your changes, run"));
+				status_printf_ln(s, c, _("	git rebase --continue"));
+			}
+		}
+		wt_status_print_trailer(s);
+	}
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
@@ -750,6 +837,8 @@ void wt_status_print(struct wt_status *s)
 			wt_status_print_tracking(s);
 	}
 
+	wt_status_print_in_progress(s);
+
 	if (s->is_initial) {
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7..3d86801 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -7,6 +7,7 @@
 
 enum color_wt_status {
 	WT_STATUS_HEADER = 0,
+	WT_STATUS_IN_PROGRESS,
 	WT_STATUS_UPDATED,
 	WT_STATUS_CHANGED,
 	WT_STATUS_UNTRACKED,
-- 
1.7.8

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

* [PATCHv2 2/2] t7512-status-warnings.sh: better advices for git status
  2012-05-26 12:38 ` [PATCHv2 1/2] wt-status: " Kong Lucien
@ 2012-05-26 12:38   ` Kong Lucien
  2012-05-27 12:57     ` Matthieu Moy
  2012-05-28  8:43     ` Matthieu Moy
  2012-05-26 13:01   ` [PATCHv2 1/2] wt-status: " Nguyen Thai Ngoc Duy
                     ` (3 subsequent siblings)
  4 siblings, 2 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-26 12:38 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

The following tests include several cases in which the user
needs to run 'git status' to know his current situation, whether there're
conflicts or he's in rebase/bisect/am progress.

Also, the test t7060-wtstatus.sh is now compatible with the new warning messages.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen Lucien <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
The 3 tests about 'am' are currently not successful because it's still
not implemented.

 t/t7060-wtstatus.sh        |    2 +
 t/t7512-status-warnings.sh |  280 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 282 insertions(+), 0 deletions(-)
 create mode 100755 t/t7512-status-warnings.sh

diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb490..d9a1e18 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,8 @@ test_expect_success 'Report new path with conflict' '
 
 cat >expect <<EOF
 # On branch side
+# You have unmerged paths: fix conflicts and then commit the result.
+#
 # Unmerged paths:
 #   (use "git add/rm <file>..." as appropriate to mark resolution)
 #
diff --git a/t/t7512-status-warnings.sh b/t/t7512-status-warnings.sh
new file mode 100755
index 0000000..ef3531f
--- /dev/null
+++ b/t/t7512-status-warnings.sh
@@ -0,0 +1,280 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'status when conflicts unresolved' '
+	git init --shared --bare conflict_test.git &&
+	git clone conflict_test.git test1 &&
+	git clone conflict_test.git test2 &&
+	cd ./test1 &&
+	test_commit A main.txt one &&
+	cd ../test2 &&
+	test_commit B main.txt two &&
+	git push --all &&
+	cd ../test1 &&
+	test_must_fail git pull &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# Your branch and '\''origin/master'\'' have diverged,
+	# and have 1 and 1 different commit each, respectively.
+	#
+	# You have unmerged paths: fix conflicts and then commit the result.
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both added:         main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	echo one > main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# Your branch and '\''origin/master'\'' have diverged,
+	# and have 1 and 1 different commit each, respectively.
+	#
+	# You are still merging, run "git commit" to conclude merge.
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+
+test_expect_success 'status when rebase in progress before resolving conflicts' '
+	git commit -m "one" &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing: fix conflicts and then run "git rebase -- continue".
+	# If you would prefer to skip this patch, instead run "git rebase --skip".
+	# To check out  the original branch and stop rebasing run "git rebase --abort".
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+test_expect_success 'status when rebase in progress before rebase --continue' '
+	test_when_finished "cd ../ && rm -rf test1 test2 conflict_test.git" &&
+	echo three >main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing: all conflicts fixed; run "git rebase --continue".
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when rebasing -i in edit mode' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git fake-editor.sh" &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	FAKE_LINES="1 edit 2" &&
+	export FAKE_LINES &&
+	git rebase -i HEAD~2 &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing in a rebase progress.
+	# You can amend the commit with
+	#	git commit --amend
+	# Once you are satisfied with your changes, run
+	#	git rebase --continue
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output &&
+	git rebase --abort
+'
+
+
+
+test_expect_success 'status in am progress : file already exists' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt "one  " &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently in am progress :
+	# One of the files added by the patch already exists in index !
+	# When you have resolved this problem run "git am --resolved".
+	# If you would prefer to skip this patch, instead run "git am --skip".
+	# To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+test_expect_success 'status in am progress : file does not exist' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt "one" &&
+	git rm main.txt &&
+	git commit -m "delete main.txt" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently in am progress :
+	# One of the files deleted by the patch does not exist in index !
+	# When you have resolved this problem run "git am --resolved".
+	# If you would prefer to skip this patch, instead run "git am --skip".
+	# To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+test_expect_success 'status in am progress : patch corrupted/wrong format' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one one.txt "one" &&
+	test_commit two two.txt "two" &&
+	test_commit three three.txt "three" &&
+	git format-patch -3 -oMaildir &&
+	git rm one.txt two.txt three.txt &&
+	git commit -m "delete all" &&
+	echo error >Maildir/0002-two.patch &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently in am progress :
+	# One of the patches is empty or corrupted !
+	# When you have resolved this problem run "git am --resolved".
+	# If you would prefer to skip this patch, instead run "git am --skip".
+	# To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+test_expect_success 'status when bisecting' '
+	git init git &&
+	cd git &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	git bisect start &&
+	git bisect bad &&
+	git bisect good one &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently bisecting.
+	# To get back to the original branch run "git bisect reset"
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+test_done
-- 
1.7.8

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

* Re: [PATCHv2 1/2] wt-status: better advices for git status
  2012-05-26 12:38 ` [PATCHv2 1/2] wt-status: " Kong Lucien
  2012-05-26 12:38   ` [PATCHv2 2/2] t7512-status-warnings.sh: " Kong Lucien
@ 2012-05-26 13:01   ` Nguyen Thai Ngoc Duy
  2012-05-26 17:17     ` NGUY Thomas
  2012-05-27 12:58     ` Matthieu Moy
  2012-05-27 13:10   ` Matthieu Moy
                     ` (2 subsequent siblings)
  4 siblings, 2 replies; 97+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-05-26 13:01 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Matthieu.Moy, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

On Sat, May 26, 2012 at 7:38 PM, Kong Lucien
<Lucien.Kong@ensimag.imag.fr> wrote:
> +       path = mkpath("%s/MERGE_HEAD", git_dir);

You can use git_path("MERGE_HEAD") for this, just don't save it. The
same for other call sites

> +       if(bisect_state) {
> +               status_printf_ln(s, c, _("You are currently bisecting."));
> +               status_printf_ln(s, c, _("To get back to the original branch run \"git bisect reset\""));
> +               wt_status_print_trailer(s);
> +       }
> +
> +       if(unmerged_state) {
> +               if (conflict)
> +                       status_printf_ln(s, c, _("You have unmerged paths: fix conflicts and then commit the result."));
> +               else
> +                       status_printf_ln(s, c, _("You are still merging, run \"git commit\" to conclude merge."));
> +               wt_status_print_trailer(s);
> +       }

Nice. Although git-status is sometimes too heavy I avoid it. But I
like this. I don't know, it might help if this info could be printed
alone, maybe with an option, without the actual status stuff (changed,
cached, others...).

> +       if(rebase_state || rebase_interactive_state) {
> +               if (conflict) {
> +                       status_printf_ln(s, c, _("You are currently rebasing: fix conflicts and then run \"git rebase -- continue\"."));
> +                       status_printf_ln(s, c, _("If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
> +                       status_printf_ln(s, c, _("To check out  the original branch and stop rebasing run \"git rebase --abort\"."));
> +               }
> +               else {
> +                       if (rebase_state)
> +                               status_printf_ln(s, c, _("You are currently rebasing: all conflicts fixed; run \"git rebase --continue\"."));
> +                       else {
> +                               status_printf_ln(s, c, _("You are currently editing in a rebase progress."));
> +                               status_printf_ln(s, c, _("You can amend the commit with"));
> +                               status_printf_ln(s, c, _("      git commit --amend"));
> +                               status_printf_ln(s, c, _("Once you are satisfied with your changes, run"));
> +                               status_printf_ln(s, c, _("      git rebase --continue"));
> +                       }
> +               }
> +               wt_status_print_trailer(s);
> +       }

Should this verbose advice be controlled by advice.* config keys?
Experienced users know by heart what to do and will appreciate screen
estate being used more helpful (to them) info
-- 
Duy

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

* Re: [PATCHv2 1/2] wt-status: better advices for git status
  2012-05-26 13:01   ` [PATCHv2 1/2] wt-status: " Nguyen Thai Ngoc Duy
@ 2012-05-26 17:17     ` NGUY Thomas
  2012-05-27 12:58     ` Matthieu Moy
  1 sibling, 0 replies; 97+ messages in thread
From: NGUY Thomas @ 2012-05-26 17:17 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy
  Cc: Kong Lucien, git, Matthieu.Moy, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

Le 26/05/2012 15:01, Nguyen Thai Ngoc Duy a écrit :

>> +       if(rebase_state || rebase_interactive_state) {
>> +               if (conflict) {
>> +                       status_printf_ln(s, c, _("You are currently rebasing: fix conflicts and then run \"git rebase -- continue\"."));
>> +                       status_printf_ln(s, c, _("If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
>> +                       status_printf_ln(s, c, _("To check out  the original branch and stop rebasing run \"git rebase --abort\"."));
>> +               }
>> +               else {
>> +                       if (rebase_state)
>> +                               status_printf_ln(s, c, _("You are currently rebasing: all conflicts fixed; run \"git rebase --continue\"."));
>> +                       else {
>> +                               status_printf_ln(s, c, _("You are currently editing in a rebase progress."));
>> +                               status_printf_ln(s, c, _("You can amend the commit with"));
>> +                               status_printf_ln(s, c, _("      git commit --amend"));
>> +                               status_printf_ln(s, c, _("Once you are satisfied with your changes, run"));
>> +                               status_printf_ln(s, c, _("      git rebase --continue"));
>> +                       }
>> +               }
>> +               wt_status_print_trailer(s);
>> +       }
> Should this verbose advice be controlled by advice.* config keys?
> Experienced users know by heart what to do and will appreciate screen
> estate being used more helpful (to them) info
Indeed, the advices are a bit long and could be restricted to the 
information about the
current state but the idea is also to give the user a way to know what 
to do next.
For long messages, such as the rebase case, we could actually use the 
advice_status_hints
variable to display what to do next or not.

Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>

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

* Re: [PATCHv2 2/2] t7512-status-warnings.sh: better advices for git status
  2012-05-26 12:38   ` [PATCHv2 2/2] t7512-status-warnings.sh: " Kong Lucien
@ 2012-05-27 12:57     ` Matthieu Moy
  2012-05-28  8:43     ` Matthieu Moy
  1 sibling, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-05-27 12:57 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

>  t/t7060-wtstatus.sh        |    2 +
>  t/t7512-status-warnings.sh |  280 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 282 insertions(+), 0 deletions(-)

> diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
> index b8cb490..d9a1e18 100755
> --- a/t/t7060-wtstatus.sh
> +++ b/t/t7060-wtstatus.sh
> @@ -30,6 +30,8 @@ test_expect_success 'Report new path with conflict' '
>  
>  cat >expect <<EOF
>  # On branch side
> +# You have unmerged paths: fix conflicts and then commit the result.
> +#
>  # Unmerged paths:
>  #   (use "git add/rm <file>..." as appropriate to mark resolution)
>  #

Doesn't the test fail after this if you don't modify the code at the
same time? Git's codebase should pass all tests at each commit (if only
to allow "git bisect" to run smoothly), so don't modify tests and code
in different commits. What you can do on the other hand is to introduce
new failing tests (test_expect_failure), and then mark them as success
when you update the code. Or introduce tests that show the current
behavior, and then patch the expected output when you update the code 
(the above patch hunk is a nice way to demonstrate the change introduced
by the code for example).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv2 1/2] wt-status: better advices for git status
  2012-05-26 13:01   ` [PATCHv2 1/2] wt-status: " Nguyen Thai Ngoc Duy
  2012-05-26 17:17     ` NGUY Thomas
@ 2012-05-27 12:58     ` Matthieu Moy
  1 sibling, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-05-27 12:58 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:

> Nice. Although git-status is sometimes too heavy I avoid it. But I
> like this. I don't know, it might help if this info could be printed
> alone, maybe with an option, without the actual status stuff (changed,
> cached, others...).

Once this is implemented as a "git status" addition, we may want to add
a "git status --very-short" (or find a better naming) to show only the
header of the status.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv2 1/2] wt-status: better advices for git status
  2012-05-26 12:38 ` [PATCHv2 1/2] wt-status: " Kong Lucien
  2012-05-26 12:38   ` [PATCHv2 2/2] t7512-status-warnings.sh: " Kong Lucien
  2012-05-26 13:01   ` [PATCHv2 1/2] wt-status: " Nguyen Thai Ngoc Duy
@ 2012-05-27 13:10   ` Matthieu Moy
  2012-05-28  4:57   ` Junio C Hamano
  2012-05-28 17:36   ` [PATCHv3 1/2] wt-status.*: better advices for git status added Kong Lucien
  4 siblings, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-05-27 13:10 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> +	const char *git_dir = getenv(GIT_DIR_ENVIRONMENT);

get_git_dir() would do the same more cleanly I think. And you don't
actually need it because git_path("...") does what you're doing with
mkpath already.

> +		it = &(s->change.items[i]);
> +		d = it->util;

Isn't it a complex way to say

                d = s->change.items[i].util

?

> +				status_printf_ln(s, c, _("You are currently editing in a rebase progress."));

I find the wording strange.

"You are currently editing a commit during a rebase"

?

> +	wt_status_print_in_progress(s);
> +

I think this deserves several functions (e.g. one for rebase in
progress, one for bisect, ...). The one you have is already rather long,
and may get longer when you start using the advice mechanism.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv2 1/2] wt-status: better advices for git status
  2012-05-26 12:38 ` [PATCHv2 1/2] wt-status: " Kong Lucien
                     ` (2 preceding siblings ...)
  2012-05-27 13:10   ` Matthieu Moy
@ 2012-05-28  4:57   ` Junio C Hamano
  2012-05-28  7:05     ` Matthieu Moy
  2012-05-28 10:54     ` konglu
  2012-05-28 17:36   ` [PATCHv3 1/2] wt-status.*: better advices for git status added Kong Lucien
  4 siblings, 2 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-05-28  4:57 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Matthieu.Moy, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:
Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> This patch provides more information about your current state after a git status command (in the cases of conflicts, before and after they are resolved, a rebase or a bisect process).
> This would help users to know what they are currently doing, in a more accurate way.

Please fix these overlong lines.

The description is unclear what problem it tries to solve and how,
and invites many questions.  Does it add more lines at the top?  At
the bottom?  How verbosely?  By pushing down existing information by
adding extra lines somewhere, the existing output lines may be made
harder to read, but how badly?  How does this affect "status
-s/status --porcelain" output?  What does the new code do to figure
out the "current state"?  By heuristics?  How often does the
heuristics get it wrong and in what circumstances?


> diff --git a/wt-status.c b/wt-status.c
> index dd6d8c4..9839280 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -15,6 +15,7 @@
>  
>  static char default_wt_status_colors[][COLOR_MAXLEN] = {
>  	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
> +	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
>  	GIT_COLOR_GREEN,  /* WT_STATUS_UPDATED */
>  	GIT_COLOR_RED,    /* WT_STATUS_CHANGED */
>  	GIT_COLOR_RED,    /* WT_STATUS_UNTRACKED */

Why add new stuff in the middle, not at the end?

> @@ -728,6 +729,92 @@ static void wt_status_print_tracking(struct wt_status *s)
>  	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
>  }
>  
> +static void wt_status_print_in_progress(struct wt_status *s)
> +{
> +	int i;
> +	const char *c = color(WT_STATUS_IN_PROGRESS, s);
> +	const char *git_dir = getenv(GIT_DIR_ENVIRONMENT);
> +	const char* path;

> +	int unmerged_state = 0;
> +	int rebase_state = 0;
> +	int rebase_interactive_state = 0;
> +	int am_state = 0;
> +	int bisect_state = 0;

These are not independent (you cannot be in bisect and am at the
same time).  Why five independent variables?

> +	int conflict = 0;

How is this different from "unmerged"?

> +	for (i = 0; i < s->change.nr; i++) {
> +		struct wt_status_change_data *d;
> +		struct string_list_item *it;
> +		it = &(s->change.items[i]);
> +		d = it->util;
> +		if (d->stagemask) {
> +			conflict = 1;
> +			continue;
> +		}
> +	}

That "continue" looks like a no-op.  Mental note: conflict seems to
remember if there was any path that was unmerged.

> +	path = mkpath("%s/MERGE_HEAD", git_dir);
> +	if (!access(path, R_OK))
> +		unmerged_state = 1;

Ahh, so "unmerged" is "conflicted during merge" (as opposed to
rebase_state is "conflicted during rebase")?  Doesn't the naming
sound odd?  If it were "merge_state", it might have made a bit more
sense (but again, these are not independent conditions, so multiple
variables do not make sense).

> +	path = mkpath("%s/rebase-apply", git_dir);
> +	if (!access(path, R_OK)) {
> +		path = mkpath("%s/rebase-apply/applying", git_dir);
> +		if (!access(path, R_OK))
> +			am_state = 1;
> +		else
> +			rebase_state = 1;
> +	}
> +	else {
> +		path = mkpath("%s/rebase-merge", git_dir);
> +		if (!access(path, R_OK)) {
> +			path = mkpath("%s/rebase-merge/interactive", git_dir);
> +			if (!access(path, R_OK))
> +				rebase_interactive_state = 1;
> +			else
> +				rebase_state = 1;
> +		}
> +	}

The above if/else makes it clear that if you are in "am" you can
never be in "rebase -i", but doesn't it strike you odd that the
check for MERGE_HEAD is not cascaded the same way?  I.e. if you know
you are in "merge", you cannot be "am" nor "rebase", but you check
the latter anyway even after you know you are in "merge".

> +	path = mkpath("%s/BISECT_LOG", git_dir);
> +	if (!access(path, R_OK))
> +		bisect_state = 1;

Likewise.

> +	if(bisect_state) {

s/if/if /;

> +		status_printf_ln(s, c, _("You are currently bisecting."));
> +		status_printf_ln(s, c, _("To get back to the original branch run \"git bisect reset\""));
> +		wt_status_print_trailer(s);
> +	}
> +
> +	if(unmerged_state) {

Likewise.

> +		if (conflict)
> +			status_printf_ln(s, c, _("You have unmerged paths: fix conflicts and then commit the result."));
> +		else
> +			status_printf_ln(s, c, _("You are still merging, run \"git commit\" to conclude merge."));
> +		wt_status_print_trailer(s);
> +	}

It is annoying that the above does things in random order, i.e.

	if (are we in X)
        	set state to X
	if (are we in Y)
        	set state to Y
	else if (are we in Z)
		set state to Z
	if (are we in W)
		set state to W

	if (Z)
        	say things about Z
	if (X)
		say things about X
	if (Y)
		say things about Y


Such a code structure invites bugs and missed cases (e.g. you do not
seem to say anything after you detect that you are in "am").


> +	if(rebase_state || rebase_interactive_state) {
> +		if (conflict) {
> +			status_printf_ln(s, c, _("You are currently rebasing: fix conflicts and then run \"git rebase -- continue\"."));
> +			status_printf_ln(s, c, _("If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
> +			status_printf_ln(s, c, _("To check out  the original branch and stop rebasing run \"git rebase --abort\"."));
> +		}
> +		else {

	if (...) {
		...
	} else {
		...
	}

> +			if (rebase_state)

Why extra level of nesting?

> +				status_printf_ln(s, c, _("You are currently rebasing: all conflicts fixed; run \"git rebase --continue\"."));
> +			else {
> +				status_printf_ln(s, c, _("You are currently editing in a rebase progress."));
> +				status_printf_ln(s, c, _("You can amend the commit with"));
> +				status_printf_ln(s, c, _("	git commit --amend"));
> +				status_printf_ln(s, c, _("Once you are satisfied with your changes, run"));
> +				status_printf_ln(s, c, _("	git rebase --continue"));
> +			}

I am not sure if this level of verbosity is a good thing, given that
you are adding this near the very beginning of the output.  When you
have many conflicted or modified paths, these advice messages will
scroll off the top.

Oh, another thing.  Perhaps these (both detection logic and output)
should be protected with a new advise.* configuration variable, no?

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

* Re: [PATCHv2 1/2] wt-status: better advices for git status
  2012-05-28  4:57   ` Junio C Hamano
@ 2012-05-28  7:05     ` Matthieu Moy
  2012-05-30  4:27       ` Junio C Hamano
  2012-05-28 10:54     ` konglu
  1 sibling, 1 reply; 97+ messages in thread
From: Matthieu Moy @ 2012-05-28  7:05 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Junio C Hamano <gitster@pobox.com> writes:

> These are not independent (you cannot be in bisect and am at the
> same time).

You should not, but it seems you can. At least, I just successfully
started a "git am" during a "git bisect".

Even if some checks may be added to actually prevent the situation, it
seems better to keep "git status" robust to this kind of situation. If
the user did something really wrong, nice advices in "git status" will
be particularly helpful.

>> +	int conflict = 0;
>
> How is this different from "unmerged"?
[...]
>> +	path = mkpath("%s/MERGE_HEAD", git_dir);
>> +	if (!access(path, R_OK))
>> +		unmerged_state = 1;
>
> Ahh, so "unmerged" is "conflicted during merge" (as opposed to
> rebase_state is "conflicted during rebase")?  Doesn't the naming
> sound odd?  If it were "merge_state", it might have made a bit more
> sense (but again, these are not independent conditions, so multiple
> variables do not make sense).

The variable naming is wrong (it could be s/conflicts/unmerged_present/
and s/unmerged_state/merge_in_progress/ for example). But these two
variables are indeed independant. You can have unmerged path without an
actual merge in progress (conflicts during "git am"), an you can have a
merge in progress without conflicts (if you've just "git add"-ed them).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv2 2/2] t7512-status-warnings.sh: better advices for git status
  2012-05-26 12:38   ` [PATCHv2 2/2] t7512-status-warnings.sh: " Kong Lucien
  2012-05-27 12:57     ` Matthieu Moy
@ 2012-05-28  8:43     ` Matthieu Moy
  1 sibling, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-05-28  8:43 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> +test_expect_success 'status when conflicts unresolved' '
> +	git init --shared --bare conflict_test.git &&
> +	git clone conflict_test.git test1 &&
> +	git clone conflict_test.git test2 &&

I already asked off-list, but why do you need 3 repositories here.
Wouldn't it be simpler to have 2 branches and test conflicts with
"git merge"?

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv2 1/2] wt-status: better advices for git status
  2012-05-28  4:57   ` Junio C Hamano
  2012-05-28  7:05     ` Matthieu Moy
@ 2012-05-28 10:54     ` konglu
  1 sibling, 0 replies; 97+ messages in thread
From: konglu @ 2012-05-28 10:54 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Matthieu.Moy, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien


Junio C Hamano <gitster@pobox.com> a écrit :

>> +	int unmerged_state = 0;
>> +	int rebase_state = 0;
>> +	int rebase_interactive_state = 0;
>> +	int am_state = 0;
>> +	int bisect_state = 0;
>
> These are not independent (you cannot be in bisect and am at the
> same time).  Why five independent variables?

Some of these variables are independant. We can be in rebase and
bisect at the same time and, as Matthieu said, we can do an am during
a bisect. However, there are dependant cases such as you cannot do a
rebase during an am.


>> +	for (i = 0; i < s->change.nr; i++) {
>> +		struct wt_status_change_data *d;
>> +		struct string_list_item *it;
>> +		it = &(s->change.items[i]);
>> +		d = it->util;
>> +		if (d->stagemask) {
>> +			conflict = 1;
>> +			continue;
>> +		}
>> +	}
>
> That "continue" looks like a no-op.  Mental note: conflict seems to
> remember if there was any path that was unmerged.

You're right. It should be a "break" instead of "continue".


> Such a code structure invites bugs and missed cases (e.g. you do not
> seem to say anything after you detect that you are in "am").

In fact, the case of 'am' is not implemented in this patch. It's supposed
to be added in the next patch.

>
>> +	if(rebase_state || rebase_interactive_state) {
>> +		if (conflict) {
>> +			status_printf_ln(s, c, _("You are currently rebasing: fix  
>> conflicts and then run \"git rebase -- continue\"."));
>> +			status_printf_ln(s, c, _("If you would prefer to skip this  
>> patch, instead run \"git rebase --skip\"."));
>> +			status_printf_ln(s, c, _("To check out  the original branch and  
>> stop rebasing run \"git rebase --abort\"."));
>> +		}
>> +		else {
>
> 	if (...) {
> 		...
> 	} else {
> 		...
> 	}
>
>> +			if (rebase_state)
>
> Why extra level of nesting?

The 'conflict' variable stands for the case when we're in a conflict  
before resolving
it (with 'git add'), as we distinguish the warning messages for when  
we're before
resolving a conflict and after resolving it. So, the case with  
"conflict" can happen in
both cases rebase_state and rebase_interactive_state but the warning  
messages are still specifical
for the rebase cases. However, There are still specifical messages for  
when you are
in rebase_state or in rebase_interactive_state.

>
> Oh, another thing.  Perhaps these (both detection logic and output)
> should be protected with a new advise.* configuration variable, no?

Yes, We think that it would be wise to add a new advice.* config variable
to control the display of the new warning messages.

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

* [PATCHv3 1/2] wt-status.*: better advices for git status added
  2012-05-26 12:38 ` [PATCHv2 1/2] wt-status: " Kong Lucien
                     ` (3 preceding siblings ...)
  2012-05-28  4:57   ` Junio C Hamano
@ 2012-05-28 17:36   ` Kong Lucien
  2012-05-28 17:36     ` [PATCHv3 2/2] t7512-status-warnings.sh: better advices for git status Kong Lucien
                       ` (3 more replies)
  4 siblings, 4 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-28 17:36 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

This patch provides new warning messages in the display of
'git status' (at the top) during conflicts, rebase, am
and bisect process. These messages can be shortened by setting
the new advice.* config key called advice.statushelp to false.

Thus, information about the new advice.* key are added in
Documentation/config.txt

Also, the test t7060-wt-status.sh is now working with the
new warning messages.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen Lucien <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
The new messages are not shown when using options such as
-s or --porcelain.It figures the current state by finding 
the files generated in .git in each case (during an am, 
a rebase, a bisect etc.). The messages about the current
situation of the user are always displayed but the advices 
on what the user needs to do in order to resume a rebase/bisect
/am/ commit after resolving conflicts can be hidden by setting advice.statushelp to 'false' in the config file.

 Documentation/config.txt |    4 ++
 advice.c                 |    2 +
 advice.h                 |    1 +
 t/t7060-wtstatus.sh      |    2 +
 wt-status.c              |  106 ++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.h              |    1 +
 6 files changed, 116 insertions(+), 0 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a..6504371 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -176,6 +176,10 @@ advice.*::
 		Advice shown when you used linkgit:git-checkout[1] to
 		move to the detach HEAD state, to instruct how to create
 		a local branch after the fact.
+	statusHelp::
+		Directions on how to end the current process shown
+		in the output of linkgit:git-status[1].
+
 --
 
 core.fileMode::
diff --git a/advice.c b/advice.c
index a492eea..31deb31 100644
--- a/advice.c
+++ b/advice.c
@@ -9,6 +9,7 @@ int advice_commit_before_merge = 1;
 int advice_resolve_conflict = 1;
 int advice_implicit_identity = 1;
 int advice_detached_head = 1;
+int advice_status_help = 1;
 
 static struct {
 	const char *name;
@@ -23,6 +24,7 @@ static struct {
 	{ "resolveconflict", &advice_resolve_conflict },
 	{ "implicitidentity", &advice_implicit_identity },
 	{ "detachedhead", &advice_detached_head },
+	{ "statushelp", &advice_status_help },
 };
 
 void advise(const char *advice, ...)
diff --git a/advice.h b/advice.h
index f3cdbbf..5fd3cce 100644
--- a/advice.h
+++ b/advice.h
@@ -12,6 +12,7 @@ extern int advice_commit_before_merge;
 extern int advice_resolve_conflict;
 extern int advice_implicit_identity;
 extern int advice_detached_head;
+extern int advice_status_help;
 
 int git_default_advice_config(const char *var, const char *value);
 void advise(const char *advice, ...);
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb490..d9a1e18 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,8 @@ test_expect_success 'Report new path with conflict' '
 
 cat >expect <<EOF
 # On branch side
+# You have unmerged paths: fix conflicts and then commit the result.
+#
 # Unmerged paths:
 #   (use "git add/rm <file>..." as appropriate to mark resolution)
 #
diff --git a/wt-status.c b/wt-status.c
index dd6d8c4..093a352 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
 	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
 	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
+	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
 };
 
 static const char *color(int slot, struct wt_status *s)
@@ -728,6 +729,109 @@ static void wt_status_print_tracking(struct wt_status *s)
 	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
 }
 
+static void wt_status_print_in_progress(struct wt_status *s)
+{
+	int i;
+	const char *c = color(WT_STATUS_IN_PROGRESS, s);
+	struct stat st;
+	int merge_in_progress = 0;
+	int rebase_state = 0;
+	int rebase_interactive_state = 0;
+	int am_state = 0;
+	int am_wrong_format_state = 0;
+	int bisect_state = 0;
+	int unmerged_present = 0;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		d = s->change.items[i].util;
+		if (d->stagemask) {
+			unmerged_present = 1;
+			break;
+		}
+	}
+
+	if (!stat(git_path("MERGE_HEAD"), &st))
+		merge_in_progress = 1;
+	else {
+		if (!stat(git_path("rebase-apply"), &st)) {
+			if (!stat(git_path("rebase-apply/applying"), &st))
+				am_state = 1;
+				if (!stat(git_path("rebase-apply/patch"), &st) && !(st.st_size))
+					am_wrong_format_state = 1;
+			else
+				rebase_state = 1;
+		}
+		else {
+			if (!stat(git_path("rebase-merge"), &st)) {
+				if (!stat(git_path("rebase-merge/interactive"), &st))
+					rebase_interactive_state = 1;
+				else
+					rebase_state = 1;
+			}
+		}
+	}
+
+	if (!stat(git_path("BISECT_LOG"), &st))
+		bisect_state = 1;
+
+	if(merge_in_progress) {
+		if (unmerged_present)
+			status_printf_ln(s, c, _("You have unmerged paths: fix conflicts and then commit the result."));
+		else
+			status_printf_ln(s, c, _("You are still merging, run \"git commit\" to conclude merge."));
+		wt_status_print_trailer(s);
+	}
+	else {
+		if(am_state) {
+			status_printf_ln(s, c, _("You are currently in am progress:"));
+			if(am_wrong_format_state)
+				status_printf_ln(s, c, _("One of the patches is empty or corrupted !"));
+			if (advice_status_help) {
+				status_printf_ln(s, c, _("When you have resolved this problem run \"git am --resolved\"."));
+				status_printf_ln(s, c, _("If you would prefer to skip this patch, instead run \"git am --skip\"."));
+				status_printf_ln(s, c, _("To restore the original branch and stop patching run \"git am --abort\"."));
+			}
+			wt_status_print_trailer(s);
+		}
+
+		else if (rebase_state || rebase_interactive_state) {
+			if (unmerged_present) {
+				status_printf_ln(s, c, _("You are currently rebasing%s"),
+				advice_status_help
+				? _(": fix conflicts and then run \"git rebase -- continue\".") : ".");
+				if (advice_status_help) {
+					status_printf_ln(s, c, _("If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
+					status_printf_ln(s, c, _("To check out  the original branch and stop rebasing run \"git rebase --abort\"."));
+				}
+			}
+			else {
+				if (rebase_state)
+					status_printf_ln(s, c, _("You are currently rebasing: all conflicts fixed%s"),
+					advice_status_help
+					? _(": run \"git rebase --continue\".") : ".");
+				else {
+					status_printf_ln(s, c, _("You are currently editing a commit during a rebase."));
+					if (advice_status_help) {
+						status_printf_ln(s, c, _("You can amend the commit with"));
+						status_printf_ln(s, c, _("	git commit --amend"));
+						status_printf_ln(s, c, _("Once you are satisfied with your changes, run"));
+						status_printf_ln(s, c, _("	git rebase --continue"));
+					}
+				}
+			}
+			wt_status_print_trailer(s);
+		}
+	}
+
+	if(bisect_state) {
+		status_printf_ln(s, c, _("You are currently bisecting."));
+		if (advice_status_help)
+		status_printf_ln(s, c, _("To get back to the original branch run \"git bisect reset\""));
+		wt_status_print_trailer(s);
+	}
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
@@ -750,6 +854,8 @@ void wt_status_print(struct wt_status *s)
 			wt_status_print_tracking(s);
 	}
 
+	wt_status_print_in_progress(s);
+
 	if (s->is_initial) {
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7..0556669 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -15,6 +15,7 @@ enum color_wt_status {
 	WT_STATUS_LOCAL_BRANCH,
 	WT_STATUS_REMOTE_BRANCH,
 	WT_STATUS_ONBRANCH,
+	WT_STATUS_IN_PROGRESS,
 	WT_STATUS_MAXSLOT
 };
 
-- 
1.7.8

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

* [PATCHv3 2/2] t7512-status-warnings.sh: better advices for git status
  2012-05-28 17:36   ` [PATCHv3 1/2] wt-status.*: better advices for git status added Kong Lucien
@ 2012-05-28 17:36     ` Kong Lucien
  2012-05-28 20:36       ` Matthieu Moy
  2012-05-28 20:23     ` [PATCHv3 1/2] wt-status.*: better advices for git status added Matthieu Moy
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 97+ messages in thread
From: Kong Lucien @ 2012-05-28 17:36 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

The following tests include several cases in which the user
needs to run 'git status' to know his current situation,
whether there're conflicts or he's in rebase/bisect/am progress.

The last test is about the set of the advice.statushelp config key
on false in .git/config.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen Lucien <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
 t/t7512-status-warnings.sh |  303 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 303 insertions(+), 0 deletions(-)
 create mode 100755 t/t7512-status-warnings.sh

diff --git a/t/t7512-status-warnings.sh b/t/t7512-status-warnings.sh
new file mode 100755
index 0000000..7824626
--- /dev/null
+++ b/t/t7512-status-warnings.sh
@@ -0,0 +1,303 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'status when conflicts unresolved' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	test_commit on_master main.txt on_master &&
+	git checkout second_branch &&
+	test_commit on_second_branch main.txt on_second_branch &&
+	test_must_fail git merge master &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths: fix conflicts and then commit the result.
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	echo one >main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You are still merging, run "git commit" to conclude merge.
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+
+test_expect_success 'status when rebase in progress before resolving conflicts' '
+	git commit -m "one" &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing: fix conflicts and then run "git rebase -- continue".
+	# If you would prefer to skip this patch, instead run "git rebase --skip".
+	# To check out  the original branch and stop rebasing run "git rebase --abort".
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+test_expect_success 'status when rebase in progress before rebase --continue' '
+	test_when_finished "cd ../ && rm -rf git" &&
+	echo three >main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing: all conflicts fixed: run "git rebase --continue".
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+test_expect_success 'status when rebasing -i in edit mode' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git fake-editor.sh" &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	FAKE_LINES="1 edit 2" &&
+	export FAKE_LINES &&
+	git rebase -i HEAD~2 &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	# You can amend the commit with
+	#	git commit --amend
+	# Once you are satisfied with your changes, run
+	#	git rebase --continue
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output &&
+	git rebase --abort
+'
+
+
+
+test_expect_success 'status in am progress: file already exists' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt "one  " &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently in am progress:
+	# When you have resolved this problem run "git am --resolved".
+	# If you would prefer to skip this patch, instead run "git am --skip".
+	# To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+test_expect_success 'status in am progress: file does not exist' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt "one" &&
+	git rm main.txt &&
+	git commit -m "delete main.txt" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently in am progress:
+	# When you have resolved this problem run "git am --resolved".
+	# If you would prefer to skip this patch, instead run "git am --skip".
+	# To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+test_expect_success 'status in am progress : patch corrupted/wrong format' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one one.txt "one" &&
+	test_commit two two.txt "two" &&
+	test_commit three three.txt "three" &&
+	git format-patch -3 -oMaildir &&
+	git rm one.txt two.txt three.txt &&
+	git commit -m "delete all" &&
+	echo error >Maildir/0002-two.patch &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently in am progress:
+	# One of the patches is empty or corrupted !
+	# When you have resolved this problem run "git am --resolved".
+	# If you would prefer to skip this patch, instead run "git am --skip".
+	# To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+
+test_expect_success 'status when bisecting' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	git bisect start &&
+	git bisect bad &&
+	git bisect good one &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently bisecting.
+	# To get back to the original branch run "git bisect reset"
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+test_expect_success 'status when rebase conflicts with statushelp disabled' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	git config --local advice.statushelp false &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+test_done
-- 
1.7.8

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

* Re: [PATCHv3 1/2] wt-status.*: better advices for git status added
  2012-05-28 17:36   ` [PATCHv3 1/2] wt-status.*: better advices for git status added Kong Lucien
  2012-05-28 17:36     ` [PATCHv3 2/2] t7512-status-warnings.sh: better advices for git status Kong Lucien
@ 2012-05-28 20:23     ` Matthieu Moy
  2012-05-29 19:22     ` Junio C Hamano
  2012-05-30 13:23     ` [PATCHv4 1/3] " Kong Lucien
  3 siblings, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-05-28 20:23 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> These messages can be shortened by setting
> the new advice.* config key called advice.statushelp to false.

It may make sense to use the existing advice.statusHint here.

> +	else {
> +		if (!stat(git_path("rebase-apply"), &st)) {

"else { if" is usually spelt "else if", without an additional level of
indentation.

> +			status_printf_ln(s, c, _("You have unmerged paths: fix conflicts and then commit the result."));

I'd even say

You have unmerged paths; fix conflicts and run "git commit"

> +				status_printf_ln(s, c, _("One of the patches is empty or corrupted !"));

No space before !

> +				status_printf_ln(s, c, _("When you have resolved this problem run \"git am --resolved\"."));
> +				status_printf_ln(s, c, _("If you would prefer to skip this patch, instead run \"git am --skip\"."));
> +				status_printf_ln(s, c, _("To restore the original branch and stop patching run \"git am --abort\"."));

You have overly long lines. I already suggested splitting the function
into smaller functions, and the presence of long lines is usually an
indication that the splitting should be done.

Documentation/CodingGuidelines says:

,----
| For C programs:
| 
|  - We use tabs to indent, and interpret tabs as taking up to
|    8 spaces.
| 
|  - We try to keep to at most 80 characters per line.
`----

> +				status_printf_ln(s, c, _("You are currently rebasing%s"),
> +				advice_status_help
> +				? _(": fix conflicts and then run \"git rebase -- continue\".") : ".");

Weird indentation, it feels like 3 different statements.

> +	if(bisect_state) {

Space between if and (.

> +		if (advice_status_help)
> +		status_printf_ln(s, c, _("To get back to the original branch run \"git bisect reset\""));

Broken indentation.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv3 2/2] t7512-status-warnings.sh: better advices for git status
  2012-05-28 17:36     ` [PATCHv3 2/2] t7512-status-warnings.sh: better advices for git status Kong Lucien
@ 2012-05-28 20:36       ` Matthieu Moy
  0 siblings, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-05-28 20:36 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> +	# You are currently rebasing: fix conflicts and then run "git rebase -- continue".
> +	# If you would prefer to skip this patch, instead run "git rebase --skip".
> +	# To check out  the original branch and stop rebasing run "git rebase --abort".

You can use a small indentation to mark the fact that the next lines are
related to the first, like done in the other messages of status:

> +	# Unmerged paths:
> +	#   (use "git reset HEAD <file>..." to unstage)
> +	#   (use "git add/rm <file>..." as appropriate to mark resolution)

I'd have written it like this:

+	# You are currently rebasing: fix conflicts and then run "git rebase -- continue".
+	#   If you would prefer to skip this patch, instead run "git rebase --skip".
+	#   To check out  the original branch and stop rebasing run "git rebase --abort".

Same for other messages.

> +	# You are currently rebasing: fix conflicts and then run "git rebase -- continue".

Extra space between -- and continue.

You could refine the advice depending on whether conflicts are (still)
present or not (like you did for merge).

> +test_expect_success 'status in am progress : patch corrupted/wrong format' '

No space before :.

> +	# One of the patches is empty or corrupted !

No space before ! (I think I mentionned it for the C code, not sure).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv3 1/2] wt-status.*: better advices for git status added
  2012-05-28 17:36   ` [PATCHv3 1/2] wt-status.*: better advices for git status added Kong Lucien
  2012-05-28 17:36     ` [PATCHv3 2/2] t7512-status-warnings.sh: better advices for git status Kong Lucien
  2012-05-28 20:23     ` [PATCHv3 1/2] wt-status.*: better advices for git status added Matthieu Moy
@ 2012-05-29 19:22     ` Junio C Hamano
  2012-05-30 11:09       ` konglu
  2012-05-30 13:23     ` [PATCHv4 1/3] " Kong Lucien
  3 siblings, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-05-29 19:22 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Matthieu.Moy, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> This patch provides new warning messages in the display of
> 'git status' (at the top) during conflicts, rebase, am
> and bisect process. These messages can be shortened by setting
> the new advice.* config key called advice.statushelp to false.
>
> Thus, information about the new advice.* key are added in
> Documentation/config.txt
>
> Also, the test t7060-wt-status.sh is now working with the
> new warning messages.
>
> Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
> Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
> Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
> Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
> Signed-off-by: Nguyen Huynh Khoi Nguyen Lucien <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
> ---
> The new messages are not shown when using options such as
> -s or --porcelain.It figures the current state by finding 
> the files generated in .git in each case (during an am, 
> a rebase, a bisect etc.). The messages about the current
> situation of the user are always displayed but the advices 
> on what the user needs to do in order to resume a rebase/bisect
> /am/ commit after resolving conflicts can be hidden by setting advice.statushelp to 'false' in the config file.

Don't some of the above explanatory sentences deserve to be in the
commit log message proper, not hidden behind the three-dash lines?


>  Documentation/config.txt |    4 ++
>  advice.c                 |    2 +
>  advice.h                 |    1 +
>  t/t7060-wtstatus.sh      |    2 +
>  wt-status.c              |  106 ++++++++++++++++++++++++++++++++++++++++++++++
>  wt-status.h              |    1 +
>  6 files changed, 116 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 915cb5a..6504371 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -176,6 +176,10 @@ advice.*::
>  		Advice shown when you used linkgit:git-checkout[1] to
>  		move to the detach HEAD state, to instruct how to create
>  		a local branch after the fact.
> +	statusHelp::
> +		Directions on how to end the current process shown
> +		in the output of linkgit:git-status[1].
> +
>  --

Have you read the existing entries in the same section you are
touching to see if the patch result as a whole makes sense and the
new entry fits well in the context?

It strikes me odd that this is not listed next to statusHints, and
it also makes me wonder if we even need to invent a new one, or it
is better to just make the output more verbose when statusHints is
not being declined.

> diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
> index b8cb490..d9a1e18 100755
> --- a/t/t7060-wtstatus.sh
> +++ b/t/t7060-wtstatus.sh
> @@ -30,6 +30,8 @@ test_expect_success 'Report new path with conflict' '
>  
>  cat >expect <<EOF
>  # On branch side
> +# You have unmerged paths: fix conflicts and then commit the result.
> +#
>  # Unmerged paths:
>  #   (use "git add/rm <file>..." as appropriate to mark resolution)
>  #
> diff --git a/wt-status.c b/wt-status.c
> index dd6d8c4..093a352 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
>  	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
>  	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
>  	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
> +	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
>  };
>  
>  static const char *color(int slot, struct wt_status *s)
> @@ -728,6 +729,109 @@ static void wt_status_print_tracking(struct wt_status *s)
>  	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
>  }
>  
> +static void wt_status_print_in_progress(struct wt_status *s)
> +{
> +	int i;
> +	const char *c = color(WT_STATUS_IN_PROGRESS, s);
> +	struct stat st;

> +	int merge_in_progress = 0;
> +	int rebase_state = 0;
> +	int rebase_interactive_state = 0;
> +	int am_state = 0;
> +	int am_wrong_format_state = 0;
> +	int bisect_state = 0;

merge_in_progress is very descriptive, but compared to that, none of
the foo_state is.

> +	int unmerged_present = 0;



> +
> +	for (i = 0; i < s->change.nr; i++) {
> +		struct wt_status_change_data *d;
> +		d = s->change.items[i].util;
> +		if (d->stagemask) {
> +			unmerged_present = 1;
> +			break;
> +		}
> +	}
> +
> +	if (!stat(git_path("MERGE_HEAD"), &st))
> +		merge_in_progress = 1;
> +	else {
> +		if (!stat(git_path("rebase-apply"), &st)) {
> +			if (!stat(git_path("rebase-apply/applying"), &st))
> +				am_state = 1;
> +				if (!stat(git_path("rebase-apply/patch"), &st) && !(st.st_size))
> +					am_wrong_format_state = 1;

Isn't nesting screwed-up around here?  Your indentation suggests you
need opening "{" after "if (applying)" and closing "}" before "else"
on the next line.

> +			else
> +				rebase_state = 1;
> +		}
> +		else {
> +			if (!stat(git_path("rebase-merge"), &st)) {
> +				if (!stat(git_path("rebase-merge/interactive"), &st))
> +					rebase_interactive_state = 1;
> +				else
> +					rebase_state = 1;
> +			}
> +		}
> +	}

Whenever you write "else {" that is immediately followed by "if",
re-read what you wrote and think if you can make it "else if () {"
to reduce the indentation level.  If you still need five levels of
indentation, the function you are writing is too complex and is a
sign that you can use a helper function.

In this case, I think you could structure it like this:

	if (merge_head) {
        	merge_in_progress++;
	} else if (rebase-apply) {
		if (applying) {
			am_in_progress++;
                        if (patch is empty)
                                ...
		} else {			
			rebase_in_progress++;
		}
	} else if (rebase-merge) {
		if (interactive)
			rebase_i_in_progress++;
		else
			rebase_in_progress++;
	}


> +	if (!stat(git_path("BISECT_LOG"), &st))
> +		bisect_state = 1;
> +
> +	if(merge_in_progress) {

s/if/if /;  Didn't I say this already in my previous message?

> +		if (unmerged_present)
> +			status_printf_ln(s, c, _("You have unmerged paths: fix conflicts and then commit the result."));
> +		else
> +			status_printf_ln(s, c, _("You are still merging, run \"git commit\" to conclude merge."));
> +		wt_status_print_trailer(s);
> +	}
> +	else {
> +		if(am_state) {

The same comments on the "else if" cascading and on the missing SP
after keyword apply here.

> +			status_printf_ln(s, c, _("You are currently in am progress:"));

-ECANTPARSE.

> +			if(am_wrong_format_state)
> +				status_printf_ln(s, c, _("One of the patches is empty or corrupted !"));

You never checked corrupted; you only detected an empty file.

> +			if (advice_status_help) {
> +				status_printf_ln(s, c, _("When you have resolved this problem run \"git am --resolved\"."));
> +				status_printf_ln(s, c, _("If you would prefer to skip this patch, instead run \"git am --skip\"."));
> +				status_printf_ln(s, c, _("To restore the original branch and stop patching run \"git am --abort\"."));
> +			}
> +			wt_status_print_trailer(s);
> +		}
> +
> +		else if (rebase_state || rebase_interactive_state) {
> +			if (unmerged_present) {
> +				status_printf_ln(s, c, _("You are currently rebasing%s"),
> +				advice_status_help
> +				? _(": fix conflicts and then run \"git rebase -- continue\".") : ".");

s/-- /--/;

> +				if (advice_status_help) {
> +					status_printf_ln(s, c, _("If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
> +					status_printf_ln(s, c, _("To check out  the original branch and stop rebasing run \"git rebase --abort\"."));
> +				}
> +			}
> +			else {
> +				if (rebase_state)
> +					status_printf_ln(s, c, _("You are currently rebasing: all conflicts fixed%s"),
> +					advice_status_help
> +					? _(": run \"git rebase --continue\".") : ".");
> +				else {
> +					status_printf_ln(s, c, _("You are currently editing a commit during a rebase."));
> +					if (advice_status_help) {
> +						status_printf_ln(s, c, _("You can amend the commit with"));
> +						status_printf_ln(s, c, _("	git commit --amend"));
> +						status_printf_ln(s, c, _("Once you are satisfied with your changes, run"));
> +						status_printf_ln(s, c, _("	git rebase --continue"));
> +					}
> +				}
> +			}
> +			wt_status_print_trailer(s);
> +		}
> +	}
> +
> +	if(bisect_state) {
> +		status_printf_ln(s, c, _("You are currently bisecting."));
> +		if (advice_status_help)
> +		status_printf_ln(s, c, _("To get back to the original branch run \"git bisect reset\""));
> +		wt_status_print_trailer(s);
> +	}
> +}
> +
>  void wt_status_print(struct wt_status *s)
>  {
>  	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
> @@ -750,6 +854,8 @@ void wt_status_print(struct wt_status *s)
>  			wt_status_print_tracking(s);
>  	}
>  
> +	wt_status_print_in_progress(s);
> +
>  	if (s->is_initial) {
>  		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
>  		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
> diff --git a/wt-status.h b/wt-status.h
> index 14aa9f7..0556669 100644
> --- a/wt-status.h
> +++ b/wt-status.h
> @@ -15,6 +15,7 @@ enum color_wt_status {
>  	WT_STATUS_LOCAL_BRANCH,
>  	WT_STATUS_REMOTE_BRANCH,
>  	WT_STATUS_ONBRANCH,
> +	WT_STATUS_IN_PROGRESS,
>  	WT_STATUS_MAXSLOT
>  };

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

* Re: [PATCHv2 1/2] wt-status: better advices for git status
  2012-05-28  7:05     ` Matthieu Moy
@ 2012-05-30  4:27       ` Junio C Hamano
  0 siblings, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-05-30  4:27 UTC (permalink / raw)
  To: Matthieu Moy
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:

> Junio C Hamano <gitster@pobox.com> writes:
>
>> These are not independent (you cannot be in bisect and am at the
>> same time).
>
> You should not, but it seems you can. At least, I just successfully
> started a "git am" during a "git bisect".

Yeah, that actually is a sensible thing to support (and I am happy
to hear it still works).

> The variable naming is wrong (it could be s/conflicts/unmerged_present/
> and s/unmerged_state/merge_in_progress/ for example). But these two
> variables are indeed independant. You can have unmerged path without an
> actual merge in progress (conflicts during "git am"), an you can have a
> merge in progress without conflicts (if you've just "git add"-ed them).

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

* Re: [PATCHv3 1/2] wt-status.*: better advices for git status added
  2012-05-29 19:22     ` Junio C Hamano
@ 2012-05-30 11:09       ` konglu
  2012-05-30 17:24         ` Junio C Hamano
  2012-05-31  6:47         ` Matthieu Moy
  0 siblings, 2 replies; 97+ messages in thread
From: konglu @ 2012-05-30 11:09 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Matthieu.Moy, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien


Junio C Hamano <gitster@pobox.com> a écrit :

>>  		Advice shown when you used linkgit:git-checkout[1] to
>>  		move to the detach HEAD state, to instruct how to create
>>  		a local branch after the fact.
>> +	statusHelp::
>> +		Directions on how to end the current process shown
>> +		in the output of linkgit:git-status[1].
>> +
>>  --
>
> Have you read the existing entries in the same section you are
> touching to see if the patch result as a whole makes sense and the
> new entry fits well in the context?
>
> It strikes me odd that this is not listed next to statusHints, and
> it also makes me wonder if we even need to invent a new one, or it
> is better to just make the output more verbose when statusHints is
> not being declined.

Yes, we first thought that we could use statusHints to protect the
new messages warnings. But users that disabled statusHints and still
wished to know what to do during am/rebase/bisect etc. won't be
able to. On the other hand, if they want to hide the new advices, they
can see in the doc the presence of the advice.statusHelp and disable it.

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

* [PATCHv4 1/3] wt-status.*: better advices for git status added
  2012-05-28 17:36   ` [PATCHv3 1/2] wt-status.*: better advices for git status added Kong Lucien
                       ` (2 preceding siblings ...)
  2012-05-29 19:22     ` Junio C Hamano
@ 2012-05-30 13:23     ` Kong Lucien
  2012-05-30 13:23       ` [PATCHv4 2/3] t7512-status-warnings.sh: better advices for git status Kong Lucien
                         ` (4 more replies)
  3 siblings, 5 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-30 13:23 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

This patch provides new warning messages in the display of
'git status' (at the top) during conflicts, rebase, am,
bisect or cherry-pick process.

The new messages are not shown when using options such as
-s or --porcelain.The messages about the current
situation of the user are always displayed but the advices
on what the user needs to do in order to resume a rebase/bisect
/am/ commit after resolving conflicts can be hidden by setting
advice.statushelp to 'false' in the config file.

Thus, information about the new advice.* key are added in
Documentation/config.txt.

Also, the test t7060-wt-status.sh is now working with the
new warning messages.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen Lucien <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
The code figures the current state by finding the files generated
in .git in each cases (during an am, a rebase, a bisect, etc.).

The function wt_status_print_in_progress is now splitted into
several smaller functions in order to avoid too many indentations.

 Documentation/config.txt |    4 +
 advice.c                 |    2 +
 advice.h                 |    1 +
 t/t7060-wtstatus.sh      |    2 +
 wt-status.c              |  161 ++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.h              |   11 +++
 6 files changed, 181 insertions(+), 0 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a..ab1c455 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -162,6 +162,9 @@ advice.*::
 		Directions on how to stage/unstage/add shown in the
 		output of linkgit:git-status[1] and the template shown
 		when writing commit messages.
+	statusHelp::
+		Directions on how to end the current process shown
+		in the output of linkgit:git-status[1].
 	commitBeforeMerge::
 		Advice shown when linkgit:git-merge[1] refuses to
 		merge to avoid overwriting local changes.
@@ -176,6 +179,7 @@ advice.*::
 		Advice shown when you used linkgit:git-checkout[1] to
 		move to the detach HEAD state, to instruct how to create
 		a local branch after the fact.
+
 --
 
 core.fileMode::
diff --git a/advice.c b/advice.c
index a492eea..31deb31 100644
--- a/advice.c
+++ b/advice.c
@@ -9,6 +9,7 @@ int advice_commit_before_merge = 1;
 int advice_resolve_conflict = 1;
 int advice_implicit_identity = 1;
 int advice_detached_head = 1;
+int advice_status_help = 1;
 
 static struct {
 	const char *name;
@@ -23,6 +24,7 @@ static struct {
 	{ "resolveconflict", &advice_resolve_conflict },
 	{ "implicitidentity", &advice_implicit_identity },
 	{ "detachedhead", &advice_detached_head },
+	{ "statushelp", &advice_status_help },
 };
 
 void advise(const char *advice, ...)
diff --git a/advice.h b/advice.h
index f3cdbbf..5fd3cce 100644
--- a/advice.h
+++ b/advice.h
@@ -12,6 +12,7 @@ extern int advice_commit_before_merge;
 extern int advice_resolve_conflict;
 extern int advice_implicit_identity;
 extern int advice_detached_head;
+extern int advice_status_help;
 
 int git_default_advice_config(const char *var, const char *value);
 void advise(const char *advice, ...);
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb490..d0fbcc7 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,8 @@ test_expect_success 'Report new path with conflict' '
 
 cat >expect <<EOF
 # On branch side
+# You have unmerged paths; fix conflicts and run "git commit".
+#
 # Unmerged paths:
 #   (use "git add/rm <file>..." as appropriate to mark resolution)
 #
diff --git a/wt-status.c b/wt-status.c
index dd6d8c4..4dd294f 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
 	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
 	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
+	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
 };
 
 static const char *color(int slot, struct wt_status *s)
@@ -728,10 +729,149 @@ static void wt_status_print_tracking(struct wt_status *s)
 	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
 }
 
+static int wt_status_unmerged_present (struct wt_status *s)
+{
+	int i;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		d = s->change.items[i].util;
+		if (d->stagemask) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static void wt_status_evaluate_state (struct wt_status_state *state)
+{
+	struct stat st;
+
+	state->merge_in_progress = 0;
+	state->am_in_progress = 0;
+	state->am_empty_patch = 0;
+	state->rebase_in_progress = 0;
+	state->rebase_interactive_in_progress = 0;
+	state->cherry_pick_in_progress = 0;
+	state->bisect_in_progress = 0;
+
+	if (!stat(git_path("MERGE_HEAD"), &st))
+		state->merge_in_progress = 1;
+	else if (!stat(git_path("rebase-apply"), &st)) {
+		if (!stat(git_path("rebase-apply/applying"), &st)) {
+			state->am_in_progress = 1;
+			if (!stat(git_path("rebase-apply/patch"), &st) && !(st.st_size))
+				state->am_empty_patch = 1;
+		}
+		else
+			state->rebase_in_progress = 1;
+	}
+	else if (!stat(git_path("rebase-merge"), &st)) {
+		if (!stat(git_path("rebase-merge/interactive"), &st))
+			state->rebase_interactive_in_progress = 1;
+		else
+			state->rebase_in_progress = 1;
+	}
+	else if (!stat(git_path("CHERRY_PICK_HEAD"), &st))
+		state->cherry_pick_in_progress = 1;
+	if (!stat(git_path("BISECT_LOG"), &st))
+		state->bisect_in_progress = 1;
+}
+
+static void wt_status_merge_in_progress (struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	if (wt_status_unmerged_present(s))
+		status_printf_ln(s, color,
+			_("You have unmerged paths; fix conflicts and run \"git commit\"."));
+	else
+		status_printf_ln(s, color,
+			_("You are still merging, run \"git commit\" to conclude merge."));
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_am_in_progress (struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color,
+		_("You are currently in am progress:"));
+	if (state->am_empty_patch)
+		status_printf_ln(s, color,
+			_("One of the patches is empty!"));
+	if (advice_status_help) {
+		status_printf_ln(s, color,
+			_("  When you have resolved this problem run \"git am --resolved\"."));
+		status_printf_ln(s, color,
+			_("  If you would prefer to skip this patch, instead run \"git am --skip\"."));
+		status_printf_ln(s, color,
+			_("  To restore the original branch and stop patching run \"git am --abort\"."));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_rebase_in_progress (struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	if (wt_status_unmerged_present(s)) {
+		status_printf_ln(s, color, _("You are currently rebasing%s"),
+			advice_status_help
+			? _(": fix conflicts and then run \"git rebase --continue\".") : ".");
+		if (advice_status_help) {
+			status_printf_ln(s, color,
+				_("  If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
+			status_printf_ln(s, color,
+				_("  To check out  the original branch and stop rebasing run \"git rebase --abort\"."));
+		}
+	}
+	else if (state->rebase_in_progress)
+		status_printf_ln(s, color, _("You are currently rebasing: all conflicts fixed%s"),
+			advice_status_help
+			? _(": run \"git rebase --continue\".") : ".");
+	else {
+		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
+		if (advice_status_help) {
+			status_printf_ln(s, color, _("  You can amend the commit with"));
+			status_printf_ln(s, color, _("	git commit --amend"));
+			status_printf_ln(s, color, _("  Once you are satisfied with your changes, run"));
+			status_printf_ln(s, color, _("	git rebase --continue"));
+		}
+	}
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_cherry_pick_in_progress (struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	if (wt_status_unmerged_present(s))
+		status_printf_ln(s, color,
+			_("You are currently cherry-picking: fix conflicts and run \"git commit\"."));
+	else
+		status_printf_ln(s, color,
+			_("You are currently cherry-picking: all conflicts fixed: run \"git commit\"."));
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_bisect_in_progress (struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	status_printf_ln(s, color, _("You are currently bisecting."));
+	if (advice_status_help)
+		status_printf_ln(s, color,
+			_("  To get back to the original branch run \"git bisect reset\""));
+	wt_status_print_trailer(s);
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
 	const char *branch_status_color = color(WT_STATUS_HEADER, s);
+	const char *state_color = color(WT_STATUS_IN_PROGRESS, s);
+	struct wt_status_state *state = calloc(1, sizeof(*state));
 
 	if (s->branch) {
 		const char *on_what = _("On branch ");
@@ -750,6 +890,27 @@ void wt_status_print(struct wt_status *s)
 			wt_status_print_tracking(s);
 	}
 
+	wt_status_evaluate_state(state);
+
+	if (state->merge_in_progress) {
+		wt_status_merge_in_progress(s, state, state_color);
+	}
+	else if (state->am_in_progress) {
+		wt_status_am_in_progress(s, state, state_color);
+	}
+
+	else if (state->rebase_in_progress || state->rebase_interactive_in_progress) {
+		wt_status_rebase_in_progress(s, state, state_color);
+	}
+
+	else if (state->cherry_pick_in_progress) {
+		wt_status_cherry_pick_in_progress(s, state, state_color);
+	}
+
+	if (state->bisect_in_progress) {
+		wt_status_bisect_in_progress(s, state, state_color);
+	}
+
 	if (s->is_initial) {
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7..c1066a0 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -15,6 +15,7 @@ enum color_wt_status {
 	WT_STATUS_LOCAL_BRANCH,
 	WT_STATUS_REMOTE_BRANCH,
 	WT_STATUS_ONBRANCH,
+	WT_STATUS_IN_PROGRESS,
 	WT_STATUS_MAXSLOT
 };
 
@@ -71,6 +72,16 @@ struct wt_status {
 	struct string_list ignored;
 };
 
+struct wt_status_state {
+	int merge_in_progress;
+	int am_in_progress;
+	int am_empty_patch;
+	int rebase_in_progress;
+	int rebase_interactive_in_progress;
+	int cherry_pick_in_progress;
+	int bisect_in_progress;
+};
+
 void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
-- 
1.7.8

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

* [PATCHv4 2/3] t7512-status-warnings.sh: better advices for git status
  2012-05-30 13:23     ` [PATCHv4 1/3] " Kong Lucien
@ 2012-05-30 13:23       ` Kong Lucien
  2012-05-30 13:23       ` [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant Kong Lucien
                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-30 13:23 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

The following tests include several cases in which the user
needs to run 'git status' to know his current situation,
whether there're conflicts or he's in rebase/bisect/am/
cherry-pick progress.

One of the test is about the set of the advice.statushelp config key
on false in .git/config.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen Lucien <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
 t/t7512-status-warnings.sh |  352 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 352 insertions(+), 0 deletions(-)
 create mode 100755 t/t7512-status-warnings.sh

diff --git a/t/t7512-status-warnings.sh b/t/t7512-status-warnings.sh
new file mode 100755
index 0000000..2806fe8
--- /dev/null
+++ b/t/t7512-status-warnings.sh
@@ -0,0 +1,352 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'status when conflicts unresolved' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	test_commit on_master main.txt on_master &&
+	git checkout second_branch &&
+	test_commit on_second_branch main.txt on_second_branch &&
+	test_must_fail git merge master &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	echo one >main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You are still merging, run "git commit" to conclude merge.
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when rebase in progress before resolving conflicts' '
+	git commit -m "one" &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing: fix conflicts and then run "git rebase --continue".
+	#   If you would prefer to skip this patch, instead run "git rebase --skip".
+	#   To check out  the original branch and stop rebasing run "git rebase --abort".
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when rebase in progress before rebase --continue' '
+	test_when_finished "cd ../ && rm -rf git" &&
+	echo three >main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing: all conflicts fixed: run "git rebase --continue".
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when rebasing -i in edit mode' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git fake-editor.sh" &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	FAKE_LINES="1 edit 2" &&
+	export FAKE_LINES &&
+	git rebase -i HEAD~2 &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   You can amend the commit with
+	#	git commit --amend
+	#   Once you are satisfied with your changes, run
+	#	git rebase --continue
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output &&
+	git rebase --abort
+'
+
+
+test_expect_success 'status in am progress: file already exists' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt "one  " &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently in am progress:
+	#   When you have resolved this problem run "git am --resolved".
+	#   If you would prefer to skip this patch, instead run "git am --skip".
+	#   To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status in am progress: file does not exist' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt "one" &&
+	git rm main.txt &&
+	git commit -m "delete main.txt" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently in am progress:
+	#   When you have resolved this problem run "git am --resolved".
+	#   If you would prefer to skip this patch, instead run "git am --skip".
+	#   To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status in am progress: patch corrupted/wrong format' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one one.txt "one" &&
+	test_commit two two.txt "two" &&
+	test_commit three three.txt "three" &&
+	git format-patch -3 -oMaildir &&
+	git rm one.txt two.txt three.txt &&
+	git commit -m "delete all" &&
+	echo error >Maildir/0002-two.patch &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently in am progress:
+	# One of the patches is empty!
+	#   When you have resolved this problem run "git am --resolved".
+	#   If you would prefer to skip this patch, instead run "git am --skip".
+	#   To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when bisecting' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	git bisect start &&
+	git bisect bad &&
+	git bisect good one &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently bisecting.
+	#   To get back to the original branch run "git bisect reset"
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when rebase conflicts with statushelp disabled' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	git config --local advice.statushelp false &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when cherry-picking before resolving conflicts' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git checkout -b second_branch &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	git checkout master &&
+	test_must_fail git cherry-pick two &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently cherry-picking: fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+test_expect_success 'status when cherry-picking after resolving conflicts' '
+	test_when_finished "cd ../ && rm -rf git"
+	echo end >main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently cherry-picking: all conflicts fixed: run "git commit".
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_done
-- 
1.7.8

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

* [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant
  2012-05-30 13:23     ` [PATCHv4 1/3] " Kong Lucien
  2012-05-30 13:23       ` [PATCHv4 2/3] t7512-status-warnings.sh: better advices for git status Kong Lucien
@ 2012-05-30 13:23       ` Kong Lucien
  2012-05-30 18:44         ` Junio C Hamano
  2012-05-31  7:06         ` Matthieu Moy
  2012-05-30 18:26       ` [PATCHv4 1/3] wt-status.*: better advices for git status added Junio C Hamano
                         ` (2 subsequent siblings)
  4 siblings, 2 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-30 13:23 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

The display of the advice '(use git add/rm [...])' (when
there are unmerged files) after running 'git status' is
now depending of the mark, whether it's 'both deleted',
'deleted by us/them' or others. For instance, when there is
just one file that's marked as 'both deleted', 'git status'
shows '(use git rm [...])' and if there are two files, one
as 'both deleted' and the other as 'added by them', the advice
is '(use git add/rm [...])'.

The previous tests in t7512-status-warnings.sh are updated and
5 tests are added about the different cases of unmerged paths.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen Lucien <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
 t/t7512-status-warnings.sh |  165 ++++++++++++++++++++++++++++++++++++++++++-
 wt-status.c                |   29 ++++++++-
 2 files changed, 189 insertions(+), 5 deletions(-)

diff --git a/t/t7512-status-warnings.sh b/t/t7512-status-warnings.sh
index 2806fe8..01d614c 100755
--- a/t/t7512-status-warnings.sh
+++ b/t/t7512-status-warnings.sh
@@ -27,7 +27,7 @@ test_expect_success 'status when conflicts unresolved' '
 	# You have unmerged paths; fix conflicts and run "git commit".
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." as appropriate to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -78,7 +78,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." as appropriate to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -280,7 +280,7 @@ test_expect_success 'status when rebase conflicts with statushelp disabled' '
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." as appropriate to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -311,7 +311,7 @@ test_expect_success 'status when cherry-picking before resolving conflicts' '
 	# You are currently cherry-picking: fix conflicts and run "git commit".
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." as appropriate to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -349,4 +349,161 @@ test_expect_success 'status when cherry-picking after resolving conflicts' '
 '
 
 
+test_expect_success 'status when conflicts without rm advice (both modified)' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	test_commit on_master main.txt on_master &&
+	git checkout second_branch &&
+	test_commit on_second_branch main.txt on_second_branch &&
+	test_must_fail git merge master &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (deleted by us)' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	test_commit on_master main.txt on_master &&
+	git checkout second_branch &&
+	git rm main.txt &&
+	git commit -m "main.txt deleted on second_branch" &&
+	test_must_fail git merge master &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	deleted by us:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (deleted by them)' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	git rm main.txt &&
+	git commit -m "main.txt deleted on master" &&
+	git checkout second_branch &&
+	test_commit on_second main.txt on_second &&
+	test_must_fail git merge master &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	deleted by them:    main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	git mv main.txt sub_master.txt &&
+	git commit -m "main.txt renamed in sub_master.txt" &&
+	git checkout second_branch &&
+	git mv main.txt sub_second.txt &&
+	git commit -m "main.txt renamed in sub_second.txt" &&
+	test_must_fail git merge master &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#	added by them:      sub_master.txt
+	#	added by us:        sub_second.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts with only rm advice (both deleted)' '
+	test_when_finished "cd ../ && rm -rf git" &&
+	git add sub_master.txt &&
+	git add sub_second.txt &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Changes to be committed:
+	#
+	#	new file:   sub_master.txt
+	#
+	# Unmerged paths:
+	#   (use "git rm <file>..." as appropriate to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
 test_done
diff --git a/wt-status.c b/wt-status.c
index 4dd294f..9d79f2b 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -131,9 +131,27 @@ void wt_status_prepare(struct wt_status *s)
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
 {
+	int i;
+	int simple_deleted_flag = 0;
+	int both_deleted_flag = 0;
+	int not_deleted_flag = 0;
 	const char *c = color(WT_STATUS_HEADER, s);
 
 	status_printf_ln(s, c, _("Unmerged paths:"));
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct string_list_item *it = &(s->change.items[i]);
+		struct wt_status_change_data *d = it->util;
+
+		if (d->stagemask == 1 && !both_deleted_flag)
+			both_deleted_flag = 1;
+		else if ((d->stagemask == 3 || d->stagemask == 5) && !simple_deleted_flag)
+			simple_deleted_flag = 1;
+		else if ((d->stagemask == 2 || d->stagemask == 4 || d->stagemask == 6 ||
+				d->stagemask == 7) && !not_deleted_flag)
+			not_deleted_flag = 1;
+	}
+
 	if (!advice_status_hints)
 		return;
 	if (s->whence != FROM_COMMIT)
@@ -142,7 +160,16 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
 		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
 		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
-	status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+
+	if (!both_deleted_flag)
+		if (!simple_deleted_flag)
+			status_printf_ln(s, c, _("  (use \"git add <file>...\" as appropriate to mark resolution)"));
+		else
+			status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	else if (!simple_deleted_flag && !not_deleted_flag)
+		status_printf_ln(s, c, _("  (use \"git rm <file>...\" as appropriate to mark resolution)"));
+	else
+		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
 	status_printf_ln(s, c, "");
 }
 
-- 
1.7.8

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

* Re: [PATCHv3 1/2] wt-status.*: better advices for git status added
  2012-05-30 11:09       ` konglu
@ 2012-05-30 17:24         ` Junio C Hamano
  2012-05-31  6:47         ` Matthieu Moy
  1 sibling, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-05-30 17:24 UTC (permalink / raw)
  To: konglu
  Cc: Kong Lucien, git, Matthieu.Moy, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

konglu@minatec.inpg.fr writes:

>> It strikes me odd that this is not listed next to statusHints, and
>> it also makes me wonder if we even need to invent a new one, or it
>> is better to just make the output more verbose when statusHints is
>> not being declined.
>
> Yes, we first thought that we could use statusHints to protect the
> new messages warnings. But users that disabled statusHints and still
> wished to know what to do during am/rebase/bisect etc. won't be
> able to. On the other hand, if they want to hide the new advices, they
> can see in the doc the presence of the advice.statusHelp and disable it.

"When we have more more knobs, we can differentiate more cases" is
not a valid argument, unless you can successfully argue that it is
worth differentiating these subcases.  Otherwise it is just another
useless knob the user needs to tweak without real gain.

In this particular case, I think the new text is merely an extension
of existing help text.  Those who have already declined statusHints
should not be bothered by it, and those who are being helped by them
would benefit from the help text being more complete.

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

* Re: [PATCHv4 1/3] wt-status.*: better advices for git status added
  2012-05-30 13:23     ` [PATCHv4 1/3] " Kong Lucien
  2012-05-30 13:23       ` [PATCHv4 2/3] t7512-status-warnings.sh: better advices for git status Kong Lucien
  2012-05-30 13:23       ` [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant Kong Lucien
@ 2012-05-30 18:26       ` Junio C Hamano
  2012-05-30 19:06         ` Junio C Hamano
  2012-05-31  6:42         ` Matthieu Moy
  2012-05-31  6:29       ` Matthieu Moy
  2012-05-31 15:15       ` [PATCHv5 " Kong Lucien
  4 siblings, 2 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-05-30 18:26 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Matthieu.Moy, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> This patch provides new warning messages in the display of
> 'git status' (at the top) during conflicts, rebase, am,
> bisect or cherry-pick process.

I hate to see these called "warnings", as there is nothing for the
end user to be alarmed about.  The user wanted to know what status
the working tree is in, and we are reporting what the user wanted to
know.  They are informative help messages.

> The new messages are not shown when using options such as
> -s or --porcelain.The messages about the current
> situation of the user are always displayed but the advices
> on what the user needs to do in order to resume a rebase/bisect
> /am/ commit after resolving conflicts can be hidden by setting
> advice.statushelp to 'false' in the config file.

Notice the spaces are sprinkled in the above paragraph in a funny
way?  You might want to get in the habit of proofreading what you
wrote before sending.

> Thus, information about the new advice.* key are added in
> Documentation/config.txt.
>
> Also, the test t7060-wt-status.sh is now working with the
> new warning messages.
>
> Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
> Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
> Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
> Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
> Signed-off-by: Nguyen Huynh Khoi Nguyen Lucien <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
> ---
> The code figures the current state by finding the files generated
> in .git in each cases (during an am, a rebase, a bisect, etc.).
>
> The function wt_status_print_in_progress is now splitted into
> several smaller functions in order to avoid too many indentations.
>
>  Documentation/config.txt |    4 +
>  advice.c                 |    2 +
>  advice.h                 |    1 +
>  t/t7060-wtstatus.sh      |    2 +
>  wt-status.c              |  161 ++++++++++++++++++++++++++++++++++++++++++++++
>  wt-status.h              |   11 +++
>  6 files changed, 181 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 915cb5a..ab1c455 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -162,6 +162,9 @@ advice.*::
>  		Directions on how to stage/unstage/add shown in the
>  		output of linkgit:git-status[1] and the template shown
>  		when writing commit messages.
> +	statusHelp::
> +		Directions on how to end the current process shown
> +		in the output of linkgit:git-status[1].
>  	commitBeforeMerge::
>  		Advice shown when linkgit:git-merge[1] refuses to
>  		merge to avoid overwriting local changes.
> @@ -176,6 +179,7 @@ advice.*::
>  		Advice shown when you used linkgit:git-checkout[1] to
>  		move to the detach HEAD state, to instruct how to create
>  		a local branch after the fact.
> +
>  --
>  
>  core.fileMode::
> diff --git a/advice.c b/advice.c
> index a492eea..31deb31 100644
> --- a/advice.c
> +++ b/advice.c
> @@ -9,6 +9,7 @@ int advice_commit_before_merge = 1;
>  int advice_resolve_conflict = 1;
>  int advice_implicit_identity = 1;
>  int advice_detached_head = 1;
> +int advice_status_help = 1;
>  
>  static struct {
>  	const char *name;
> @@ -23,6 +24,7 @@ static struct {
>  	{ "resolveconflict", &advice_resolve_conflict },
>  	{ "implicitidentity", &advice_implicit_identity },
>  	{ "detachedhead", &advice_detached_head },
> +	{ "statushelp", &advice_status_help },
>  };
>  
>  void advise(const char *advice, ...)
> diff --git a/advice.h b/advice.h
> index f3cdbbf..5fd3cce 100644
> --- a/advice.h
> +++ b/advice.h
> @@ -12,6 +12,7 @@ extern int advice_commit_before_merge;
>  extern int advice_resolve_conflict;
>  extern int advice_implicit_identity;
>  extern int advice_detached_head;
> +extern int advice_status_help;
>  
>  int git_default_advice_config(const char *var, const char *value);
>  void advise(const char *advice, ...);
> diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
> index b8cb490..d0fbcc7 100755
> --- a/t/t7060-wtstatus.sh
> +++ b/t/t7060-wtstatus.sh
> @@ -30,6 +30,8 @@ test_expect_success 'Report new path with conflict' '
>  
>  cat >expect <<EOF
>  # On branch side
> +# You have unmerged paths; fix conflicts and run "git commit".
> +#
>  # Unmerged paths:
>  #   (use "git add/rm <file>..." as appropriate to mark resolution)
>  #
> diff --git a/wt-status.c b/wt-status.c
> index dd6d8c4..4dd294f 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
>  	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
>  	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
>  	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
> +	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
>  };
>  
>  static const char *color(int slot, struct wt_status *s)
> @@ -728,10 +729,149 @@ static void wt_status_print_tracking(struct wt_status *s)
>  	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
>  }
>  
> +static int wt_status_unmerged_present (struct wt_status *s)

Please drop needless extra SP between function name and its
parameter list (I won't repeat this but the same breakage is
everywhere in this patch).

Is it worth giving this file-local helper function a long name like
that?  A short-and-sweet has_unmerged() would work just as well and
probably easier to read.

> +{
> +	int i;
> +
> +	for (i = 0; i < s->change.nr; i++) {
> +		struct wt_status_change_data *d;
> +		d = s->change.items[i].util;
> +		if (d->stagemask) {
> +			return 1;
> +		}

Please drop needless {} around a single statement block (I won't
repeat this but the same breakage is everywhere in this patch).

> +	}
> +	return 0;
> +}
> +
> +static void wt_status_evaluate_state (struct wt_status_state *state)
> +{
> +	struct stat st;
> +
> +	state->merge_in_progress = 0;
> +	state->am_in_progress = 0;
> +	state->am_empty_patch = 0;
> +	state->rebase_in_progress = 0;
> +	state->rebase_interactive_in_progress = 0;
> +	state->cherry_pick_in_progress = 0;
> +	state->bisect_in_progress = 0;
> +
> +	if (!stat(git_path("MERGE_HEAD"), &st))
> +		state->merge_in_progress = 1;
> +	else if (!stat(git_path("rebase-apply"), &st)) {
> +		if (!stat(git_path("rebase-apply/applying"), &st)) {
> +			state->am_in_progress = 1;
> +			if (!stat(git_path("rebase-apply/patch"), &st) && !(st.st_size))

Please drop needless () around st.st_size.

> +				state->am_empty_patch = 1;
> +		}
> +		else
> +			state->rebase_in_progress = 1;

Two points on style (also appear elsewhere in this patch):

	if (!"applying") {
 		...
	} else {
		state->rebase_in_progress = 1;
	}

 - "else" comes on the same line as closing "}" of its "if" block;

 - if one of if/else if/else chain has multiple statement block, use {}
   even for a single statement block in the chain.

> +	}
> +	else if (!stat(git_path("rebase-merge"), &st)) {
> +		if (!stat(git_path("rebase-merge/interactive"), &st))
> +			state->rebase_interactive_in_progress = 1;
> +		else
> +			state->rebase_in_progress = 1;
> +	}
> +	else if (!stat(git_path("CHERRY_PICK_HEAD"), &st))
> +		state->cherry_pick_in_progress = 1;
> +	if (!stat(git_path("BISECT_LOG"), &st))
> +		state->bisect_in_progress = 1;
> +}
> +
> +static void wt_status_merge_in_progress (struct wt_status *s,
> +					struct wt_status_state *state,
> +					const char *color)

The earlier "evaluate-state" was a well-named function, but this is
not. "merge_in_progress" what? It is not about asking "is a merge in
progress?", but is about showing message when it is the case.
Please have "print" or "show" or something that tells what it _does_
somewhere in its name (same applies to other functions in this patch).

> +{
> +	if (wt_status_unmerged_present(s))
> +		status_printf_ln(s, color,
> +			_("You have unmerged paths; fix conflicts and run \"git commit\"."));
> +	else
> +		status_printf_ln(s, color,
> +			_("You are still merging, run \"git commit\" to conclude merge."));
> +	wt_status_print_trailer(s);
> +}
> +
> +static void wt_status_am_in_progress (struct wt_status *s,
> +				struct wt_status_state *state,
> +				const char *color)
> +{
> +	status_printf_ln(s, color,
> +		_("You are currently in am progress:"));

Is it just me, or is the above -ECANTPARSE?  "You are currently in
commit/merge/meal/commute progress?"

Perhaps	"You are in the middle of an am session" or something?

> +	if (state->am_empty_patch)
> +		status_printf_ln(s, color,
> +			_("One of the patches is empty!"));

Can we state this better?  It is not like you have 4 patches, you
are processing its third one, and you found that the first patch you
have already skipped was empty and keep nagging the user about "one
of them" being empty.  As far as I can tell, you observed that
"current one" that is being processed is empty in evaluate-state, so
I think it makes more sense to tell the user the current one is
empty instead of being vague like the above.

> +	if (advice_status_help) {
> +		status_printf_ln(s, color,
> +			_("  When you have resolved this problem run \"git am --resolved\"."));
> +		status_printf_ln(s, color,
> +			_("  If you would prefer to skip this patch, instead run \"git am --skip\"."));
> +		status_printf_ln(s, color,
> +			_("  To restore the original branch and stop patching run \"git am --abort\"."));
> +	}

I doubt it makes much sense to hide only these messages behind "if
(advice_status_help)".  Look at how you give your "what to do"
advices in wt-status-merge-in-progress function.

Probably it is a good idea to show this unconditionally *if* the
caller decides to call this function, and other "print/show" kind of
functions, this patch adds.


> +	wt_status_print_trailer(s);
> +}
> +
> +static void wt_status_rebase_in_progress (struct wt_status *s,
> +					struct wt_status_state *state,
> +					const char *color)
> +{
> +	if (wt_status_unmerged_present(s)) {
> +		status_printf_ln(s, color, _("You are currently rebasing%s"),
> +			advice_status_help
> +			? _(": fix conflicts and then run \"git rebase --continue\".") : ".");

Likewise.

> +		if (advice_status_help) {
> +			status_printf_ln(s, color,
> +				_("  If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
> +			status_printf_ln(s, color,
> +				_("  To check out  the original branch and stop rebasing run \"git rebase --abort\"."));
> +		}
> +	}
> +	else if (state->rebase_in_progress)
> +		status_printf_ln(s, color, _("You are currently rebasing: all conflicts fixed%s"),
> +			advice_status_help
> +			? _(": run \"git rebase --continue\".") : ".");
> +	else {
> +		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
> +		if (advice_status_help) {
> +			status_printf_ln(s, color, _("  You can amend the commit with"));
> +			status_printf_ln(s, color, _("	git commit --amend"));
> +			status_printf_ln(s, color, _("  Once you are satisfied with your changes, run"));
> +			status_printf_ln(s, color, _("	git rebase --continue"));
> +		}
> +	}
> +	wt_status_print_trailer(s);
> +}
> +
> +static void wt_status_cherry_pick_in_progress (struct wt_status *s,
> +					struct wt_status_state *state,
> +					const char *color)
> +{
> +	if (wt_status_unmerged_present(s))
> +		status_printf_ln(s, color,
> +			_("You are currently cherry-picking: fix conflicts and run \"git commit\"."));
> +	else
> +		status_printf_ln(s, color,
> +			_("You are currently cherry-picking: all conflicts fixed: run \"git commit\"."));
> +	wt_status_print_trailer(s);
> +}
> +
> +static void wt_status_bisect_in_progress (struct wt_status *s,
> +					struct wt_status_state *state,
> +					const char *color)
> +{
> +	status_printf_ln(s, color, _("You are currently bisecting."));
> +	if (advice_status_help)
> +		status_printf_ln(s, color,
> +			_("  To get back to the original branch run \"git bisect reset\""));
> +	wt_status_print_trailer(s);
> +}
> +
>  void wt_status_print(struct wt_status *s)
>  {
>  	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
>  	const char *branch_status_color = color(WT_STATUS_HEADER, s);
> +	const char *state_color = color(WT_STATUS_IN_PROGRESS, s);
> +	struct wt_status_state *state = calloc(1, sizeof(*state));
>  
>  	if (s->branch) {
>  		const char *on_what = _("On branch ");
> @@ -750,6 +890,27 @@ void wt_status_print(struct wt_status *s)
>  			wt_status_print_tracking(s);
>  	}
>  
> +	wt_status_evaluate_state(state);
> +
> +	if (state->merge_in_progress) {
> +		wt_status_merge_in_progress(s, state, state_color);
> +	}
> +	else if (state->am_in_progress) {
> +		wt_status_am_in_progress(s, state, state_color);
> +	}
> +
> +	else if (state->rebase_in_progress || state->rebase_interactive_in_progress) {
> +		wt_status_rebase_in_progress(s, state, state_color);
> +	}
> +
> +	else if (state->cherry_pick_in_progress) {
> +		wt_status_cherry_pick_in_progress(s, state, state_color);
> +	}
> +
> +	if (state->bisect_in_progress) {
> +		wt_status_bisect_in_progress(s, state, state_color);
> +	}
> +

And instead, hide the above new lines behind advice.statusHints,
without introducing advice.statusHelp.  As to the global code
structure, it probably would make more sense to:

  - rename wt_status_evaluate_state() to wt_status_print_state();

  - rename the various "print help information for this state" functions
    that are called in the above if/else/... cascade to merge_in_progress_show()
    etc.

  - move the above if/else/... cascade to the end of
    wt_status_print_state(), which would make the above part more
    like:

	 wt_status_print()
         {
		if (s->branch) {
                	...
		}
	+	wt_status_print_state(s);
		if (s->is_initial) {
			...

  - at the beginning of wt_status_print_state(), check advice.statusHints
    and return without doing anything if the user does not want hints.

Otherwise, overall the patch is getting better looking.

Thanks for a pleasant read.

>  	if (s->is_initial) {
>  		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
>  		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
> diff --git a/wt-status.h b/wt-status.h
> index 14aa9f7..c1066a0 100644
> --- a/wt-status.h
> +++ b/wt-status.h
> @@ -15,6 +15,7 @@ enum color_wt_status {
>  	WT_STATUS_LOCAL_BRANCH,
>  	WT_STATUS_REMOTE_BRANCH,
>  	WT_STATUS_ONBRANCH,
> +	WT_STATUS_IN_PROGRESS,
>  	WT_STATUS_MAXSLOT
>  };
>  
> @@ -71,6 +72,16 @@ struct wt_status {
>  	struct string_list ignored;
>  };
>  
> +struct wt_status_state {
> +	int merge_in_progress;
> +	int am_in_progress;
> +	int am_empty_patch;
> +	int rebase_in_progress;
> +	int rebase_interactive_in_progress;
> +	int cherry_pick_in_progress;
> +	int bisect_in_progress;
> +};
> +
>  void wt_status_prepare(struct wt_status *s);
>  void wt_status_print(struct wt_status *s);
>  void wt_status_collect(struct wt_status *s);

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

* Re: [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant
  2012-05-30 13:23       ` [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant Kong Lucien
@ 2012-05-30 18:44         ` Junio C Hamano
  2012-05-30 21:50           ` konglu
  2012-05-31  7:06         ` Matthieu Moy
  1 sibling, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-05-30 18:44 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Matthieu.Moy, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

>  static void wt_status_print_unmerged_header(struct wt_status *s)
>  {
> +	int i;
> +	int simple_deleted_flag = 0;
> +	int both_deleted_flag = 0;
> +	int not_deleted_flag = 0;
>  	const char *c = color(WT_STATUS_HEADER, s);
>  
>  	status_printf_ln(s, c, _("Unmerged paths:"));
> +
> +	for (i = 0; i < s->change.nr; i++) {
> +		struct string_list_item *it = &(s->change.items[i]);
> +		struct wt_status_change_data *d = it->util;
> +
> +		if (d->stagemask == 1 && !both_deleted_flag)
> +			both_deleted_flag = 1;
> +		else if ((d->stagemask == 3 || d->stagemask == 5) && !simple_deleted_flag)
> +			simple_deleted_flag = 1;
> +		else if ((d->stagemask == 2 || d->stagemask == 4 || d->stagemask == 6 ||
> +				d->stagemask == 7) && !not_deleted_flag)
> +			not_deleted_flag = 1;
> +	}

Yuck.  Do you need to "&& !flag" in any of these?

	switch (d->stagemask) {
        case 1:
        	both_deleted = 1;
                break;
        case 3:
        case 5:
        	simple_deleted = 1;
                break;
        default:
        	not_deleted = 1;
                break;
	}

Also, I think "simple deleted" is grossly misnamed.  It is "one side
deleted, other side possibly modified", isn't it?  Because it is
almost always safe to resolve "both sides deleted" to a deletion,
but "one deleted, the other modified" needs a lot more thought to
resolve correctly, it is a much more complex case.  I'd call it
del_mod_conflict or something if I were writing this code.

In any case, drop "_flag" from the names.  They are annoying and do
not add much value.

>  	if (!advice_status_hints)
>  		return;
>  	if (s->whence != FROM_COMMIT)
> @@ -142,7 +160,16 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
>  		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
>  	else
>  		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
> -	status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
> +
> +	if (!both_deleted_flag)

If you meant the control flow to follow your indentation, I think
you are missing opening "{" at the end of the above line.

> +		if (!simple_deleted_flag)
> +			status_printf_ln(s, c, _("  (use \"git add <file>...\" as appropriate to mark resolution)"));

Nobody deleted, so we do not suggest "rm" as resolution, which makes
sense.

As far as I know, in the current message we say "as appropriate"
because we leave the choice of add/rm to the end user.  Do you still
need "as appropriate" after deciding that "add" is the only choice
for the user?

> +		else
> +			status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));

There is del/mod conflict and nothing else; the user needs to choose
between add/rm.  OK.

> +	else if (!simple_deleted_flag && !not_deleted_flag)
> +		status_printf_ln(s, c, _("  (use \"git rm <file>...\" as appropriate to mark resolution)"));

Assuming that a closing "}" for the "if (!both_deleted)" above is
missing at the beginning of this line, there is no del/mod conflict,
some del/del and no addition, so "rm" is the only choice, which
makes sense.  The same comment on "as appropriate" applies here.

> +	else
> +		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
>  	status_printf_ln(s, c, "");
>  }

I like the way it tries to be helpful, but I doubt this patch would
make much difference in the real life.  As you follow the logic like
I demonstrated above, you show specific help only in a very narrow
case (i.e. there is no possible removal or there are nothing but
"both sides removed").

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

* Re: [PATCHv4 1/3] wt-status.*: better advices for git status added
  2012-05-30 18:26       ` [PATCHv4 1/3] wt-status.*: better advices for git status added Junio C Hamano
@ 2012-05-30 19:06         ` Junio C Hamano
  2012-05-31  6:42         ` Matthieu Moy
  1 sibling, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-05-30 19:06 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Matthieu.Moy, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Junio C Hamano <gitster@pobox.com> writes:

> And instead, hide the above new lines behind advice.statusHints,
> without introducing advice.statusHelp.  As to the global code
> structure, it probably would make more sense to:
>
>   - rename wt_status_evaluate_state() to wt_status_print_state();
>
>   - rename the various "print help information for this state" functions
>     that are called in the above if/else/... cascade to merge_in_progress_show()
>     etc.
>
>   - move the above if/else/... cascade to the end of
>     wt_status_print_state(), which would make the above part more
>     like:
>
> 	 wt_status_print()
>          {
> 		if (s->branch) {
>                 	...
> 		}
> 	+	wt_status_print_state(s);
> 		if (s->is_initial) {
> 			...
>
>   - at the beginning of wt_status_print_state(), check advice.statusHints
>     and return without doing anything if the user does not want hints.
>
> Otherwise, overall the patch is getting better looking.
>
> Thanks for a pleasant read.

After reading the current code, I changed my mind slightly.

The way the new code tries to separate the state information
(i.e. statement of the fact it found) and the advice messages
(i.e. what could be done next) is indeed in line with what the
advice.statusHints configuration is used in the existing code.  We
unconditionally show what we find to the user, and we give help by
default but let the user decline.

So an updated suggestion would be to still move the whole thing to
wt_status_print_state(), but not check advice.statusHints at the
beginning of the function (as we will show what we find even when
the user declines help text) and do the discovery, and hide the help
messages (i.e. "do this to proceed") behind advice.statusHints,
without introducing advice.statusHelp.

As I pointed out in my review, there were some places in the patch
that gave help text unconditionally, which needs to be corrected.

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

* Re: [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant
  2012-05-30 18:44         ` Junio C Hamano
@ 2012-05-30 21:50           ` konglu
  0 siblings, 0 replies; 97+ messages in thread
From: konglu @ 2012-05-30 21:50 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Matthieu.Moy, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien


Junio C Hamano <gitster@pobox.com> a écrit :

>> +		if (d->stagemask == 1 && !both_deleted_flag)
>> +			both_deleted_flag = 1;
>> +		else if ((d->stagemask == 3 || d->stagemask == 5) &&  
>> !simple_deleted_flag)
>> +			simple_deleted_flag = 1;
>> +		else if ((d->stagemask == 2 || d->stagemask == 4 || d->stagemask == 6 ||
>> +				d->stagemask == 7) && !not_deleted_flag)
>> +			not_deleted_flag = 1;
>> +	}
>
> 	switch (d->stagemask) {
>         case 1:
>         	both_deleted = 1;
>                 break;
>         case 3:
>         case 5:
>         	simple_deleted = 1;
>                 break;
>         default:
>         	not_deleted = 1;
>                 break;
> 	}

Yes, using switch makes the code easier to read. In fact, I put explicitly the
condition when there are no delete (cases 2, 4, 6 and 7) because there  
are cases
when d->stagemask can take other number than 1..7. For example:

git init git &&
cd git &&
test_commit foo main.txt foo &&
git branch second_branch &&
git mv main.txt sub_master.txt &&
git commit -m "main.txt renamed in sub_master.txt" &&
git checkout second_branch &&
git mv main.txt sub_second.txt &&
git commit -m "main.txt renamed in sub_second.txt" &&
git merge master &&
git add sub_master.txt &&
git add sub_second.txt

At this point, the output of git status shows in unmerged paths the  
file main.txt
that is marked as 'both deleted' so the number of elements in  
s->change.items should
be 1. However, in this case, there are 2 elements. One is about the  
file main.txt and
its stagemask is '1' (as expected) but the stagemask of the other  
element (I don't
know its origin) is '0'.
Anyway, the new code becomes something like:

switch (d->stagemask) {
case 0:
	break;
case 1:
	both_deleted = 1;
	break;
case 3:
case 5:
	del_mod_conflict = 1;
	break;
default:
	not_deleted = 1;
	break;
}

Though I don't know if d->stagemask can take values such as 8, 9, etc.

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

* Re: [PATCHv4 1/3] wt-status.*: better advices for git status added
  2012-05-30 13:23     ` [PATCHv4 1/3] " Kong Lucien
                         ` (2 preceding siblings ...)
  2012-05-30 18:26       ` [PATCHv4 1/3] wt-status.*: better advices for git status added Junio C Hamano
@ 2012-05-31  6:29       ` Matthieu Moy
  2012-05-31  6:34         ` Andrew Ardill
  2012-05-31 15:15       ` [PATCHv5 " Kong Lucien
  4 siblings, 1 reply; 97+ messages in thread
From: Matthieu Moy @ 2012-05-31  6:29 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> The new messages are not shown when using options such as
> -s or --porcelain.The messages about the current

space between . and The (normally, 2 spaces in english).

> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -176,6 +179,7 @@ advice.*::
>  		Advice shown when you used linkgit:git-checkout[1] to
>  		move to the detach HEAD state, to instruct how to create
>  		a local branch after the fact.
> +
>  --

Why add a blank line here?

> +	if (state->merge_in_progress) {
> +		wt_status_merge_in_progress(s, state, state_color);
> +	}
> +	else if (state->am_in_progress) {
> +		wt_status_am_in_progress(s, state, state_color);
> +	}
> +
> +	else if (state->rebase_in_progress || state->rebase_interactive_in_progress) {
> +		wt_status_rebase_in_progress(s, state, state_color);
> +	}
> +
> +	else if (state->cherry_pick_in_progress) {
> +		wt_status_cherry_pick_in_progress(s, state, state_color);
> +	}
> +
> +	if (state->bisect_in_progress) {
> +		wt_status_bisect_in_progress(s, state, state_color);
> +	}

Do these have to be if/else if/... ?

In most cases, the user will have only one of these at the same time,
but in the few cases where there's, e.g. a rebase during a bisect or so,
I think it makes more sense to show both advices to the user (probably
as a sign that something's wrong).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv4 1/3] wt-status.*: better advices for git status added
  2012-05-31  6:29       ` Matthieu Moy
@ 2012-05-31  6:34         ` Andrew Ardill
  0 siblings, 0 replies; 97+ messages in thread
From: Andrew Ardill @ 2012-05-31  6:34 UTC (permalink / raw)
  To: Matthieu Moy
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

On 31 May 2012 16:29, Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> wrote:
> Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:
>
>> The new messages are not shown when using options such as
>> -s or --porcelain.The messages about the current
>
> space between . and The (normally, 2 spaces in english).

It is not common practice to use 2 spaces after a period any more,
especially on the web. A good summary of information around using 1 or
2 spaces after a period can be found at [1]

Regards,

Andrew Ardill

[1] http://www.webword.com/reports/period.html

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

* Re: [PATCHv4 1/3] wt-status.*: better advices for git status added
  2012-05-30 18:26       ` [PATCHv4 1/3] wt-status.*: better advices for git status added Junio C Hamano
  2012-05-30 19:06         ` Junio C Hamano
@ 2012-05-31  6:42         ` Matthieu Moy
  2012-05-31  6:44           ` Matthieu Moy
  1 sibling, 1 reply; 97+ messages in thread
From: Matthieu Moy @ 2012-05-31  6:42 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Junio C Hamano <gitster@pobox.com> writes:

>> +	status_printf_ln(s, color,
>> +		_("You are currently in am progress:"));
>
> Is it just me, or is the above -ECANTPARSE?  "You are currently in
> commit/merge/meal/commute progress?"

It's not just you ;-).

> Perhaps	"You are in the middle of an am session" or something?

I'd just say "rebase in progress".

>> +	status_printf_ln(s, color,
>> +		_("You are currently in am progress:"));
[...]
>> +	if (advice_status_help) {
>> +		status_printf_ln(s, color,
>> +			_("  When you have resolved this problem run \"git am --resolved\"."));
>> +		status_printf_ln(s, color,
>> +			_("  If you would prefer to skip this patch, instead run \"git am --skip\"."));
>> +		status_printf_ln(s, color,
>> +			_("  To restore the original branch and stop patching run \"git am --abort\"."));
>> +	}
>
> I doubt it makes much sense to hide only these messages behind "if
> (advice_status_help)".  Look at how you give your "what to do"
> advices in wt-status-merge-in-progress function.

I disagree.

"rebase in progress" adds information for advanced Git users as well as
for newbies. I think it makes sense to display it unconditionnally, like
we currently display "Not currently on any branch." or "Your branch is
ahead of ...".

The state in which the user is is important for anyone, but the set of
commands to get out of this state is not relevant for advanced users,
and simply eats a few terminal lines for them.

I think the situation is no different from other messages like "Changes
not staged for commit:", where the list matters for everyone, but the
suggested commands don't, and that's why I still think
advice.statusHints should be used here too.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv4 1/3] wt-status.*: better advices for git status added
  2012-05-31  6:42         ` Matthieu Moy
@ 2012-05-31  6:44           ` Matthieu Moy
  0 siblings, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-05-31  6:44 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:

>> I doubt it makes much sense to hide only these messages behind "if
>> (advice_status_help)".  Look at how you give your "what to do"
>> advices in wt-status-merge-in-progress function.
>
> I disagree.

But I do agree with your updated suggestion (which I read too late):

Junio C Hamano <gitster@pobox.com> writes:

> So an updated suggestion would be to still move the whole thing to
> wt_status_print_state(), but not check advice.statusHints at the
> beginning of the function (as we will show what we find even when
> the user declines help text) and do the discovery, and hide the help
> messages (i.e. "do this to proceed") behind advice.statusHints,
> without introducing advice.statusHelp.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv3 1/2] wt-status.*: better advices for git status added
  2012-05-30 11:09       ` konglu
  2012-05-30 17:24         ` Junio C Hamano
@ 2012-05-31  6:47         ` Matthieu Moy
  1 sibling, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-05-31  6:47 UTC (permalink / raw)
  To: konglu
  Cc: Junio C Hamano, Kong Lucien, git, Duperray Valentin,
	Jonas Franck, Nguy Thomas, Nguyen Huynh Khoi Nguyen Lucien

konglu@minatec.inpg.fr writes:

> Yes, we first thought that we could use statusHints to protect the
> new messages warnings. But users that disabled statusHints and still
> wished to know what to do during am/rebase/bisect etc.

I don't think you should worry too much about people who already set
statusHints. By definition, they are people who read the documentation,
which already disqualifies them as "newbies". If you show the state
unconditionally, and just hide the commands, then at worse, they will
have to read the doc again.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant
  2012-05-30 13:23       ` [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant Kong Lucien
  2012-05-30 18:44         ` Junio C Hamano
@ 2012-05-31  7:06         ` Matthieu Moy
  2012-05-31  7:59           ` konglu
  1 sibling, 1 reply; 97+ messages in thread
From: Matthieu Moy @ 2012-05-31  7:06 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> Subject: Re: [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant

"more relevant" doesn't say much, and your subject line doesn't say it's
about "status". What about

status: don't suggest "git rm" if not appropriate

?

> +test_expect_success 'status when conflicts without rm advice (both modified)' '

How is this different from the other existing tests? Avoid adding
redundant tests, they slow down the test suite without added value.

> +test_expect_success 'status when conflicts with add and rm advice (deleted by us)' '
> +test_expect_success 'status when conflicts with add and rm advice (deleted by them)' '

You can probably save a few line (and test execution time) by reusing
the same repository in the second test, like

git reset --hard
git checkout master
git merge second_branch

(i.e. reply the merge, but symmetrically, from the other branch)

Perhaps this sould be added to t7060-wtstatus.sh (basic work tree status
reporting) instead, which already tests "deleted by us:". Ideally, you
could add tests for "deleted by them" and "both deleted" in a first
patch, and turn the add/rm into add in the implementation patch.

+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	deleted by us:      main.txt
+	#

To really test the logic, you need to have more than one file in the
list (the logic should say "suggest rm if _at least one_ file may need
it", but currently, a patch implementing "if _all_ files" would pass the
test).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant
  2012-05-31  7:06         ` Matthieu Moy
@ 2012-05-31  7:59           ` konglu
  0 siblings, 0 replies; 97+ messages in thread
From: konglu @ 2012-05-31  7:59 UTC (permalink / raw)
  To: Matthieu Moy
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen Lucien

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=";"; format=flowed	DelSp=Yes, Size: 589 bytes --]


Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> a écrit :

>> Subject: Re: [PATCHv4 3/3] Advices about 'git rm' during conflicts  
>> (unmerged paths) more relevant
>
> "more relevant" doesn't say much, and your subject line doesn't say it's
> about "status". What about
>
> status: don't suggest "git rm" if not appropriate
>
> ?
In the case of only 'both deleted', what we don't want 'git status' to suggest
is "git add". Maybe something like

status: advices appropriated during conflicts
or
status: don't suggest "git rm" or "git add" if not appropriate

would fit.

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

* [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-05-30 13:23     ` [PATCHv4 1/3] " Kong Lucien
                         ` (3 preceding siblings ...)
  2012-05-31  6:29       ` Matthieu Moy
@ 2012-05-31 15:15       ` Kong Lucien
  2012-05-31 15:15         ` [PATCHv5 2/3] t7512-status-help.sh: better advices for git status Kong Lucien
                           ` (4 more replies)
  4 siblings, 5 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-31 15:15 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen

This patch provides new informative help messages in the display of
'git status' (at the top) during conflicts, rebase, am, bisect or
cherry-pick process.

The new messages are not shown when using options such as -s or
--porcelain. The messages about the current situation of the user are
always displayed but the advices on what the user needs to do in order
to resume a rebase/bisect /am/ commit after resolving conflicts can be
hidden by setting advice.statushints to 'false' in the config file.

Thus, information about the updated advice.statushints key are added
in Documentation/config.txt.

Also, the test t7060-wt-status.sh is now working with the new help
messages. Tests about suggestions of "git rm" are also added.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
The key advice.statushelp introduced in the previous patches is
deleted. The messages are now controlled by advice.statushints.

 Documentation/config.txt |    2 +
 t/t7060-wtstatus.sh      |   71 +++++++++++++++++++++
 wt-status.c              |  154 ++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.h              |   11 +++
 4 files changed, 238 insertions(+), 0 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a..52f5009 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -162,6 +162,8 @@ advice.*::
 		Directions on how to stage/unstage/add shown in the
 		output of linkgit:git-status[1] and the template shown
 		when writing commit messages.
+		Directions on how to end the current process shown
+		in the output of linkgit:git-status[1].
 	commitBeforeMerge::
 		Advice shown when linkgit:git-merge[1] refuses to
 		merge to avoid overwriting local changes.
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb490..8a6d68a 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,8 @@ test_expect_success 'Report new path with conflict' '
 
 cat >expect <<EOF
 # On branch side
+# You have unmerged paths; fix conflicts and run "git commit".
+#
 # Unmerged paths:
 #   (use "git add/rm <file>..." as appropriate to mark resolution)
 #
@@ -118,4 +120,73 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
 	test_cmp expected actual
 '
 
+
+test_expect_success 'status when conflicts with add and rm advice (deleted by them)' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit init main.txt init &&
+	git checkout -b second_branch &&
+	git rm main.txt &&
+	git commit -m "main.txt deleted on second_branch" &&
+	test_commit second conflict.txt second &&
+	git checkout master &&
+	test_commit on_second main.txt on_second &&
+	test_commit master conflict.txt master &&
+	test_must_fail git merge second_branch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both added:         conflict.txt
+	#	deleted by them:    main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	git mv main.txt sub_master.txt &&
+	git commit -m "main.txt renamed in sub_master.txt" &&
+	git checkout second_branch &&
+	git mv main.txt sub_second.txt &&
+	git commit -m "main.txt renamed in sub_second.txt" &&
+	test_must_fail git merge master &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#	added by them:      sub_master.txt
+	#	added by us:        sub_second.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
 test_done
diff --git a/wt-status.c b/wt-status.c
index dd6d8c4..f4ba021 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
 	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
 	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
+	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
 };
 
 static const char *color(int slot, struct wt_status *s)
@@ -728,6 +729,158 @@ static void wt_status_print_tracking(struct wt_status *s)
 	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
 }
 
+static int has_unmerged(struct wt_status *s)
+{
+	int i;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		d = s->change.items[i].util;
+		if (d->stagemask)
+			return 1;
+	}
+	return 0;
+}
+
+static void merge_in_progress_show(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	if (has_unmerged(s))
+		status_printf_ln(s, color, _("You have unmerged paths%s"),
+			advice_status_hints
+			? _("; fix conflicts and run \"git commit\".") : ".");
+	else
+		status_printf_ln(s, color, _("You are still merging%s"),
+			advice_status_hints
+			? _(", run \"git commit\" to conclude merge.") : ".");
+	wt_status_print_trailer(s);
+}
+
+static void am_in_progress_show(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color,
+		_("You are in the middle of an am session:"));
+	if (state->am_empty_patch)
+		status_printf_ln(s, color,
+			_("The current patch is empty!"));
+	if (advice_status_hints) {
+		status_printf_ln(s, color,
+			_("  When you have resolved this problem run \"git am --resolved\"."));
+		status_printf_ln(s, color,
+			_("  If you would prefer to skip this patch, instead run \"git am --skip\"."));
+		status_printf_ln(s, color,
+			_("  To restore the original branch and stop patching run \"git am --abort\"."));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void rebase_in_progress_show(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You are currently rebasing%s"),
+			advice_status_hints
+			? _(": fix conflicts and then run \"git rebase --continue\".") : ".");
+		if (advice_status_hints) {
+			status_printf_ln(s, color,
+				_("  If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
+			status_printf_ln(s, color,
+				_("  To check out  the original branch and stop rebasing run \"git rebase --abort\"."));
+		}
+	} else if (state->rebase_in_progress) {
+		status_printf_ln(s, color, _("You are currently rebasing%s"),
+			advice_status_hints
+			? _(": all conflicts fixed: run \"git rebase --continue\".") : ".");
+	} else {
+		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
+		if (advice_status_hints) {
+			status_printf_ln(s, color, _("  You can amend the commit with"));
+			status_printf_ln(s, color, _("	git commit --amend"));
+			status_printf_ln(s, color, _("  Once you are satisfied with your changes, run"));
+			status_printf_ln(s, color, _("	git rebase --continue"));
+		}
+	}
+	wt_status_print_trailer(s);
+}
+
+static void cherry_pick_in_progress_show(struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	if (has_unmerged(s))
+		status_printf_ln(s, color, _("You are currently cherry-picking%s"),
+			advice_status_hints
+			? _(": fix conflicts and run \"git commit\".") : ".");
+	else
+		status_printf_ln(s, color, _("You are currently cherry-picking%s"),
+			advice_status_hints
+			? _(": all conflicts fixed: run \"git commit\".") : ".");
+	wt_status_print_trailer(s);
+}
+
+static void bisect_in_progress_show(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color, _("You are currently bisecting."));
+	if (advice_status_hints)
+		status_printf_ln(s, color,
+			_("  To get back to the original branch run \"git bisect reset\""));
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_print_state(struct wt_status *s)
+{
+	const char *state_color = color(WT_STATUS_IN_PROGRESS, s);
+	struct wt_status_state *state = calloc(1, sizeof(*state));
+	struct stat st;
+
+	state->merge_in_progress = 0;
+	state->am_in_progress = 0;
+	state->am_empty_patch = 0;
+	state->rebase_in_progress = 0;
+	state->rebase_interactive_in_progress = 0;
+	state->cherry_pick_in_progress = 0;
+	state->bisect_in_progress = 0;
+
+	if (!stat(git_path("MERGE_HEAD"), &st)) {
+		state->merge_in_progress = 1;
+	} else if (!stat(git_path("rebase-apply"), &st)) {
+		if (!stat(git_path("rebase-apply/applying"), &st)) {
+			state->am_in_progress = 1;
+			if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
+				state->am_empty_patch = 1;
+		} else {
+			state->rebase_in_progress = 1;
+		}
+	} else if (!stat(git_path("rebase-merge"), &st)) {
+		if (!stat(git_path("rebase-merge/interactive"), &st))
+			state->rebase_interactive_in_progress = 1;
+		else
+			state->rebase_in_progress = 1;
+	} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
+		state->cherry_pick_in_progress = 1;
+	}
+	if (!stat(git_path("BISECT_LOG"), &st))
+		state->bisect_in_progress = 1;
+
+	if (state->merge_in_progress)
+		merge_in_progress_show(s, state, state_color);
+	else if (state->am_in_progress)
+		am_in_progress_show(s, state, state_color);
+	else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
+		rebase_in_progress_show(s, state, state_color);
+	else if (state->cherry_pick_in_progress)
+		cherry_pick_in_progress_show(s, state, state_color);
+	if (state->bisect_in_progress)
+		bisect_in_progress_show(s, state, state_color);
+	free(state);
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
@@ -750,6 +903,7 @@ void wt_status_print(struct wt_status *s)
 			wt_status_print_tracking(s);
 	}
 
+	wt_status_print_state(s);
 	if (s->is_initial) {
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7..c1066a0 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -15,6 +15,7 @@ enum color_wt_status {
 	WT_STATUS_LOCAL_BRANCH,
 	WT_STATUS_REMOTE_BRANCH,
 	WT_STATUS_ONBRANCH,
+	WT_STATUS_IN_PROGRESS,
 	WT_STATUS_MAXSLOT
 };
 
@@ -71,6 +72,16 @@ struct wt_status {
 	struct string_list ignored;
 };
 
+struct wt_status_state {
+	int merge_in_progress;
+	int am_in_progress;
+	int am_empty_patch;
+	int rebase_in_progress;
+	int rebase_interactive_in_progress;
+	int cherry_pick_in_progress;
+	int bisect_in_progress;
+};
+
 void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
-- 
1.7.8

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

* [PATCHv5 2/3] t7512-status-help.sh: better advices for git status
  2012-05-31 15:15       ` [PATCHv5 " Kong Lucien
@ 2012-05-31 15:15         ` Kong Lucien
  2012-05-31 15:15         ` [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
                           ` (3 subsequent siblings)
  4 siblings, 0 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-31 15:15 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen

The following tests include several cases in which the user needs to
run 'git status' to know his current situation, whether there're
conflicts or he's in rebase/bisect/am/ cherry-pick progress.

One of the test is about the set of the advice.statushints config key
to 'false' in .git/config.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
 t/t7512-status-help.sh |  347 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 347 insertions(+), 0 deletions(-)
 create mode 100755 t/t7512-status-help.sh

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
new file mode 100755
index 0000000..af1d130
--- /dev/null
+++ b/t/t7512-status-help.sh
@@ -0,0 +1,347 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'status when conflicts unresolved' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	test_commit on_master main.txt on_master &&
+	git checkout second_branch &&
+	test_commit on_second_branch main.txt on_second_branch &&
+	test_must_fail git merge master &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	echo one >main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You are still merging, run "git commit" to conclude merge.
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when rebase in progress before resolving conflicts' '
+	git commit -m "one" &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing: fix conflicts and then run "git rebase --continue".
+	#   If you would prefer to skip this patch, instead run "git rebase --skip".
+	#   To check out  the original branch and stop rebasing run "git rebase --abort".
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when rebase in progress before rebase --continue' '
+	test_when_finished "cd ../ && rm -rf git" &&
+	echo three >main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing: all conflicts fixed: run "git rebase --continue".
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when rebasing -i in edit mode' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git fake-editor.sh" &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	FAKE_LINES="1 edit 2" &&
+	export FAKE_LINES &&
+	git rebase -i HEAD~2 &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   You can amend the commit with
+	#	git commit --amend
+	#   Once you are satisfied with your changes, run
+	#	git rebase --continue
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output &&
+	git rebase --abort
+'
+
+
+test_expect_success 'status in an am session: file already exists' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt "one  " &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are in the middle of an am session:
+	#   When you have resolved this problem run "git am --resolved".
+	#   If you would prefer to skip this patch, instead run "git am --skip".
+	#   To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status in an am session: file does not exist' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt "one" &&
+	git rm main.txt &&
+	git commit -m "delete main.txt" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are in the middle of an am session:
+	#   When you have resolved this problem run "git am --resolved".
+	#   If you would prefer to skip this patch, instead run "git am --skip".
+	#   To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status in an am session: wrong format' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one one.txt "one" &&
+	test_commit two two.txt "two" &&
+	test_commit three three.txt "three" &&
+	git format-patch -3 -oMaildir &&
+	git rm one.txt two.txt three.txt &&
+	git commit -m "delete all" &&
+	echo error >Maildir/0002-two.patch &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are in the middle of an am session:
+	# The current patch is empty!
+	#   When you have resolved this problem run "git am --resolved".
+	#   If you would prefer to skip this patch, instead run "git am --skip".
+	#   To restore the original branch and stop patching run "git am --abort".
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	Maildir/
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when bisecting' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	git bisect start &&
+	git bisect bad &&
+	git bisect good one &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently bisecting.
+	#   To get back to the original branch run "git bisect reset"
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	nothing added to commit but untracked files present (use "git add" to track)
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when rebase conflicts with statushints disabled' '
+	git init git &&
+	cd git &&
+	test_when_finished "cd ../ && rm -rf git" &&
+	git config --local advice.statushints false &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expect <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#
+	# Unmerged paths:
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#	expect
+	#	output
+	no changes added to commit
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_expect_success 'status when cherry-picking before resolving conflicts' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git checkout -b second_branch &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	git checkout master &&
+	test_must_fail git cherry-pick two &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently cherry-picking: fix conflicts and run "git commit".
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+test_expect_success 'status when cherry-picking after resolving conflicts' '
+	test_when_finished "cd ../ && rm -rf git"
+	echo end >main.txt &&
+	git add main.txt &&
+	cat >expect <<-\EOF &&
+	# On branch master
+	# You are currently cherry-picking: all conflicts fixed: run "git commit".
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
+
+test_done
-- 
1.7.8

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

* [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate
  2012-05-31 15:15       ` [PATCHv5 " Kong Lucien
  2012-05-31 15:15         ` [PATCHv5 2/3] t7512-status-help.sh: better advices for git status Kong Lucien
@ 2012-05-31 15:15         ` Kong Lucien
  2012-06-01  8:55           ` Matthieu Moy
  2012-06-01 12:15           ` Phil Hord
  2012-05-31 21:36         ` [PATCHv5 1/3] wt-status.*: better advices for git status added Junio C Hamano
                           ` (2 subsequent siblings)
  4 siblings, 2 replies; 97+ messages in thread
From: Kong Lucien @ 2012-05-31 15:15 UTC (permalink / raw)
  To: git
  Cc: Matthieu.Moy, Kong Lucien, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen

The display of the advice '(use git add/rm [...])' (when there are
unmerged files) after running 'git status' is now depending of the
mark, whether it's 'both deleted', 'deleted by us/them' or others. For
instance, when there is just one file that's marked as 'both deleted',
'git status' shows '(use git rm [...])' and if there are two files,
one as 'both deleted' and the other as 'added by them', the advice is
'(use git add/rm [...])'.

The previous tests in t7512-status-help.sh are updated.

Test about the case of only 'both deleted' is added in
t7060-wtstatus.sh

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
---
 t/t7060-wtstatus.sh    |   28 ++++++++++++++++++++++++++++
 t/t7512-status-help.sh |    6 +++---
 wt-status.c            |   37 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index 8a6d68a..60a1b99 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -189,4 +189,32 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted)
 	test_cmp expect output
 '
 
+
+test_expect_success 'status when conflicts with only rm advice (both deleted)' '
+	test_when_finished "cd ../ && rm -rf git" &&
+	git add sub_master.txt &&
+	git add sub_second.txt &&
+	cat >expect <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths; fix conflicts and run "git commit".
+	#
+	# Changes to be committed:
+	#
+	#	new file:   sub_master.txt
+	#
+	# Unmerged paths:
+	#   (use "git rm <file>..." to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#
+	# Untracked files:
+	#   (use "git add <file>..." to include in what will be committed)
+	#
+	#	expect
+	#	output
+	EOF
+	git status >output &&
+	test_cmp expect output
+'
+
 test_done
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index af1d130..83c42df 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -27,7 +27,7 @@ test_expect_success 'status when conflicts unresolved' '
 	# You have unmerged paths; fix conflicts and run "git commit".
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -78,7 +78,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -306,7 +306,7 @@ test_expect_success 'status when cherry-picking before resolving conflicts' '
 	# You are currently cherry-picking: fix conflicts and run "git commit".
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
diff --git a/wt-status.c b/wt-status.c
index f4ba021..ee503b8 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -131,9 +131,34 @@ void wt_status_prepare(struct wt_status *s)
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
 {
+	int i;
+	int del_mod_conflict = 0;
+	int both_deleted = 0;
+	int not_deleted = 0;
 	const char *c = color(WT_STATUS_HEADER, s);
 
 	status_printf_ln(s, c, _("Unmerged paths:"));
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct string_list_item *it = &(s->change.items[i]);
+		struct wt_status_change_data *d = it->util;
+
+		switch (d->stagemask) {
+		case 0:
+			break;
+		case 1:
+			both_deleted = 1;
+			break;
+		case 3:
+		case 5:
+			del_mod_conflict = 1;
+			break;
+		default:
+			not_deleted = 1;
+			break;
+		}
+	}
+
 	if (!advice_status_hints)
 		return;
 	if (s->whence != FROM_COMMIT)
@@ -142,7 +167,17 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
 		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
 		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
-	status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+
+	if (!both_deleted) {
+		if (!del_mod_conflict)
+			status_printf_ln(s, c, _("  (use \"git add <file>...\" to mark resolution)"));
+		else
+			status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	} else if (!del_mod_conflict && !not_deleted) {
+		status_printf_ln(s, c, _("  (use \"git rm <file>...\" to mark resolution)"));
+	} else {
+		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	}
 	status_printf_ln(s, c, "");
 }
 
-- 
1.7.8

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-05-31 15:15       ` [PATCHv5 " Kong Lucien
  2012-05-31 15:15         ` [PATCHv5 2/3] t7512-status-help.sh: better advices for git status Kong Lucien
  2012-05-31 15:15         ` [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
@ 2012-05-31 21:36         ` Junio C Hamano
  2012-06-01  9:16           ` konglu
  2012-06-01  8:42         ` Matthieu Moy
  2012-06-03 18:30         ` [PATCHv6 1/4] " Kong Lucien
  4 siblings, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-05-31 21:36 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Matthieu.Moy, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> This patch provides new informative help messages in the display of
> 'git status' (at the top) during conflicts, rebase, am, bisect or
> cherry-pick process.
>
> The new messages are not shown when using options such as -s or
> --porcelain. The messages about the current situation of the user are
> always displayed but the advices on what the user needs to do in order
> to resume a rebase/bisect /am/ commit after resolving conflicts can be

Is there a reason why there is a SP after bisect here?

> hidden by setting advice.statushints to 'false' in the config file.
>
> Thus, information about the updated advice.statushints key are added
> in Documentation/config.txt.
>
> Also, the test t7060-wt-status.sh is now working with the new help
> messages. Tests about suggestions of "git rm" are also added.

Looks much better and getting ready for being at least on 'pu' if
not 'next', it seems.

> Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
> Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
> Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
> Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
> Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>

How is your development process work, by the way?  Does everybody on
this list have code in this patch?  Or are you just listing people
who are in the same class taught by Matthieu who reviewed and
commented on this patch?

>  Documentation/config.txt |    2 +
>  t/t7060-wtstatus.sh      |   71 +++++++++++++++++++++
>  wt-status.c              |  154 ++++++++++++++++++++++++++++++++++++++++++++++
>  wt-status.h              |   11 +++
>  4 files changed, 238 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 915cb5a..52f5009 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -162,6 +162,8 @@ advice.*::
>  		Directions on how to stage/unstage/add shown in the
>  		output of linkgit:git-status[1] and the template shown
>  		when writing commit messages.
> +		Directions on how to end the current process shown
> +		in the output of linkgit:git-status[1].

I kind of find this hard to read.  Perhaps it shouldn't be a
separate sentence, but instead should just enhance the existing
limited "stage/unstage/add" set?  The list of updated, modified and
untracked paths with instructions given by the current code is an
incomplete description of the current state, and I view this patch
as filling the missing bits to it to make the output more complete.

So from that point of view, perhaps more like this?

-	Directions on how to stage/unstage/add shown in the
-	output of linkgit:git-status[1] and the template shown
-	when writing commit messages.
+	Show directions on how to proceed from the current state
+	in the output of linkgit:git-status[1] and in the template
+	shown when writing commit messages in linkgit:git-commit[1].

> diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
> index b8cb490..8a6d68a 100755
> --- a/t/t7060-wtstatus.sh
> +++ b/t/t7060-wtstatus.sh
> @@ -30,6 +30,8 @@ test_expect_success 'Report new path with conflict' '
>  
>  cat >expect <<EOF
>  # On branch side
> +# You have unmerged paths; fix conflicts and run "git commit".
> +#
>  # Unmerged paths:
>  #   (use "git add/rm <file>..." as appropriate to mark resolution)
>  #
> @@ -118,4 +120,73 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
>  	test_cmp expected actual
>  '

Note what filenames are used to store the expected output and grab
the actual output out of the command.

> +
> +test_expect_success 'status when conflicts with add and rm advice (deleted by them)' '
> +	git init git &&
> +	cd git &&
> +	test_when_finished "cd ../ && rm -rf git" &&

This is a tangent, but this sequence is wrong.  If "git init"
succeeds but "cd git" fails for some reason, you wouldn't clean the
new test repository, and worse, you go up and try to remove a random
"git" that is different from what you created here.

Perhaps I am being a bit superstitous, but I would feel a lot safer
to see if this were written like this:

        git init git &&
        (
		cd git &&
                ... the rest of this test ...
	) &&
        rm -fr git

to avoid mistakes.  For example, if you add any "cd somewhere-else"
in the remainder of the test, your test_when_finished to go to a
relative "cd ../" wouldn't do you any good.

> +	test_commit init main.txt init &&
> +	git checkout -b second_branch &&
> +	git rm main.txt &&
> +	git commit -m "main.txt deleted on second_branch" &&
> +	test_commit second conflict.txt second &&
> +	git checkout master &&
> +	test_commit on_second main.txt on_second &&
> +	test_commit master conflict.txt master &&
> +	test_must_fail git merge second_branch &&
> +	cat >expect <<-\EOF &&
> +	# On branch master
> +	# You have unmerged paths; fix conflicts and run "git commit".
> +	#
> +	# Unmerged paths:
> +	#   (use "git add/rm <file>..." as appropriate to mark resolution)
> +	#
> +	#	both added:         conflict.txt
> +	#	deleted by them:    main.txt
> +	#
> +	# Untracked files:
> +	#   (use "git add <file>..." to include in what will be committed)
> +	#
> +	#	expect
> +	#	output
> +	no changes added to commit (use "git add" and/or "git commit -a")
> +	EOF
> +	git status >output &&
> +	test_cmp expect output
> +'

And rename "output" to "actual" to match the existing practice
(unless there is a compelling reason not to).

> diff --git a/wt-status.c b/wt-status.c
> index dd6d8c4..f4ba021 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
>  	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
>  	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
>  	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
> +	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
>  };
>  
>  static const char *color(int slot, struct wt_status *s)
> @@ -728,6 +729,158 @@ static void wt_status_print_tracking(struct wt_status *s)
>  	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
>  }
>  
> +static int has_unmerged(struct wt_status *s)
> +{
> +	int i;
> +
> +	for (i = 0; i < s->change.nr; i++) {
> +		struct wt_status_change_data *d;
> +		d = s->change.items[i].util;
> +		if (d->stagemask)
> +			return 1;
> +	}
> +	return 0;
> +}
> +
> +static void merge_in_progress_show(struct wt_status *s,
> +				struct wt_status_state *state,
> +				const char *color)

Minor nit: perhaps "show-merge-in-progress" would read more
naturally (same for all other helpers).

> +{
> +	if (has_unmerged(s))
> +		status_printf_ln(s, color, _("You have unmerged paths%s"),
> +			advice_status_hints
> +			? _("; fix conflicts and run \"git commit\".") : ".");
> +	else
> +		status_printf_ln(s, color, _("You are still merging%s"),
> +			advice_status_hints
> +			? _(", run \"git commit\" to conclude merge.") : ".");

The former uses ';' while the latter uses ','.  There is a use of
':' in the rebase-in-progress helper.  Be consistent (if I were
writing this code, I would pick ';').

Would this qualify as a "language lego" i18n/l10n people loathe?
IOW would it be better to have four independent messages?

        "You have unmerged paths."
        "You are still merging."
        "You have unmerged paths; fix conflicts and..."
	"You are still merging; fun \"git commit\" to conclude..."

This is not a rhetorical question.  There is the same issue in the
rebase-in-progress helper.

> +static void am_in_progress_show(struct wt_status *s,
> +				struct wt_status_state *state,
> +				const char *color)
> +{
> +	status_printf_ln(s, color,
> +		_("You are in the middle of an am session:"));
> +	if (state->am_empty_patch)
> +		status_printf_ln(s, color,
> +			_("The current patch is empty!"));

This situation may deserve a "; run 'am --skip' to skip it." advice.

> +static void rebase_in_progress_show(struct wt_status *s,
> +				struct wt_status_state *state,
> +				const char *color)
> +{
> +	if (has_unmerged(s)) {
> +		status_printf_ln(s, color, _("You are currently rebasing%s"),
> +			advice_status_hints
> +			? _(": fix conflicts and then run \"git rebase --continue\".") : ".");
> +		if (advice_status_hints) {
> +			status_printf_ln(s, color,
> +				_("  If you would prefer to skip this patch, instead run \"git rebase --skip\"."));
> +			status_printf_ln(s, color,
> +				_("  To check out  the original branch and stop rebasing run \"git rebase --abort\"."));

Double-space in the middle intended?

This line looks overly long.  Does it fit (with the # prefix) on
typical 80-column terminals?

> +		}
> +	} else if (state->rebase_in_progress) {
> +		status_printf_ln(s, color, _("You are currently rebasing%s"),
> +			advice_status_hints
> +			? _(": all conflicts fixed: run \"git rebase --continue\".") : ".");

The above will show this:

# You are currently rebasing: all conflicts fixed: run "git rebase --continue.

That's 78 cols, which is pushing the right edge too closely,
especially considering that translations tend to make messages
longer.

Aside from questionable use of ':' (I think ';' is better for the
first one, and '.' is better for the latter; and s/run/Run/ to begin
a new sentence), I think this is nicer than the merge-in-progress
message after the user has already marked all paths resolved, which
says "You are still merging" without saying "you have resolved
everything".  Perhaps you meant to hint that by saying "still" (as
opposed to "currently"), but the distinction feels a bit too subtle.


> +	} else {
> +		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
> +		if (advice_status_hints) {
> +			status_printf_ln(s, color, _("  You can amend the commit with"));
> +			status_printf_ln(s, color, _("	git commit --amend"));
> +			status_printf_ln(s, color, _("  Once you are satisfied with your changes, run"));
> +			status_printf_ln(s, color, _("	git rebase --continue"));

For an advice in "git status" output, the above may be appropriate,
but would the user see this in "git commit" template, and if so,
isn't it because the user typed "git commit --amend"?  Does it make
sense to suggest to run "git commit --amend" in that context?

The same comment applies to all new advice messages added by this
patch.

Thanks.

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-05-31 15:15       ` [PATCHv5 " Kong Lucien
                           ` (2 preceding siblings ...)
  2012-05-31 21:36         ` [PATCHv5 1/3] wt-status.*: better advices for git status added Junio C Hamano
@ 2012-06-01  8:42         ` Matthieu Moy
  2012-06-01 11:27           ` konglu
  2012-06-03 18:30         ` [PATCHv6 1/4] " Kong Lucien
  4 siblings, 1 reply; 97+ messages in thread
From: Matthieu Moy @ 2012-06-01  8:42 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> +	cat >expect <<-\EOF &&
[...]
> +	# Untracked files:
> +	#   (use "git add <file>..." to include in what will be committed)
> +	#
> +	#	expect
> +	#	output
> +	no changes added to commit (use "git add" and/or "git commit -a")
> +	EOF
> +	git status >output &&

You can run

  git status --untracked-files=no

instead, to get rid of these "expect" and "output". as Junio mentionned
on another topic, these make the test scripts a bit harder to maintain,
for example you should rename "output" to "actual", and you don't want
that to interfere with the content of "expect".

> +	} else if (state->rebase_in_progress) {
> +		status_printf_ln(s, color, _("You are currently rebasing%s"),
> +			advice_status_hints
> +			? _(": all conflicts fixed: run \"git rebase --continue\".") : ".");

Avoid having two ":" in the same sentense.

> +		if (advice_status_hints) {
> +			status_printf_ln(s, color, _("  You can amend the commit with"));
> +			status_printf_ln(s, color, _("	git commit --amend"));
> +			status_printf_ln(s, color, _("  Once you are satisfied with your changes, run"));
> +			status_printf_ln(s, color, _("	git rebase --continue"));
> +		}

Can this be more consistant with other status hints? When a hint follows
a statement on the next line, it's usually

# Say something
#   (use "git whatever" to change the current state)

e.g.

# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)

So this may be turned into

# Rebase in progress
#   (use "git commit --amend" to amend the current commit)
#   (use "git rebase --continue" once you are satisfied with your changes)

> +	if (state->merge_in_progress)
> +		merge_in_progress_show(s, state, state_color);
> +	else if (state->am_in_progress)
> +		am_in_progress_show(s, state, state_color);
> +	else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
> +		rebase_in_progress_show(s, state, state_color);
> +	else if (state->cherry_pick_in_progress)
> +		cherry_pick_in_progress_show(s, state, state_color);
> +	if (state->bisect_in_progress)
> +		bisect_in_progress_show(s, state, state_color);

I still disagree with the "else if" logic here. If the user started two
operations, I think we should show both messages.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate
  2012-05-31 15:15         ` [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
@ 2012-06-01  8:55           ` Matthieu Moy
  2012-06-01 12:15           ` Phil Hord
  1 sibling, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-06-01  8:55 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

>  	# Unmerged paths:
> -	#   (use "git add/rm <file>..." as appropriate to mark resolution)
> +	#   (use "git add <file>..." to mark resolution)
>  	#
>  	#	both modified:      main.txt
>  	#

This makes me think of another possible improvement (unrelated from this
one). When merging a binary file, one gets

# On branch branch
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      binary.bin
#

But no conflict markers, as they would make no sense in the file. Then,
it's a real pain to fix if you're not a Git expert. It would help, in
the presence of binary files, to turn that into :

# Unmerged paths:
#   (use "git checkout --ours [-- path]" to checkout your version)
#   (use "git checkout --theirs [-- path]" to checkout the version being merged)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      binary.bin
#

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-05-31 21:36         ` [PATCHv5 1/3] wt-status.*: better advices for git status added Junio C Hamano
@ 2012-06-01  9:16           ` konglu
  2012-06-01  9:26             ` Matthieu Moy
  2012-06-01 16:51             ` Junio C Hamano
  0 siblings, 2 replies; 97+ messages in thread
From: konglu @ 2012-06-01  9:16 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Matthieu.Moy, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen


Junio C Hamano <gitster@pobox.com> a écrit :

> How is your development process work, by the way?  Does everybody on
> this list have code in this patch?  Or are you just listing people
> who are in the same class taught by Matthieu who reviewed and
> commented on this patch?

Basically, we 5 people are in the same group and work together on
the same project. Some are more involved into improving the advices
in git status, and some are more involved into the XDG configuration
but we are all in the same room thus there're a lot of communication so
everyone knows what's happening in each topics. Matthieu is helping us
when we have technical questions but he doesn't review our code beforehand
(he is very busy :p).

Btw, we're also working on other small improvements such as the implementation
of "git rebase -i --exec <cmd>".

> And rename "output" to "actual" to match the existing practice
> (unless there is a compelling reason not to).

We based our coding-style on the t7508-status.sh script which
seem to use out-of-date style (some instructions are not in
test_expect_success for example). We will use the modern coding
style from now on.

>> +	} else {
>> +		status_printf_ln(s, color, _("You are currently editing a commit  
>> during a rebase."));
>> +		if (advice_status_hints) {
>> +			status_printf_ln(s, color, _("  You can amend the commit with"));
>> +			status_printf_ln(s, color, _("	git commit --amend"));
>> +			status_printf_ln(s, color, _("  Once you are satisfied with  
>> your changes, run"));
>> +			status_printf_ln(s, color, _("	git rebase --continue"));
>
> For an advice in "git status" output, the above may be appropriate,
> but would the user see this in "git commit" template, and if so,
> isn't it because the user typed "git commit --amend"?  Does it make
> sense to suggest to run "git commit --amend" in that context?

True, the user will see the messages in the "git commit" template. We
didn't take this case into account because we thought that not many people
read the status in the "git commit" template. Anyway, just adding a condition

if (advice_status_hints && !s->amend)

does the job.

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-06-01  9:16           ` konglu
@ 2012-06-01  9:26             ` Matthieu Moy
  2012-06-01 14:50               ` Junio C Hamano
  2012-06-01 16:51             ` Junio C Hamano
  1 sibling, 1 reply; 97+ messages in thread
From: Matthieu Moy @ 2012-06-01  9:26 UTC (permalink / raw)
  To: konglu
  Cc: Junio C Hamano, Kong Lucien, git, Duperray Valentin,
	Jonas Franck, Nguy Thomas, Nguyen Huynh Khoi Nguyen

konglu@minatec.inpg.fr writes:

> Junio C Hamano <gitster@pobox.com> a écrit :
>
>> How is your development process work, by the way?  Does everybody on
>> this list have code in this patch?  Or are you just listing people
>> who are in the same class taught by Matthieu who reviewed and
>> commented on this patch?
>
> Basically, we 5 people are in the same group and work together on
> the same project. Some are more involved into improving the advices
> in git status, and some are more involved into the XDG configuration
> but we are all in the same room thus there're a lot of communication so
> everyone knows what's happening in each topics. Matthieu is helping us
> when we have technical questions but he doesn't review our code beforehand
> (he is very busy :p).

Just an addition: I'm not really a co-author of the work, but I'm the
one who authorize the students to contribute their code to Git (they are
normally not allowed to distribute the code they develop for school
projects).

I think this implies that I should appear in the Signed-off-by: of the
patches.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-06-01  8:42         ` Matthieu Moy
@ 2012-06-01 11:27           ` konglu
  2012-06-01 12:40             ` Phil Hord
  0 siblings, 1 reply; 97+ messages in thread
From: konglu @ 2012-06-01 11:27 UTC (permalink / raw)
  To: Matthieu Moy
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=";"; format=flowed	DelSp=Yes, Size: 1364 bytes --]


Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> a écrit :

>> +	if (state->merge_in_progress)
>> +		merge_in_progress_show(s, state, state_color);
>> +	else if (state->am_in_progress)
>> +		am_in_progress_show(s, state, state_color);
>> +	else if (state->rebase_in_progress ||  
>> state->rebase_interactive_in_progress)
>> +		rebase_in_progress_show(s, state, state_color);
>> +	else if (state->cherry_pick_in_progress)
>> +		cherry_pick_in_progress_show(s, state, state_color);
>> +	if (state->bisect_in_progress)
>> +		bisect_in_progress_show(s, state, state_color);
>
> I still disagree with the "else if" logic here. If the user started two
> operations, I think we should show both messages.

We show both messages in the case of bisect. However, we decided to
implement a priority for the other cases because of how the code figures
out the current state.
The cases in which you're in 'am' AND 'rebase' or only in 'am' is hard to
handle. Thus The priority is given to the 'am' because running 'am' during
a 'rebase' is possible (and the other way is not).
On top of that, I think that the user only needs to know his "most recent"
current state. Given that he's running 'am' during a 'rebase', knowing that
he's in am progress is enough. If he finishes the 'am', then he will still
know that he's in a 'rebase' with 'git status'.

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

* Re: [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate
  2012-05-31 15:15         ` [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
  2012-06-01  8:55           ` Matthieu Moy
@ 2012-06-01 12:15           ` Phil Hord
  2012-06-01 14:08             ` konglu
  1 sibling, 1 reply; 97+ messages in thread
From: Phil Hord @ 2012-06-01 12:15 UTC (permalink / raw)
  To: git, Jeff King, Michael J Gruber
  Cc: Matthieu.Moy, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Kong Lucien

On Thu, May 31, 2012 at 11:15 AM, Kong Lucien
<Lucien.Kong@ensimag.imag.fr> wrote:
> The display of the advice '(use git add/rm [...])' (when there are
> unmerged files) after running 'git status' is now depending of the
> mark, whether it's 'both deleted', 'deleted by us/them' or others. For
> instance, when there is just one file that's marked as 'both deleted',
> 'git status' shows '(use git rm [...])' and if there are two files,
> one as 'both deleted' and the other as 'added by them', the advice is
> '(use git add/rm [...])'.
>
...
diff --git a/wt-status.c b/wt-status.c
...
> @@ -142,7 +167,17 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
>                status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
>        else
>                status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
> -       status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
> +
> +       if (!both_deleted) {
> +               if (!del_mod_conflict)
> +                       status_printf_ln(s, c, _("  (use \"git add <file>...\" to mark resolution)"));
> +               else
> +                       status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
> +       } else if (!del_mod_conflict && !not_deleted) {
> +               status_printf_ln(s, c, _("  (use \"git rm <file>...\" to mark resolution)"));
> +       } else {
> +               status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
> +       }
>        status_printf_ln(s, c, "");
>  }


This brings a frequent frustration to the front.  It is not the fault
of this commit, so please don't think I am blaming you, Lucien.  Thank
you for highlighting it.

> +       } else if (!del_mod_conflict && !not_deleted) {
> +               status_printf_ln(s, c, _("  (use \"git rm <file>...\" to mark resolution)"));

Why should I be bothered when both sides delete the same file?  Does
this case only occur when each side has made different changes to the
file prior to deleting it, or does it occur any time each commit has
deleted the same exact file?

As this patch highlights, the only expected resolution is to 'git rm'
the file; why can't git figure this out for me and continue on?

Is there a config option to alter this behavior?

Phil

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-06-01 11:27           ` konglu
@ 2012-06-01 12:40             ` Phil Hord
  2012-06-01 16:57               ` Junio C Hamano
  0 siblings, 1 reply; 97+ messages in thread
From: Phil Hord @ 2012-06-01 12:40 UTC (permalink / raw)
  To: konglu
  Cc: Matthieu Moy, Kong Lucien, git, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen

On Fri, Jun 1, 2012 at 7:27 AM,  <konglu@minatec.inpg.fr> wrote:
>
> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> a écrit :
>
>>> +    if (state->merge_in_progress)
>>> +            merge_in_progress_show(s, state, state_color);
>>> +    else if (state->am_in_progress)
>>> +            am_in_progress_show(s, state, state_color);
>>> +    else if (state->rebase_in_progress ||
>>> state->rebase_interactive_in_progress)
>>> +            rebase_in_progress_show(s, state, state_color);
>>> +    else if (state->cherry_pick_in_progress)
>>> +            cherry_pick_in_progress_show(s, state, state_color);
>>> +    if (state->bisect_in_progress)
>>> +            bisect_in_progress_show(s, state, state_color);
>>
>> I still disagree with the "else if" logic here. If the user started two
>> operations, I think we should show both messages.
>
> We show both messages in the case of bisect. However, we decided to
> implement a priority for the other cases because of how the code figures
> out the current state.
> The cases in which you're in 'am' AND 'rebase' or only in 'am' is hard to
> handle. Thus The priority is given to the 'am' because running 'am' during
> a 'rebase' is possible (and the other way is not).
> On top of that, I think that the user only needs to know his "most recent"
> current state. Given that he's running 'am' during a 'rebase', knowing that
> he's in am progress is enough. If he finishes the 'am', then he will still
> know that he's in a 'rebase' with 'git status'.


Related to this, I think this is all useful information which is being
gathered and analyzed here.  It would be useful if all of the git code
could use these status functions in common instead of implementing
similar functionality individually.  But that is a topic for another
commit.

More appropriate for now is that I think there should be a
porcelain(?) version of this information.  First, imagine we can get
just this new session status information with a switch named
'--sequencer'[*]::

  $ git status --sequencer
  You have unmerged paths.
  You are in an am session.
  You are in the middle of an interactive rebase.

  $ git status --porcelain --sequencer
  airu

The "--porcelain --sequencer" combination I am imagining here would
show the status as a script-parseable sequence of single-letter
indicators telling the status of these same various conditions:
  u - unmerged paths
  a - git-am session
  i - interactive rebase
  r - rebase
  c - cherry-pick
  m - merge
etc.

By giving a value to --porcelain, we could limit the test to certain
conditions and return a meaningful result code if any are true.

  $ if git status --porcelain --sequencer=u ; then echo "Unmerged
paths exist" ; fi

I don't know if it makes sense to spell the --porcelain version with
or without spaces/newlines.  Any opinions?

What about the idea overall?

Phil

[*] Though I hate the choice of 'sequencer' as an option name for the
user, it makes sense to me in this context. Please suggest any
alternatives that spring to mind.

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

* Re: [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate
  2012-06-01 12:15           ` Phil Hord
@ 2012-06-01 14:08             ` konglu
  2012-06-01 16:38               ` Junio C Hamano
  0 siblings, 1 reply; 97+ messages in thread
From: konglu @ 2012-06-01 14:08 UTC (permalink / raw)
  To: Phil Hord
  Cc: git, Jeff King, Michael J Gruber, Matthieu.Moy,
	Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Kong Lucien


Phil Hord <phil.hord@gmail.com> a écrit :

>> +       } else if (!del_mod_conflict && !not_deleted) {
>> +               status_printf_ln(s, c, _("  (use \"git rm  
>> <file>...\" to mark resolution)"));
>
> Why should I be bothered when both sides delete the same file?  Does
> this case only occur when each side has made different changes to the
> file prior to deleting it, or does it occur any time each commit has
> deleted the same exact file?

If both sides delete the same file with "git rm", this case does not occur
because there is no conflict when merging. However, it can occur when
both sides rename the file and then merge.

> As this patch highlights, the only expected resolution is to 'git rm'
> the file; why can't git figure this out for me and continue on?

I agree. The only option for the user is to run "git rm". You also have
to type the whole name of the deleted file as you can't tab for completion
and you can't avoid it as it's part of "unmerged path" (so you have to
resolve the current index). It would be great if git could figure it by
itself so we don't have to go through this process. Nevertheless, the
current display of the advice shows "git add" which can infer that you
can still recover the deleted file, which is not the case. At least, with
this code, the user will avoid this confusion.

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-06-01  9:26             ` Matthieu Moy
@ 2012-06-01 14:50               ` Junio C Hamano
  0 siblings, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-06-01 14:50 UTC (permalink / raw)
  To: Matthieu Moy
  Cc: konglu, Kong Lucien, git, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen

Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:

> Just an addition: I'm not really a co-author of the work, but I'm the
> one who authorize the students to contribute their code to Git (they are
> normally not allowed to distribute the code they develop for school
> projects).
>
> I think this implies that I should appear in the Signed-off-by: of the
> patches.

Glad I asked.  Yes, it would very much help if you sign off these
patches if that is the case.

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

* Re: [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate
  2012-06-01 14:08             ` konglu
@ 2012-06-01 16:38               ` Junio C Hamano
  0 siblings, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-06-01 16:38 UTC (permalink / raw)
  To: konglu
  Cc: Phil Hord, git, Jeff King, Michael J Gruber, Matthieu.Moy,
	Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Kong Lucien

konglu@minatec.inpg.fr writes:

> If both sides delete the same file with "git rm", this case does not occur
> because there is no conflict when merging. However, it can occur when
> both sides rename the file and then merge.
>
>> As this patch highlights, the only expected resolution is to 'git rm'
>> the file; why can't git figure this out for me and continue on?
>
> I agree. The only option for the user is to run "git rm".

If both sides remove the path A and one side creates a similar
looking B but the other side does so for C, it is clear that neither
side wants A in the result, so the only option FOR THE PATH A is to
run "git rm".

But when looking at B and C to decide, it would help knowing that
the corresponding source of these renames is potentially A.  If we
auto-resolved A, we would lose that information, no?

You need to look at a larger picture.

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-06-01  9:16           ` konglu
  2012-06-01  9:26             ` Matthieu Moy
@ 2012-06-01 16:51             ` Junio C Hamano
  2012-06-01 19:39               ` konglu
  1 sibling, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-06-01 16:51 UTC (permalink / raw)
  To: konglu
  Cc: Kong Lucien, git, Matthieu.Moy, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen

konglu@minatec.inpg.fr writes:

>>> +	} else {
>>> +		status_printf_ln(s, color, _("You are currently editing a commit  
>>> during a rebase."));
>>> +		if (advice_status_hints) {
>>> +			status_printf_ln(s, color, _("  You can amend the commit with"));
>>> +			status_printf_ln(s, color, _("	git commit --amend"));
>>> +			status_printf_ln(s, color, _("  Once you are satisfied with  
>>> your changes, run"));
>>> +			status_printf_ln(s, color, _("	git rebase --continue"));
>>
>> For an advice in "git status" output, the above may be appropriate,
>> but would the user see this in "git commit" template, and if so,
>> isn't it because the user typed "git commit --amend"?  Does it make
>> sense to suggest to run "git commit --amend" in that context?
>
> True, the user will see the messages in the "git commit" template. We
> didn't take this case into account because we thought that not many people
> read the status in the "git commit" template. Anyway, just adding a condition
>
> if (advice_status_hints && !s->amend)
>
> does the job.

Hrm, what would happen if the user ran "git commit" without --amend?

It could be done by mistake, which will be greatly helped by the
information you already gathered during the inspection phase.  

This also can be done deliberately to split a commit in "rebase -i",
so "You are in 'rebase -i', do not commit without --amend!" is a
wrong message, but it may be sensible to give "are you sure you
meant to commit without --amend?"

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-06-01 12:40             ` Phil Hord
@ 2012-06-01 16:57               ` Junio C Hamano
  2012-06-04 18:00                 ` Phil Hord
  0 siblings, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-06-01 16:57 UTC (permalink / raw)
  To: Phil Hord
  Cc: konglu, Matthieu Moy, Kong Lucien, git, Duperray Valentin,
	Jonas Franck, Nguy Thomas, Nguyen Huynh Khoi Nguyen

Phil Hord <phil.hord@gmail.com> writes:

>   $ git status --sequencer
>   You have unmerged paths.
>   You are in an am session.
>   You are in the middle of an interactive rebase.
>
>   $ git status --porcelain --sequencer
>   airu
>
> The "--porcelain --sequencer" combination I am imagining here would
> show the status as a script-parseable sequence of single-letter
> indicators telling the status of these same various conditions:
>   u - unmerged paths
>   a - git-am session
>   i - interactive rebase
>   r - rebase
>   c - cherry-pick
>   m - merge
> etc.

Some people seem to think that machine-readable has to mean
unreadable cryptic line noises.  It's a disease.

If you have to write "etc.", you clearly do not know what the
range of possible values of these things will eventually be.

And I do not think it is your fault not to know what we would want
to add in the future.  But it is your fault to choose unreadable
cryptic line noises as an output format.

Just spell them out, and do not mark them for translation.

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-06-01 16:51             ` Junio C Hamano
@ 2012-06-01 19:39               ` konglu
  0 siblings, 0 replies; 97+ messages in thread
From: konglu @ 2012-06-01 19:39 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Matthieu.Moy, Duperray Valentin, Jonas Franck,
	Nguy Thomas, Nguyen Huynh Khoi Nguyen


Junio C Hamano <gitster@pobox.com> a écrit :

> konglu@minatec.inpg.fr writes:
>
>>>> +	} else {
>>>> +		status_printf_ln(s, color, _("You are currently editing a commit
>>>> during a rebase."));
>>>> +		if (advice_status_hints) {
>>>> +			status_printf_ln(s, color, _("  You can amend the commit with"));
>>>> +			status_printf_ln(s, color, _("	git commit --amend"));
>>>> +			status_printf_ln(s, color, _("  Once you are satisfied with
>>>> your changes, run"));
>>>> +			status_printf_ln(s, color, _("	git rebase --continue"));
>>>
>>> For an advice in "git status" output, the above may be appropriate,
>>> but would the user see this in "git commit" template, and if so,
>>> isn't it because the user typed "git commit --amend"?  Does it make
>>> sense to suggest to run "git commit --amend" in that context?
>>
>> True, the user will see the messages in the "git commit" template. We
>> didn't take this case into account because we thought that not many people
>> read the status in the "git commit" template. Anyway, just adding a  
>> condition
>>
>> if (advice_status_hints && !s->amend)
>>
>> does the job.
>
> Hrm, what would happen if the user ran "git commit" without --amend?

The new advices will still be displayed (of course only if advice.statushints
is enabled).

> It could be done by mistake, which will be greatly helped by the
> information you already gathered during the inspection phase.

Thus, if done by mistake, the user will know that he needs to do
"git commit --amend" to edit the commit.

> This also can be done deliberately to split a commit in "rebase -i",
> so "You are in 'rebase -i', do not commit without --amend!" is a
> wrong message, but it may be sensible to give "are you sure you
> meant to commit without --amend?"

An interesting case. In fact, more than warning the user about running
git commit without --amend, wouldn't it be better if there were specific
help messages about splitting a commit ? Like

# Not currently on any branch.
# You are currently splitting a commit.
#   (Once your working directory is clean, run "git rebase --continue")
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   t/t7060-wtstatus.sh
#       modified:   t/t7512-status-help.sh
#       modified:   wt-status.c
#
no changes added to commit (use "git add" and/or "git commit -a")

that will be the output of git status after a "git reset HEAD^" during
a rebase -i. There's already the advice "(use git add <file>...)" so
putting it twice is not really relevant.

What do you think about it ?

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

* [PATCHv6 1/4] wt-status.*: better advices for git status added
  2012-05-31 15:15       ` [PATCHv5 " Kong Lucien
                           ` (3 preceding siblings ...)
  2012-06-01  8:42         ` Matthieu Moy
@ 2012-06-03 18:30         ` Kong Lucien
  2012-06-03 18:30           ` [PATCHv6 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
                             ` (4 more replies)
  4 siblings, 5 replies; 97+ messages in thread
From: Kong Lucien @ 2012-06-03 18:30 UTC (permalink / raw)
  To: git
  Cc: Kong Lucien, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

This patch provides new informative help messages in the display of
'git status' (at the top) during conflicts, rebase, am, bisect or
cherry-pick process.

The new messages are not shown when using options such as -s or
--porcelain. The messages about the current situation of the user are
always displayed but the advices on what the user needs to do in order
to resume a rebase/bisect/am/commit after resolving conflicts can be
hidden by setting advice.statushints to 'false' in the config file.

Thus, information about the updated advice.statushints key are added
in Documentation/config.txt.

Also, the test t7060-wt-status.sh is now working with the new help
messages. Tests about suggestions of "git rm" are also added.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Moy Matthieu <Matthieu.Moy@grenoble-inp.fr>
---
The new advices that are protected by the key advice.statushints are
now stated the same way the other messages protected by the same config
key are.

 Documentation/config.txt |    4 +
 t/t7060-wtstatus.sh      |   67 +++++++++++++++++++
 wt-status.c              |  165 ++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.h              |   11 +++
 4 files changed, 247 insertions(+), 0 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a..670945d 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -162,6 +162,10 @@ advice.*::
 		Directions on how to stage/unstage/add shown in the
 		output of linkgit:git-status[1] and the template shown
 		when writing commit messages.
+		Show directions on how to proceed from the current
+		state in the output of linkgit:git-status[1] and in
+		the template shown when writing commit messages in
+		linkgit:git-commit[1].
 	commitBeforeMerge::
 		Advice shown when linkgit:git-merge[1] refuses to
 		merge to avoid overwriting local changes.
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb490..61d1f38 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,9 @@ test_expect_success 'Report new path with conflict' '
 
 cat >expect <<EOF
 # On branch side
+# You have unmerged paths.
+#   (fix conflicts and run "git commit")
+#
 # Unmerged paths:
 #   (use "git add/rm <file>..." as appropriate to mark resolution)
 #
@@ -118,4 +121,68 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
 	test_cmp expected actual
 '
 
+
+test_expect_success 'status when conflicts with add and rm advice (deleted by them)' '
+	git init git &&
+	(
+		cd git &&
+		test_commit init main.txt init &&
+		git checkout -b second_branch &&
+		git rm main.txt &&
+		git commit -m "main.txt deleted on second_branch" &&
+		test_commit second conflict.txt second &&
+		git checkout master &&
+		test_commit on_second main.txt on_second &&
+		test_commit master conflict.txt master &&
+		test_must_fail git merge second_branch &&
+		cat >expected <<-\EOF &&
+		# On branch master
+		# You have unmerged paths.
+		#   (fix conflicts and run "git commit")
+		#
+		# Unmerged paths:
+		#   (use "git add/rm <file>..." as appropriate to mark resolution)
+		#
+		#	both added:         conflict.txt
+		#	deleted by them:    main.txt
+		#
+		no changes added to commit (use "git add" and/or "git commit -a")
+		EOF
+		git status --untracked-files=no >actual &&
+		test_cmp expected actual
+	) &&
+	rm -rf git
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	git mv main.txt sub_master.txt &&
+	git commit -m "main.txt renamed in sub_master.txt" &&
+	git checkout second_branch &&
+	git mv main.txt sub_second.txt &&
+	git commit -m "main.txt renamed in sub_second.txt" &&
+	test_must_fail git merge master &&
+	cat >expected <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#	added by them:      sub_master.txt
+	#	added by us:        sub_second.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
 test_done
diff --git a/wt-status.c b/wt-status.c
index dd6d8c4..2460e20 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
 	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
 	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
+	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
 };
 
 static const char *color(int slot, struct wt_status *s)
@@ -728,6 +729,169 @@ static void wt_status_print_tracking(struct wt_status *s)
 	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
 }
 
+static int has_unmerged(struct wt_status *s)
+{
+	int i;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		d = s->change.items[i].util;
+		if (d->stagemask)
+			return 1;
+	}
+	return 0;
+}
+
+static void show_merge_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You have unmerged paths."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+	} else {
+		status_printf_ln(s, color,
+			_("All conflicts fixed but you are still merging."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (use \"git commit\" to conclude merge)"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_am_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color,
+		_("You are in the middle of an am session."));
+	if (state->am_empty_patch) {
+		status_printf_ln(s, color,
+			_("The current patch is empty; run \"git am --skip\" to skip it."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (use \"git am --abort\" to restore the original branch)"));
+	} else if (advice_status_hints) {
+		status_printf_ln(s, color,
+			_("  (when you have fixed this problem run \"git am --resolved\")"));
+		status_printf_ln(s, color,
+			_("  (use \"git am --skip\" to skip this patch)"));
+		status_printf_ln(s, color,
+			_("  (use \"git am --abort\" to restore the original branch)"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_rebase_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints) {
+			status_printf_ln(s, color,
+				_("  (fix conflicts and then run \"git rebase --continue\")"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --skip\" to skip this patch)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --abort\" to check out the original branch)"));
+		}
+	} else if (state->rebase_in_progress) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else {
+		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
+		if (advice_status_hints && !s->amend) {
+			status_printf_ln(s, color,
+				_("  (use \"git commit --amend\" to amend the current commit)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --continue\" once you are satisfied with your changes)"));
+		}
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_cherry_pick_in_progress(struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You are currently cherry-picking."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+	} else {
+		status_printf_ln(s, color, _("You are currently cherry-picking."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git commit\")"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_bisect_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color, _("You are currently bisecting."));
+	if (advice_status_hints)
+		status_printf_ln(s, color,
+			_("  (use \"git bisect reset\" to get back to the original branch)"));
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_print_state(struct wt_status *s)
+{
+	const char *state_color = color(WT_STATUS_IN_PROGRESS, s);
+	struct wt_status_state *state = calloc(1, sizeof(*state));
+	struct stat st;
+
+	state->merge_in_progress = 0;
+	state->am_in_progress = 0;
+	state->am_empty_patch = 0;
+	state->rebase_in_progress = 0;
+	state->rebase_interactive_in_progress = 0;
+	state->cherry_pick_in_progress = 0;
+	state->bisect_in_progress = 0;
+
+	if (!stat(git_path("MERGE_HEAD"), &st)) {
+		state->merge_in_progress = 1;
+	} else if (!stat(git_path("rebase-apply"), &st)) {
+		if (!stat(git_path("rebase-apply/applying"), &st)) {
+			state->am_in_progress = 1;
+			if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
+				state->am_empty_patch = 1;
+		} else {
+			state->rebase_in_progress = 1;
+		}
+	} else if (!stat(git_path("rebase-merge"), &st)) {
+		if (!stat(git_path("rebase-merge/interactive"), &st))
+			state->rebase_interactive_in_progress = 1;
+		else
+			state->rebase_in_progress = 1;
+	} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
+		state->cherry_pick_in_progress = 1;
+	}
+	if (!stat(git_path("BISECT_LOG"), &st))
+		state->bisect_in_progress = 1;
+
+	if (state->merge_in_progress)
+		show_merge_in_progress(s, state, state_color);
+	else if (state->am_in_progress)
+		show_am_in_progress(s, state, state_color);
+	else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
+		show_rebase_in_progress(s, state, state_color);
+	else if (state->cherry_pick_in_progress)
+		show_cherry_pick_in_progress(s, state, state_color);
+	if (state->bisect_in_progress)
+		show_bisect_in_progress(s, state, state_color);
+	free(state);
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
@@ -750,6 +914,7 @@ void wt_status_print(struct wt_status *s)
 			wt_status_print_tracking(s);
 	}
 
+	wt_status_print_state(s);
 	if (s->is_initial) {
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7..c1066a0 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -15,6 +15,7 @@ enum color_wt_status {
 	WT_STATUS_LOCAL_BRANCH,
 	WT_STATUS_REMOTE_BRANCH,
 	WT_STATUS_ONBRANCH,
+	WT_STATUS_IN_PROGRESS,
 	WT_STATUS_MAXSLOT
 };
 
@@ -71,6 +72,16 @@ struct wt_status {
 	struct string_list ignored;
 };
 
+struct wt_status_state {
+	int merge_in_progress;
+	int am_in_progress;
+	int am_empty_patch;
+	int rebase_in_progress;
+	int rebase_interactive_in_progress;
+	int cherry_pick_in_progress;
+	int bisect_in_progress;
+};
+
 void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
-- 
1.7.8

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

* [PATCHv6 2/4] t7512-status-help.sh: better advices for git status
  2012-06-03 18:30         ` [PATCHv6 1/4] " Kong Lucien
@ 2012-06-03 18:30           ` Kong Lucien
  2012-06-03 21:18             ` Junio C Hamano
  2012-06-03 18:30           ` [PATCHv6 3/4] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
                             ` (3 subsequent siblings)
  4 siblings, 1 reply; 97+ messages in thread
From: Kong Lucien @ 2012-06-03 18:30 UTC (permalink / raw)
  To: git
  Cc: Kong Lucien, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

The following tests include several cases in which the user needs to
run 'git status' to know his current situation, whether there're
conflicts or he's in rebase/bisect/am/ cherry-pick progress.

One of the test is about the set of the advice.statushints config key
to 'false' in .git/config.

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Moy Matthieu <Matthieu.Moy@grenoble-inp.fr>
---
 t/t7512-status-help.sh |  303 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 303 insertions(+), 0 deletions(-)
 create mode 100755 t/t7512-status-help.sh

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
new file mode 100755
index 0000000..5f62262
--- /dev/null
+++ b/t/t7512-status-help.sh
@@ -0,0 +1,303 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'status when conflicts unresolved' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	test_commit on_master main.txt on_master &&
+	git checkout second_branch &&
+	test_commit on_second_branch main.txt on_second_branch &&
+	test_must_fail git merge master &&
+	cat >expected <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	echo one >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch second_branch
+	# All conflicts fixed but you are still merging.
+	#   (use "git commit" to conclude merge)
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when rebase in progress before resolving conflicts' '
+	git commit -m "one" &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (fix conflicts and then run "git rebase --continue")
+	#   (use "git rebase --skip" to skip this patch)
+	#   (use "git rebase --abort" to check out the original branch)
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when rebase in progress before rebase --continue' '
+	test_when_finished "cd ../ && rm -rf git" &&
+	echo three >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (all conflicts fixed: run "git rebase --continue")
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when rebasing -i in edit mode' '
+	git init git &&
+	test_when_finished "rm -rf git fake-editor.sh" &&
+	(
+		cd git &&
+		test_commit one main.txt one &&
+		test_commit two main.txt two &&
+		test_commit three main.txt three &&
+		FAKE_LINES="1 edit 2" &&
+		export FAKE_LINES &&
+		git rebase -i HEAD~2 &&
+		cat >expected <<-\EOF &&
+		# Not currently on any branch.
+		# You are currently editing a commit during a rebase.
+		#   (use "git commit --amend" to amend the current commit)
+		#   (use "git rebase --continue" once you are satisfied with your changes)
+		#
+		nothing to commit (use -u to show untracked files)
+		EOF
+		git status --untracked-files=no >actual &&
+		test_cmp expected actual &&
+		git rebase --abort
+	)
+'
+
+
+test_expect_success 'status in an am session: file already exists' '
+	git init git &&
+	test_when_finished "rm -rf git" &&
+	(
+		cd git &&
+		test_commit one main.txt "one  " &&
+		git format-patch -1 -oMaildir &&
+		test_must_fail git am Maildir/*.patch &&
+		cat >expected <<-\EOF &&
+		# On branch master
+		# You are in the middle of an am session.
+		#   (when you have fixed this problem run "git am --resolved")
+		#   (use "git am --skip" to skip this patch)
+		#   (use "git am --abort" to restore the original branch)
+		#
+		nothing to commit (use -u to show untracked files)
+		EOF
+		git status --untracked-files=no >actual &&
+		test_cmp expected actual
+	)
+'
+
+
+test_expect_success 'status in an am session: file does not exist' '
+	git init git &&
+	test_when_finished "rm -rf git" &&
+	(
+		cd git &&
+		test_commit one main.txt "one" &&
+		git rm main.txt &&
+		git commit -m "delete main.txt" &&
+		git format-patch -1 -oMaildir &&
+		test_must_fail git am Maildir/*.patch &&
+		cat >expected <<-\EOF &&
+		# On branch master
+		# You are in the middle of an am session.
+		#   (when you have fixed this problem run "git am --resolved")
+		#   (use "git am --skip" to skip this patch)
+		#   (use "git am --abort" to restore the original branch)
+		#
+		nothing to commit (use -u to show untracked files)
+		EOF
+		git status --untracked-files=no >actual &&
+		test_cmp expected actual
+	)
+'
+
+
+test_expect_success 'status in an am session: empty patch' '
+	git init git &&
+	test_when_finished "rm -rf git" &&
+	(
+		cd git &&
+		test_commit one one.txt "one" &&
+		test_commit two two.txt "two" &&
+		test_commit three three.txt "three" &&
+		git format-patch -3 -oMaildir &&
+		git rm one.txt two.txt three.txt &&
+		git commit -m "delete all" &&
+		echo error >Maildir/0002-two.patch &&
+		test_must_fail git am Maildir/*.patch &&
+		cat >expected <<-\EOF &&
+		# On branch master
+		# You are in the middle of an am session.
+		# The current patch is empty; run "git am --skip" to skip it.
+		#   (use "git am --abort" to restore the original branch)
+		#
+		nothing to commit (use -u to show untracked files)
+		EOF
+		git status --untracked-files=no >actual &&
+		test_cmp expected actual
+	)
+'
+
+
+test_expect_success 'status when bisecting' '
+	git init git &&
+	test_when_finished "rm -rf git" &&
+	(
+		cd git &&
+		test_commit one main.txt one &&
+		test_commit two main.txt two &&
+		test_commit three main.txt three &&
+		git bisect start &&
+		git bisect bad &&
+		git bisect good one &&
+		cat >expected <<-\EOF &&
+		# Not currently on any branch.
+		# You are currently bisecting.
+		#   (use "git bisect reset" to get back to the original branch)
+		#
+		nothing to commit (use -u to show untracked files)
+		EOF
+		git status --untracked-files=no >actual &&
+		test_cmp expected actual
+	)
+'
+
+
+test_expect_success 'status when rebase conflicts with statushints disabled' '
+	git init git &&
+	test_when_finished "rm -rf git" &&
+	(
+		cd git &&
+		git config --local advice.statushints false &&
+		test_commit one main.txt one &&
+		test_commit two main.txt two &&
+		test_commit three main.txt three &&
+		test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+		cat >expected <<-\EOF &&
+		# Not currently on any branch.
+		# You are currently rebasing.
+		#
+		# Unmerged paths:
+		#	both modified:      main.txt
+		#
+		no changes added to commit
+		EOF
+		git status --untracked-files=no >actual &&
+		test_cmp expected actual
+	)
+'
+
+
+test_expect_success 'status when cherry-picking before resolving conflicts' '
+	git init git &&
+	cd git &&
+	test_commit init main.txt init &&
+	git checkout -b second_branch &&
+	test_commit one main.txt one &&
+	test_commit two main.txt two &&
+	test_commit three main.txt three &&
+	git checkout master &&
+	test_must_fail git cherry-pick two &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You are currently cherry-picking.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'status when cherry-picking after resolving conflicts' '
+	test_when_finished "cd ../ && rm -rf git"
+	echo end >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You are currently cherry-picking.
+	#   (all conflicts fixed: run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_done
-- 
1.7.8

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

* [PATCHv6 3/4] status: don't suggest "git rm" or "git add" if not appropriate
  2012-06-03 18:30         ` [PATCHv6 1/4] " Kong Lucien
  2012-06-03 18:30           ` [PATCHv6 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
@ 2012-06-03 18:30           ` Kong Lucien
  2012-06-03 19:34             ` Matthieu Moy
  2012-06-03 18:30           ` [PATCHv6 4/4] status: better advices when splitting a commit (during rebase -i) Kong Lucien
                             ` (2 subsequent siblings)
  4 siblings, 1 reply; 97+ messages in thread
From: Kong Lucien @ 2012-06-03 18:30 UTC (permalink / raw)
  To: git
  Cc: Kong Lucien, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

The display of the advice '(use git add/rm [...])' (when there are
unmerged files) after running 'git status' is now depending of the
mark, whether it's 'both deleted', 'deleted by us/them' or others. For
instance, when there is just one file that's marked as 'both deleted',
'git status' shows '(use git rm [...])' and if there are two files,
one as 'both deleted' and the other as 'added by them', the advice is
'(use git add/rm [...])'.

The previous tests in t7512-status-help.sh are updated.

Test about the case of only 'both deleted' is added in
t7060-wtstatus.sh

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Moy Matthieu <Matthieu.Moy@grenoble-inp.fr>
---
 t/t7060-wtstatus.sh    |   25 +++++++++++++++++++++++++
 t/t7512-status-help.sh |    6 +++---
 wt-status.c            |   37 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index 61d1f38..442d340 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -185,4 +185,29 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted)
 '
 
 
+test_expect_success 'status when conflicts with only rm advice (both deleted)' '
+	test_when_finished "cd ../ && rm -rf git" &&
+	git add sub_master.txt &&
+	git add sub_second.txt &&
+	cat >expected <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	new file:   sub_master.txt
+	#
+	# Unmerged paths:
+	#   (use "git rm <file>..." to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
 test_done
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 5f62262..2bb43f3 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -28,7 +28,7 @@ test_expect_success 'status when conflicts unresolved' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -72,7 +72,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -270,7 +270,7 @@ test_expect_success 'status when cherry-picking before resolving conflicts' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
diff --git a/wt-status.c b/wt-status.c
index 2460e20..5034eee 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -131,9 +131,34 @@ void wt_status_prepare(struct wt_status *s)
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
 {
+	int i;
+	int del_mod_conflict = 0;
+	int both_deleted = 0;
+	int not_deleted = 0;
 	const char *c = color(WT_STATUS_HEADER, s);
 
 	status_printf_ln(s, c, _("Unmerged paths:"));
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct string_list_item *it = &(s->change.items[i]);
+		struct wt_status_change_data *d = it->util;
+
+		switch (d->stagemask) {
+		case 0:
+			break;
+		case 1:
+			both_deleted = 1;
+			break;
+		case 3:
+		case 5:
+			del_mod_conflict = 1;
+			break;
+		default:
+			not_deleted = 1;
+			break;
+		}
+	}
+
 	if (!advice_status_hints)
 		return;
 	if (s->whence != FROM_COMMIT)
@@ -142,7 +167,17 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
 		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
 		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
-	status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+
+	if (!both_deleted) {
+		if (!del_mod_conflict)
+			status_printf_ln(s, c, _("  (use \"git add <file>...\" to mark resolution)"));
+		else
+			status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	} else if (!del_mod_conflict && !not_deleted) {
+		status_printf_ln(s, c, _("  (use \"git rm <file>...\" to mark resolution)"));
+	} else {
+		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	}
 	status_printf_ln(s, c, "");
 }
 
-- 
1.7.8

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

* [PATCHv6 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-03 18:30         ` [PATCHv6 1/4] " Kong Lucien
  2012-06-03 18:30           ` [PATCHv6 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
  2012-06-03 18:30           ` [PATCHv6 3/4] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
@ 2012-06-03 18:30           ` Kong Lucien
  2012-06-03 22:00             ` Junio C Hamano
  2012-06-04 15:35             ` Phil Hord
  2012-06-03 21:06           ` [PATCHv6 1/4] wt-status.*: better advices for git status added Junio C Hamano
  2012-06-04 17:19           ` [PATCHv7 " Kong Lucien
  4 siblings, 2 replies; 97+ messages in thread
From: Kong Lucien @ 2012-06-03 18:30 UTC (permalink / raw)
  To: git
  Cc: Kong Lucien, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

Add new informative help messages at the output of 'git status' when
the user is splitting a commit. The code figures this state by
comparing the contents of the following files in the .git/ directory:
	  - HEAD
	  - ORIG_HEAD
	  - rebase-merge/amend
	  - rebase-merge/orig-head

Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Moy Matthieu <Matthieu.Moy@grenoble-inp.fr>
---
The second test added by this patch fails because the case in which
the user amend the last commit through rebase -i is not taken care of.
We infer that the user would directly run "git commit --amend" instead
of amending it with a rebase -i.

 t/t7512-status-help.sh |   63 +++++++++++++++++++++++++++++++++++++++++++-
 wt-status.c            |   69 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 131 insertions(+), 1 deletions(-)

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 2bb43f3..0b7f231 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -106,7 +106,7 @@ test_expect_success 'status when rebase in progress before rebase --continue' '
 
 test_expect_success 'status when rebasing -i in edit mode' '
 	git init git &&
-	test_when_finished "rm -rf git fake-editor.sh" &&
+	test_when_finished "rm -rf git" &&
 	(
 		cd git &&
 		test_commit one main.txt one &&
@@ -130,6 +130,67 @@ test_expect_success 'status when rebasing -i in edit mode' '
 '
 
 
+test_expect_success 'status when splitting a commit' '
+	git init git &&
+	test_when_finished "rm -rf git" &&
+	(
+		cd git &&
+		test_commit one main.txt one &&
+		test_commit two main.txt two &&
+		test_commit three main.txt three &&
+		test_commit four main.txt four &&
+		FAKE_LINES="1 edit 2 3" &&
+		export FAKE_LINES &&
+		git rebase -i HEAD~3 &&
+		git reset HEAD^ &&
+		cat >expected <<-\EOF &&
+		# Not currently on any branch.
+		# You are currently splitting a commit.
+		#   (Once your working directory is clean, run "git rebase --continue")
+		#
+		# Changes not staged for commit:
+		#   (use "git add <file>..." to update what will be committed)
+		#   (use "git checkout -- <file>..." to discard changes in working directory)
+		#
+		#	modified:   main.txt
+		#
+		no changes added to commit (use "git add" and/or "git commit -a")
+		EOF
+		git status --untracked-files=no >actual &&
+		test_cmp expected actual &&
+		git rebase --abort
+	)
+'
+
+
+test_expect_failure 'status after editing the last commit with --amend during a rebase -i' '
+	git init git &&
+	test_when_finished "rm -rf git fake-editor.sh" &&
+	(
+		cd git &&
+		test_commit one main.txt one &&
+		test_commit two main.txt two &&
+		test_commit three main.txt three &&
+		test_commit four main.txt four &&
+		FAKE_LINES="1 2 edit 3" &&
+		export FAKE_LINES &&
+		git rebase -i HEAD~3 &&
+		git commit --amend -m "foo" &&
+		cat >expected <<-\EOF &&
+		# Not currently on any branch.
+		# You are currently editing a commit during a rebase.
+		#   (use "git commit --amend" to amend the current commit)
+		#   (use "git rebase --continue" once you are satisfied with your changes)
+		#
+		nothing to commit (working directory clean)
+		EOF
+		git status --untracked-files=no >actual &&
+		test_cmp expected actual &&
+		git rebase --abort
+	)
+'
+
+
 test_expect_success 'status in an am session: file already exists' '
 	git init git &&
 	test_when_finished "rm -rf git" &&
diff --git a/wt-status.c b/wt-status.c
index 5034eee..bbb3370 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -12,6 +12,7 @@
 #include "refs.h"
 #include "submodule.h"
 #include "column.h"
+#include "strbuf.h"
 
 static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -819,6 +820,69 @@ static void show_am_in_progress(struct wt_status *s,
 	wt_status_print_trailer(s);
 }
 
+static int split_commit_in_progress()
+{
+	int split_in_progress = 0;
+
+	FILE *head = fopen(git_path("HEAD"), "r");
+	if (!head)
+		return 0;
+
+	FILE *orig_head = fopen(git_path("ORIG_HEAD"), "r");
+	if (!orig_head) {
+		fclose(head);
+		return 0;
+	}
+
+	FILE *rebase_amend = fopen(git_path("rebase-merge/amend"), "r");
+	if (!rebase_amend) {
+		fclose(head);
+		fclose(orig_head);
+		return 0;
+	}
+
+	FILE *rebase_orig_head = fopen(git_path("rebase-merge/orig-head"), "r");
+	if (!rebase_orig_head) {
+		fclose(head);
+		fclose(orig_head);
+		fclose(rebase_amend);
+		return 0;
+	}
+
+	struct strbuf buf_head = STRBUF_INIT;
+	struct strbuf buf_orig_head = STRBUF_INIT;
+	struct strbuf buf_rebase_amend = STRBUF_INIT;
+	struct strbuf buf_rebase_orig_head = STRBUF_INIT;
+
+	strbuf_getline(&buf_head, head, '\n');
+	strbuf_getline(&buf_orig_head, orig_head, '\n');
+	strbuf_getline(&buf_rebase_amend, rebase_amend, '\n');
+	strbuf_getline(&buf_rebase_orig_head, rebase_orig_head, '\n');
+
+	fclose(head);
+	fclose(orig_head);
+	fclose(rebase_amend);
+	fclose(rebase_orig_head);
+
+	if (!strbuf_cmp(&buf_rebase_amend, &buf_rebase_orig_head)) {
+		if (strbuf_cmp(&buf_head, &buf_rebase_amend))
+			split_in_progress = 1;
+	} else if (!strbuf_cmp(&buf_orig_head, &buf_rebase_amend)) {
+		split_in_progress = 1;
+	} else if (strbuf_cmp(&buf_orig_head, &buf_rebase_orig_head)) {
+		split_in_progress = 1;
+	}
+
+	if (!strbuf_cmp(&buf_head, &buf_rebase_amend))
+		split_in_progress = 0;
+
+	strbuf_release(&buf_head);
+	strbuf_release(&buf_orig_head);
+	strbuf_release(&buf_rebase_amend);
+	strbuf_release(&buf_rebase_orig_head);
+	return split_in_progress;
+}
+
 static void show_rebase_in_progress(struct wt_status *s,
 				struct wt_status_state *state,
 				const char *color)
@@ -838,6 +902,11 @@ static void show_rebase_in_progress(struct wt_status *s,
 		if (advice_status_hints)
 			status_printf_ln(s, color,
 				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else if (split_commit_in_progress()) {
+		status_printf_ln(s, color, _("You are currently splitting a commit."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (Once your working directory is clean, run \"git rebase --continue\")"));
 	} else {
 		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
 		if (advice_status_hints && !s->amend) {
-- 
1.7.8

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

* Re: [PATCHv6 3/4] status: don't suggest "git rm" or "git add" if not appropriate
  2012-06-03 18:30           ` [PATCHv6 3/4] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
@ 2012-06-03 19:34             ` Matthieu Moy
  0 siblings, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-06-03 19:34 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> +test_expect_success 'status when conflicts with only rm advice (both deleted)' '
> +	test_when_finished "cd ../ && rm -rf git" &&

Is it intentional that you kept this potentially dangerous "cd ../ && rm
-rf git"? I saw you rewrote some instances in other patches, but not all
of them.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv6 1/4] wt-status.*: better advices for git status added
  2012-06-03 18:30         ` [PATCHv6 1/4] " Kong Lucien
                             ` (2 preceding siblings ...)
  2012-06-03 18:30           ` [PATCHv6 4/4] status: better advices when splitting a commit (during rebase -i) Kong Lucien
@ 2012-06-03 21:06           ` Junio C Hamano
  2012-06-04  9:51             ` konglu
  2012-06-04 17:19           ` [PATCHv7 " Kong Lucien
  4 siblings, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-06-03 21:06 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 915cb5a..670945d 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -162,6 +162,10 @@ advice.*::
>  		Directions on how to stage/unstage/add shown in the
>  		output of linkgit:git-status[1] and the template shown
>  		when writing commit messages.
> +		Show directions on how to proceed from the current
> +		state in the output of linkgit:git-status[1] and in
> +		the template shown when writing commit messages in
> +		linkgit:git-commit[1].

I meant these four lines to _replace_, not _add_.

Reading the three lines we can see in the context before this hunk,
don't you agree that they are now unnecessary because what they say
is merely a subset of the four lines you added say?

> diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
> index b8cb490..61d1f38 100755
> --- a/t/t7060-wtstatus.sh
> +++ b/t/t7060-wtstatus.sh
> @@ -118,4 +121,68 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
> ...
> +test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
> +	git init git &&
> +	cd git &&
> +	test_commit init main.txt init &&

Please do not chdir around outside a subshell.

"This is the last test in this script" is not an excuse, as that
will forbid others from improving the script by adding new ones
later.

> diff --git a/wt-status.c b/wt-status.c
> index dd6d8c4..2460e20 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -728,6 +729,169 @@ static void wt_status_print_tracking(struct wt_status *s)
> ...
> +static void show_merge_in_progress(struct wt_status *s,
> +				struct wt_status_state *state,
> +				const char *color)
> +{
> +	if (has_unmerged(s)) {
> +		status_printf_ln(s, color, _("You have unmerged paths."));
> +		if (advice_status_hints)
> +			status_printf_ln(s, color,
> +				_("  (fix conflicts and run \"git commit\")"));
> +	} else {
> +		status_printf_ln(s, color,
> +			_("All conflicts fixed but you are still merging."));

Thanks for rephrasing; this reads much easier.

> +static void show_am_in_progress(struct wt_status *s,
> +				struct wt_status_state *state,
> +				const char *color)
> +{
> +	status_printf_ln(s, color,
> +		_("You are in the middle of an am session."));
> +	if (state->am_empty_patch) {
> +		status_printf_ln(s, color,
> +			_("The current patch is empty; run \"git am --skip\" to skip it."));

Isn't everything after "; " an advice?

> +		if (advice_status_hints)
> +			status_printf_ln(s, color,
> +				_("  (use \"git am --abort\" to restore the original branch)"));
> +	} else if (advice_status_hints) {
> +		status_printf_ln(s, color,
> +			_("  (when you have fixed this problem run \"git am --resolved\")"));
> +		status_printf_ln(s, color,
> +			_("  (use \"git am --skip\" to skip this patch)"));
> +		status_printf_ln(s, color,
> +			_("  (use \"git am --abort\" to restore the original branch)"));
> +	}

I think the structure can simply be:

	if (am_empty_patch)
		"The current patch is empty.";
	if (advice_status_hints) {
		"  (use --abort to restore)";
		"  (use --skip to skip)";
                if (!am_empty_patch)
			"  (use --resolved after you are done)";
	}

Note that I am not suggesting to change the wording of the message
in the above; just showing the flow-structure.

Also when you are in the middle of "git am -3", there may be
unmerged entries in the index; do we want to suggest "add/rm" to
resolve to fill in the missing detail of "fix" in your "when you
have fixed this problem" message?

We may want to decide how detailed we want to make the help texts;
the same fuzziness exists in "fix conflicts and then" at the
beginning of show_rebase_in_progress().

> +static void show_rebase_in_progress(struct wt_status *s,
> +				struct wt_status_state *state,
> +				const char *color)
> +{
> +	if (has_unmerged(s)) {
> +		status_printf_ln(s, color, _("You are currently rebasing."));
> +		if (advice_status_hints) {
> +			status_printf_ln(s, color,
> +				_("  (fix conflicts and then run \"git rebase --continue\")"));

> +			status_printf_ln(s, color,
> +				_("  (use \"git rebase --skip\" to skip this patch)"));
> +			status_printf_ln(s, color,
> +				_("  (use \"git rebase --abort\" to check out the original branch)"));
> +		}
> +	} else if (state->rebase_in_progress) {
> +		status_printf_ln(s, color, _("You are currently rebasing."));
> +		if (advice_status_hints)
> +			status_printf_ln(s, color,
> +				_("  (all conflicts fixed: run \"git rebase --continue\")"));
> +	} else {
> +		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
> +		if (advice_status_hints && !s->amend) {
> +			status_printf_ln(s, color,
> +				_("  (use \"git commit --amend\" to amend the current commit)"));
> +			status_printf_ln(s, color,
> +				_("  (use \"git rebase --continue\" once you are satisfied with your changes)"));
> +		}

This last "else" block is taken when running "rebase -i" and there
is no longer any unmerged index entry.  I wonder if the message from
the first printf_ln needs to be clarified further depending on the
context.

Specifically, in this sequence:

	- the user marked a commit as "pick";
        - replaying of that commit resulted in conflicts;
        - the user edited files and used add/rm to resolve conflicts;
        - the user did one of these:
	  1. "git status"
          2. "git commit" without "--amend"
          3. "git commit --amend"

can this message come up?

In such a case, "You are currently editing a commit" is actively
wrong.  The user has finished resolving the conflict and are about
to record the result.  Also, "git status" and "git commit" without
"--amend" are both sensible commands in this situation, but running
"git commit --amend" is likely to be a mistake, no?

	Side note: I am not absolutely sure if "--amend" is always a
	mistake in this situation; I'd very much appreciate users
	who creatively use "rebase -i" in real life to offer valid
	uses of "commit --amend" in this scenario.

> +static void show_cherry_pick_in_progress(struct wt_status *s,
> +					struct wt_status_state *state,
> +					const char *color)
> +{
> +	if (has_unmerged(s)) {
> +		status_printf_ln(s, color, _("You are currently cherry-picking."));
> +		if (advice_status_hints)
> +			status_printf_ln(s, color,
> +				_("  (fix conflicts and run \"git commit\")"));
> +	} else {
> +		status_printf_ln(s, color, _("You are currently cherry-picking."));
> +		if (advice_status_hints)
> +			status_printf_ln(s, color,
> +				_("  (all conflicts fixed: run \"git commit\")"));
> +	}

The current status is the same in either arm of if/else; shouldn't
they be lifted outside, i.e.

	"You are currently cherry-picking";
        if (advice_status_hints) {
        	if (has_unmerged(s))
			"  (fix conflicts ...)";
		else
                	"  (all fixed, run ...)";
	}

The rest of this patch I did not quote looked all very much
sensible.

Thanks.

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

* Re: [PATCHv6 2/4] t7512-status-help.sh: better advices for git status
  2012-06-03 18:30           ` [PATCHv6 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
@ 2012-06-03 21:18             ` Junio C Hamano
  2012-06-04 10:04               ` konglu
  0 siblings, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-06-03 21:18 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> The following tests include several cases in which the user needs to
> run 'git status' to know his current situation, whether there're
> conflicts or he's in rebase/bisect/am/ cherry-pick progress.
>
> One of the test is about the set of the advice.statushints config key
> to 'false' in .git/config.
>
> Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
> Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
> Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
> Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
> Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
> Signed-off-by: Moy Matthieu <Matthieu.Moy@grenoble-inp.fr>

Are these spelling of names correct?

I thought Matthieu always called himself "Matthieu Moy", not the
other way around.  I also inferred the convention used for naming
the mailboxes at your institution to be "$First.$Last@$Domain",
which tells me that perhaps these names are all spelled backwards,
i.e. "$Last $First", which probably goes against the convention used
around you and Matthieu?

> diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
> new file mode 100755
> index 0000000..5f62262
> --- /dev/null
> +++ b/t/t7512-status-help.sh
> @@ -0,0 +1,303 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
> +#		     Thomas Nguy, Khoi Nguyen
> +#		     Grenoble INP Ensimag
> +#
> +
> +test_description='git status advices'
> +
> +. ./test-lib.sh
> +
> +. "$TEST_DIRECTORY"/lib-rebase.sh
> +
> +set_fake_editor
> +
> +test_expect_success 'status when conflicts unresolved' '
> +	git init git &&
> +	cd git &&

Eek.

Later tests seem to use

	git init git &&
	(
		cd git &&
                ... everything is done inside git subdirectory ...
	)

with either "test_when_finished 'rm -fr git'" clean-up before the
first "git init git" or "&& rm -fr git" at the end of the && chain.

Please be consistent.  If you want _me_ to pick one, I'd say

	test_when_finished 'rm -fr git' &&
        git init git &&
        (
        	cd git &&
                ... do everything in git subdirectory ...
	)

would be my choice.

> +test_expect_success 'status when rebase in progress before rebase --continue' '
> +	test_when_finished "cd ../ && rm -rf git" &&

I've said why this is wrong; I won't repeat it.

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

* Re: [PATCHv6 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-03 18:30           ` [PATCHv6 4/4] status: better advices when splitting a commit (during rebase -i) Kong Lucien
@ 2012-06-03 22:00             ` Junio C Hamano
  2012-06-04 15:35             ` Phil Hord
  1 sibling, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-06-03 22:00 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
> index 2bb43f3..0b7f231 100755
> --- a/t/t7512-status-help.sh
> +++ b/t/t7512-status-help.sh
> @@ -106,7 +106,7 @@ test_expect_success 'status when rebase in progress before rebase --continue' '
>  
>  test_expect_success 'status when rebasing -i in edit mode' '
>  	git init git &&
> -	test_when_finished "rm -rf git fake-editor.sh" &&
> +	test_when_finished "rm -rf git" &&

Hrph.  Is this an "oops" fixup of an earlier patch?

> @@ -130,6 +130,67 @@ test_expect_success 'status when rebasing -i in edit mode' '
> ...
> +test_expect_failure 'status after editing the last commit with --amend during a rebase -i' '
> +	git init git &&
> +	test_when_finished "rm -rf git fake-editor.sh" &&

You do not seem to remove fake-editor.sh in this test.  Why do you
remove it here?

> diff --git a/wt-status.c b/wt-status.c
> index 5034eee..bbb3370 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -819,6 +820,69 @@ static void show_am_in_progress(struct wt_status *s,
>  	wt_status_print_trailer(s);
>  }
>  
> +static int split_commit_in_progress()
> +{
> +	int split_in_progress = 0;
> +
> +	FILE *head = fopen(git_path("HEAD"), "r");
> +	if (!head)
> +		return 0;
> +
> ...
> +	struct strbuf buf_head = STRBUF_INIT;
> +	struct strbuf buf_orig_head = STRBUF_INIT;
> +	struct strbuf buf_rebase_amend = STRBUF_INIT;
> +	struct strbuf buf_rebase_orig_head = STRBUF_INIT;


Please avoid decl-after-statement by declaring all variables at the
beginning of the function before the first statement.

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

* Re: [PATCHv6 1/4] wt-status.*: better advices for git status added
  2012-06-03 21:06           ` [PATCHv6 1/4] wt-status.*: better advices for git status added Junio C Hamano
@ 2012-06-04  9:51             ` konglu
  2012-06-04 14:54               ` Junio C Hamano
  0 siblings, 1 reply; 97+ messages in thread
From: konglu @ 2012-06-04  9:51 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu


Junio C Hamano <gitster@pobox.com> a écrit :

>> +		if (advice_status_hints)
>> +			status_printf_ln(s, color,
>> +				_("  (use \"git am --abort\" to restore the original branch)"));
>> +	} else if (advice_status_hints) {
>> +		status_printf_ln(s, color,
>> +			_("  (when you have fixed this problem run \"git am --resolved\")"));
>> +		status_printf_ln(s, color,
>> +			_("  (use \"git am --skip\" to skip this patch)"));
>> +		status_printf_ln(s, color,
>> +			_("  (use \"git am --abort\" to restore the original branch)"));
>> +	}
>
> I think the structure can simply be:
>
> 	if (am_empty_patch)
> 		"The current patch is empty.";
> 	if (advice_status_hints) {
> 		"  (use --abort to restore)";
> 		"  (use --skip to skip)";
>                 if (!am_empty_patch)
> 			"  (use --resolved after you are done)";
> 	}
>
> Note that I am not suggesting to change the wording of the message
> in the above; just showing the flow-structure.
>
> Also when you are in the middle of "git am -3", there may be
> unmerged entries in the index; do we want to suggest "add/rm" to
> resolve to fill in the missing detail of "fix" in your "when you
> have fixed this problem" message?
>
> We may want to decide how detailed we want to make the help texts;
> the same fuzziness exists in "fix conflicts and then" at the
> beginning of show_rebase_in_progress().

In fact, to detail more "fix" in this case by suggesting "add/rm"
would be repetitive, as this advice is already given under the block
"unmerged paths":

# Not currently on any branch.
# You are currently rebasing.
#   (fix conflicts and then run "git rebase --continue")
#   (use "git rebase --skip" to skip this patch)
#   (use "git rebase --abort" to check out the original branch)
#
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add <file>..." to mark resolution)
#
#	both modified:      main.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

>> +static void show_rebase_in_progress(struct wt_status *s,
>> +				struct wt_status_state *state,
>> +				const char *color)
>> +{
>> +	if (has_unmerged(s)) {
>> +		status_printf_ln(s, color, _("You are currently rebasing."));
>> +		if (advice_status_hints) {
>> +			status_printf_ln(s, color,
>> +				_("  (fix conflicts and then run \"git rebase --continue\")"));
>
>> +			status_printf_ln(s, color,
>> +				_("  (use \"git rebase --skip\" to skip this patch)"));
>> +			status_printf_ln(s, color,
>> +				_("  (use \"git rebase --abort\" to check out the original branch)"));
>> +		}
>> +	} else if (state->rebase_in_progress) {
>> +		status_printf_ln(s, color, _("You are currently rebasing."));
>> +		if (advice_status_hints)
>> +			status_printf_ln(s, color,
>> +				_("  (all conflicts fixed: run \"git rebase --continue\")"));
>> +	} else {
>> +		status_printf_ln(s, color, _("You are currently editing a commit  
>> during a rebase."));
>> +		if (advice_status_hints && !s->amend) {
>> +			status_printf_ln(s, color,
>> +				_("  (use \"git commit --amend\" to amend the current commit)"));
>> +			status_printf_ln(s, color,
>> +				_("  (use \"git rebase --continue\" once you are satisfied  
>> with your changes)"));
>> +		}
>
> This last "else" block is taken when running "rebase -i" and there
> is no longer any unmerged index entry.  I wonder if the message from
> the first printf_ln needs to be clarified further depending on the
> context.
>
> Specifically, in this sequence:
>
> 	- the user marked a commit as "pick";
>         - replaying of that commit resulted in conflicts;
>         - the user edited files and used add/rm to resolve conflicts;
>         - the user did one of these:
> 	  1. "git status"
>           2. "git commit" without "--amend"
>           3. "git commit --amend"
>
> can this message come up?
>
> In such a case, "You are currently editing a commit" is actively
> wrong.  The user has finished resolving the conflict and are about
> to record the result.  Also, "git status" and "git commit" without
> "--amend" are both sensible commands in this situation, but running
> "git commit --amend" is likely to be a mistake, no?

True, the last "else" block is not supposed to be taken. The correct
message that should be displayed is the first "else if" block, saying
just that all conflicts are fixed and to run rebase --continue.

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

* Re: [PATCHv6 2/4] t7512-status-help.sh: better advices for git status
  2012-06-03 21:18             ` Junio C Hamano
@ 2012-06-04 10:04               ` konglu
  2012-06-04 15:04                 ` Junio C Hamano
  2012-06-04 22:07                 ` Junio C Hamano
  0 siblings, 2 replies; 97+ messages in thread
From: konglu @ 2012-06-04 10:04 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu


Junio C Hamano <gitster@pobox.com> a écrit :

> I thought Matthieu always called himself "Matthieu Moy", not the
> other way around.  I also inferred the convention used for naming
> the mailboxes at your institution to be "$First.$Last@$Domain",
> which tells me that perhaps these names are all spelled backwards,
> i.e. "$Last $First", which probably goes against the convention used
> around you and Matthieu?

Hm, yeah it's spelled backwards, I didn't take notice of that.

>> +. ./test-lib.sh
>> +
>> +. "$TEST_DIRECTORY"/lib-rebase.sh
>> +
>> +set_fake_editor
>> +
>> +test_expect_success 'status when conflicts unresolved' '
>> +	git init git &&
>> +	cd git &&
>
> Eek.
>
> Later tests seem to use
>
> 	git init git &&
> 	(
> 		cd git &&
>                 ... everything is done inside git subdirectory ...
> 	)
>
> with either "test_when_finished 'rm -fr git'" clean-up before the
> first "git init git" or "&& rm -fr git" at the end of the && chain.
>
> Please be consistent.  If you want _me_ to pick one, I'd say
>
> 	test_when_finished 'rm -fr git' &&
>         git init git &&
>         (
>         	cd git &&
>                 ... do everything in git subdirectory ...
> 	)
>
> would be my choice.

Btw, should each test be independant with the others ? We saw that there
are already a lot of tests that are dependant. In this case, can we apply
this method with the parenthesis ?

Wouldn't it be better if we remove the "git init git" part?

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

* Re: [PATCHv6 1/4] wt-status.*: better advices for git status added
  2012-06-04  9:51             ` konglu
@ 2012-06-04 14:54               ` Junio C Hamano
  0 siblings, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-06-04 14:54 UTC (permalink / raw)
  To: konglu
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

konglu@minatec.inpg.fr writes:

> Junio C Hamano <gitster@pobox.com> a écrit:
> ...
>>
>> Also when you are in the middle of "git am -3", there may be
>> unmerged entries in the index; do we want to suggest "add/rm" to
>> resolve to fill in the missing detail of "fix" in your "when you
>> have fixed this problem" message?
>>
>> We may want to decide how detailed we want to make the help texts;
>> the same fuzziness exists in "fix conflicts and then" at the
>> beginning of show_rebase_in_progress().
>
> In fact, to detail more "fix" in this case by suggesting "add/rm"
> would be repetitive, as this advice is already given under the block
> "unmerged paths":

OK, then I agree that "resolve and do X" is a sufficient level of
detail for these messages.

>> This last "else" block is taken when running "rebase -i" and there
>> is no longer any unmerged index entry.  I wonder if the message from
>> the first printf_ln needs to be clarified further depending on the
>> context.
>>
>> Specifically, in this sequence:
>>
>> 	- the user marked a commit as "pick";
>>         - replaying of that commit resulted in conflicts;
>>         - the user edited files and used add/rm to resolve conflicts;
>>         - the user did one of these:
>> 	  1. "git status"
>>           2. "git commit" without "--amend"
>>           3. "git commit --amend"
>>
>> can this message come up?
>>
>> In such a case, "You are currently editing a commit" is actively
>> wrong.  The user has finished resolving the conflict and are about
>> to record the result.  Also, "git status" and "git commit" without
>> "--amend" are both sensible commands in this situation, but running
>> "git commit --amend" is likely to be a mistake, no?
>
> True, the last "else" block is not supposed to be taken. The correct
> message that should be displayed is the first "else if" block, saying
> just that all conflicts are fixed and to run rebase --continue.

OK, so this part still needs a bit more work, then.

Thanks.

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

* Re: [PATCHv6 2/4] t7512-status-help.sh: better advices for git status
  2012-06-04 10:04               ` konglu
@ 2012-06-04 15:04                 ` Junio C Hamano
  2012-06-04 22:07                 ` Junio C Hamano
  1 sibling, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-06-04 15:04 UTC (permalink / raw)
  To: konglu
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

konglu@minatec.inpg.fr writes:

> Junio C Hamano <gitster@pobox.com>:
> ...
>> Please be consistent.  If you want _me_ to pick one, I'd say
>>
>> 	test_when_finished 'rm -fr git' &&
>>         git init git &&
>>         (
>>         	cd git &&
>>                 ... do everything in git subdirectory ...
>> 	)
>>
>> would be my choice.
>
> Btw, should each test be independant with the others?

It would be ideal if you can make them independent with each other,
so that after one fails, later ones do not have to.

> Wouldn't it be better if we remove the "git init git" part?

If you do not need to keep your tests from using the test repository
in $TRASH_DIRECTORY (e.g. "t/trash directory.t7512-status-help"),
you do not have to create a new one with "git init".

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

* Re: [PATCHv6 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-03 18:30           ` [PATCHv6 4/4] status: better advices when splitting a commit (during rebase -i) Kong Lucien
  2012-06-03 22:00             ` Junio C Hamano
@ 2012-06-04 15:35             ` Phil Hord
  2012-06-05  9:13               ` konglu
  1 sibling, 1 reply; 97+ messages in thread
From: Phil Hord @ 2012-06-04 15:35 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

On Sun, Jun 3, 2012 at 2:30 PM, Kong Lucien <Lucien.Kong@ensimag.imag.fr> wrote:
> Add new informative help messages at the output of 'git status' when
> the user is splitting a commit. The code figures this state by
> comparing the contents of the following files in the .git/ directory:
>          - HEAD
>          - ORIG_HEAD
>          - rebase-merge/amend
>          - rebase-merge/orig-head
>
> Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
> Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
> Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
> Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
> Signed-off-by: Nguyen Huynh Khoi Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
> Signed-off-by: Moy Matthieu <Matthieu.Moy@grenoble-inp.fr>
> ---
> The second test added by this patch fails because the case in which
> the user amend the last commit through rebase -i is not taken care of.
> We infer that the user would directly run "git commit --amend" instead
> of amending it with a rebase -i.


Maybe this is safe and logical for most workflows, or maybe this is a
convenience that makes this patch possible (I did not read the patch
yet).  But I know that I sometimes use rebase-i instead of
commit--amend because I did not realize the patch I am fixing is the
most recent one until after continuing, or because the patch I am
amending was moved into the most-recent position during the rebase-i
itself.

Just a note to consider, in case this decision was made arbitrarily.

Thanks for looking after these kinds of corner cases.

Phil

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

* [PATCHv7 1/4] wt-status.*: better advices for git status added
  2012-06-03 18:30         ` [PATCHv6 1/4] " Kong Lucien
                             ` (3 preceding siblings ...)
  2012-06-03 21:06           ` [PATCHv6 1/4] wt-status.*: better advices for git status added Junio C Hamano
@ 2012-06-04 17:19           ` Kong Lucien
  2012-06-04 17:19             ` [PATCHv7 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
                               ` (4 more replies)
  4 siblings, 5 replies; 97+ messages in thread
From: Kong Lucien @ 2012-06-04 17:19 UTC (permalink / raw)
  To: git
  Cc: Kong Lucien, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

This patch provides new informative help messages in the display of
'git status' (at the top) during conflicts, rebase, am, bisect or
cherry-pick process.

The new messages are not shown when using options such as -s or
--porcelain. The messages about the current situation of the user are
always displayed but the advices on what the user needs to do in order
to resume a rebase/bisect/am/commit after resolving conflicts can be
hidden by setting advice.statushints to 'false' in the config file.

Thus, information about the updated advice.statushints key are added
in Documentation/config.txt.

Also, the test t7060-wt-status.sh is now working with the new help
messages. Tests about suggestions of "git rm" are also added.

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
The case of conflicts during a rebase -i is now taken care of. The form
of the tests has also been modified.

 Documentation/config.txt |    7 +-
 t/t7060-wtstatus.sh      |   64 ++++++++++++++++++
 wt-status.c              |  163 ++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.h              |   11 +++
 4 files changed, 242 insertions(+), 3 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a..ccce4f6 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -159,9 +159,10 @@ advice.*::
 		specified a refspec that isn't your current branch) and
 		it resulted in a non-fast-forward error.
 	statusHints::
-		Directions on how to stage/unstage/add shown in the
-		output of linkgit:git-status[1] and the template shown
-		when writing commit messages.
+		Show directions on how to proceed from the current
+		state in the output of linkgit:git-status[1] and in
+		the template shown when writing commit messages in
+		linkgit:git-commit[1].
 	commitBeforeMerge::
 		Advice shown when linkgit:git-merge[1] refuses to
 		merge to avoid overwriting local changes.
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb490..4326df7 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,9 @@ test_expect_success 'Report new path with conflict' '
 
 cat >expect <<EOF
 # On branch side
+# You have unmerged paths.
+#   (fix conflicts and run "git commit")
+#
 # Unmerged paths:
 #   (use "git add/rm <file>..." as appropriate to mark resolution)
 #
@@ -118,4 +121,65 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
 	test_cmp expected actual
 '
 
+
+test_expect_success 'status when conflicts with add and rm advice (deleted by them)' '
+	git reset --hard &&
+	git checkout master &&
+	test_commit init main.txt init &&
+	git checkout -b second_branch &&
+	git rm main.txt &&
+	git commit -m "main.txt deleted on second_branch" &&
+	test_commit second conflict.txt second &&
+	git checkout master &&
+	test_commit on_second main.txt on_second &&
+	test_commit master conflict.txt master &&
+	test_must_fail git merge second_branch &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both added:         conflict.txt
+	#	deleted by them:    main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+	git reset --hard &&
+	git checkout -b conflict &&
+	test_commit one main.txt one &&
+	git branch conflict_second &&
+	git mv main.txt sub_master.txt &&
+	git commit -m "main.txt renamed in sub_master.txt" &&
+	git checkout conflict_second &&
+	git mv main.txt sub_second.txt &&
+	git commit -m "main.txt renamed in sub_second.txt" &&
+	test_must_fail git merge conflict &&
+	cat >expected <<-\EOF &&
+	# On branch conflict_second
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#	added by them:      sub_master.txt
+	#	added by us:        sub_second.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
 test_done
diff --git a/wt-status.c b/wt-status.c
index dd6d8c4..2b19fe3 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
 	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
 	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
+	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
 };
 
 static const char *color(int slot, struct wt_status *s)
@@ -728,6 +729,167 @@ static void wt_status_print_tracking(struct wt_status *s)
 	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
 }
 
+static int has_unmerged(struct wt_status *s)
+{
+	int i;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		d = s->change.items[i].util;
+		if (d->stagemask)
+			return 1;
+	}
+	return 0;
+}
+
+static void show_merge_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You have unmerged paths."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+	} else {
+		status_printf_ln(s, color,
+			_("All conflicts fixed but you are still merging."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (use \"git commit\" to conclude merge)"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_am_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color,
+		_("You are in the middle of an am session."));
+	if (state->am_empty_patch)
+		status_printf_ln(s, color,
+			_("The current patch is empty."));
+	if (advice_status_hints) {
+		status_printf_ln(s, color,
+			_("  (use \"git am --abort\" to restore the original branch)"));
+		status_printf_ln(s, color,
+			_("  (use \"git am --skip\" to skip this patch)"));
+		if (!state->am_empty_patch)
+			status_printf_ln(s, color,
+				_("  (when you have fixed this problem run \"git am --resolved\")"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_rebase_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	struct stat st;
+
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints) {
+			status_printf_ln(s, color,
+				_("  (fix conflicts and then run \"git rebase --continue\")"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --skip\" to skip this patch)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --abort\" to check out the original branch)"));
+		}
+	} else if (state->rebase_in_progress || !stat(git_path("MERGE_MSG"), &st)) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else {
+		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
+		if (advice_status_hints && !s->amend) {
+			status_printf_ln(s, color,
+				_("  (use \"git commit --amend\" to amend the current commit)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --continue\" once you are satisfied with your changes)"));
+		}
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_cherry_pick_in_progress(struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	status_printf_ln(s, color, _("You are currently cherry-picking."));
+	if (advice_status_hints) {
+		if (has_unmerged(s))
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+		else
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git commit\")"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_bisect_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color, _("You are currently bisecting."));
+	if (advice_status_hints)
+		status_printf_ln(s, color,
+			_("  (use \"git bisect reset\" to get back to the original branch)"));
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_print_state(struct wt_status *s)
+{
+	const char *state_color = color(WT_STATUS_IN_PROGRESS, s);
+	struct wt_status_state *state = calloc(1, sizeof(*state));
+	struct stat st;
+
+	state->merge_in_progress = 0;
+	state->am_in_progress = 0;
+	state->am_empty_patch = 0;
+	state->rebase_in_progress = 0;
+	state->rebase_interactive_in_progress = 0;
+	state->cherry_pick_in_progress = 0;
+	state->bisect_in_progress = 0;
+
+	if (!stat(git_path("MERGE_HEAD"), &st)) {
+		state->merge_in_progress = 1;
+	} else if (!stat(git_path("rebase-apply"), &st)) {
+		if (!stat(git_path("rebase-apply/applying"), &st)) {
+			state->am_in_progress = 1;
+			if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
+				state->am_empty_patch = 1;
+		} else {
+			state->rebase_in_progress = 1;
+		}
+	} else if (!stat(git_path("rebase-merge"), &st)) {
+		if (!stat(git_path("rebase-merge/interactive"), &st))
+			state->rebase_interactive_in_progress = 1;
+		else
+			state->rebase_in_progress = 1;
+	} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
+		state->cherry_pick_in_progress = 1;
+	}
+	if (!stat(git_path("BISECT_LOG"), &st))
+		state->bisect_in_progress = 1;
+
+	if (state->merge_in_progress)
+		show_merge_in_progress(s, state, state_color);
+	else if (state->am_in_progress)
+		show_am_in_progress(s, state, state_color);
+	else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
+		show_rebase_in_progress(s, state, state_color);
+	else if (state->cherry_pick_in_progress)
+		show_cherry_pick_in_progress(s, state, state_color);
+	if (state->bisect_in_progress)
+		show_bisect_in_progress(s, state, state_color);
+	free(state);
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
@@ -750,6 +912,7 @@ void wt_status_print(struct wt_status *s)
 			wt_status_print_tracking(s);
 	}
 
+	wt_status_print_state(s);
 	if (s->is_initial) {
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7..c1066a0 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -15,6 +15,7 @@ enum color_wt_status {
 	WT_STATUS_LOCAL_BRANCH,
 	WT_STATUS_REMOTE_BRANCH,
 	WT_STATUS_ONBRANCH,
+	WT_STATUS_IN_PROGRESS,
 	WT_STATUS_MAXSLOT
 };
 
@@ -71,6 +72,16 @@ struct wt_status {
 	struct string_list ignored;
 };
 
+struct wt_status_state {
+	int merge_in_progress;
+	int am_in_progress;
+	int am_empty_patch;
+	int rebase_in_progress;
+	int rebase_interactive_in_progress;
+	int cherry_pick_in_progress;
+	int bisect_in_progress;
+};
+
 void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
-- 
1.7.8

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

* [PATCHv7 2/4] t7512-status-help.sh: better advices for git status
  2012-06-04 17:19           ` [PATCHv7 " Kong Lucien
@ 2012-06-04 17:19             ` Kong Lucien
  2012-06-04 21:02               ` Matthieu Moy
  2012-06-04 23:12               ` Junio C Hamano
  2012-06-04 17:19             ` [PATCHv7 3/4] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
                               ` (3 subsequent siblings)
  4 siblings, 2 replies; 97+ messages in thread
From: Kong Lucien @ 2012-06-04 17:19 UTC (permalink / raw)
  To: git
  Cc: Kong Lucien, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

The following tests include several cases in which the user needs to
run 'git status' to know his current situation, whether there're
conflicts or he's in rebase/bisect/am/cherry-pick progress.

One of the test is about the set of the advice.statushints config key
to 'false' in .git/config.

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
The form of the tests has been modified.

 t/t7512-status-help.sh |  346 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 346 insertions(+), 0 deletions(-)
 create mode 100755 t/t7512-status-help.sh

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
new file mode 100755
index 0000000..53d0e05
--- /dev/null
+++ b/t/t7512-status-help.sh
@@ -0,0 +1,346 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'status when conflicts unresolved' '
+	test_commit init main.txt init &&
+	git branch second_branch &&
+	test_commit on_master main.txt on_master &&
+	git checkout second_branch &&
+	test_commit on_second_branch main.txt on_second_branch &&
+	test_must_fail git merge master &&
+	cat >expected <<-\EOF &&
+	# On branch second_branch
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	test_when_finished "
+		git commit -m "end_merge" &&
+		git checkout master &&
+		git branch -D second_branch &&
+		echo >main.txt
+	" &&
+	echo one >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch second_branch
+	# All conflicts fixed but you are still merging.
+	#   (use "git commit" to conclude merge)
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when rebase in progress before resolving conflicts' '
+	test_commit one_rebase main.txt one &&
+	test_commit two_rebase main.txt two &&
+	test_commit three_rebase main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (fix conflicts and then run "git rebase --continue")
+	#   (use "git rebase --skip" to skip this patch)
+	#   (use "git rebase --abort" to check out the original branch)
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when rebase in progress before rebase --continue' '
+	test_when_finished "git rebase --abort" &&
+	echo three >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (all conflicts fixed: run "git rebase --continue")
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status during rebase -i when conflicts unresolved' '
+	test_commit one_unmerge main.txt one_unmerge &&
+	git branch second_branch &&
+	test_commit one_master main.txt one_master &&
+	git checkout second_branch &&
+	test_commit one_second main.txt one_second &&
+	test_must_fail git rebase -i master &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (fix conflicts and then run "git rebase --continue")
+	#   (use "git rebase --skip" to skip this patch)
+	#   (use "git rebase --abort" to check out the original branch)
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status during rebase -i after resolving conflicts' '
+	test_when_finished "
+		git rebase --abort &&
+		git checkout master &&
+		git branch -D second_branch
+	" &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (all conflicts fixed: run "git rebase --continue")
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when rebasing -i in edit mode' '
+	test_when_finished "git rebase --abort" &&
+	test_commit one_rebase_i main.txt one &&
+	test_commit two_rebase_i main.txt two &&
+	test_commit three_rebase_i main.txt three &&
+	FAKE_LINES="1 edit 2" &&
+	export FAKE_LINES &&
+	git rebase -i HEAD~2 &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status in an am session: file already exists' '
+	test_when_finished "
+		git am --abort &&
+		rm -r Maildir/
+	" &&
+	test_commit one_am main.txt "one  " &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You are in the middle of an am session.
+	#   (use "git am --abort" to restore the original branch)
+	#   (use "git am --skip" to skip this patch)
+	#   (when you have fixed this problem run "git am --resolved")
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status in an am session: file does not exist' '
+	test_when_finished "
+		git am --abort &&
+		rm -r Maildir/
+	" &&
+	test_commit two_am main.txt "two" &&
+	git rm main.txt &&
+	git commit -m "delete main.txt" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You are in the middle of an am session.
+	#   (use "git am --abort" to restore the original branch)
+	#   (use "git am --skip" to skip this patch)
+	#   (when you have fixed this problem run "git am --resolved")
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status in an am session: empty patch' '
+	test_when_finished "
+		git am --abort &&
+		rm -r Maildir/
+	" &&
+	test_commit one_am_empty one.txt "one" &&
+	test_commit two_am_empty two.txt "two" &&
+	test_commit three_am_empty three.txt "three" &&
+	git format-patch -3 -oMaildir &&
+	git rm one.txt two.txt three.txt &&
+	git commit -m "delete all am_empty" &&
+	echo error >Maildir/0002-two_am_empty.patch &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You are in the middle of an am session.
+	# The current patch is empty.
+	#   (use "git am --abort" to restore the original branch)
+	#   (use "git am --skip" to skip this patch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when bisecting' '
+	test_when_finished "git bisect reset" &&
+	test_commit one_bisect main.txt one &&
+	test_commit two_bisect main.txt two &&
+	test_commit three_bisect main.txt three &&
+	git bisect start &&
+	git bisect bad &&
+	git bisect good one_bisect &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently bisecting.
+	#   (use "git bisect reset" to get back to the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when rebase conflicts with statushints disabled' '
+	test_when_finished "
+		git rebase --abort &&
+		git config --local advice.statushints true
+	" &&
+	git config --local advice.statushints false &&
+	test_commit one_statushints main.txt one &&
+	test_commit two_statushints main.txt two &&
+	test_commit three_statushints main.txt three &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#
+	# Unmerged paths:
+	#	both modified:      main.txt
+	#
+	no changes added to commit
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_success 'status when cherry-picking before resolving conflicts' '
+	git checkout -b cherry_branch &&
+	test_commit one_cherry main.txt one &&
+	test_commit two_cherries main.txt two &&
+	test_commit three_cherries main.txt three &&
+	git checkout master &&
+	test_must_fail git cherry-pick two_cherries &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You are currently cherry-picking.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'status when cherry-picking after resolving conflicts' '
+	test_when_finished "
+		git cherry-pick --abort
+		git branch -D cherry_branch
+	" &&
+	echo end >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You are currently cherry-picking.
+	#   (all conflicts fixed: run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_done
-- 
1.7.8

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

* [PATCHv7 3/4] status: don't suggest "git rm" or "git add" if not appropriate
  2012-06-04 17:19           ` [PATCHv7 " Kong Lucien
  2012-06-04 17:19             ` [PATCHv7 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
@ 2012-06-04 17:19             ` Kong Lucien
  2012-06-04 17:19             ` [PATCHv7 4/4] status: better advices when splitting a commit (during rebase -i) Kong Lucien
                               ` (2 subsequent siblings)
  4 siblings, 0 replies; 97+ messages in thread
From: Kong Lucien @ 2012-06-04 17:19 UTC (permalink / raw)
  To: git
  Cc: Kong Lucien, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

The display of the advice '(use git add/rm [...])' (when there are
unmerged files) after running 'git status' is now depending of the
mark, whether it's 'both deleted', 'deleted by us/them' or others. For
instance, when there is just one file that's marked as 'both deleted',
'git status' shows '(use git rm [...])' and if there are two files,
one as 'both deleted' and the other as 'added by them', the advice is
'(use git add/rm [...])'.

The previous tests in t7512-status-help.sh are updated.

Test about the case of only 'both deleted' is added in
t7060-wtstatus.sh

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
 t/t7060-wtstatus.sh    |   26 ++++++++++++++++++++++++++
 t/t7512-status-help.sh |    8 ++++----
 wt-status.c            |   37 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 66 insertions(+), 5 deletions(-)

diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index 4326df7..1e6ec37 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -182,4 +182,30 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted)
 '
 
 
+test_expect_success 'status when conflicts with only rm advice (both deleted)' '
+	git add sub_master.txt &&
+	git add sub_second.txt &&
+	cat >expected <<-\EOF &&
+	# On branch conflict_second
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	new file:   sub_master.txt
+	#
+	# Unmerged paths:
+	#   (use "git rm <file>..." to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual &&
+	git reset --hard &&
+	git checkout master
+'
+
+
 test_done
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 53d0e05..e52a05a 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -26,7 +26,7 @@ test_expect_success 'status when conflicts unresolved' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -76,7 +76,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -124,7 +124,7 @@ test_expect_success 'status during rebase -i when conflicts unresolved' '
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -310,7 +310,7 @@ test_expect_success 'status when cherry-picking before resolving conflicts' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
diff --git a/wt-status.c b/wt-status.c
index 2b19fe3..3a2b787 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -131,9 +131,34 @@ void wt_status_prepare(struct wt_status *s)
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
 {
+	int i;
+	int del_mod_conflict = 0;
+	int both_deleted = 0;
+	int not_deleted = 0;
 	const char *c = color(WT_STATUS_HEADER, s);
 
 	status_printf_ln(s, c, _("Unmerged paths:"));
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct string_list_item *it = &(s->change.items[i]);
+		struct wt_status_change_data *d = it->util;
+
+		switch (d->stagemask) {
+		case 0:
+			break;
+		case 1:
+			both_deleted = 1;
+			break;
+		case 3:
+		case 5:
+			del_mod_conflict = 1;
+			break;
+		default:
+			not_deleted = 1;
+			break;
+		}
+	}
+
 	if (!advice_status_hints)
 		return;
 	if (s->whence != FROM_COMMIT)
@@ -142,7 +167,17 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
 		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
 		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
-	status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+
+	if (!both_deleted) {
+		if (!del_mod_conflict)
+			status_printf_ln(s, c, _("  (use \"git add <file>...\" to mark resolution)"));
+		else
+			status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	} else if (!del_mod_conflict && !not_deleted) {
+		status_printf_ln(s, c, _("  (use \"git rm <file>...\" to mark resolution)"));
+	} else {
+		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	}
 	status_printf_ln(s, c, "");
 }
 
-- 
1.7.8

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

* [PATCHv7 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-04 17:19           ` [PATCHv7 " Kong Lucien
  2012-06-04 17:19             ` [PATCHv7 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
  2012-06-04 17:19             ` [PATCHv7 3/4] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
@ 2012-06-04 17:19             ` Kong Lucien
  2012-06-04 23:01             ` [PATCHv7 1/4] wt-status.*: better advices for git status added Junio C Hamano
  2012-06-05 20:21             ` [PATCHv8 " Lucien Kong
  4 siblings, 0 replies; 97+ messages in thread
From: Kong Lucien @ 2012-06-04 17:19 UTC (permalink / raw)
  To: git
  Cc: Kong Lucien, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Add new informative help messages at the output of 'git status' when
the user is splitting a commit. The code figures this state by
comparing the contents of the following files in the .git/ directory:
	  - HEAD
	  - ORIG_HEAD
	  - rebase-merge/amend
	  - rebase-merge/orig-head

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
This part of the patch is the same as the one in the v6. The code has not
been modified.

 t/t7512-status-help.sh |   51 +++++++++++++++++++++++++++++++
 wt-status.c            |   77 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 128 insertions(+), 0 deletions(-)

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index e52a05a..413808e 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -180,6 +180,57 @@ test_expect_success 'status when rebasing -i in edit mode' '
 '
 
 
+test_expect_success 'status when splitting a commit' '
+	test_when_finished "git rebase --abort" &&
+	test_commit one_split main.txt one &&
+	test_commit two_split main.txt two &&
+	test_commit three_split main.txt three &&
+	test_commit four_split main.txt four &&
+	FAKE_LINES="1 edit 2 3" &&
+	export FAKE_LINES &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
+test_expect_failure 'status after editing the last commit with --amend during a rebase -i' '
+	test_when_finished "git rebase --abort" &&
+	test_commit one_amend main.txt one &&
+	test_commit two_amend main.txt two &&
+	test_commit three_amend main.txt three &&
+	test_commit four_amend main.txt four &&
+	FAKE_LINES="1 2 edit 3" &&
+	export FAKE_LINES &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "foo" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (working directory clean)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_cmp expected actual
+'
+
+
 test_expect_success 'status in an am session: file already exists' '
 	test_when_finished "
 		git am --abort &&
diff --git a/wt-status.c b/wt-status.c
index 3a2b787..2016b12 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -12,6 +12,7 @@
 #include "refs.h"
 #include "submodule.h"
 #include "column.h"
+#include "strbuf.h"
 
 static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -817,6 +818,77 @@ static void show_am_in_progress(struct wt_status *s,
 	wt_status_print_trailer(s);
 }
 
+static int split_commit_in_progress()
+{
+	FILE *head;
+	struct strbuf buf_head;
+	FILE *orig_head;
+	struct strbuf buf_orig_head;
+	FILE *rebase_amend;
+	struct strbuf buf_rebase_amend;
+	FILE *rebase_orig_head;
+	struct strbuf buf_rebase_orig_head;
+	int split_in_progress = 0;
+
+	head = fopen(git_path("HEAD"), "r");
+	if (!head)
+		return 0;
+
+	orig_head = fopen(git_path("ORIG_HEAD"), "r");
+	if (!orig_head) {
+		fclose(head);
+		return 0;
+	}
+
+	rebase_amend = fopen(git_path("rebase-merge/amend"), "r");
+	if (!rebase_amend) {
+		fclose(head);
+		fclose(orig_head);
+		return 0;
+	}
+
+	rebase_orig_head = fopen(git_path("rebase-merge/orig-head"), "r");
+	if (!rebase_orig_head) {
+		fclose(head);
+		fclose(orig_head);
+		fclose(rebase_amend);
+		return 0;
+	}
+
+	strbuf_init(&buf_head, 0);
+	strbuf_init(&buf_orig_head, 0);
+	strbuf_init(&buf_rebase_amend, 0);
+	strbuf_init(&buf_rebase_orig_head, 0);
+
+	strbuf_getline(&buf_head, head, '\n');
+	strbuf_getline(&buf_orig_head, orig_head, '\n');
+	strbuf_getline(&buf_rebase_amend, rebase_amend, '\n');
+	strbuf_getline(&buf_rebase_orig_head, rebase_orig_head, '\n');
+
+	fclose(head);
+	fclose(orig_head);
+	fclose(rebase_amend);
+	fclose(rebase_orig_head);
+
+	if (!strbuf_cmp(&buf_rebase_amend, &buf_rebase_orig_head)) {
+		if (strbuf_cmp(&buf_head, &buf_rebase_amend))
+			split_in_progress = 1;
+	} else if (!strbuf_cmp(&buf_orig_head, &buf_rebase_amend)) {
+		split_in_progress = 1;
+	} else if (strbuf_cmp(&buf_orig_head, &buf_rebase_orig_head)) {
+		split_in_progress = 1;
+	}
+
+	if (!strbuf_cmp(&buf_head, &buf_rebase_amend))
+		split_in_progress = 0;
+
+	strbuf_release(&buf_head);
+	strbuf_release(&buf_orig_head);
+	strbuf_release(&buf_rebase_amend);
+	strbuf_release(&buf_rebase_orig_head);
+	return split_in_progress;
+}
+
 static void show_rebase_in_progress(struct wt_status *s,
 				struct wt_status_state *state,
 				const char *color)
@@ -838,6 +910,11 @@ static void show_rebase_in_progress(struct wt_status *s,
 		if (advice_status_hints)
 			status_printf_ln(s, color,
 				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else if (split_commit_in_progress()) {
+		status_printf_ln(s, color, _("You are currently splitting a commit."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (Once your working directory is clean, run \"git rebase --continue\")"));
 	} else {
 		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
 		if (advice_status_hints && !s->amend) {
-- 
1.7.8

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

* Re: [PATCHv5 1/3] wt-status.*: better advices for git status added
  2012-06-01 16:57               ` Junio C Hamano
@ 2012-06-04 18:00                 ` Phil Hord
  0 siblings, 0 replies; 97+ messages in thread
From: Phil Hord @ 2012-06-04 18:00 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: konglu, Matthieu Moy, Kong Lucien, git, Duperray Valentin,
	Jonas Franck, Nguy Thomas, Nguyen Huynh Khoi Nguyen

On Fri, Jun 1, 2012 at 12:57 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Phil Hord <phil.hord@gmail.com> writes:
>
>>   $ git status --sequencer
>>   You have unmerged paths.
>>   You are in an am session.
>>   You are in the middle of an interactive rebase.
>>
>>   $ git status --porcelain --sequencer
>>   airu
>>
>> The "--porcelain --sequencer" combination I am imagining here would
>> show the status as a script-parseable sequence of single-letter
>> indicators telling the status of these same various conditions:
>>   u - unmerged paths
>>   a - git-am session
>>   i - interactive rebase
>>   r - rebase
>>   c - cherry-pick
>>   m - merge
>> etc.
>
> Some people seem to think that machine-readable has to mean
> unreadable cryptic line noises.  It's a disease.
>
> If you have to write "etc.", you clearly do not know what the
> range of possible values of these things will eventually be.
>
> And I do not think it is your fault not to know what we would want
> to add in the future.  But it is your fault to choose unreadable
> cryptic line noises as an output format.
>
> Just spell them out, and do not mark them for translation.

I agree.  And I waffled a bit between single-letter indicators,
abbreviated token-words, and fully spelled out words as you suggested.
 But I do think about future spelling or wording corrections (see
--indexed and http-referer), and I opted for letters in this example.

Thanks for the suggestion.  If I push this along, I'll use words and
let the list sort out the spellings.

Phil

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

* Re: [PATCHv7 2/4] t7512-status-help.sh: better advices for git status
  2012-06-04 17:19             ` [PATCHv7 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
@ 2012-06-04 21:02               ` Matthieu Moy
  2012-06-04 23:12               ` Junio C Hamano
  1 sibling, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-06-04 21:02 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> +test_expect_success 'status when conflicts resolved before commit' '
> +	test_when_finished "
> +		git commit -m "end_merge" &&

The " are respectively closing quote for the one on the line before, and
opening quote. Avoid nesting quotes, avoid quotes ;-).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* Re: [PATCHv6 2/4] t7512-status-help.sh: better advices for git status
  2012-06-04 10:04               ` konglu
  2012-06-04 15:04                 ` Junio C Hamano
@ 2012-06-04 22:07                 ` Junio C Hamano
  1 sibling, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-06-04 22:07 UTC (permalink / raw)
  To: konglu
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu

konglu@minatec.inpg.fr writes:

> Junio C Hamano <gitster@pobox.com>:
>
>> I thought Matthieu always called himself "Matthieu Moy", not the
>> other way around.  I also inferred the convention used for naming
>> the mailboxes at your institution to be "$First.$Last@$Domain",
>> which tells me that perhaps these names are all spelled backwards,
>> i.e. "$Last $First", which probably goes against the convention used
>> around you and Matthieu?
>
> Hm, yeah it's spelled backwards, I didn't take notice of that.

Oh, another thing.  In your v7 series, your author name (appears on
the From: header of the email) is spelled in K-L order, but your
Sign-off is the other way around, i.e. L-K.

Names of some people are spelled in Family-Given order even in
English context [*1*], and I do not have any objection if you are
following that cultural practice for _your own_ name.

I however want to see it done consistently between Author: and
Signed-off-by: lines.


[Footnote]

*1* Prime minister Lee Myung-bak, chairman Mao Zedong are some
examples.  Somewhat strangely, not prime minister Yoshihiko Noda,
even though some Japanese insist on spelling their names like
"FAMILY Given", with family name in all caps.

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

* Re: [PATCHv7 1/4] wt-status.*: better advices for git status added
  2012-06-04 17:19           ` [PATCHv7 " Kong Lucien
                               ` (2 preceding siblings ...)
  2012-06-04 17:19             ` [PATCHv7 4/4] status: better advices when splitting a commit (during rebase -i) Kong Lucien
@ 2012-06-04 23:01             ` Junio C Hamano
  2012-06-05 10:32               ` konglu
  2012-06-05 20:21             ` [PATCHv8 " Lucien Kong
  4 siblings, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-06-04 23:01 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> The case of conflicts during a rebase -i is now taken care of. The form
> of the tests has also been modified.

> diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
> index b8cb490..4326df7 100755
> --- a/t/t7060-wtstatus.sh
> +++ b/t/t7060-wtstatus.sh
> @@ -30,6 +30,9 @@ test_expect_success 'Report new path with conflict' '
>  
>  cat >expect <<EOF
>  # On branch side
> +# You have unmerged paths.
> +#   (fix conflicts and run "git commit")
> +#
>  # Unmerged paths:
>  #   (use "git add/rm <file>..." as appropriate to mark resolution)
>  #
> @@ -118,4 +121,65 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
>  	test_cmp expected actual
>  '

These probably would want to become test_i18ncmp.

Other than that, modulo message details, the code structure is very
pleasant to follow and this patch looks ready to be tested.

Good job.

> diff --git a/wt-status.c b/wt-status.c
> index dd6d8c4..2b19fe3 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -728,6 +729,167 @@ static void wt_status_print_tracking(struct wt_status *s)
> ...
> +static void show_am_in_progress(struct wt_status *s,
> +				struct wt_status_state *state,
> +				const char *color)
> +{
> +	status_printf_ln(s, color,
> +		_("You are in the middle of an am session."));
> +	if (state->am_empty_patch)
> +		status_printf_ln(s, color,
> +			_("The current patch is empty."));
> +	if (advice_status_hints) {
> +		status_printf_ln(s, color,
> +			_("  (use \"git am --abort\" to restore the original branch)"));
> +		status_printf_ln(s, color,
> +			_("  (use \"git am --skip\" to skip this patch)"));
> +		if (!state->am_empty_patch)
> +			status_printf_ln(s, color,
> +				_("  (when you have fixed this problem run \"git am --resolved\")"));
> +	}
> +	wt_status_print_trailer(s);
> +}

Perhaps s/fixed this problem/resolved conflicts/ or a similar
rephrasing is a good idea.

Conflicts from mergy operations are perfectly normal parts of a
regular workday, and it is not a "problem" that needs to be "fixed".
Both words scare the user by implying something is broken (or worse,
"git broke something") in the contents of user's repository.

There are existing messages that use the verb "fix" on "conflicts",
only because it is shorter than "resolve", but this one that calls a
conflict a "problem" goes too far in the wrong direction.

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

* Re: [PATCHv7 2/4] t7512-status-help.sh: better advices for git status
  2012-06-04 17:19             ` [PATCHv7 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
  2012-06-04 21:02               ` Matthieu Moy
@ 2012-06-04 23:12               ` Junio C Hamano
  1 sibling, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-06-04 23:12 UTC (permalink / raw)
  To: Kong Lucien
  Cc: git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Kong Lucien <Lucien.Kong@ensimag.imag.fr> writes:

> +test_description='git status advices'
> +
> +. ./test-lib.sh
> +
> +. "$TEST_DIRECTORY"/lib-rebase.sh
> +
> +set_fake_editor
> +
> +test_expect_success 'status when conflicts unresolved' '
> +	test_commit init main.txt init &&
> +	git branch second_branch &&
> +	test_commit on_master main.txt on_master &&
> +	git checkout second_branch &&
> +	test_commit on_second_branch main.txt on_second_branch &&
> +	test_must_fail git merge master &&
> +	cat >expected <<-\EOF &&
> +	# On branch second_branch
> +	# You have unmerged paths.
> +	#   (fix conflicts and run "git commit")
> +	#
> +	# Unmerged paths:
> +	#   (use "git add/rm <file>..." as appropriate to mark resolution)
> +	#
> +	#	both modified:      main.txt
> +	#
> +	no changes added to commit (use "git add" and/or "git commit -a")
> +	EOF
> +	git status --untracked-files=no >actual &&
> +	test_cmp expected actual
> +'

OK.

> +test_expect_success 'status when conflicts resolved before commit' '
> +	test_when_finished "
> +		git commit -m "end_merge" &&
> +		git checkout master &&
> +		git branch -D second_branch &&
> +		echo >main.txt
> +	" &&

I do not think this is a good idea.  The previous one may have
failed before even reaching "git merge" that was supposed to fail,
or "git merge" may have succeeded by mistake.

If you are assuming that all tests succeed when we didn't introduce
any bug to Git, and when breakages happen the developer should only
look at the first breakage, then it is better not to pretend as if
you are prepared for some tests in the sequence to fail by giving a
clean slate to later tests.

For these two tests, I think it is much simpler and cleaner to
organize them by

 (1) have code to prepare two branches in the first test, tag the
     tip of second one, and assume this test won't break;

 (2) move the remainder of the first test, starting with the merge
     of master that is expected to fail, into a separate one; and

 (3) begin the third test (the second one in your patch) with:

 	git reset --hard $that_tag_you_added_to_the_tip_of_second &&
	test_must_fail git merge master &&

     so that it begins from the state the test expects it to begin
     in, even if the previous test somehow merged master cleanly by
     mistake.

> +test_expect_success 'status when rebase in progress before resolving conflicts' '
> +	test_commit one_rebase main.txt one &&
> +	test_commit two_rebase main.txt two &&
> +	test_commit three_rebase main.txt three &&
> +	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
> +	cat >expected <<-\EOF &&
> +	# Not currently on any branch.
> +	# You are currently rebasing.
> +	#   (fix conflicts and then run "git rebase --continue")
> +	#   (use "git rebase --skip" to skip this patch)
> +	#   (use "git rebase --abort" to check out the original branch)
> +	#
> +	# Unmerged paths:
> +	#   (use "git reset HEAD <file>..." to unstage)
> +	#   (use "git add/rm <file>..." as appropriate to mark resolution)
> +	#
> +	#	both modified:      main.txt
> +	#
> +	no changes added to commit (use "git add" and/or "git commit -a")
> +	EOF
> +	git status --untracked-files=no >actual &&
> +	test_cmp expected actual
> +'
> +
> +
> +test_expect_success 'status when rebase in progress before rebase --continue' '
> +	test_when_finished "git rebase --abort" &&

Likewise.  If anything, "git rebase --abort" belongs to the previous
test that tried to run "git rebase".

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

* Re: [PATCHv6 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-04 15:35             ` Phil Hord
@ 2012-06-05  9:13               ` konglu
  0 siblings, 0 replies; 97+ messages in thread
From: konglu @ 2012-06-05  9:13 UTC (permalink / raw)
  To: Phil Hord
  Cc: Kong Lucien, git, Duperray Valentin, Jonas Franck, Nguy Thomas,
	Nguyen Huynh Khoi Nguyen, Moy Matthieu


Phil Hord <phil.hord@gmail.com> a écrit :

> On Sun, Jun 3, 2012 at 2:30 PM, Kong Lucien  
> <Lucien.Kong@ensimag.imag.fr> wrote:
>> Add new informative help messages at the output of 'git status' when
>> the user is splitting a commit. The code figures this state by
>> comparing the contents of the following files in the .git/ directory:
>>          - HEAD
>>          - ORIG_HEAD
>>          - rebase-merge/amend
>>          - rebase-merge/orig-head
>>
>> Signed-off-by: Kong Lucien <Lucien.Kong@ensimag.imag.fr>
>> Signed-off-by: Duperray Valentin <Valentin.Duperray@ensimag.imag.fr>
>> Signed-off-by: Jonas Franck <Franck.Jonas@ensimag.imag.fr>
>> Signed-off-by: Nguy Thomas <Thomas.Nguy@ensimag.imag.fr>
>> Signed-off-by: Nguyen Huynh Khoi Nguyen  
>> <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
>> Signed-off-by: Moy Matthieu <Matthieu.Moy@grenoble-inp.fr>
>> ---
>> The second test added by this patch fails because the case in which
>> the user amend the last commit through rebase -i is not taken care of.
>> We infer that the user would directly run "git commit --amend" instead
>> of amending it with a rebase -i.
>
>
> Maybe this is safe and logical for most workflows, or maybe this is a
> convenience that makes this patch possible (I did not read the patch
> yet).  But I know that I sometimes use rebase-i instead of
> commit--amend because I did not realize the patch I am fixing is the
> most recent one until after continuing, or because the patch I am
> amending was moved into the most-recent position during the rebase-i
> itself.

Right, This case has to be taken care of. It will need some work as
it's quite difficult to distinguish the current state after doing
a reset HEAD^ or doing a commit --amend when the rebase-merge/amend
is set on the last commit.

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

* Re: [PATCHv7 1/4] wt-status.*: better advices for git status added
  2012-06-04 23:01             ` [PATCHv7 1/4] wt-status.*: better advices for git status added Junio C Hamano
@ 2012-06-05 10:32               ` konglu
  2012-06-05 11:33                 ` Matthieu Moy
  0 siblings, 1 reply; 97+ messages in thread
From: konglu @ 2012-06-05 10:32 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Kong Lucien, git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy


Junio C Hamano <gitster@pobox.com> a écrit :

>> @@ -728,6 +729,167 @@ static void wt_status_print_tracking(struct  
>> wt_status *s)
>> ...
>> +static void show_am_in_progress(struct wt_status *s,
>> +				struct wt_status_state *state,
>> +				const char *color)
>> +{
>> +	status_printf_ln(s, color,
>> +		_("You are in the middle of an am session."));
>> +	if (state->am_empty_patch)
>> +		status_printf_ln(s, color,
>> +			_("The current patch is empty."));
>> +	if (advice_status_hints) {
>> +		status_printf_ln(s, color,
>> +			_("  (use \"git am --abort\" to restore the original branch)"));
>> +		status_printf_ln(s, color,
>> +			_("  (use \"git am --skip\" to skip this patch)"));
>> +		if (!state->am_empty_patch)
>> +			status_printf_ln(s, color,
>> +				_("  (when you have fixed this problem run \"git am --resolved\")"));
>> +	}
>> +	wt_status_print_trailer(s);
>> +}
>
> Perhaps s/fixed this problem/resolved conflicts/ or a similar
> rephrasing is a good idea.
>
> Conflicts from mergy operations are perfectly normal parts of a
> regular workday, and it is not a "problem" that needs to be "fixed".
> Both words scare the user by implying something is broken (or worse,
> "git broke something") in the contents of user's repository.
>
> There are existing messages that use the verb "fix" on "conflicts",
> only because it is shorter than "resolve", but this one that calls a
> conflict a "problem" goes too far in the wrong direction.

I agree. Still, experienced users probably have their advice.statushints
disabled and won't have any problems resolving a conflict. However, for
"beginners" that need the advices, resolving a conflict may not seem
as trivial as it is. And even though the word "problem" may scare them,
it will attract their attention.

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

* Re: [PATCHv7 1/4] wt-status.*: better advices for git status added
  2012-06-05 10:32               ` konglu
@ 2012-06-05 11:33                 ` Matthieu Moy
  0 siblings, 0 replies; 97+ messages in thread
From: Matthieu Moy @ 2012-06-05 11:33 UTC (permalink / raw)
  To: konglu
  Cc: Junio C Hamano, Kong Lucien, git, Valentin Duperray,
	Franck Jonas, Thomas Nguy, Huynh Khoi Nguyen Nguyen

konglu@minatec.inpg.fr writes:

> > Perhaps s/fixed this problem/resolved conflicts/ [...]
>
> I agree. Still, experienced users probably have their advice.statushints
> disabled and won't have any problems resolving a conflict. However, for
> "beginners" that need the advices, resolving a conflict may not seem
> as trivial as it is. And even though the word "problem" may scare them,
> it will attract their attention.

But beginners are scared by conflicts. Indeed, "there are conflicts" is
automatically translated into "sir, it doesn't work" by many beginners I
know ;-). I prefer Junio's wording as a subliminal message that
conflicts are not "a problem", but just "something you should avoid when
possible, and fix otherwise".

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

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

* [PATCHv8 1/4] wt-status.*: better advices for git status added
  2012-06-04 17:19           ` [PATCHv7 " Kong Lucien
                               ` (3 preceding siblings ...)
  2012-06-04 23:01             ` [PATCHv7 1/4] wt-status.*: better advices for git status added Junio C Hamano
@ 2012-06-05 20:21             ` Lucien Kong
  2012-06-05 20:21               ` [PATCHv8 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
                                 ` (3 more replies)
  4 siblings, 4 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-05 20:21 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

This patch provides new informative help messages in the display of
'git status' (at the top) during conflicts, rebase, am, bisect or
cherry-pick process.

The new messages are not shown when using options such as -s or
--porcelain. The messages about the current situation of the user are
always displayed but the advices on what the user needs to do in order
to resume a rebase/bisect/am/commit after resolving conflicts can be
hidden by setting advice.statushints to 'false' in the config file.

Thus, information about the updated advice.statushints key are added
in Documentation/config.txt.

Also, the test t7060-wt-status.sh is now working with the new help
messages. Tests about suggestions of "git rm" are also added.

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
The help messages in the case of an am session are changed to be
consistent with the other messages.

 Documentation/config.txt |    7 +-
 t/t7060-wtstatus.sh      |   64 ++++++++++++++++++
 wt-status.c              |  163 ++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.h              |   11 +++
 4 files changed, 242 insertions(+), 3 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a..ccce4f6 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -159,9 +159,10 @@ advice.*::
 		specified a refspec that isn't your current branch) and
 		it resulted in a non-fast-forward error.
 	statusHints::
-		Directions on how to stage/unstage/add shown in the
-		output of linkgit:git-status[1] and the template shown
-		when writing commit messages.
+		Show directions on how to proceed from the current
+		state in the output of linkgit:git-status[1] and in
+		the template shown when writing commit messages in
+		linkgit:git-commit[1].
 	commitBeforeMerge::
 		Advice shown when linkgit:git-merge[1] refuses to
 		merge to avoid overwriting local changes.
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb490..e8c3690 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,9 @@ test_expect_success 'Report new path with conflict' '
 
 cat >expect <<EOF
 # On branch side
+# You have unmerged paths.
+#   (fix conflicts and run "git commit")
+#
 # Unmerged paths:
 #   (use "git add/rm <file>..." as appropriate to mark resolution)
 #
@@ -118,4 +121,65 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
 	test_cmp expected actual
 '
 
+
+test_expect_success 'status when conflicts with add and rm advice (deleted by them)' '
+	git reset --hard &&
+	git checkout master &&
+	test_commit init main.txt init &&
+	git checkout -b second_branch &&
+	git rm main.txt &&
+	git commit -m "main.txt deleted on second_branch" &&
+	test_commit second conflict.txt second &&
+	git checkout master &&
+	test_commit on_second main.txt on_second &&
+	test_commit master conflict.txt master &&
+	test_must_fail git merge second_branch &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both added:         conflict.txt
+	#	deleted by them:    main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+	git reset --hard &&
+	git checkout -b conflict &&
+	test_commit one main.txt one &&
+	git branch conflict_second &&
+	git mv main.txt sub_master.txt &&
+	git commit -m "main.txt renamed in sub_master.txt" &&
+	git checkout conflict_second &&
+	git mv main.txt sub_second.txt &&
+	git commit -m "main.txt renamed in sub_second.txt" &&
+	test_must_fail git merge conflict &&
+	cat >expected <<-\EOF &&
+	# On branch conflict_second
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#	added by them:      sub_master.txt
+	#	added by us:        sub_second.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
 test_done
diff --git a/wt-status.c b/wt-status.c
index dd6d8c4..7548509 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
 	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
 	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
+	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
 };
 
 static const char *color(int slot, struct wt_status *s)
@@ -728,6 +729,167 @@ static void wt_status_print_tracking(struct wt_status *s)
 	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
 }
 
+static int has_unmerged(struct wt_status *s)
+{
+	int i;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		d = s->change.items[i].util;
+		if (d->stagemask)
+			return 1;
+	}
+	return 0;
+}
+
+static void show_merge_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You have unmerged paths."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+	} else {
+		status_printf_ln(s, color,
+			_("All conflicts fixed but you are still merging."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (use \"git commit\" to conclude merge)"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_am_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color,
+		_("You are in the middle of an am session."));
+	if (state->am_empty_patch)
+		status_printf_ln(s, color,
+			_("The current patch is empty."));
+	if (advice_status_hints) {
+		if (!state->am_empty_patch)
+			status_printf_ln(s, color,
+				_("  (fix conflicts and then run \"git am --resolved\")"));
+		status_printf_ln(s, color,
+			_("  (use \"git am --skip\" to skip this patch)"));
+		status_printf_ln(s, color,
+			_("  (use \"git am --abort\" to restore the original branch)"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_rebase_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	struct stat st;
+
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints) {
+			status_printf_ln(s, color,
+				_("  (fix conflicts and then run \"git rebase --continue\")"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --skip\" to skip this patch)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --abort\" to check out the original branch)"));
+		}
+	} else if (state->rebase_in_progress || !stat(git_path("MERGE_MSG"), &st)) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else {
+		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
+		if (advice_status_hints && !s->amend) {
+			status_printf_ln(s, color,
+				_("  (use \"git commit --amend\" to amend the current commit)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --continue\" once you are satisfied with your changes)"));
+		}
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_cherry_pick_in_progress(struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	status_printf_ln(s, color, _("You are currently cherry-picking."));
+	if (advice_status_hints) {
+		if (has_unmerged(s))
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+		else
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git commit\")"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_bisect_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color, _("You are currently bisecting."));
+	if (advice_status_hints)
+		status_printf_ln(s, color,
+			_("  (use \"git bisect reset\" to get back to the original branch)"));
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_print_state(struct wt_status *s)
+{
+	const char *state_color = color(WT_STATUS_IN_PROGRESS, s);
+	struct wt_status_state *state = calloc(1, sizeof(*state));
+	struct stat st;
+
+	state->merge_in_progress = 0;
+	state->am_in_progress = 0;
+	state->am_empty_patch = 0;
+	state->rebase_in_progress = 0;
+	state->rebase_interactive_in_progress = 0;
+	state->cherry_pick_in_progress = 0;
+	state->bisect_in_progress = 0;
+
+	if (!stat(git_path("MERGE_HEAD"), &st)) {
+		state->merge_in_progress = 1;
+	} else if (!stat(git_path("rebase-apply"), &st)) {
+		if (!stat(git_path("rebase-apply/applying"), &st)) {
+			state->am_in_progress = 1;
+			if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
+				state->am_empty_patch = 1;
+		} else {
+			state->rebase_in_progress = 1;
+		}
+	} else if (!stat(git_path("rebase-merge"), &st)) {
+		if (!stat(git_path("rebase-merge/interactive"), &st))
+			state->rebase_interactive_in_progress = 1;
+		else
+			state->rebase_in_progress = 1;
+	} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
+		state->cherry_pick_in_progress = 1;
+	}
+	if (!stat(git_path("BISECT_LOG"), &st))
+		state->bisect_in_progress = 1;
+
+	if (state->merge_in_progress)
+		show_merge_in_progress(s, state, state_color);
+	else if (state->am_in_progress)
+		show_am_in_progress(s, state, state_color);
+	else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
+		show_rebase_in_progress(s, state, state_color);
+	else if (state->cherry_pick_in_progress)
+		show_cherry_pick_in_progress(s, state, state_color);
+	if (state->bisect_in_progress)
+		show_bisect_in_progress(s, state, state_color);
+	free(state);
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
@@ -750,6 +912,7 @@ void wt_status_print(struct wt_status *s)
 			wt_status_print_tracking(s);
 	}
 
+	wt_status_print_state(s);
 	if (s->is_initial) {
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7..c1066a0 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -15,6 +15,7 @@ enum color_wt_status {
 	WT_STATUS_LOCAL_BRANCH,
 	WT_STATUS_REMOTE_BRANCH,
 	WT_STATUS_ONBRANCH,
+	WT_STATUS_IN_PROGRESS,
 	WT_STATUS_MAXSLOT
 };
 
@@ -71,6 +72,16 @@ struct wt_status {
 	struct string_list ignored;
 };
 
+struct wt_status_state {
+	int merge_in_progress;
+	int am_in_progress;
+	int am_empty_patch;
+	int rebase_in_progress;
+	int rebase_interactive_in_progress;
+	int cherry_pick_in_progress;
+	int bisect_in_progress;
+};
+
 void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
-- 
1.7.8

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

* [PATCHv8 2/4] t7512-status-help.sh: better advices for git status
  2012-06-05 20:21             ` [PATCHv8 " Lucien Kong
@ 2012-06-05 20:21               ` Lucien Kong
  2012-06-05 20:21               ` [PATCHv8 3/4] status: don't suggest "git rm" or "git add" if not appropriate Lucien Kong
                                 ` (2 subsequent siblings)
  3 siblings, 0 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-05 20:21 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

The following tests include several cases in which the user needs to
run 'git status' to know his current situation, whether there're
conflicts or he's in rebase/bisect/am/cherry-pick progress.

One of the test is about the set of the advice.statushints config key
to 'false' in .git/config.

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
The structure of the tests are changed so that they are now independant
with each other.

 t/t7512-status-help.sh |  372 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 372 insertions(+), 0 deletions(-)
 create mode 100755 t/t7512-status-help.sh

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
new file mode 100755
index 0000000..3714e8e
--- /dev/null
+++ b/t/t7512-status-help.sh
@@ -0,0 +1,372 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'prepare for conflicts' '
+	test_commit init main.txt init &&
+	git branch conflicts &&
+	test_commit on_master main.txt on_master &&
+	git checkout conflicts &&
+	test_commit on_conflicts main.txt on_conflicts
+'
+
+
+test_expect_success 'status when conflicts unresolved' '
+	test_must_fail git merge master &&
+	cat >expected <<-\EOF &&
+	# On branch conflicts
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	git reset --hard conflicts &&
+	test_must_fail git merge master &&
+	echo one >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch conflicts
+	# All conflicts fixed but you are still merging.
+	#   (use "git commit" to conclude merge)
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for rebase conflicts' '
+	git reset --hard master &&
+	git checkout -b rebase_conflicts &&
+	test_commit one_rebase main.txt one &&
+	test_commit two_rebase main.txt two &&
+	test_commit three_rebase main.txt three
+'
+
+
+test_expect_success 'status when rebase in progress before resolving conflicts' '
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (fix conflicts and then run "git rebase --continue")
+	#   (use "git rebase --skip" to skip this patch)
+	#   (use "git rebase --abort" to check out the original branch)
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when rebase in progress before rebase --continue' '
+	git reset --hard rebase_conflicts &&
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	echo three >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (all conflicts fixed: run "git rebase --continue")
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for rebase_i_conflicts' '
+	git reset --hard master &&
+	git checkout -b rebase_i_conflicts &&
+	test_commit one_unmerge main.txt one_unmerge &&
+	git branch rebase_i_conflicts_second &&
+	test_commit one_master main.txt one_master &&
+	git checkout rebase_i_conflicts_second &&
+	test_commit one_second main.txt one_second
+'
+
+
+test_expect_success 'status during rebase -i when conflicts unresolved' '
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase -i rebase_i_conflicts &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (fix conflicts and then run "git rebase --continue")
+	#   (use "git rebase --skip" to skip this patch)
+	#   (use "git rebase --abort" to check out the original branch)
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status during rebase -i after resolving conflicts' '
+	git reset --hard rebase_i_conflicts_second &&
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase -i rebase_i_conflicts &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (all conflicts fixed: run "git rebase --continue")
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when rebasing -i in edit mode' '
+	git reset --hard master &&
+	git checkout -b rebase_i_edit &&
+	test_commit one_rebase_i main.txt one &&
+	test_commit two_rebase_i main.txt two &&
+	test_commit three_rebase_i main.txt three &&
+	FAKE_LINES="1 edit 2" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~2 &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare am_session' '
+	git reset --hard master &&
+	git checkout -b am_session &&
+	test_commit one_am one.txt "one" &&
+	test_commit two_am two.txt "two" &&
+	test_commit three_am three.txt "three"
+'
+
+
+test_expect_success 'status in an am session: file already exists' '
+	git checkout -b am_already_exists &&
+	test_when_finished "rm Maildir/* && git am --abort" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch am_already_exists
+	# You are in the middle of an am session.
+	#   (fix conflicts and then run "git am --resolved")
+	#   (use "git am --skip" to skip this patch)
+	#   (use "git am --abort" to restore the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status in an am session: file does not exist' '
+	git reset --hard am_session &&
+	git checkout -b am_not_exists &&
+	git rm three.txt &&
+	git commit -m "delete three.txt" &&
+	test_when_finished "rm Maildir/* && git am --abort" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch am_not_exists
+	# You are in the middle of an am session.
+	#   (fix conflicts and then run "git am --resolved")
+	#   (use "git am --skip" to skip this patch)
+	#   (use "git am --abort" to restore the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status in an am session: empty patch' '
+	git reset --hard am_session &&
+	git checkout -b am_empty &&
+	test_when_finished "rm Maildir/* && git am --abort" &&
+	git format-patch -3 -oMaildir &&
+	git rm one.txt two.txt three.txt &&
+	git commit -m "delete all am_empty" &&
+	echo error >Maildir/0002-two_am.patch &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch am_empty
+	# You are in the middle of an am session.
+	# The current patch is empty.
+	#   (use "git am --skip" to skip this patch)
+	#   (use "git am --abort" to restore the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when bisecting' '
+	git reset --hard master &&
+	git checkout -b bisect &&
+	test_commit one_bisect main.txt one &&
+	test_commit two_bisect main.txt two &&
+	test_commit three_bisect main.txt three &&
+	test_when_finished "git bisect reset" &&
+	git bisect start &&
+	git bisect bad &&
+	git bisect good one_bisect &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently bisecting.
+	#   (use "git bisect reset" to get back to the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when rebase conflicts with statushints disabled' '
+	git reset --hard master &&
+	git checkout -b statushints_disabled &&
+	test_when_finished "git config --local advice.statushints true" &&
+	git config --local advice.statushints false &&
+	test_commit one_statushints main.txt one &&
+	test_commit two_statushints main.txt two &&
+	test_commit three_statushints main.txt three &&
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#
+	# Unmerged paths:
+	#	both modified:      main.txt
+	#
+	no changes added to commit
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for cherry-pick conflicts' '
+	git reset --hard master &&
+	git checkout -b cherry_branch &&
+	test_commit one_cherry main.txt one &&
+	test_commit two_cherries main.txt two &&
+	git checkout -b cherry_branch_second &&
+	test_commit second_cherry main.txt second &&
+	git checkout cherry_branch &&
+	test_commit three_cherries main.txt three
+'
+
+
+test_expect_success 'status when cherry-picking before resolving conflicts' '
+	test_when_finished "git cherry-pick --abort" &&
+	test_must_fail git cherry-pick cherry_branch_second &&
+	cat >expected <<-\EOF &&
+	# On branch cherry_branch
+	# You are currently cherry-picking.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when cherry-picking after resolving conflicts' '
+	git reset --hard cherry_branch &&
+	test_when_finished "git cherry-pick --abort" &&
+	test_must_fail git cherry-pick cherry_branch_second &&
+	echo end >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch cherry_branch
+	# You are currently cherry-picking.
+	#   (all conflicts fixed: run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_done
-- 
1.7.8

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

* [PATCHv8 3/4] status: don't suggest "git rm" or "git add" if not appropriate
  2012-06-05 20:21             ` [PATCHv8 " Lucien Kong
  2012-06-05 20:21               ` [PATCHv8 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
@ 2012-06-05 20:21               ` Lucien Kong
  2012-06-05 20:21               ` [PATCHv8 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
  2012-06-07 13:17               ` [PATCHv9 1/4] wt-status.*: better advices for git status added Lucien Kong
  3 siblings, 0 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-05 20:21 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

The display of the advice '(use git add/rm [...])' (when there are
unmerged files) after running 'git status' is now depending of the
mark, whether it's 'both deleted', 'deleted by us/them' or others. For
instance, when there is just one file that's marked as 'both deleted',
'git status' shows '(use git rm [...])' and if there are two files,
one as 'both deleted' and the other as 'added by them', the advice is
'(use git add/rm [...])'.

The previous tests in t7512-status-help.sh are updated.

Test about the case of only 'both deleted' is added in
t7060-wtstatus.sh

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
 t/t7060-wtstatus.sh    |   36 ++++++++++++++++++++++++++++++++++--
 t/t7512-status-help.sh |    8 ++++----
 wt-status.c            |   37 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index e8c3690..f4f38a5 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -152,7 +152,7 @@ test_expect_success 'status when conflicts with add and rm advice (deleted by th
 '
 
 
-test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+test_expect_success 'prepare for conflicts' '
 	git reset --hard &&
 	git checkout -b conflict &&
 	test_commit one main.txt one &&
@@ -161,7 +161,11 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted)
 	git commit -m "main.txt renamed in sub_master.txt" &&
 	git checkout conflict_second &&
 	git mv main.txt sub_second.txt &&
-	git commit -m "main.txt renamed in sub_second.txt" &&
+	git commit -m "main.txt renamed in sub_second.txt"
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
 	test_must_fail git merge conflict &&
 	cat >expected <<-\EOF &&
 	# On branch conflict_second
@@ -182,4 +186,32 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted)
 '
 
 
+test_expect_success 'status when conflicts with only rm advice (both deleted)' '
+	git reset --hard conflict_second &&
+	test_must_fail git merge conflict &&
+	git add sub_master.txt &&
+	git add sub_second.txt &&
+	cat >expected <<-\EOF &&
+	# On branch conflict_second
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	new file:   sub_master.txt
+	#
+	# Unmerged paths:
+	#   (use "git rm <file>..." to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual &&
+	git reset --hard &&
+	git checkout master
+'
+
+
 test_done
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 3714e8e..bdce192 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -30,7 +30,7 @@ test_expect_success 'status when conflicts unresolved' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -83,7 +83,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -140,7 +140,7 @@ test_expect_success 'status during rebase -i when conflicts unresolved' '
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -336,7 +336,7 @@ test_expect_success 'status when cherry-picking before resolving conflicts' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
diff --git a/wt-status.c b/wt-status.c
index 7548509..fcde045 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -131,9 +131,34 @@ void wt_status_prepare(struct wt_status *s)
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
 {
+	int i;
+	int del_mod_conflict = 0;
+	int both_deleted = 0;
+	int not_deleted = 0;
 	const char *c = color(WT_STATUS_HEADER, s);
 
 	status_printf_ln(s, c, _("Unmerged paths:"));
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct string_list_item *it = &(s->change.items[i]);
+		struct wt_status_change_data *d = it->util;
+
+		switch (d->stagemask) {
+		case 0:
+			break;
+		case 1:
+			both_deleted = 1;
+			break;
+		case 3:
+		case 5:
+			del_mod_conflict = 1;
+			break;
+		default:
+			not_deleted = 1;
+			break;
+		}
+	}
+
 	if (!advice_status_hints)
 		return;
 	if (s->whence != FROM_COMMIT)
@@ -142,7 +167,17 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
 		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
 		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
-	status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+
+	if (!both_deleted) {
+		if (!del_mod_conflict)
+			status_printf_ln(s, c, _("  (use \"git add <file>...\" to mark resolution)"));
+		else
+			status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	} else if (!del_mod_conflict && !not_deleted) {
+		status_printf_ln(s, c, _("  (use \"git rm <file>...\" to mark resolution)"));
+	} else {
+		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	}
 	status_printf_ln(s, c, "");
 }
 
-- 
1.7.8

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

* [PATCHv8 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-05 20:21             ` [PATCHv8 " Lucien Kong
  2012-06-05 20:21               ` [PATCHv8 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
  2012-06-05 20:21               ` [PATCHv8 3/4] status: don't suggest "git rm" or "git add" if not appropriate Lucien Kong
@ 2012-06-05 20:21               ` Lucien Kong
  2012-06-05 21:16                 ` Junio C Hamano
  2012-06-07 13:17               ` [PATCHv9 1/4] wt-status.*: better advices for git status added Lucien Kong
  3 siblings, 1 reply; 97+ messages in thread
From: Lucien Kong @ 2012-06-05 20:21 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Add new informative help messages at the output of 'git status' when
the user is splitting a commit. The code figures this state by
comparing the contents of the following files in the .git/ directory:
	  - HEAD
	  - ORIG_HEAD
	  - rebase-merge/amend
	  - rebase-merge/orig-head

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
 t/t7512-status-help.sh |   55 ++++++++++++++++++++++++++++++++++
 wt-status.c            |   77 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 132 insertions(+), 0 deletions(-)

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index bdce192..a77574f 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -196,6 +196,61 @@ test_expect_success 'status when rebasing -i in edit mode' '
 '
 
 
+test_expect_success 'status when splitting a commit' '
+	git reset --hard master &&
+	git checkout -b split_commit &&
+	test_commit one_split main.txt one &&
+	test_commit two_split main.txt two &&
+	test_commit three_split main.txt three &&
+	test_commit four_split main.txt four &&
+	FAKE_LINES="1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_failure 'status after editing the last commit with --amend during a rebase -i' '
+	git reset --hard master &&
+	git checkout -b amend_last &&
+	test_commit one_amend main.txt one &&
+	test_commit two_amend main.txt two &&
+	test_commit three_amend main.txt three &&
+	test_commit four_amend main.txt four &&
+	FAKE_LINES="1 2 edit 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "foo" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (working directory clean)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
 test_expect_success 'prepare am_session' '
 	git reset --hard master &&
 	git checkout -b am_session &&
diff --git a/wt-status.c b/wt-status.c
index fcde045..5445dbf 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -12,6 +12,7 @@
 #include "refs.h"
 #include "submodule.h"
 #include "column.h"
+#include "strbuf.h"
 
 static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -817,6 +818,77 @@ static void show_am_in_progress(struct wt_status *s,
 	wt_status_print_trailer(s);
 }
 
+static int split_commit_in_progress()
+{
+	FILE *head;
+	struct strbuf buf_head;
+	FILE *orig_head;
+	struct strbuf buf_orig_head;
+	FILE *rebase_amend;
+	struct strbuf buf_rebase_amend;
+	FILE *rebase_orig_head;
+	struct strbuf buf_rebase_orig_head;
+	int split_in_progress = 0;
+
+	head = fopen(git_path("HEAD"), "r");
+	if (!head)
+		return 0;
+
+	orig_head = fopen(git_path("ORIG_HEAD"), "r");
+	if (!orig_head) {
+		fclose(head);
+		return 0;
+	}
+
+	rebase_amend = fopen(git_path("rebase-merge/amend"), "r");
+	if (!rebase_amend) {
+		fclose(head);
+		fclose(orig_head);
+		return 0;
+	}
+
+	rebase_orig_head = fopen(git_path("rebase-merge/orig-head"), "r");
+	if (!rebase_orig_head) {
+		fclose(head);
+		fclose(orig_head);
+		fclose(rebase_amend);
+		return 0;
+	}
+
+	strbuf_init(&buf_head, 0);
+	strbuf_init(&buf_orig_head, 0);
+	strbuf_init(&buf_rebase_amend, 0);
+	strbuf_init(&buf_rebase_orig_head, 0);
+
+	strbuf_getline(&buf_head, head, '\n');
+	strbuf_getline(&buf_orig_head, orig_head, '\n');
+	strbuf_getline(&buf_rebase_amend, rebase_amend, '\n');
+	strbuf_getline(&buf_rebase_orig_head, rebase_orig_head, '\n');
+
+	fclose(head);
+	fclose(orig_head);
+	fclose(rebase_amend);
+	fclose(rebase_orig_head);
+
+	if (!strbuf_cmp(&buf_rebase_amend, &buf_rebase_orig_head)) {
+		if (strbuf_cmp(&buf_head, &buf_rebase_amend))
+			split_in_progress = 1;
+	} else if (!strbuf_cmp(&buf_orig_head, &buf_rebase_amend)) {
+		split_in_progress = 1;
+	} else if (strbuf_cmp(&buf_orig_head, &buf_rebase_orig_head)) {
+		split_in_progress = 1;
+	}
+
+	if (!strbuf_cmp(&buf_head, &buf_rebase_amend))
+		split_in_progress = 0;
+
+	strbuf_release(&buf_head);
+	strbuf_release(&buf_orig_head);
+	strbuf_release(&buf_rebase_amend);
+	strbuf_release(&buf_rebase_orig_head);
+	return split_in_progress;
+}
+
 static void show_rebase_in_progress(struct wt_status *s,
 				struct wt_status_state *state,
 				const char *color)
@@ -838,6 +910,11 @@ static void show_rebase_in_progress(struct wt_status *s,
 		if (advice_status_hints)
 			status_printf_ln(s, color,
 				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else if (split_commit_in_progress()) {
+		status_printf_ln(s, color, _("You are currently splitting a commit."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (Once your working directory is clean, run \"git rebase --continue\")"));
 	} else {
 		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
 		if (advice_status_hints && !s->amend) {
-- 
1.7.8

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

* Re: [PATCHv8 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-05 20:21               ` [PATCHv8 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
@ 2012-06-05 21:16                 ` Junio C Hamano
  2012-06-08  9:29                   ` konglu
  0 siblings, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-06-05 21:16 UTC (permalink / raw)
  To: Lucien Kong
  Cc: git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:

> +static int split_commit_in_progress()

static int split_commit_in_progress(void)

> +{
> +	FILE *head;
> +	struct strbuf buf_head;
> +	FILE *orig_head;
> +	struct strbuf buf_orig_head;
> +	FILE *rebase_amend;
> +	struct strbuf buf_rebase_amend;
> +	FILE *rebase_orig_head;
> +	struct strbuf buf_rebase_orig_head;
> +	int split_in_progress = 0;
> +
> +	head = fopen(git_path("HEAD"), "r");
> +	if (!head)
> +		return 0;
> +
> +	orig_head = fopen(git_path("ORIG_HEAD"), "r");
> +	if (!orig_head) {
> +		fclose(head);
> +		return 0;
> +	}
> +
> +	rebase_amend = fopen(git_path("rebase-merge/amend"), "r");
> +	if (!rebase_amend) {
> +		fclose(head);
> +		fclose(orig_head);
> +		return 0;
> +	}
> +
> +	rebase_orig_head = fopen(git_path("rebase-merge/orig-head"), "r");
> +	if (!rebase_orig_head) {
> +		fclose(head);
> +		fclose(orig_head);
> +		fclose(rebase_amend);
> +		return 0;
> +	}
> +
> +	strbuf_init(&buf_head, 0);
> +	strbuf_init(&buf_orig_head, 0);
> +	strbuf_init(&buf_rebase_amend, 0);
> +	strbuf_init(&buf_rebase_orig_head, 0);
> +
> +	strbuf_getline(&buf_head, head, '\n');
> +	strbuf_getline(&buf_orig_head, orig_head, '\n');
> +	strbuf_getline(&buf_rebase_amend, rebase_amend, '\n');
> +	strbuf_getline(&buf_rebase_orig_head, rebase_orig_head, '\n');
> +
> +	fclose(head);
> +	fclose(orig_head);
> +	fclose(rebase_amend);
> +	fclose(rebase_orig_head);


That is somewhat an ugly sequence; wouldn't it make sense to have a
small helper that takes a path in git_path() and returns a pointer
to an allocated string, i.e. something like...

	static char *read_line_from_git_path(const char *filename)
        {
        	struct struct buf = STRBUF_INIT;
                FILE *fp = fopen(git_path(filename), "r");
                if (!fp)
                	return NULL;
		strbuf_getline(&buf, fp, '\n');
		fclose(fp);
                return strbuf_detach(&buf, NULL);
	}

nb. return value from fclose() may need to be be checked as well,
but this is just an illustration.

Reading from git_path("HEAD") looked funny, as you may end up
reading the "ref: refs/heads/master".  Of course that would not
compare equal to what you would read from "rebase-merge/amend", and
that may be fine for the purpose of your test, but it still looks
somewhat funny.  As modern rebase is done on a detached HEAD,
perhaps it is a good idea to check if the HEAD is detached and
return false from this function if that is not the case.  I dunno.

Other than that, all four patches in the series looked good.  Will
replace what I queued on 'pu' last night.

Thanks.

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

* [PATCHv9 1/4] wt-status.*: better advices for git status added
  2012-06-05 20:21             ` [PATCHv8 " Lucien Kong
                                 ` (2 preceding siblings ...)
  2012-06-05 20:21               ` [PATCHv8 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
@ 2012-06-07 13:17               ` Lucien Kong
  2012-06-07 13:17                 ` [PATCHv9 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
                                   ` (3 more replies)
  3 siblings, 4 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-07 13:17 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

This patch provides new informative help messages in the display of
'git status' (at the top) during conflicts, rebase, am, bisect or
cherry-pick process.

The new messages are not shown when using options such as -s or
--porcelain. The messages about the current situation of the user are
always displayed but the advices on what the user needs to do in order
to resume a rebase/bisect/am/commit after resolving conflicts can be
hidden by setting advice.statushints to 'false' in the config file.

Thus, information about the updated advice.statushints key are added
in Documentation/config.txt.

Also, the test t7060-wt-status.sh is now working with the new help
messages. Tests about suggestions of "git rm" are also added.

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
part 1/4 unchanged since v8. Only the part 4/4 is changed.

 Documentation/config.txt |    7 +-
 t/t7060-wtstatus.sh      |   64 ++++++++++++++++++
 wt-status.c              |  163 ++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.h              |   11 +++
 4 files changed, 242 insertions(+), 3 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a..ccce4f6 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -159,9 +159,10 @@ advice.*::
 		specified a refspec that isn't your current branch) and
 		it resulted in a non-fast-forward error.
 	statusHints::
-		Directions on how to stage/unstage/add shown in the
-		output of linkgit:git-status[1] and the template shown
-		when writing commit messages.
+		Show directions on how to proceed from the current
+		state in the output of linkgit:git-status[1] and in
+		the template shown when writing commit messages in
+		linkgit:git-commit[1].
 	commitBeforeMerge::
 		Advice shown when linkgit:git-merge[1] refuses to
 		merge to avoid overwriting local changes.
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb490..e8c3690 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,9 @@ test_expect_success 'Report new path with conflict' '
 
 cat >expect <<EOF
 # On branch side
+# You have unmerged paths.
+#   (fix conflicts and run "git commit")
+#
 # Unmerged paths:
 #   (use "git add/rm <file>..." as appropriate to mark resolution)
 #
@@ -118,4 +121,65 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
 	test_cmp expected actual
 '
 
+
+test_expect_success 'status when conflicts with add and rm advice (deleted by them)' '
+	git reset --hard &&
+	git checkout master &&
+	test_commit init main.txt init &&
+	git checkout -b second_branch &&
+	git rm main.txt &&
+	git commit -m "main.txt deleted on second_branch" &&
+	test_commit second conflict.txt second &&
+	git checkout master &&
+	test_commit on_second main.txt on_second &&
+	test_commit master conflict.txt master &&
+	test_must_fail git merge second_branch &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both added:         conflict.txt
+	#	deleted by them:    main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+	git reset --hard &&
+	git checkout -b conflict &&
+	test_commit one main.txt one &&
+	git branch conflict_second &&
+	git mv main.txt sub_master.txt &&
+	git commit -m "main.txt renamed in sub_master.txt" &&
+	git checkout conflict_second &&
+	git mv main.txt sub_second.txt &&
+	git commit -m "main.txt renamed in sub_second.txt" &&
+	test_must_fail git merge conflict &&
+	cat >expected <<-\EOF &&
+	# On branch conflict_second
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#	added by them:      sub_master.txt
+	#	added by us:        sub_second.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
 test_done
diff --git a/wt-status.c b/wt-status.c
index dd6d8c4..7548509 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
 	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
 	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
+	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
 };
 
 static const char *color(int slot, struct wt_status *s)
@@ -728,6 +729,167 @@ static void wt_status_print_tracking(struct wt_status *s)
 	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
 }
 
+static int has_unmerged(struct wt_status *s)
+{
+	int i;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		d = s->change.items[i].util;
+		if (d->stagemask)
+			return 1;
+	}
+	return 0;
+}
+
+static void show_merge_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You have unmerged paths."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+	} else {
+		status_printf_ln(s, color,
+			_("All conflicts fixed but you are still merging."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (use \"git commit\" to conclude merge)"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_am_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color,
+		_("You are in the middle of an am session."));
+	if (state->am_empty_patch)
+		status_printf_ln(s, color,
+			_("The current patch is empty."));
+	if (advice_status_hints) {
+		if (!state->am_empty_patch)
+			status_printf_ln(s, color,
+				_("  (fix conflicts and then run \"git am --resolved\")"));
+		status_printf_ln(s, color,
+			_("  (use \"git am --skip\" to skip this patch)"));
+		status_printf_ln(s, color,
+			_("  (use \"git am --abort\" to restore the original branch)"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_rebase_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	struct stat st;
+
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints) {
+			status_printf_ln(s, color,
+				_("  (fix conflicts and then run \"git rebase --continue\")"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --skip\" to skip this patch)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --abort\" to check out the original branch)"));
+		}
+	} else if (state->rebase_in_progress || !stat(git_path("MERGE_MSG"), &st)) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else {
+		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
+		if (advice_status_hints && !s->amend) {
+			status_printf_ln(s, color,
+				_("  (use \"git commit --amend\" to amend the current commit)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --continue\" once you are satisfied with your changes)"));
+		}
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_cherry_pick_in_progress(struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	status_printf_ln(s, color, _("You are currently cherry-picking."));
+	if (advice_status_hints) {
+		if (has_unmerged(s))
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+		else
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git commit\")"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_bisect_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color, _("You are currently bisecting."));
+	if (advice_status_hints)
+		status_printf_ln(s, color,
+			_("  (use \"git bisect reset\" to get back to the original branch)"));
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_print_state(struct wt_status *s)
+{
+	const char *state_color = color(WT_STATUS_IN_PROGRESS, s);
+	struct wt_status_state *state = calloc(1, sizeof(*state));
+	struct stat st;
+
+	state->merge_in_progress = 0;
+	state->am_in_progress = 0;
+	state->am_empty_patch = 0;
+	state->rebase_in_progress = 0;
+	state->rebase_interactive_in_progress = 0;
+	state->cherry_pick_in_progress = 0;
+	state->bisect_in_progress = 0;
+
+	if (!stat(git_path("MERGE_HEAD"), &st)) {
+		state->merge_in_progress = 1;
+	} else if (!stat(git_path("rebase-apply"), &st)) {
+		if (!stat(git_path("rebase-apply/applying"), &st)) {
+			state->am_in_progress = 1;
+			if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
+				state->am_empty_patch = 1;
+		} else {
+			state->rebase_in_progress = 1;
+		}
+	} else if (!stat(git_path("rebase-merge"), &st)) {
+		if (!stat(git_path("rebase-merge/interactive"), &st))
+			state->rebase_interactive_in_progress = 1;
+		else
+			state->rebase_in_progress = 1;
+	} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
+		state->cherry_pick_in_progress = 1;
+	}
+	if (!stat(git_path("BISECT_LOG"), &st))
+		state->bisect_in_progress = 1;
+
+	if (state->merge_in_progress)
+		show_merge_in_progress(s, state, state_color);
+	else if (state->am_in_progress)
+		show_am_in_progress(s, state, state_color);
+	else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
+		show_rebase_in_progress(s, state, state_color);
+	else if (state->cherry_pick_in_progress)
+		show_cherry_pick_in_progress(s, state, state_color);
+	if (state->bisect_in_progress)
+		show_bisect_in_progress(s, state, state_color);
+	free(state);
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
@@ -750,6 +912,7 @@ void wt_status_print(struct wt_status *s)
 			wt_status_print_tracking(s);
 	}
 
+	wt_status_print_state(s);
 	if (s->is_initial) {
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7..c1066a0 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -15,6 +15,7 @@ enum color_wt_status {
 	WT_STATUS_LOCAL_BRANCH,
 	WT_STATUS_REMOTE_BRANCH,
 	WT_STATUS_ONBRANCH,
+	WT_STATUS_IN_PROGRESS,
 	WT_STATUS_MAXSLOT
 };
 
@@ -71,6 +72,16 @@ struct wt_status {
 	struct string_list ignored;
 };
 
+struct wt_status_state {
+	int merge_in_progress;
+	int am_in_progress;
+	int am_empty_patch;
+	int rebase_in_progress;
+	int rebase_interactive_in_progress;
+	int cherry_pick_in_progress;
+	int bisect_in_progress;
+};
+
 void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
-- 
1.7.8

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

* [PATCHv9 2/4] t7512-status-help.sh: better advices for git status
  2012-06-07 13:17               ` [PATCHv9 1/4] wt-status.*: better advices for git status added Lucien Kong
@ 2012-06-07 13:17                 ` Lucien Kong
  2012-06-07 13:17                 ` [PATCHv9 3/4] status: don't suggest "git rm" or "git add" if not appropriate Lucien Kong
                                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-07 13:17 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

The following tests include several cases in which the user needs to
run 'git status' to know his current situation, whether there're
conflicts or he's in rebase/bisect/am/cherry-pick progress.

One of the test is about the set of the advice.statushints config key
to 'false' in .git/config.

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
part 2/4 unchanged since v8.

 t/t7512-status-help.sh |  372 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 372 insertions(+), 0 deletions(-)
 create mode 100755 t/t7512-status-help.sh

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
new file mode 100755
index 0000000..3714e8e
--- /dev/null
+++ b/t/t7512-status-help.sh
@@ -0,0 +1,372 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'prepare for conflicts' '
+	test_commit init main.txt init &&
+	git branch conflicts &&
+	test_commit on_master main.txt on_master &&
+	git checkout conflicts &&
+	test_commit on_conflicts main.txt on_conflicts
+'
+
+
+test_expect_success 'status when conflicts unresolved' '
+	test_must_fail git merge master &&
+	cat >expected <<-\EOF &&
+	# On branch conflicts
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	git reset --hard conflicts &&
+	test_must_fail git merge master &&
+	echo one >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch conflicts
+	# All conflicts fixed but you are still merging.
+	#   (use "git commit" to conclude merge)
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for rebase conflicts' '
+	git reset --hard master &&
+	git checkout -b rebase_conflicts &&
+	test_commit one_rebase main.txt one &&
+	test_commit two_rebase main.txt two &&
+	test_commit three_rebase main.txt three
+'
+
+
+test_expect_success 'status when rebase in progress before resolving conflicts' '
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (fix conflicts and then run "git rebase --continue")
+	#   (use "git rebase --skip" to skip this patch)
+	#   (use "git rebase --abort" to check out the original branch)
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when rebase in progress before rebase --continue' '
+	git reset --hard rebase_conflicts &&
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	echo three >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (all conflicts fixed: run "git rebase --continue")
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for rebase_i_conflicts' '
+	git reset --hard master &&
+	git checkout -b rebase_i_conflicts &&
+	test_commit one_unmerge main.txt one_unmerge &&
+	git branch rebase_i_conflicts_second &&
+	test_commit one_master main.txt one_master &&
+	git checkout rebase_i_conflicts_second &&
+	test_commit one_second main.txt one_second
+'
+
+
+test_expect_success 'status during rebase -i when conflicts unresolved' '
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase -i rebase_i_conflicts &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (fix conflicts and then run "git rebase --continue")
+	#   (use "git rebase --skip" to skip this patch)
+	#   (use "git rebase --abort" to check out the original branch)
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status during rebase -i after resolving conflicts' '
+	git reset --hard rebase_i_conflicts_second &&
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase -i rebase_i_conflicts &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (all conflicts fixed: run "git rebase --continue")
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when rebasing -i in edit mode' '
+	git reset --hard master &&
+	git checkout -b rebase_i_edit &&
+	test_commit one_rebase_i main.txt one &&
+	test_commit two_rebase_i main.txt two &&
+	test_commit three_rebase_i main.txt three &&
+	FAKE_LINES="1 edit 2" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~2 &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare am_session' '
+	git reset --hard master &&
+	git checkout -b am_session &&
+	test_commit one_am one.txt "one" &&
+	test_commit two_am two.txt "two" &&
+	test_commit three_am three.txt "three"
+'
+
+
+test_expect_success 'status in an am session: file already exists' '
+	git checkout -b am_already_exists &&
+	test_when_finished "rm Maildir/* && git am --abort" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch am_already_exists
+	# You are in the middle of an am session.
+	#   (fix conflicts and then run "git am --resolved")
+	#   (use "git am --skip" to skip this patch)
+	#   (use "git am --abort" to restore the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status in an am session: file does not exist' '
+	git reset --hard am_session &&
+	git checkout -b am_not_exists &&
+	git rm three.txt &&
+	git commit -m "delete three.txt" &&
+	test_when_finished "rm Maildir/* && git am --abort" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch am_not_exists
+	# You are in the middle of an am session.
+	#   (fix conflicts and then run "git am --resolved")
+	#   (use "git am --skip" to skip this patch)
+	#   (use "git am --abort" to restore the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status in an am session: empty patch' '
+	git reset --hard am_session &&
+	git checkout -b am_empty &&
+	test_when_finished "rm Maildir/* && git am --abort" &&
+	git format-patch -3 -oMaildir &&
+	git rm one.txt two.txt three.txt &&
+	git commit -m "delete all am_empty" &&
+	echo error >Maildir/0002-two_am.patch &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch am_empty
+	# You are in the middle of an am session.
+	# The current patch is empty.
+	#   (use "git am --skip" to skip this patch)
+	#   (use "git am --abort" to restore the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when bisecting' '
+	git reset --hard master &&
+	git checkout -b bisect &&
+	test_commit one_bisect main.txt one &&
+	test_commit two_bisect main.txt two &&
+	test_commit three_bisect main.txt three &&
+	test_when_finished "git bisect reset" &&
+	git bisect start &&
+	git bisect bad &&
+	git bisect good one_bisect &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently bisecting.
+	#   (use "git bisect reset" to get back to the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when rebase conflicts with statushints disabled' '
+	git reset --hard master &&
+	git checkout -b statushints_disabled &&
+	test_when_finished "git config --local advice.statushints true" &&
+	git config --local advice.statushints false &&
+	test_commit one_statushints main.txt one &&
+	test_commit two_statushints main.txt two &&
+	test_commit three_statushints main.txt three &&
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#
+	# Unmerged paths:
+	#	both modified:      main.txt
+	#
+	no changes added to commit
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for cherry-pick conflicts' '
+	git reset --hard master &&
+	git checkout -b cherry_branch &&
+	test_commit one_cherry main.txt one &&
+	test_commit two_cherries main.txt two &&
+	git checkout -b cherry_branch_second &&
+	test_commit second_cherry main.txt second &&
+	git checkout cherry_branch &&
+	test_commit three_cherries main.txt three
+'
+
+
+test_expect_success 'status when cherry-picking before resolving conflicts' '
+	test_when_finished "git cherry-pick --abort" &&
+	test_must_fail git cherry-pick cherry_branch_second &&
+	cat >expected <<-\EOF &&
+	# On branch cherry_branch
+	# You are currently cherry-picking.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when cherry-picking after resolving conflicts' '
+	git reset --hard cherry_branch &&
+	test_when_finished "git cherry-pick --abort" &&
+	test_must_fail git cherry-pick cherry_branch_second &&
+	echo end >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch cherry_branch
+	# You are currently cherry-picking.
+	#   (all conflicts fixed: run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_done
-- 
1.7.8

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

* [PATCHv9 3/4] status: don't suggest "git rm" or "git add" if not appropriate
  2012-06-07 13:17               ` [PATCHv9 1/4] wt-status.*: better advices for git status added Lucien Kong
  2012-06-07 13:17                 ` [PATCHv9 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
@ 2012-06-07 13:17                 ` Lucien Kong
  2012-06-07 13:17                 ` [PATCHv9 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
  2012-06-10 11:17                 ` [PATCHv10 1/4] wt-status.*: better advices for git status added Lucien Kong
  3 siblings, 0 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-07 13:17 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

The display of the advice '(use git add/rm [...])' (when there are
unmerged files) after running 'git status' is now depending of the
mark, whether it's 'both deleted', 'deleted by us/them' or others. For
instance, when there is just one file that's marked as 'both deleted',
'git status' shows '(use git rm [...])' and if there are two files,
one as 'both deleted' and the other as 'added by them', the advice is
'(use git add/rm [...])'.

The previous tests in t7512-status-help.sh are updated.

Test about the case of only 'both deleted' is added in
t7060-wtstatus.sh

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
part 3/4 unchanged since v8.

 t/t7060-wtstatus.sh    |   36 ++++++++++++++++++++++++++++++++++--
 t/t7512-status-help.sh |    8 ++++----
 wt-status.c            |   37 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index e8c3690..f4f38a5 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -152,7 +152,7 @@ test_expect_success 'status when conflicts with add and rm advice (deleted by th
 '
 
 
-test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+test_expect_success 'prepare for conflicts' '
 	git reset --hard &&
 	git checkout -b conflict &&
 	test_commit one main.txt one &&
@@ -161,7 +161,11 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted)
 	git commit -m "main.txt renamed in sub_master.txt" &&
 	git checkout conflict_second &&
 	git mv main.txt sub_second.txt &&
-	git commit -m "main.txt renamed in sub_second.txt" &&
+	git commit -m "main.txt renamed in sub_second.txt"
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
 	test_must_fail git merge conflict &&
 	cat >expected <<-\EOF &&
 	# On branch conflict_second
@@ -182,4 +186,32 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted)
 '
 
 
+test_expect_success 'status when conflicts with only rm advice (both deleted)' '
+	git reset --hard conflict_second &&
+	test_must_fail git merge conflict &&
+	git add sub_master.txt &&
+	git add sub_second.txt &&
+	cat >expected <<-\EOF &&
+	# On branch conflict_second
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	new file:   sub_master.txt
+	#
+	# Unmerged paths:
+	#   (use "git rm <file>..." to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual &&
+	git reset --hard &&
+	git checkout master
+'
+
+
 test_done
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 3714e8e..bdce192 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -30,7 +30,7 @@ test_expect_success 'status when conflicts unresolved' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -83,7 +83,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -140,7 +140,7 @@ test_expect_success 'status during rebase -i when conflicts unresolved' '
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -336,7 +336,7 @@ test_expect_success 'status when cherry-picking before resolving conflicts' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
diff --git a/wt-status.c b/wt-status.c
index 7548509..fcde045 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -131,9 +131,34 @@ void wt_status_prepare(struct wt_status *s)
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
 {
+	int i;
+	int del_mod_conflict = 0;
+	int both_deleted = 0;
+	int not_deleted = 0;
 	const char *c = color(WT_STATUS_HEADER, s);
 
 	status_printf_ln(s, c, _("Unmerged paths:"));
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct string_list_item *it = &(s->change.items[i]);
+		struct wt_status_change_data *d = it->util;
+
+		switch (d->stagemask) {
+		case 0:
+			break;
+		case 1:
+			both_deleted = 1;
+			break;
+		case 3:
+		case 5:
+			del_mod_conflict = 1;
+			break;
+		default:
+			not_deleted = 1;
+			break;
+		}
+	}
+
 	if (!advice_status_hints)
 		return;
 	if (s->whence != FROM_COMMIT)
@@ -142,7 +167,17 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
 		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
 		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
-	status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+
+	if (!both_deleted) {
+		if (!del_mod_conflict)
+			status_printf_ln(s, c, _("  (use \"git add <file>...\" to mark resolution)"));
+		else
+			status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	} else if (!del_mod_conflict && !not_deleted) {
+		status_printf_ln(s, c, _("  (use \"git rm <file>...\" to mark resolution)"));
+	} else {
+		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	}
 	status_printf_ln(s, c, "");
 }
 
-- 
1.7.8

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

* [PATCHv9 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-07 13:17               ` [PATCHv9 1/4] wt-status.*: better advices for git status added Lucien Kong
  2012-06-07 13:17                 ` [PATCHv9 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
  2012-06-07 13:17                 ` [PATCHv9 3/4] status: don't suggest "git rm" or "git add" if not appropriate Lucien Kong
@ 2012-06-07 13:17                 ` Lucien Kong
  2012-06-07 18:07                   ` Junio C Hamano
  2012-06-07 20:42                   ` Junio C Hamano
  2012-06-10 11:17                 ` [PATCHv10 1/4] wt-status.*: better advices for git status added Lucien Kong
  3 siblings, 2 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-07 13:17 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Add new informative help messages at the output of 'git status' when
the user is splitting a commit. The code figures this state by
comparing the contents of the following files in the .git/ directory:
	  - HEAD
	  - ORIG_HEAD
	  - rebase-merge/amend
	  - rebase-merge/orig-head

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
The code is now restructured. The right help message is now displayed when
you amend the last commit through rebase interactive, and when you're
editing several edits whether you're amending or splitting them.

 t/t7512-status-help.sh |  277 ++++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.c            |   52 +++++++++
 2 files changed, 329 insertions(+), 0 deletions(-)

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index bdce192..3ce384a 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -196,6 +196,283 @@ test_expect_success 'status when rebasing -i in edit mode' '
 '
 
 
+test_expect_success 'status when splitting a commit' '
+	git reset --hard master &&
+	git checkout -b split_commit &&
+	test_commit one_split main.txt one &&
+	test_commit two_split main.txt two &&
+	test_commit three_split main.txt three &&
+	test_commit four_split main.txt four &&
+	FAKE_LINES="1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status after editing the last commit with --amend during a rebase -i' '
+	git reset --hard master &&
+	git checkout -b amend_last &&
+	test_commit one_amend main.txt one &&
+	test_commit two_amend main.txt two &&
+	test_commit three_amend main.txt three &&
+	test_commit four_amend main.txt four &&
+	FAKE_LINES="1 2 edit 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "foo" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for several edits' '
+	git reset --hard master &&
+	git checkout -b several_edits &&
+	test_commit one_edits main.txt one &&
+	test_commit two_edits main.txt two &&
+	test_commit three_edits main.txt three &&
+	test_commit four_edits main.txt four
+'
+
+
+test_expect_success 'status: (continue first edit) second edit' '
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git rebase --continue &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (continue first edit) second edit and split' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git rebase --continue &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (continue first edit) second edit and amend' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git rebase --continue &&
+	git commit --amend -m "foo" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (amend first edit) second edit' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "a" &&
+	git rebase --continue &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (amend first edit) second edit and split' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "b" &&
+	git rebase --continue &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (amend first edit) second edit and amend' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "c" &&
+	git rebase --continue &&
+	git commit --amend -m "d" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (split first edit) second edit' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	git add main.txt &&
+	git commit -m "e" &&
+	git rebase --continue &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (split first edit) second edit and split' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	git add main.txt &&
+	git commit --amend -m "f" &&
+	git rebase --continue &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (split first edit) second edit and amend' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	git add main.txt &&
+	git commit --amend -m "g" &&
+	git rebase --continue &&
+	git commit --amend -m "h" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
 test_expect_success 'prepare am_session' '
 	git reset --hard master &&
 	git checkout -b am_session &&
diff --git a/wt-status.c b/wt-status.c
index fcde045..5c0706b 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -12,6 +12,7 @@
 #include "refs.h"
 #include "submodule.h"
 #include "column.h"
+#include "strbuf.h"
 
 static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -817,6 +818,52 @@ static void show_am_in_progress(struct wt_status *s,
 	wt_status_print_trailer(s);
 }
 
+static char *read_line_from_git_path(const char *filename)
+{
+	struct strbuf buf = STRBUF_INIT;
+	FILE *fp = fopen(git_path(filename), "r");
+	if (!fp) {
+		strbuf_release(&buf);
+		return NULL;
+	}
+	strbuf_getline(&buf, fp, '\n');
+	if (!fclose(fp)) {
+		return strbuf_detach(&buf, NULL);
+	} else {
+		strbuf_release(&buf);
+		return NULL;
+	}
+}
+
+static int split_commit_in_progress(struct wt_status *s)
+{
+	int split_in_progress = 0;
+	const char *head = read_line_from_git_path("HEAD");
+	const char *orig_head = read_line_from_git_path("ORIG_HEAD");
+	const char *rebase_amend = read_line_from_git_path("rebase-merge/amend");
+	const char *rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
+
+	if (!head || !orig_head || !rebase_amend ||
+			!rebase_orig_head || !prefixcmp(head, "refs/heads/"))
+		return split_in_progress;
+
+	if (!strcmp(rebase_amend, rebase_orig_head)) {
+		if (strcmp(head, rebase_amend))
+			split_in_progress = 1;
+	} else if (strcmp(orig_head, rebase_orig_head)) {
+		split_in_progress = 1;
+	}
+
+	if (!s->amend && !s->nowarn && !s->workdir_dirty)
+		split_in_progress = 0;
+
+	free((char*)head);
+	free((char*)orig_head);
+	free((char*)rebase_amend);
+	free((char*)rebase_orig_head);
+	return split_in_progress;
+}
+
 static void show_rebase_in_progress(struct wt_status *s,
 				struct wt_status_state *state,
 				const char *color)
@@ -838,6 +885,11 @@ static void show_rebase_in_progress(struct wt_status *s,
 		if (advice_status_hints)
 			status_printf_ln(s, color,
 				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else if (split_commit_in_progress(s)) {
+		status_printf_ln(s, color, _("You are currently splitting a commit."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (Once your working directory is clean, run \"git rebase --continue\")"));
 	} else {
 		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
 		if (advice_status_hints && !s->amend) {
-- 
1.7.8

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

* Re: [PATCHv9 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-07 13:17                 ` [PATCHv9 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
@ 2012-06-07 18:07                   ` Junio C Hamano
  2012-06-07 20:42                   ` Junio C Hamano
  1 sibling, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-06-07 18:07 UTC (permalink / raw)
  To: Lucien Kong
  Cc: git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:

> +static int split_commit_in_progress(struct wt_status *s)
> +{
> +	int split_in_progress = 0;
> +	const char *head = read_line_from_git_path("HEAD");
> +	const char *orig_head = read_line_from_git_path("ORIG_HEAD");
> +	const char *rebase_amend = read_line_from_git_path("rebase-merge/amend");
> +	const char *rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");

By declaring these newly allocated memory you own in this function
and free() yourself as "const char *", the only thing you are
gaining is the need to cast constness away when you call free().

Why are these necessary?

> +	if (!head || !orig_head || !rebase_amend ||
> +			!rebase_orig_head || !prefixcmp(head, "refs/heads/"))
> +		return split_in_progress;

Can't .git/HEAD be a symlinked symref?

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

* Re: [PATCHv9 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-07 13:17                 ` [PATCHv9 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
  2012-06-07 18:07                   ` Junio C Hamano
@ 2012-06-07 20:42                   ` Junio C Hamano
  2012-06-07 21:05                     ` konglu
  1 sibling, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-06-07 20:42 UTC (permalink / raw)
  To: Lucien Kong
  Cc: git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:

> +static char *read_line_from_git_path(const char *filename)
> +{
> +	struct strbuf buf = STRBUF_INIT;
> +	FILE *fp = fopen(git_path(filename), "r");

We currently do not pass any filename with per-cent in it, but that
call should be git_path("%s", filename) for sanity.

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

* Re: [PATCHv9 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-07 20:42                   ` Junio C Hamano
@ 2012-06-07 21:05                     ` konglu
  0 siblings, 0 replies; 97+ messages in thread
From: konglu @ 2012-06-07 21:05 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Lucien Kong, git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy


Junio C Hamano <gitster@pobox.com> a écrit :

> Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:
>
>> +static char *read_line_from_git_path(const char *filename)
>> +{
>> +	struct strbuf buf = STRBUF_INIT;
>> +	FILE *fp = fopen(git_path(filename), "r");
>
> We currently do not pass any filename with per-cent in it, but that
> call should be git_path("%s", filename) for sanity.

Thanks, that should fix our problem (sometimes, a warning message appears
during compilation about this line and we didn't know what to change).

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

* Re: [PATCHv8 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-05 21:16                 ` Junio C Hamano
@ 2012-06-08  9:29                   ` konglu
  2012-06-08 15:05                     ` Junio C Hamano
  0 siblings, 1 reply; 97+ messages in thread
From: konglu @ 2012-06-08  9:29 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Lucien Kong, git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy


Junio C Hamano <gitster@pobox.com> a écrit :

> Reading from git_path("HEAD") looked funny, as you may end up
> reading the "ref: refs/heads/master".  Of course that would not
> compare equal to what you would read from "rebase-merge/amend", and
> that may be fine for the purpose of your test, but it still looks
> somewhat funny.  As modern rebase is done on a detached HEAD,
> perhaps it is a good idea to check if the HEAD is detached and
> return false from this function if that is not the case.  I dunno.

On second thoughts, I do not think that checking if HEAD is detached
or not is needed, as the part of the code that includes reading can
only be called during a rebase interactive, in which case the HEAD
can only be detached.

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

* Re: [PATCHv8 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-08  9:29                   ` konglu
@ 2012-06-08 15:05                     ` Junio C Hamano
  0 siblings, 0 replies; 97+ messages in thread
From: Junio C Hamano @ 2012-06-08 15:05 UTC (permalink / raw)
  To: konglu
  Cc: Lucien Kong, git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

konglu@minatec.inpg.fr writes:

>> Reading from git_path("HEAD") looked funny, as you may end up
>> reading the "ref: refs/heads/master".  Of course that would not
>> compare equal to what you would read from "rebase-merge/amend", and
>> that may be fine for the purpose of your test, but it still looks
>> somewhat funny.  As modern rebase is done on a detached HEAD,
>> perhaps it is a good idea to check if the HEAD is detached and
>> return false from this function if that is not the case.  I dunno.
>
> On second thoughts, I do not think that checking if HEAD is detached
> or not is needed, as the part of the code that includes reading can
> only be called during a rebase interactive, in which case the HEAD
> can only be detached.

"can only be detached" is making a huge assumption.

I'd rather see a code that verifies that the assumption still holds
after changes are made to other parts of the system and gracefully
degrade its behaviour when the assumption it makes no longer holds.

Besides, making sure that the HEAD is detached when you _think_ you
are in the middle of a rebase is a necessary part of catching and
reporting a potential mistake like this, no?

	$ git checkout -b throwaway
        $ git rebase --onto HEAD~5 HEAD~2
        ... conflicts ...
        $ git checkout throwaway

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

* [PATCHv10 1/4] wt-status.*: better advices for git status added
  2012-06-07 13:17               ` [PATCHv9 1/4] wt-status.*: better advices for git status added Lucien Kong
                                   ` (2 preceding siblings ...)
  2012-06-07 13:17                 ` [PATCHv9 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
@ 2012-06-10 11:17                 ` Lucien Kong
  2012-06-10 11:17                   ` [PATCHv10 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
                                     ` (2 more replies)
  3 siblings, 3 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-10 11:17 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

This patch provides new informative help messages in the display of
'git status' (at the top) during conflicts, rebase, am, bisect or
cherry-pick process.

The new messages are not shown when using options such as -s or
--porcelain. The messages about the current situation of the user are
always displayed but the advices on what the user needs to do in order
to resume a rebase/bisect/am/commit after resolving conflicts can be
hidden by setting advice.statushints to 'false' in the config file.

Thus, information about the updated advice.statushints key are added
in Documentation/config.txt.

Also, the test t7060-wt-status.sh is now working with the new help
messages. Tests about suggestions of "git rm" are also added.

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
part 1/4 unchanged since v9.

 Documentation/config.txt |    7 +-
 t/t7060-wtstatus.sh      |   64 ++++++++++++++++++
 wt-status.c              |  163 ++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.h              |   11 +++
 4 files changed, 242 insertions(+), 3 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a..ccce4f6 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -159,9 +159,10 @@ advice.*::
 		specified a refspec that isn't your current branch) and
 		it resulted in a non-fast-forward error.
 	statusHints::
-		Directions on how to stage/unstage/add shown in the
-		output of linkgit:git-status[1] and the template shown
-		when writing commit messages.
+		Show directions on how to proceed from the current
+		state in the output of linkgit:git-status[1] and in
+		the template shown when writing commit messages in
+		linkgit:git-commit[1].
 	commitBeforeMerge::
 		Advice shown when linkgit:git-merge[1] refuses to
 		merge to avoid overwriting local changes.
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index b8cb490..e8c3690 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -30,6 +30,9 @@ test_expect_success 'Report new path with conflict' '
 
 cat >expect <<EOF
 # On branch side
+# You have unmerged paths.
+#   (fix conflicts and run "git commit")
+#
 # Unmerged paths:
 #   (use "git add/rm <file>..." as appropriate to mark resolution)
 #
@@ -118,4 +121,65 @@ test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
 	test_cmp expected actual
 '
 
+
+test_expect_success 'status when conflicts with add and rm advice (deleted by them)' '
+	git reset --hard &&
+	git checkout master &&
+	test_commit init main.txt init &&
+	git checkout -b second_branch &&
+	git rm main.txt &&
+	git commit -m "main.txt deleted on second_branch" &&
+	test_commit second conflict.txt second &&
+	git checkout master &&
+	test_commit on_second main.txt on_second &&
+	test_commit master conflict.txt master &&
+	test_must_fail git merge second_branch &&
+	cat >expected <<-\EOF &&
+	# On branch master
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both added:         conflict.txt
+	#	deleted by them:    main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+	git reset --hard &&
+	git checkout -b conflict &&
+	test_commit one main.txt one &&
+	git branch conflict_second &&
+	git mv main.txt sub_master.txt &&
+	git commit -m "main.txt renamed in sub_master.txt" &&
+	git checkout conflict_second &&
+	git mv main.txt sub_second.txt &&
+	git commit -m "main.txt renamed in sub_second.txt" &&
+	test_must_fail git merge conflict &&
+	cat >expected <<-\EOF &&
+	# On branch conflict_second
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#	added by them:      sub_master.txt
+	#	added by us:        sub_second.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
 test_done
diff --git a/wt-status.c b/wt-status.c
index dd6d8c4..7548509 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -23,6 +23,7 @@ static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_GREEN,  /* WT_STATUS_LOCAL_BRANCH */
 	GIT_COLOR_RED,    /* WT_STATUS_REMOTE_BRANCH */
 	GIT_COLOR_NIL,    /* WT_STATUS_ONBRANCH */
+	GIT_COLOR_NORMAL, /* WT_STATUS_IN_PROGRESS */
 };
 
 static const char *color(int slot, struct wt_status *s)
@@ -728,6 +729,167 @@ static void wt_status_print_tracking(struct wt_status *s)
 	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
 }
 
+static int has_unmerged(struct wt_status *s)
+{
+	int i;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		d = s->change.items[i].util;
+		if (d->stagemask)
+			return 1;
+	}
+	return 0;
+}
+
+static void show_merge_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You have unmerged paths."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+	} else {
+		status_printf_ln(s, color,
+			_("All conflicts fixed but you are still merging."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (use \"git commit\" to conclude merge)"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_am_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color,
+		_("You are in the middle of an am session."));
+	if (state->am_empty_patch)
+		status_printf_ln(s, color,
+			_("The current patch is empty."));
+	if (advice_status_hints) {
+		if (!state->am_empty_patch)
+			status_printf_ln(s, color,
+				_("  (fix conflicts and then run \"git am --resolved\")"));
+		status_printf_ln(s, color,
+			_("  (use \"git am --skip\" to skip this patch)"));
+		status_printf_ln(s, color,
+			_("  (use \"git am --abort\" to restore the original branch)"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_rebase_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	struct stat st;
+
+	if (has_unmerged(s)) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints) {
+			status_printf_ln(s, color,
+				_("  (fix conflicts and then run \"git rebase --continue\")"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --skip\" to skip this patch)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --abort\" to check out the original branch)"));
+		}
+	} else if (state->rebase_in_progress || !stat(git_path("MERGE_MSG"), &st)) {
+		status_printf_ln(s, color, _("You are currently rebasing."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else {
+		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
+		if (advice_status_hints && !s->amend) {
+			status_printf_ln(s, color,
+				_("  (use \"git commit --amend\" to amend the current commit)"));
+			status_printf_ln(s, color,
+				_("  (use \"git rebase --continue\" once you are satisfied with your changes)"));
+		}
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_cherry_pick_in_progress(struct wt_status *s,
+					struct wt_status_state *state,
+					const char *color)
+{
+	status_printf_ln(s, color, _("You are currently cherry-picking."));
+	if (advice_status_hints) {
+		if (has_unmerged(s))
+			status_printf_ln(s, color,
+				_("  (fix conflicts and run \"git commit\")"));
+		else
+			status_printf_ln(s, color,
+				_("  (all conflicts fixed: run \"git commit\")"));
+	}
+	wt_status_print_trailer(s);
+}
+
+static void show_bisect_in_progress(struct wt_status *s,
+				struct wt_status_state *state,
+				const char *color)
+{
+	status_printf_ln(s, color, _("You are currently bisecting."));
+	if (advice_status_hints)
+		status_printf_ln(s, color,
+			_("  (use \"git bisect reset\" to get back to the original branch)"));
+	wt_status_print_trailer(s);
+}
+
+static void wt_status_print_state(struct wt_status *s)
+{
+	const char *state_color = color(WT_STATUS_IN_PROGRESS, s);
+	struct wt_status_state *state = calloc(1, sizeof(*state));
+	struct stat st;
+
+	state->merge_in_progress = 0;
+	state->am_in_progress = 0;
+	state->am_empty_patch = 0;
+	state->rebase_in_progress = 0;
+	state->rebase_interactive_in_progress = 0;
+	state->cherry_pick_in_progress = 0;
+	state->bisect_in_progress = 0;
+
+	if (!stat(git_path("MERGE_HEAD"), &st)) {
+		state->merge_in_progress = 1;
+	} else if (!stat(git_path("rebase-apply"), &st)) {
+		if (!stat(git_path("rebase-apply/applying"), &st)) {
+			state->am_in_progress = 1;
+			if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
+				state->am_empty_patch = 1;
+		} else {
+			state->rebase_in_progress = 1;
+		}
+	} else if (!stat(git_path("rebase-merge"), &st)) {
+		if (!stat(git_path("rebase-merge/interactive"), &st))
+			state->rebase_interactive_in_progress = 1;
+		else
+			state->rebase_in_progress = 1;
+	} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
+		state->cherry_pick_in_progress = 1;
+	}
+	if (!stat(git_path("BISECT_LOG"), &st))
+		state->bisect_in_progress = 1;
+
+	if (state->merge_in_progress)
+		show_merge_in_progress(s, state, state_color);
+	else if (state->am_in_progress)
+		show_am_in_progress(s, state, state_color);
+	else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
+		show_rebase_in_progress(s, state, state_color);
+	else if (state->cherry_pick_in_progress)
+		show_cherry_pick_in_progress(s, state, state_color);
+	if (state->bisect_in_progress)
+		show_bisect_in_progress(s, state, state_color);
+	free(state);
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	const char *branch_color = color(WT_STATUS_ONBRANCH, s);
@@ -750,6 +912,7 @@ void wt_status_print(struct wt_status *s)
 			wt_status_print_tracking(s);
 	}
 
+	wt_status_print_state(s);
 	if (s->is_initial) {
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), "");
 		status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
diff --git a/wt-status.h b/wt-status.h
index 14aa9f7..c1066a0 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -15,6 +15,7 @@ enum color_wt_status {
 	WT_STATUS_LOCAL_BRANCH,
 	WT_STATUS_REMOTE_BRANCH,
 	WT_STATUS_ONBRANCH,
+	WT_STATUS_IN_PROGRESS,
 	WT_STATUS_MAXSLOT
 };
 
@@ -71,6 +72,16 @@ struct wt_status {
 	struct string_list ignored;
 };
 
+struct wt_status_state {
+	int merge_in_progress;
+	int am_in_progress;
+	int am_empty_patch;
+	int rebase_in_progress;
+	int rebase_interactive_in_progress;
+	int cherry_pick_in_progress;
+	int bisect_in_progress;
+};
+
 void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
-- 
1.7.8

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

* [PATCHv10 2/4] t7512-status-help.sh: better advices for git status
  2012-06-10 11:17                 ` [PATCHv10 1/4] wt-status.*: better advices for git status added Lucien Kong
@ 2012-06-10 11:17                   ` Lucien Kong
  2012-06-10 11:17                   ` [PATCHv10 3/4] status: don't suggest "git rm" or "git add" if not appropriate Lucien Kong
  2012-06-10 11:17                   ` [PATCHv10 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
  2 siblings, 0 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-10 11:17 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

The following tests include several cases in which the user needs to
run 'git status' to know his current situation, whether there're
conflicts or he's in rebase/bisect/am/cherry-pick progress.

One of the test is about the set of the advice.statushints config key
to 'false' in .git/config.

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
part 2/4 unchanged since v9.

 t/t7512-status-help.sh |  372 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 372 insertions(+), 0 deletions(-)
 create mode 100755 t/t7512-status-help.sh

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
new file mode 100755
index 0000000..3714e8e
--- /dev/null
+++ b/t/t7512-status-help.sh
@@ -0,0 +1,372 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Valentin Duperray, Lucien Kong, Franck Jonas,
+#		     Thomas Nguy, Khoi Nguyen
+#		     Grenoble INP Ensimag
+#
+
+test_description='git status advices'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'prepare for conflicts' '
+	test_commit init main.txt init &&
+	git branch conflicts &&
+	test_commit on_master main.txt on_master &&
+	git checkout conflicts &&
+	test_commit on_conflicts main.txt on_conflicts
+'
+
+
+test_expect_success 'status when conflicts unresolved' '
+	test_must_fail git merge master &&
+	cat >expected <<-\EOF &&
+	# On branch conflicts
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when conflicts resolved before commit' '
+	git reset --hard conflicts &&
+	test_must_fail git merge master &&
+	echo one >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch conflicts
+	# All conflicts fixed but you are still merging.
+	#   (use "git commit" to conclude merge)
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for rebase conflicts' '
+	git reset --hard master &&
+	git checkout -b rebase_conflicts &&
+	test_commit one_rebase main.txt one &&
+	test_commit two_rebase main.txt two &&
+	test_commit three_rebase main.txt three
+'
+
+
+test_expect_success 'status when rebase in progress before resolving conflicts' '
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (fix conflicts and then run "git rebase --continue")
+	#   (use "git rebase --skip" to skip this patch)
+	#   (use "git rebase --abort" to check out the original branch)
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when rebase in progress before rebase --continue' '
+	git reset --hard rebase_conflicts &&
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	echo three >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (all conflicts fixed: run "git rebase --continue")
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for rebase_i_conflicts' '
+	git reset --hard master &&
+	git checkout -b rebase_i_conflicts &&
+	test_commit one_unmerge main.txt one_unmerge &&
+	git branch rebase_i_conflicts_second &&
+	test_commit one_master main.txt one_master &&
+	git checkout rebase_i_conflicts_second &&
+	test_commit one_second main.txt one_second
+'
+
+
+test_expect_success 'status during rebase -i when conflicts unresolved' '
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase -i rebase_i_conflicts &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (fix conflicts and then run "git rebase --continue")
+	#   (use "git rebase --skip" to skip this patch)
+	#   (use "git rebase --abort" to check out the original branch)
+	#
+	# Unmerged paths:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status during rebase -i after resolving conflicts' '
+	git reset --hard rebase_i_conflicts_second &&
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase -i rebase_i_conflicts &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#   (all conflicts fixed: run "git rebase --continue")
+	#
+	# Changes to be committed:
+	#   (use "git reset HEAD <file>..." to unstage)
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when rebasing -i in edit mode' '
+	git reset --hard master &&
+	git checkout -b rebase_i_edit &&
+	test_commit one_rebase_i main.txt one &&
+	test_commit two_rebase_i main.txt two &&
+	test_commit three_rebase_i main.txt three &&
+	FAKE_LINES="1 edit 2" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~2 &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare am_session' '
+	git reset --hard master &&
+	git checkout -b am_session &&
+	test_commit one_am one.txt "one" &&
+	test_commit two_am two.txt "two" &&
+	test_commit three_am three.txt "three"
+'
+
+
+test_expect_success 'status in an am session: file already exists' '
+	git checkout -b am_already_exists &&
+	test_when_finished "rm Maildir/* && git am --abort" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch am_already_exists
+	# You are in the middle of an am session.
+	#   (fix conflicts and then run "git am --resolved")
+	#   (use "git am --skip" to skip this patch)
+	#   (use "git am --abort" to restore the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status in an am session: file does not exist' '
+	git reset --hard am_session &&
+	git checkout -b am_not_exists &&
+	git rm three.txt &&
+	git commit -m "delete three.txt" &&
+	test_when_finished "rm Maildir/* && git am --abort" &&
+	git format-patch -1 -oMaildir &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch am_not_exists
+	# You are in the middle of an am session.
+	#   (fix conflicts and then run "git am --resolved")
+	#   (use "git am --skip" to skip this patch)
+	#   (use "git am --abort" to restore the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status in an am session: empty patch' '
+	git reset --hard am_session &&
+	git checkout -b am_empty &&
+	test_when_finished "rm Maildir/* && git am --abort" &&
+	git format-patch -3 -oMaildir &&
+	git rm one.txt two.txt three.txt &&
+	git commit -m "delete all am_empty" &&
+	echo error >Maildir/0002-two_am.patch &&
+	test_must_fail git am Maildir/*.patch &&
+	cat >expected <<-\EOF &&
+	# On branch am_empty
+	# You are in the middle of an am session.
+	# The current patch is empty.
+	#   (use "git am --skip" to skip this patch)
+	#   (use "git am --abort" to restore the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when bisecting' '
+	git reset --hard master &&
+	git checkout -b bisect &&
+	test_commit one_bisect main.txt one &&
+	test_commit two_bisect main.txt two &&
+	test_commit three_bisect main.txt three &&
+	test_when_finished "git bisect reset" &&
+	git bisect start &&
+	git bisect bad &&
+	git bisect good one_bisect &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently bisecting.
+	#   (use "git bisect reset" to get back to the original branch)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when rebase conflicts with statushints disabled' '
+	git reset --hard master &&
+	git checkout -b statushints_disabled &&
+	test_when_finished "git config --local advice.statushints true" &&
+	git config --local advice.statushints false &&
+	test_commit one_statushints main.txt one &&
+	test_commit two_statushints main.txt two &&
+	test_commit three_statushints main.txt three &&
+	test_when_finished "git rebase --abort" &&
+	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently rebasing.
+	#
+	# Unmerged paths:
+	#	both modified:      main.txt
+	#
+	no changes added to commit
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for cherry-pick conflicts' '
+	git reset --hard master &&
+	git checkout -b cherry_branch &&
+	test_commit one_cherry main.txt one &&
+	test_commit two_cherries main.txt two &&
+	git checkout -b cherry_branch_second &&
+	test_commit second_cherry main.txt second &&
+	git checkout cherry_branch &&
+	test_commit three_cherries main.txt three
+'
+
+
+test_expect_success 'status when cherry-picking before resolving conflicts' '
+	test_when_finished "git cherry-pick --abort" &&
+	test_must_fail git cherry-pick cherry_branch_second &&
+	cat >expected <<-\EOF &&
+	# On branch cherry_branch
+	# You are currently cherry-picking.
+	#   (fix conflicts and run "git commit")
+	#
+	# Unmerged paths:
+	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#
+	#	both modified:      main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status when cherry-picking after resolving conflicts' '
+	git reset --hard cherry_branch &&
+	test_when_finished "git cherry-pick --abort" &&
+	test_must_fail git cherry-pick cherry_branch_second &&
+	echo end >main.txt &&
+	git add main.txt &&
+	cat >expected <<-\EOF &&
+	# On branch cherry_branch
+	# You are currently cherry-picking.
+	#   (all conflicts fixed: run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	modified:   main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_done
-- 
1.7.8

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

* [PATCHv10 3/4] status: don't suggest "git rm" or "git add" if not appropriate
  2012-06-10 11:17                 ` [PATCHv10 1/4] wt-status.*: better advices for git status added Lucien Kong
  2012-06-10 11:17                   ` [PATCHv10 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
@ 2012-06-10 11:17                   ` Lucien Kong
  2012-06-10 11:17                   ` [PATCHv10 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
  2 siblings, 0 replies; 97+ messages in thread
From: Lucien Kong @ 2012-06-10 11:17 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

The display of the advice '(use git add/rm [...])' (when there are
unmerged files) after running 'git status' is now depending of the
mark, whether it's 'both deleted', 'deleted by us/them' or others. For
instance, when there is just one file that's marked as 'both deleted',
'git status' shows '(use git rm [...])' and if there are two files,
one as 'both deleted' and the other as 'added by them', the advice is
'(use git add/rm [...])'.

The previous tests in t7512-status-help.sh are updated.

Test about the case of only 'both deleted' is added in
t7060-wtstatus.sh

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
part 3/4 unchanged since v9.

 t/t7060-wtstatus.sh    |   36 ++++++++++++++++++++++++++++++++++--
 t/t7512-status-help.sh |    8 ++++----
 wt-status.c            |   37 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index e8c3690..f4f38a5 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -152,7 +152,7 @@ test_expect_success 'status when conflicts with add and rm advice (deleted by th
 '
 
 
-test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
+test_expect_success 'prepare for conflicts' '
 	git reset --hard &&
 	git checkout -b conflict &&
 	test_commit one main.txt one &&
@@ -161,7 +161,11 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted)
 	git commit -m "main.txt renamed in sub_master.txt" &&
 	git checkout conflict_second &&
 	git mv main.txt sub_second.txt &&
-	git commit -m "main.txt renamed in sub_second.txt" &&
+	git commit -m "main.txt renamed in sub_second.txt"
+'
+
+
+test_expect_success 'status when conflicts with add and rm advice (both deleted)' '
 	test_must_fail git merge conflict &&
 	cat >expected <<-\EOF &&
 	# On branch conflict_second
@@ -182,4 +186,32 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted)
 '
 
 
+test_expect_success 'status when conflicts with only rm advice (both deleted)' '
+	git reset --hard conflict_second &&
+	test_must_fail git merge conflict &&
+	git add sub_master.txt &&
+	git add sub_second.txt &&
+	cat >expected <<-\EOF &&
+	# On branch conflict_second
+	# You have unmerged paths.
+	#   (fix conflicts and run "git commit")
+	#
+	# Changes to be committed:
+	#
+	#	new file:   sub_master.txt
+	#
+	# Unmerged paths:
+	#   (use "git rm <file>..." to mark resolution)
+	#
+	#	both deleted:       main.txt
+	#
+	# Untracked files not listed (use -u option to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual &&
+	git reset --hard &&
+	git checkout master
+'
+
+
 test_done
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 3714e8e..bdce192 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -30,7 +30,7 @@ test_expect_success 'status when conflicts unresolved' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -83,7 +83,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -140,7 +140,7 @@ test_expect_success 'status during rebase -i when conflicts unresolved' '
 	#
 	# Unmerged paths:
 	#   (use "git reset HEAD <file>..." to unstage)
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
@@ -336,7 +336,7 @@ test_expect_success 'status when cherry-picking before resolving conflicts' '
 	#   (fix conflicts and run "git commit")
 	#
 	# Unmerged paths:
-	#   (use "git add/rm <file>..." as appropriate to mark resolution)
+	#   (use "git add <file>..." to mark resolution)
 	#
 	#	both modified:      main.txt
 	#
diff --git a/wt-status.c b/wt-status.c
index 7548509..fcde045 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -131,9 +131,34 @@ void wt_status_prepare(struct wt_status *s)
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
 {
+	int i;
+	int del_mod_conflict = 0;
+	int both_deleted = 0;
+	int not_deleted = 0;
 	const char *c = color(WT_STATUS_HEADER, s);
 
 	status_printf_ln(s, c, _("Unmerged paths:"));
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct string_list_item *it = &(s->change.items[i]);
+		struct wt_status_change_data *d = it->util;
+
+		switch (d->stagemask) {
+		case 0:
+			break;
+		case 1:
+			both_deleted = 1;
+			break;
+		case 3:
+		case 5:
+			del_mod_conflict = 1;
+			break;
+		default:
+			not_deleted = 1;
+			break;
+		}
+	}
+
 	if (!advice_status_hints)
 		return;
 	if (s->whence != FROM_COMMIT)
@@ -142,7 +167,17 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
 		status_printf_ln(s, c, _("  (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
 		status_printf_ln(s, c, _("  (use \"git rm --cached <file>...\" to unstage)"));
-	status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+
+	if (!both_deleted) {
+		if (!del_mod_conflict)
+			status_printf_ln(s, c, _("  (use \"git add <file>...\" to mark resolution)"));
+		else
+			status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	} else if (!del_mod_conflict && !not_deleted) {
+		status_printf_ln(s, c, _("  (use \"git rm <file>...\" to mark resolution)"));
+	} else {
+		status_printf_ln(s, c, _("  (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	}
 	status_printf_ln(s, c, "");
 }
 
-- 
1.7.8

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

* [PATCHv10 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-10 11:17                 ` [PATCHv10 1/4] wt-status.*: better advices for git status added Lucien Kong
  2012-06-10 11:17                   ` [PATCHv10 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
  2012-06-10 11:17                   ` [PATCHv10 3/4] status: don't suggest "git rm" or "git add" if not appropriate Lucien Kong
@ 2012-06-10 11:17                   ` Lucien Kong
  2012-06-11 20:21                     ` Junio C Hamano
  2 siblings, 1 reply; 97+ messages in thread
From: Lucien Kong @ 2012-06-10 11:17 UTC (permalink / raw)
  To: git
  Cc: Lucien Kong, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Add new informative help messages at the output of 'git status' when
the user is splitting a commit. The code figures this state by
comparing the contents of the following files in the .git/ directory:
	  - HEAD
	  - ORIG_HEAD
	  - rebase-merge/amend
	  - rebase-merge/orig-head

Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---
The "const" have been dropped and the check about "HEAD" been
detached or not is fixed.

 t/t7512-status-help.sh |  277 ++++++++++++++++++++++++++++++++++++++++++++++++
 wt-status.c            |   51 +++++++++
 2 files changed, 328 insertions(+), 0 deletions(-)

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index bdce192..3ce384a 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -196,6 +196,283 @@ test_expect_success 'status when rebasing -i in edit mode' '
 '
 
 
+test_expect_success 'status when splitting a commit' '
+	git reset --hard master &&
+	git checkout -b split_commit &&
+	test_commit one_split main.txt one &&
+	test_commit two_split main.txt two &&
+	test_commit three_split main.txt three &&
+	test_commit four_split main.txt four &&
+	FAKE_LINES="1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status after editing the last commit with --amend during a rebase -i' '
+	git reset --hard master &&
+	git checkout -b amend_last &&
+	test_commit one_amend main.txt one &&
+	test_commit two_amend main.txt two &&
+	test_commit three_amend main.txt three &&
+	test_commit four_amend main.txt four &&
+	FAKE_LINES="1 2 edit 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "foo" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'prepare for several edits' '
+	git reset --hard master &&
+	git checkout -b several_edits &&
+	test_commit one_edits main.txt one &&
+	test_commit two_edits main.txt two &&
+	test_commit three_edits main.txt three &&
+	test_commit four_edits main.txt four
+'
+
+
+test_expect_success 'status: (continue first edit) second edit' '
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git rebase --continue &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (continue first edit) second edit and split' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git rebase --continue &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (continue first edit) second edit and amend' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git rebase --continue &&
+	git commit --amend -m "foo" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (amend first edit) second edit' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "a" &&
+	git rebase --continue &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (amend first edit) second edit and split' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "b" &&
+	git rebase --continue &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (amend first edit) second edit and amend' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git commit --amend -m "c" &&
+	git rebase --continue &&
+	git commit --amend -m "d" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (split first edit) second edit' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	git add main.txt &&
+	git commit -m "e" &&
+	git rebase --continue &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (split first edit) second edit and split' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	git add main.txt &&
+	git commit --amend -m "f" &&
+	git rebase --continue &&
+	git reset HEAD^ &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently splitting a commit.
+	#   (Once your working directory is clean, run "git rebase --continue")
+	#
+	# Changes not staged for commit:
+	#   (use "git add <file>..." to update what will be committed)
+	#   (use "git checkout -- <file>..." to discard changes in working directory)
+	#
+	#	modified:   main.txt
+	#
+	no changes added to commit (use "git add" and/or "git commit -a")
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
+test_expect_success 'status: (split first edit) second edit and amend' '
+	git reset --hard several_edits &&
+	FAKE_LINES="edit 1 edit 2 3" &&
+	export FAKE_LINES &&
+	test_when_finished "git rebase --abort" &&
+	git rebase -i HEAD~3 &&
+	git reset HEAD^ &&
+	git add main.txt &&
+	git commit --amend -m "g" &&
+	git rebase --continue &&
+	git commit --amend -m "h" &&
+	cat >expected <<-\EOF &&
+	# Not currently on any branch.
+	# You are currently editing a commit during a rebase.
+	#   (use "git commit --amend" to amend the current commit)
+	#   (use "git rebase --continue" once you are satisfied with your changes)
+	#
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual
+'
+
+
 test_expect_success 'prepare am_session' '
 	git reset --hard master &&
 	git checkout -b am_session &&
diff --git a/wt-status.c b/wt-status.c
index fcde045..5496a1f 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -12,6 +12,7 @@
 #include "refs.h"
 #include "submodule.h"
 #include "column.h"
+#include "strbuf.h"
 
 static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -817,6 +818,51 @@ static void show_am_in_progress(struct wt_status *s,
 	wt_status_print_trailer(s);
 }
 
+static char *read_line_from_git_path(const char *filename)
+{
+	struct strbuf buf = STRBUF_INIT;
+	FILE *fp = fopen(git_path("%s", filename), "r");
+	if (!fp) {
+		strbuf_release(&buf);
+		return NULL;
+	}
+	strbuf_getline(&buf, fp, '\n');
+	if (!fclose(fp)) {
+		return strbuf_detach(&buf, NULL);
+	} else {
+		strbuf_release(&buf);
+		return NULL;
+	}
+}
+
+static int split_commit_in_progress(struct wt_status *s)
+{
+	int split_in_progress = 0;
+	char *head = read_line_from_git_path("HEAD");
+	char *orig_head = read_line_from_git_path("ORIG_HEAD");
+	char *rebase_amend = read_line_from_git_path("rebase-merge/amend");
+	char *rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
+
+	if (!head || !orig_head || !rebase_amend || !rebase_orig_head || !prefixcmp(head, "ref: "))
+		return split_in_progress;
+
+	if (!strcmp(rebase_amend, rebase_orig_head)) {
+		if (strcmp(head, rebase_amend))
+			split_in_progress = 1;
+	} else if (strcmp(orig_head, rebase_orig_head)) {
+		split_in_progress = 1;
+	}
+
+	if (!s->amend && !s->nowarn && !s->workdir_dirty)
+		split_in_progress = 0;
+
+	free(head);
+	free(orig_head);
+	free(rebase_amend);
+	free(rebase_orig_head);
+	return split_in_progress;
+}
+
 static void show_rebase_in_progress(struct wt_status *s,
 				struct wt_status_state *state,
 				const char *color)
@@ -838,6 +884,11 @@ static void show_rebase_in_progress(struct wt_status *s,
 		if (advice_status_hints)
 			status_printf_ln(s, color,
 				_("  (all conflicts fixed: run \"git rebase --continue\")"));
+	} else if (split_commit_in_progress(s)) {
+		status_printf_ln(s, color, _("You are currently splitting a commit."));
+		if (advice_status_hints)
+			status_printf_ln(s, color,
+				_("  (Once your working directory is clean, run \"git rebase --continue\")"));
 	} else {
 		status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
 		if (advice_status_hints && !s->amend) {
-- 
1.7.8

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

* Re: [PATCHv10 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-10 11:17                   ` [PATCHv10 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
@ 2012-06-11 20:21                     ` Junio C Hamano
  2012-06-12  7:14                       ` konglu
  0 siblings, 1 reply; 97+ messages in thread
From: Junio C Hamano @ 2012-06-11 20:21 UTC (permalink / raw)
  To: Lucien Kong
  Cc: git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy

Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:

> Add new informative help messages at the output of 'git status' when
> the user is splitting a commit. The code figures this state by
> comparing the contents of the following files in the .git/ directory:
> 	  - HEAD
> 	  - ORIG_HEAD
> 	  - rebase-merge/amend
> 	  - rebase-merge/orig-head

It may be just me but I would find it easier to read if you had a
blank line before this four-item enumerated list.

> diff --git a/wt-status.c b/wt-status.c
> index fcde045..5496a1f 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -12,6 +12,7 @@
>  #include "refs.h"
>  #include "submodule.h"
>  #include "column.h"
> +#include "strbuf.h"
>  
>  static char default_wt_status_colors[][COLOR_MAXLEN] = {
>  	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
> @@ -817,6 +818,51 @@ static void show_am_in_progress(struct wt_status *s,
>  	wt_status_print_trailer(s);
>  }
>  
> +static char *read_line_from_git_path(const char *filename)
> +{
> +	struct strbuf buf = STRBUF_INIT;
> +	FILE *fp = fopen(git_path("%s", filename), "r");
> +	if (!fp) {
> +		strbuf_release(&buf);
> +		return NULL;
> +	}
> +	strbuf_getline(&buf, fp, '\n');
> +	if (!fclose(fp)) {
> +		return strbuf_detach(&buf, NULL);
> +	} else {
> +		strbuf_release(&buf);
> +		return NULL;
> +	}
> +}

With this code, read_line_from_git_path("HEAD") will read:

	[0-9a-f]{40} when the HEAD is detached;

        ref: refs/heads/<current-branch-name> when textual symref is
        in use (and you are on the branch); or

	[0-9a-f]{40} stored in refs/heads/<current-branch-name> when
	symlink symref is in use (and you are on the branch).

> +static int split_commit_in_progress(struct wt_status *s)
> +{
> +	int split_in_progress = 0;
> +	char *head = read_line_from_git_path("HEAD");
> +	char *orig_head = read_line_from_git_path("ORIG_HEAD");
> +	char *rebase_amend = read_line_from_git_path("rebase-merge/amend");
> +	char *rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
> +
> +	if (!head || !orig_head || !rebase_amend || !rebase_orig_head || !prefixcmp(head, "ref: "))
> +		return split_in_progress;

I think the above

	!prefixcmp(head, "ref: ")

is probably a mistake; shouldn't it be

	strcmp(s->branch, "HEAD")

which is used in wt_status_print() to diagnose that you are on a
detached HEAD (which is the normal case)?  Otherwise head may point
at the commit object name read from "refs/heads/current" through a
symbolic link .git/HEAD that points at "refs/heads/current".

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

* Re: [PATCHv10 4/4] status: better advices when splitting a commit (during rebase -i)
  2012-06-11 20:21                     ` Junio C Hamano
@ 2012-06-12  7:14                       ` konglu
  0 siblings, 0 replies; 97+ messages in thread
From: konglu @ 2012-06-12  7:14 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Lucien Kong, git, Valentin Duperray, Franck Jonas, Thomas Nguy,
	Huynh Khoi Nguyen Nguyen, Matthieu Moy


Junio C Hamano <gitster@pobox.com> a écrit :

>> +static int split_commit_in_progress(struct wt_status *s)
>> +{
>> +	int split_in_progress = 0;
>> +	char *head = read_line_from_git_path("HEAD");
>> +	char *orig_head = read_line_from_git_path("ORIG_HEAD");
>> +	char *rebase_amend = read_line_from_git_path("rebase-merge/amend");
>> +	char *rebase_orig_head =  
>> read_line_from_git_path("rebase-merge/orig-head");
>> +
>> +	if (!head || !orig_head || !rebase_amend || !rebase_orig_head ||  
>> !prefixcmp(head, "ref: "))
>> +		return split_in_progress;
>
> I think the above
>
> 	!prefixcmp(head, "ref: ")
>
> is probably a mistake; shouldn't it be
>
> 	strcmp(s->branch, "HEAD")
>
> which is used in wt_status_print() to diagnose that you are on a
> detached HEAD (which is the normal case)?  Otherwise head may point
> at the commit object name read from "refs/heads/current" through a
> symbolic link .git/HEAD that points at "refs/heads/current".

Aah, that's the variable I was looking for.
Thanks for fixing it up :).

Lucien Kong

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

end of thread, other threads:[~2012-06-12  7:14 UTC | newest]

Thread overview: 97+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-24  9:37 [PATCH/RFC] t7512-status-warnings.sh : better advices for git status Kong Lucien
2012-05-24 17:31 ` Matthieu Moy
2012-05-26 12:38 ` [PATCHv2 1/2] wt-status: " Kong Lucien
2012-05-26 12:38   ` [PATCHv2 2/2] t7512-status-warnings.sh: " Kong Lucien
2012-05-27 12:57     ` Matthieu Moy
2012-05-28  8:43     ` Matthieu Moy
2012-05-26 13:01   ` [PATCHv2 1/2] wt-status: " Nguyen Thai Ngoc Duy
2012-05-26 17:17     ` NGUY Thomas
2012-05-27 12:58     ` Matthieu Moy
2012-05-27 13:10   ` Matthieu Moy
2012-05-28  4:57   ` Junio C Hamano
2012-05-28  7:05     ` Matthieu Moy
2012-05-30  4:27       ` Junio C Hamano
2012-05-28 10:54     ` konglu
2012-05-28 17:36   ` [PATCHv3 1/2] wt-status.*: better advices for git status added Kong Lucien
2012-05-28 17:36     ` [PATCHv3 2/2] t7512-status-warnings.sh: better advices for git status Kong Lucien
2012-05-28 20:36       ` Matthieu Moy
2012-05-28 20:23     ` [PATCHv3 1/2] wt-status.*: better advices for git status added Matthieu Moy
2012-05-29 19:22     ` Junio C Hamano
2012-05-30 11:09       ` konglu
2012-05-30 17:24         ` Junio C Hamano
2012-05-31  6:47         ` Matthieu Moy
2012-05-30 13:23     ` [PATCHv4 1/3] " Kong Lucien
2012-05-30 13:23       ` [PATCHv4 2/3] t7512-status-warnings.sh: better advices for git status Kong Lucien
2012-05-30 13:23       ` [PATCHv4 3/3] Advices about 'git rm' during conflicts (unmerged paths) more relevant Kong Lucien
2012-05-30 18:44         ` Junio C Hamano
2012-05-30 21:50           ` konglu
2012-05-31  7:06         ` Matthieu Moy
2012-05-31  7:59           ` konglu
2012-05-30 18:26       ` [PATCHv4 1/3] wt-status.*: better advices for git status added Junio C Hamano
2012-05-30 19:06         ` Junio C Hamano
2012-05-31  6:42         ` Matthieu Moy
2012-05-31  6:44           ` Matthieu Moy
2012-05-31  6:29       ` Matthieu Moy
2012-05-31  6:34         ` Andrew Ardill
2012-05-31 15:15       ` [PATCHv5 " Kong Lucien
2012-05-31 15:15         ` [PATCHv5 2/3] t7512-status-help.sh: better advices for git status Kong Lucien
2012-05-31 15:15         ` [PATCHv5 3/3] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
2012-06-01  8:55           ` Matthieu Moy
2012-06-01 12:15           ` Phil Hord
2012-06-01 14:08             ` konglu
2012-06-01 16:38               ` Junio C Hamano
2012-05-31 21:36         ` [PATCHv5 1/3] wt-status.*: better advices for git status added Junio C Hamano
2012-06-01  9:16           ` konglu
2012-06-01  9:26             ` Matthieu Moy
2012-06-01 14:50               ` Junio C Hamano
2012-06-01 16:51             ` Junio C Hamano
2012-06-01 19:39               ` konglu
2012-06-01  8:42         ` Matthieu Moy
2012-06-01 11:27           ` konglu
2012-06-01 12:40             ` Phil Hord
2012-06-01 16:57               ` Junio C Hamano
2012-06-04 18:00                 ` Phil Hord
2012-06-03 18:30         ` [PATCHv6 1/4] " Kong Lucien
2012-06-03 18:30           ` [PATCHv6 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
2012-06-03 21:18             ` Junio C Hamano
2012-06-04 10:04               ` konglu
2012-06-04 15:04                 ` Junio C Hamano
2012-06-04 22:07                 ` Junio C Hamano
2012-06-03 18:30           ` [PATCHv6 3/4] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
2012-06-03 19:34             ` Matthieu Moy
2012-06-03 18:30           ` [PATCHv6 4/4] status: better advices when splitting a commit (during rebase -i) Kong Lucien
2012-06-03 22:00             ` Junio C Hamano
2012-06-04 15:35             ` Phil Hord
2012-06-05  9:13               ` konglu
2012-06-03 21:06           ` [PATCHv6 1/4] wt-status.*: better advices for git status added Junio C Hamano
2012-06-04  9:51             ` konglu
2012-06-04 14:54               ` Junio C Hamano
2012-06-04 17:19           ` [PATCHv7 " Kong Lucien
2012-06-04 17:19             ` [PATCHv7 2/4] t7512-status-help.sh: better advices for git status Kong Lucien
2012-06-04 21:02               ` Matthieu Moy
2012-06-04 23:12               ` Junio C Hamano
2012-06-04 17:19             ` [PATCHv7 3/4] status: don't suggest "git rm" or "git add" if not appropriate Kong Lucien
2012-06-04 17:19             ` [PATCHv7 4/4] status: better advices when splitting a commit (during rebase -i) Kong Lucien
2012-06-04 23:01             ` [PATCHv7 1/4] wt-status.*: better advices for git status added Junio C Hamano
2012-06-05 10:32               ` konglu
2012-06-05 11:33                 ` Matthieu Moy
2012-06-05 20:21             ` [PATCHv8 " Lucien Kong
2012-06-05 20:21               ` [PATCHv8 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
2012-06-05 20:21               ` [PATCHv8 3/4] status: don't suggest "git rm" or "git add" if not appropriate Lucien Kong
2012-06-05 20:21               ` [PATCHv8 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
2012-06-05 21:16                 ` Junio C Hamano
2012-06-08  9:29                   ` konglu
2012-06-08 15:05                     ` Junio C Hamano
2012-06-07 13:17               ` [PATCHv9 1/4] wt-status.*: better advices for git status added Lucien Kong
2012-06-07 13:17                 ` [PATCHv9 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
2012-06-07 13:17                 ` [PATCHv9 3/4] status: don't suggest "git rm" or "git add" if not appropriate Lucien Kong
2012-06-07 13:17                 ` [PATCHv9 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
2012-06-07 18:07                   ` Junio C Hamano
2012-06-07 20:42                   ` Junio C Hamano
2012-06-07 21:05                     ` konglu
2012-06-10 11:17                 ` [PATCHv10 1/4] wt-status.*: better advices for git status added Lucien Kong
2012-06-10 11:17                   ` [PATCHv10 2/4] t7512-status-help.sh: better advices for git status Lucien Kong
2012-06-10 11:17                   ` [PATCHv10 3/4] status: don't suggest "git rm" or "git add" if not appropriate Lucien Kong
2012-06-10 11:17                   ` [PATCHv10 4/4] status: better advices when splitting a commit (during rebase -i) Lucien Kong
2012-06-11 20:21                     ` Junio C Hamano
2012-06-12  7:14                       ` konglu

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