All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>, "Jeff King" <peff@peff.net>,
	"Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
	"Alejandro Sanchez" <asanchez1987@gmail.com>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: [PATCH 1/2] prompt.c: split up the password and non-password handling
Date: Tue,  2 Nov 2021 17:48:09 +0100	[thread overview]
Message-ID: <patch-1.2-ce5bea43f03-20211102T155046Z-avarab@gmail.com> (raw)
In-Reply-To: <cover-0.2-00000000000-20211102T155046Z-avarab@gmail.com>

Rather than pass PROMPT_ASKPASS and PROMPT_ECHO flags to git_prompt()
let's split it up into git_prompt_echo() and git_prompt_noecho()
functions, the latter only ever needs to be called from credential.c,
and the same goes for the previous password-only codepath in
git_prompt(), which is now exposed as a git_prompt_password().

Doing this paves the way towards addressing some of the issues brought
up in 97387c8bdd9 (am: read interactive input from stdin, 2019-05-20).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Makefile                 |  1 +
 builtin/bisect--helper.c |  5 ++-
 credential.c             | 17 ++++++----
 help.c                   |  2 +-
 prompt-password.c        | 63 ++++++++++++++++++++++++++++++++++
 prompt-password.h        |  7 ++++
 prompt.c                 | 73 ++++++----------------------------------
 prompt.h                 |  7 ++--
 8 files changed, 97 insertions(+), 78 deletions(-)
 create mode 100644 prompt-password.c
 create mode 100644 prompt-password.h

diff --git a/Makefile b/Makefile
index 12be39ac497..e8815860e22 100644
--- a/Makefile
+++ b/Makefile
@@ -967,6 +967,7 @@ LIB_OBJS += pretty.o
 LIB_OBJS += prio-queue.o
 LIB_OBJS += progress.o
 LIB_OBJS += promisor-remote.o
+LIB_OBJS += prompt-password.o
 LIB_OBJS += prompt.o
 LIB_OBJS += protocol.o
 LIB_OBJS += protocol-caps.o
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 28a2e6a5750..30533a70b53 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -370,7 +370,7 @@ static int decide_next(const struct bisect_terms *terms,
 		 * translation. The program will only accept English input
 		 * at this point.
 		 */
-		yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO);
+		yesno = git_prompt_echo(_("Are you sure [Y/n]? "));
 		if (starts_with(yesno, "N") || starts_with(yesno, "n"))
 			return -1;
 		return 0;
@@ -838,8 +838,7 @@ static int bisect_autostart(struct bisect_terms *terms)
 	 * translation. The program will only accept English input
 	 * at this point.
 	 */
-	yesno = git_prompt(_("Do you want me to do it for you "
-			     "[Y/n]? "), PROMPT_ECHO);
+	yesno = git_prompt_echo(_("Do you want me to do it for you [Y/n]? "));
 	res = tolower(*yesno) == 'n' ?
 		-1 : bisect_start(terms, empty_strvec, 0);
 
diff --git a/credential.c b/credential.c
index e7240f3f636..5509de382a5 100644
--- a/credential.c
+++ b/credential.c
@@ -5,6 +5,7 @@
 #include "run-command.h"
 #include "url.h"
 #include "prompt.h"
+#include "prompt-password.h"
 #include "sigchain.h"
 #include "urlmatch.h"
 
@@ -169,11 +170,11 @@ static void credential_format(struct credential *c, struct strbuf *out)
 	}
 }
 
