diff mbox series

[v2,1/2] Refactor code asking the user for input interactively

Message ID 9d2ee78a9e414c0b6aacbc9c878ab08eb70703d5.1586518072.git.gitgitgadget@gmail.com (mailing list archive)
State New, archived
Headers show
Series Explicitly fflush stdout in git clean | expand

Commit Message

John Passaro via GitGitGadget April 10, 2020, 11:27 a.m. UTC
From: Johannes Schindelin <johannes.schindelin@gmx.de>

There are quite a few code locations (e.g. `git clean --interactive`)
where Git asks the user for an answer. In preparation for fixing a bug
shared by all of them, and also to DRY up the code, let's refactor it.

Please note that most of these callers trimmed white-space both at the
beginning and at the end of the answer, instead of trimming only the
end (as the caller in `add-patch.c` does).

THerefore, technically speaking, we change behavior in this patch. At
the same time, it can be argued that this is actually a bug fix.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 add-interactive.c |  4 ++--
 add-patch.c       |  4 ++--
 builtin/clean.c   | 14 ++++----------
 prompt.c          | 10 ++++++++++
 prompt.h          |  2 ++
 shell.c           |  4 ++--
 6 files changed, 22 insertions(+), 16 deletions(-)

Comments

Derrick Stolee April 10, 2020, 12:27 p.m. UTC | #1
On 4/10/2020 7:27 AM, Johannes Schindelin via GitGitGadget wrote:
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> There are quite a few code locations (e.g. `git clean --interactive`)
> where Git asks the user for an answer. In preparation for fixing a bug
> shared by all of them, and also to DRY up the code, let's refactor it.
> 
> Please note that most of these callers trimmed white-space both at the
> beginning and at the end of the answer, instead of trimming only the
> end (as the caller in `add-patch.c` does).

add-patch also only trims the newline! This is still a good change.

> THerefore, technically speaking, we change behavior in this patch. At

Strange capitalization here.

> the same time, it can be argued that this is actually a bug fix.
> 

> @@ -1158,9 +1159,8 @@ static int read_single_character(struct add_p_state *s)
>  		return res;
>  	}
>  
> -	if (strbuf_getline(&s->answer, stdin) == EOF)
> +	if (git_read_line_interactively(&s->answer) == EOF)
>  		return EOF;
> -	strbuf_trim_trailing_newline(&s->answer);

(Pointing out the trailing newline trim here.)

> +
> +int git_read_line_interactively(struct strbuf *line)
> +{
> +	int ret = strbuf_getline_lf(line, stdin);
> +
> +	if (ret != EOF)
> +		strbuf_trim_trailing_newline(line);
> +
> +	return ret;
> +}

This looks good. Do we need a trailing newline or something?
The way the diff ends abruptly after the "}" line made me
think so.

Thanks,
-Stolee
Johannes Schindelin April 10, 2020, 2:01 p.m. UTC | #2
Hi Dr Stolee,

On Fri, 10 Apr 2020, Derrick Stolee wrote:

> On 4/10/2020 7:27 AM, Johannes Schindelin via GitGitGadget wrote:
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > There are quite a few code locations (e.g. `git clean --interactive`)
> > where Git asks the user for an answer. In preparation for fixing a bug
> > shared by all of them, and also to DRY up the code, let's refactor it.
> >
> > Please note that most of these callers trimmed white-space both at the
> > beginning and at the end of the answer, instead of trimming only the
> > end (as the caller in `add-patch.c` does).
>
> add-patch also only trims the newline! This is still a good change.
>
> > THerefore, technically speaking, we change behavior in this patch. At
>
> Strange capitalization here.

I fixed it and force-pushed, waiting a little with submitting it in case
there are more things reviewers point out.

> > the same time, it can be argued that this is actually a bug fix.
> >
>
> > @@ -1158,9 +1159,8 @@ static int read_single_character(struct add_p_state *s)
> >  		return res;
> >  	}
> >
> > -	if (strbuf_getline(&s->answer, stdin) == EOF)
> > +	if (git_read_line_interactively(&s->answer) == EOF)
> >  		return EOF;
> > -	strbuf_trim_trailing_newline(&s->answer);
>
> (Pointing out the trailing newline trim here.)
>
> > +
> > +int git_read_line_interactively(struct strbuf *line)
> > +{
> > +	int ret = strbuf_getline_lf(line, stdin);
> > +
> > +	if (ret != EOF)
> > +		strbuf_trim_trailing_newline(line);
> > +
> > +	return ret;
> > +}
>
> This looks good. Do we need a trailing newline or something?
> The way the diff ends abruptly after the "}" line made me
> think so.

No, this file ends in that line, therefore it ends abruptly ;-)

If I add another newline, `git diff` shows a red `+` at the end, i.e. we
consider it a white-space problem.

Thank you for your review!
Dscho

>
> Thanks,
> -Stolee
>
>
Jeff King April 10, 2020, 3:07 p.m. UTC | #3
On Fri, Apr 10, 2020 at 11:27:50AM +0000, Johannes Schindelin via GitGitGadget wrote:

> diff --git a/prompt.h b/prompt.h
> index e04cced030c..e294e93541c 100644
> --- a/prompt.h
> +++ b/prompt.h
> @@ -6,4 +6,6 @@
>  
>  char *git_prompt(const char *prompt, int flags);
>  
> +int git_read_line_interactively(struct strbuf *line);
> +

It might be worth adding some comments discussing why one would use
git_prompt() versus git_read_line_interactively().

Other than that, both patches look good to me. Thanks for calling out
the changed trimming behavior preemptively. I agree it should not be a
big deal either way.