-static char *credential_ask_one(const char *what, struct credential *c,
-				int flags)
+static char *credential_ask_one(struct credential *c, unsigned int password)
 {
 	struct strbuf desc = STRBUF_INIT;
 	struct strbuf prompt = STRBUF_INIT;
+	const char *what = password ? "Password" : "Username";
 	char *r;
 
 	credential_describe(c, &desc);
@@ -182,7 +183,11 @@ static char *credential_ask_one(const char *what, struct credential *c,
 	else
 		strbuf_addf(&prompt, "%s: ", what);
 
-	r = git_prompt(prompt.buf, flags);
+	/* We'll try "askpass" for both usernames and passwords */
+	r = git_prompt_askpass(prompt.buf);
+	if (!r)
+		r = password ? git_prompt_noecho(prompt.buf)
+			     : git_prompt_echo(prompt.buf);
 
 	strbuf_release(&desc);
 	strbuf_release(&prompt);
@@ -192,11 +197,9 @@ static char *credential_ask_one(const char *what, struct credential *c,
 static void credential_getpass(struct credential *c)
 {
 	if (!c->username)
-		c->username = credential_ask_one("Username", c,
-						 PROMPT_ASKPASS|PROMPT_ECHO);
+		c->username = credential_ask_one(c, 0);
 	if (!c->password)
-		c->password = credential_ask_one("Password", c,
-						 PROMPT_ASKPASS);
+		c->password = credential_ask_one(c, 1);
 }
 
 int credential_read(struct credential *c, FILE *fp)
diff --git a/help.c b/help.c
index 973e47cdc30..6eebc26fbeb 100644
--- a/help.c
+++ b/help.c
@@ -644,7 +644,7 @@ const char *help_unknown_cmd(const char *cmd)
 			char *answer;
 			struct strbuf msg = STRBUF_INIT;
 			strbuf_addf(&msg, _("Run '%s' instead? (y/N)"), assumed);
-			answer = git_prompt(msg.buf, PROMPT_ECHO);
+			answer = git_prompt_echo(msg.buf);
 			strbuf_release(&msg);
 			if (!(starts_with(answer, "y") ||
 			      starts_with(answer, "Y")))
diff --git a/prompt-password.c b/prompt-password.c
new file mode 100644
index 00000000000..5fa00363d6c
--- /dev/null
+++ b/prompt-password.c
@@ -0,0 +1,63 @@
+#include "cache.h"
+#include "prompt-password.h"
+#include "strbuf.h"
+#include "run-command.h"
+#include "prompt.h"
+
+static char *do_askpass(const char *cmd, const char *prompt)
+{
+	struct child_process pass = CHILD_PROCESS_INIT;
+	const char *args[3];
+	static struct strbuf buffer = STRBUF_INIT;
+	int err = 0;
+
+	args[0] = cmd;
+	args[1]	= prompt;
+	args[2] = NULL;
+
+	pass.argv = args;
+	pass.out = -1;
+
+	if (start_command(&pass))
+		return NULL;
+
+	strbuf_reset(&buffer);
+	if (strbuf_read(&buffer, pass.out, 20) < 0)
+		err = 1;
+
+	close(pass.out);
+
+	if (finish_command(&pass))
+		err = 1;
+
+	if (err) {
+		error("unable to read askpass response from '%s'", cmd);
+		strbuf_release(&buffer);
+		return NULL;
+	}
+
+	strbuf_setlen(&buffer, strcspn(buffer.buf, "\r\n"));
+
+	return buffer.buf;
+}
+
+char *git_prompt_askpass(const char *prompt)
+{
+	const char *askpass;
+	char *r = NULL;
+
+	askpass = getenv("GIT_ASKPASS");
+	if (!askpass)
+		askpass = askpass_program;
+	if (!askpass)
+		askpass = getenv("SSH_ASKPASS");
+	if (askpass && *askpass)
+		r = do_askpass(askpass, prompt);
+
+	return r;
+}
+
+char *git_prompt_noecho(const char *prompt)
+{
+	return git_prompt(prompt, 0);
+}
diff --git a/prompt-password.h b/prompt-password.h
new file mode 100644
index 00000000000..84933d2b7c5
--- /dev/null
+++ b/prompt-password.h
@@ -0,0 +1,7 @@
+#ifndef PROMPT_PASSWORD_H
+#define PROMPT_PASSWORD_H
+
+char *git_prompt_askpass(const char *prompt);
+char *git_prompt_noecho(const char *prompt);
+
+#endif
diff --git a/prompt.c b/prompt.c
index 5ded21a017f..458d6637506 100644
--- a/prompt.c
+++ b/prompt.c
@@ -1,78 +1,27 @@
 #include "cache.h"
 #include "config.h"
-#include "run-command.h"
 #include "strbuf.h"
 #include "prompt.h"
 #include "compat/terminal.h"
 
-static char *do_askpass(const char *cmd, const char *prompt)
+char *git_prompt(const char *prompt, unsigned int echo)
 {
-	struct child_process pass = CHILD_PROCESS_INIT;
-	const char *args[3];
-	static struct strbuf buffer = STRBUF_INIT;
-	int err = 0;
-
-	args[0] = cmd;
-	args[1]	= prompt;
-	args[2] = NULL;
-
-	pass.argv = args;
-	pass.out = -1;
-
-	if (start_command(&pass))
-		return NULL;
-
-	strbuf_reset(&buffer);
-	if (strbuf_read(&buffer, pass.out, 20) < 0)
-		err = 1;
-
-	close(pass.out);
-
-	if (finish_command(&pass))
-		err = 1;
+	char *r = NULL;
 
-	if (err) {
-		error("unable to read askpass response from '%s'", cmd);
-		strbuf_release(&buffer);
-		return NULL;
+	if (git_env_bool("GIT_TERMINAL_PROMPT", 1)) {
+		r = git_terminal_prompt(prompt, echo);
+		if (!r)
+			die_errno("could not read");
+	} else {
+		die("could not read terminal prompts disabled");
 	}
 
-	strbuf_setlen(&buffer, strcspn(buffer.buf, "\r\n"));
-
-	return buffer.buf;
+	return r;
 }
 
-char *git_prompt(const char *prompt, int flags)
+char *git_prompt_echo(const char *prompt)
 {
-	char *r = NULL;
-
-	if (flags & PROMPT_ASKPASS) {
-		const char *askpass;
-
-		askpass = getenv("GIT_ASKPASS");
-		if (!askpass)
-			askpass = askpass_program;
-		if (!askpass)
-			askpass = getenv("SSH_ASKPASS");
-		if (askpass && *askpass)
-			r = do_askpass(askpass, prompt);
-	}
-
-	if (!r) {
-		const char *err;
-
-		if (git_env_bool("GIT_TERMINAL_PROMPT", 1)) {
-			r = git_terminal_prompt(prompt, flags & PROMPT_ECHO);
-			err = strerror(errno);
-		} else {
-			err = "terminal prompts disabled";
-		}
-		if (!r) {
-			/* prompts already contain ": " at the end */
-			die("could not read %s%s", prompt, err);
-		}
-	}
-	return r;
+	return git_prompt(prompt, 1);
 }
 
 int git_read_line_interactively(struct strbuf *line)
diff --git a/prompt.h b/prompt.h
index e294e93541c..f4d38178bc4 100644
--- a/prompt.h
+++ b/prompt.h
@@ -1,11 +1,8 @@
 #ifndef PROMPT_H
 #define PROMPT_H
 
-#define PROMPT_ASKPASS (1<<0)
-#define PROMPT_ECHO    (1<<1)
-
-char *git_prompt(const char *prompt, int flags);
-
+char *git_prompt(const char *prompt, unsigned int echo);
+char *git_prompt_echo(const char *prompt);
 int git_read_line_interactively(struct strbuf *line);
 
 #endif /* PROMPT_H */
-- 
2.33.1.1570.g069344fdd45


  reply	other threads:[~2021-11-02 16:48 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-20  8:35 Abort (core dumped) Alejandro Sanchez
2019-05-20 10:02 ` Jeff King
2019-05-20 12:06   ` [PATCH 0/4] fix BUG() with "git am -i --resolved" Jeff King
2019-05-20 12:07     ` [PATCH 1/4] am: simplify prompt response handling Jeff King
2019-05-20 12:09     ` [PATCH 2/4] am: read interactive input from stdin Jeff King
2019-05-20 12:11     ` [PATCH 3/4] am: drop tty requirement for --interactive Jeff King
2019-05-20 12:50       ` Jeff King
2019-05-23  6:44         ` Johannes Schindelin
2019-05-24  6:27           ` Jeff King
2021-11-02 16:48             ` [PATCH 0/2] prompt.c: split up git_prompt(), read from /dev/tty, not STDIN Ævar Arnfjörð Bjarmason
2021-11-02 16:48               ` Ævar Arnfjörð Bjarmason [this message]
2021-11-03 11:53                 ` [PATCH 1/2] prompt.c: split up the password and non-password handling Jeff King
2021-11-03 17:28                   ` Junio C Hamano
2021-11-02 16:48               ` [PATCH 2/2] prompt.c: add and use a GIT_TEST_TERMINAL_PROMPT=true Ævar Arnfjörð Bjarmason
2021-11-03 11:57                 ` Jeff King
2021-11-03 15:12                   ` Ævar Arnfjörð Bjarmason
2021-11-04  9:58                     ` Jeff King
2021-11-03 17:42                   ` Junio C Hamano
2021-11-04  8:48                     ` Johannes Schindelin
2021-11-04  9:47                       ` Jeff King
2021-11-04  9:53                     ` Jeff King
2019-05-20 12:13     ` [PATCH 4/4] am: fix --interactive HEAD tree resolution Jeff King
2019-05-23  7:12       ` Johannes Schindelin
2019-05-24  6:39         ` Jeff King
2019-05-24  6:46           ` [PATCH v2 " Jeff King
2019-05-28 11:06           ` [PATCH " Johannes Schindelin
2019-05-28 21:35             ` Jeff King
2019-05-29 11:56               ` Johannes Schindelin
2019-09-26 14:20                 ` Alejandro Sanchez
2019-09-26 21:11                   ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=patch-1.2-ce5bea43f03-20211102T155046Z-avarab@gmail.com \
    --to=avarab@gmail.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=asanchez1987@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.