-Peff
Junio C Hamano April 10, 2020, 5:44 p.m. UTC | #4
"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> -		if (strbuf_getline(&input, stdin) == EOF) {
> +		if (git_read_line_interactively(&input) == EOF) {

It's not like we are mimicking or giving a thin wrapper to improve
an existing read_line_interactively() from a third-party, so I do
not see much point in giving "git_" prefix here.  On the other hand,
"strbuf_" prefix may not hurt (but the type of its first parameter
is sufficient so it is not exactly required).

>  			printf(_("Remove %s [y/N]? "), qname);
> -			if (strbuf_getline_lf(&confirm, stdin) != EOF) {
> -				strbuf_trim(&confirm);
> -			} else {
> +			if (git_read_line_interactively(&confirm) == EOF) {
>  				putchar('\n');
>  				eof = 1;

A fat-finger that gave an answer " yes <RET>" used to be still taken
as a yes but now it is interpreted as "no", because the new helper
trims a lot less.  In general, the existing code should be already
choosing the safer default, so such a change in behaviour brought in
by this change, even if they were not intentional, should probably
be safe.

Thanks.
diff mbox series

Patch

diff --git a/add-interactive.c b/add-interactive.c
index 4a9bf85cac0..29cd2fe0201 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -9,6 +9,7 @@ 
 #include "lockfile.h"
 #include "dir.h"
 #include "run-command.h"
+#include "prompt.h"
 
 static void init_color(struct repository *r, struct add_i_state *s,
 		       const char *slot_name, char *dst,
@@ -289,13 +290,12 @@  static ssize_t list_and_choose(struct add_i_state *s,
 		fputs(singleton ? "> " : ">> ", stdout);
 		fflush(stdout);
 
-		if (strbuf_getline(&input, stdin) == EOF) {
+		if (git_read_line_interactively(&input) == EOF) {
 			putchar('\n');
 			if (immediate)
 				res = LIST_AND_CHOOSE_QUIT;
 			break;
 		}
-		strbuf_trim(&input);
 
 		if (!input.len)
 			break;
diff --git a/add-patch.c b/add-patch.c
index d8dafa8168d..d8bfe379be4 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -7,6 +7,7 @@ 
 #include "color.h"
 #include "diff.h"
 #include "compat/terminal.h"
+#include "prompt.h"
 
 enum prompt_mode_type {
 	PROMPT_MODE_CHANGE = 0, PROMPT_DELETION, PROMPT_HUNK,
@@ -1158,9 +1159,8 @@  static int read_single_character(struct add_p_state *s)
 		return res;
 	}
 
-	if (strbuf_getline(&s->answer, stdin) == EOF)
+	if (git_read_line_interactively(&s->answer) == EOF)
 		return EOF;
-	strbuf_trim_trailing_newline(&s->answer);
 	return 0;
 }
 
diff --git a/builtin/clean.c b/builtin/clean.c
index 5abf087e7c4..c8c011d2ddf 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -18,6 +18,7 @@ 
 #include "color.h"
 #include "pathspec.h"
 #include "help.h"
+#include "prompt.h"
 
 static int force = -1; /* unset */
 static int interactive;
@@ -420,7 +421,6 @@  static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
 	return found;
 }
 
-
 /*
  * Parse user input, and return choice(s) for menu (menu_stuff).
  *
@@ -580,9 +580,7 @@  static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
 			       clean_get_color(CLEAN_COLOR_RESET));
 		}
 
-		if (strbuf_getline_lf(&choice, stdin) != EOF) {
-			strbuf_trim(&choice);
-		} else {
+		if (git_read_line_interactively(&choice) == EOF) {
 			eof = 1;
 			break;
 		}
@@ -662,9 +660,7 @@  static int filter_by_patterns_cmd(void)
 		clean_print_color(CLEAN_COLOR_PROMPT);
 		printf(_("Input ignore patterns>> "));
 		clean_print_color(CLEAN_COLOR_RESET);
-		if (strbuf_getline_lf(&confirm, stdin) != EOF)
-			strbuf_trim(&confirm);
-		else
+		if (git_read_line_interactively(&confirm) == EOF)
 			putchar('\n');
 
 		/* quit filter_by_pattern mode if press ENTER or Ctrl-D */
@@ -760,9 +756,7 @@  static int ask_each_cmd(void)
 			qname = quote_path_relative(item->string, NULL, &buf);
 			/* TRANSLATORS: Make sure to keep [y/N] as is */
 			printf(_("Remove %s [y/N]? "), qname);
-			if (strbuf_getline_lf(&confirm, stdin) != EOF) {
-				strbuf_trim(&confirm);
-			} else {
+			if (git_read_line_interactively(&confirm) == EOF) {
 				putchar('\n');
 				eof = 1;
 			}
diff --git a/prompt.c b/prompt.c
index 6d5885d0096..098dcfb7cf9 100644
--- a/prompt.c
+++ b/prompt.c
@@ -74,3 +74,13 @@  char *git_prompt(const char *prompt, int flags)
 	}
 	return r;
 }
+
+int git_read_line_interactively(struct strbuf *line)
+{
+	int ret = strbuf_getline_lf(line, stdin);
+
+	if (ret != EOF)
+		strbuf_trim_trailing_newline(line);
+
+	return ret;
+}
diff --git a/prompt.h b/prompt.h
index e04cced030c..e294e93541c 100644
--- a/prompt.h
+++ b/prompt.h
@@ -6,4 +6,6 @@ 
 
 char *git_prompt(const char *prompt, int flags);
 
+int git_read_line_interactively(struct strbuf *line);
+
 #endif /* PROMPT_H */
diff --git a/shell.c b/shell.c
index 54cca7439de..cef7ffdc9e1 100644
--- a/shell.c
+++ b/shell.c
@@ -4,6 +4,7 @@ 
 #include "strbuf.h"
 #include "run-command.h"
 #include "alias.h"
+#include "prompt.h"
 
 #define COMMAND_DIR "git-shell-commands"
 #define HELP_COMMAND COMMAND_DIR "/help"
@@ -76,12 +77,11 @@  static void run_shell(void)
 		int count;
 
 		fprintf(stderr, "git> ");
-		if (strbuf_getline_lf(&line, stdin) == EOF) {
+		if (git_read_line_interactively(&line) == EOF) {
 			fprintf(stderr, "\n");
 			strbuf_release(&line);
 			break;
 		}
-		strbuf_trim(&line);
 		rawargs = strbuf_detach(&line, NULL);
 		split_args = xstrdup(rawargs);
 		count = split_cmdline(split_args, &argv);