From patchwork Tue Jan 14 18:43:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Linus Arver via GitGitGadget X-Patchwork-Id: 11332745 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 99C3F14B7 for ; Tue, 14 Jan 2020 18:44:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 784E024670 for ; Tue, 14 Jan 2020 18:44:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="l1VqCkXy" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728778AbgANSn7 (ORCPT ); Tue, 14 Jan 2020 13:43:59 -0500 Received: from mail-wr1-f45.google.com ([209.85.221.45]:42088 "EHLO mail-wr1-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728739AbgANSn6 (ORCPT ); Tue, 14 Jan 2020 13:43:58 -0500 Received: by mail-wr1-f45.google.com with SMTP id q6so13198863wro.9 for ; Tue, 14 Jan 2020 10:43:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:mime-version :content-transfer-encoding:fcc:to:cc; bh=Q6kHVjqb6IwM4rsLItSjNPHvIVjXOb5FhwMqk+5KWpQ=; b=l1VqCkXyU3BuPvM6JvsKY60vubiXWeD2QagAa9rp/K3Z645YLi+ZDVDUzmOPxLCIFu 3jiHRO0BXm0m88J+T25G3eM8NL0yWaFVSnvRx6n5MUD0uP6Ri7Xjm/0iTT5VgpT1pXJc /2BAnF/oZ2ZEE3nuZZH300nhfLuoaWLd7AObQyjkCZP4RyMpV7N7Ttk3h9lDq5OXpzwN p8T15eREpZ7tV5BQ8wqEsilD5xIpCy1Juv/tS7dzZSqyjrVfzNnCtCWoczVt8ny3sAaT WqSqGpYVsVj3z8KLVtHWuQ5rN0KqOrB/qiUF6YQbUzsvp0gpXxWFfEYwXAZ5/KgISOYx TkWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:mime-version:content-transfer-encoding:fcc:to:cc; bh=Q6kHVjqb6IwM4rsLItSjNPHvIVjXOb5FhwMqk+5KWpQ=; b=YZlpvrgj6BjER07EnyYaMm3kItfUo0cpf6TQzx6BsxzkFZiR9wMpGhJk4i8evZ6oNH madbn1E1bNNrQpBwmwbOLv0fE+SE1kp18FNc3zhJHO2cy/NEancpxaAIW5rzX/Ebx7xu MOWXA8DA/3IH+LEEBQ0/PiOKR6GqFlbDvDFE1AZGSRN65w/yVp3uLHxeSnB9qb3NA3p2 lRCeIieAxrIALU+3rUK/H0lf7tq7dwCjOYaYuvtHacPi9VJ/WN6HqEihPzrXoH5/6XEQ MZyqilLd0zrpzQJPKX0GgoAxeTxvMui/n/htFGrOhJIpWIXyl4Jh+6bdS3FvfqvbwQjX 96jQ== X-Gm-Message-State: APjAAAWXrRxkVipU6qk+wQpEx8oJzoEVs9glpPQwyTvXJAYSRKN6l5Py 6T69FzCltyUln96+1H57SbyH0CD7 X-Google-Smtp-Source: APXvYqxxB2+Hcr8JS6XGZyUjY/LWA2biRwX3e3DSGvTMOTOgwnUpWeEzsIRVTGb29fvaGCF/Y+PIRQ== X-Received: by 2002:a05:6000:160d:: with SMTP id u13mr27470928wrb.22.1579027436041; Tue, 14 Jan 2020 10:43:56 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id r15sm19712545wmh.21.2020.01.14.10.43.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:43:55 -0800 (PST) Message-Id: In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:44 +0000 Subject: [PATCH v4 01/10] t3701: adjust difffilter test MIME-Version: 1.0 Fcc: Sent To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin In 42f7d45428e (add--interactive: detect bogus diffFilter output, 2018-03-03), we added a test case that verifies that the diffFilter feature complains appropriately when the output is too short. In preparation for the upcoming change where the built-in `add -p` is taught to respect that setting, let's adjust that test a little. The problem is that `echo too-short` is configured as diffFilter, and it does not read the `stdin`. When calling it through `pipe_command()`, it is therefore possible that we try to feed the `diff` to it while it is no longer listening, and we receive a `SIGPIPE`. The Perl code apparently handles this in a way similar to an end-of-file, but taking a step back, we realize that a diffFilter that does not even _look_ at its standard input is very unrealistic. The entire point of this feature is to transform the diff, not to ignore it altogether. So let's modify the test case to reflect that insight: instead of printing some bogus text, let's use a diffFilter that deletes the first line of the diff instead. This still tests for the same thing, but it does not confuse the built-in `add -p` with that `SIGPIPE`. Helped-by: SZEDER Gábor Helped-by: Jeff King Signed-off-by: Johannes Schindelin --- t/t3701-add-interactive.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 12ee321707..ac43f835a5 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -561,7 +561,7 @@ test_expect_success 'detect bogus diffFilter output' ' git reset --hard && echo content >test && - test_config interactive.diffFilter "echo too-short" && + test_config interactive.diffFilter "sed 1d" && printf y >y && test_must_fail force_color git add -p X-Patchwork-Id: 11332747 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 67208921 for ; Tue, 14 Jan 2020 18:44:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4672024673 for ; Tue, 14 Jan 2020 18:44:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YKoT5Yn4" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728794AbgANSoB (ORCPT ); Tue, 14 Jan 2020 13:44:01 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:40343 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728754AbgANSn7 (ORCPT ); Tue, 14 Jan 2020 13:43:59 -0500 Received: by mail-wr1-f67.google.com with SMTP id c14so13257804wrn.7 for ; Tue, 14 Jan 2020 10:43:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=iNgdJu33yWmrC3CO0xyJZ8AewEp6xJw0yMtoc0eSul0=; b=YKoT5Yn4sO8r8YuMcJ1nwFs9atpfkdJwSAGO1Gva7zOT0o9jOTdnDj5G7pum3Q7BwF RBZKSvbcV58qZlewwA68ql+h16SSck464we0+VZAsiN/MEX/Wgtx47AqtP43AEjuuaWA D1gttZAYZEs1WkD2lut6L3Nzr4DFInS2z21xI/bOaOJvDPj0dO/PVoFklSM9nBKdfIc7 XTBjNPh8T0/wtNgA4Gajgno1J1gA1PgdgveiTcK8uOGi5PCInCDBf9nQJizweGaN3Cb6 osCBoatSKpcAGiRCdwB0fN4ZPCwxtr58jem2A5qy+y68x278JFo2e0awSEjkVlTEAgC8 zlog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=iNgdJu33yWmrC3CO0xyJZ8AewEp6xJw0yMtoc0eSul0=; b=bQO3COOFCh/Fg1DHqK7yYNTMbHdKgO0BpwSaHEB80Q6b7YjDQbDXXpM15y3ftadTkC KmhuRds1oK0lOwaIzopsItEnfLGC6nD0juBYsrCJR3sRSLhotgSyEXIYkC4TjcYC1jq0 C6q6gsg89f4qTgox2k3mZf8YFHJqMR8xWEqKSYmMuldufBaIrP+AOXDnfide4IPcYcnp 59OVNq4wvpsv31NAT5OnnqASdrNQKkvP6QnXOC14gnmBDRLAdb88IcleEvzWE6Bx9giF ImVkU6BgOrLjVjb+9N23mGyw+WiWPKHvX4wXAy/wtGw4HGx1A9K4IMTk3ZjDS49xAKET SH0w== X-Gm-Message-State: APjAAAWgmGst/yxfxRzqCIgv5e3cl0ntvkTD5RFR0Da2zz6QXgsCsqsT Hh0oG0pYIAvzdJOAQ70BVAqDg5SO X-Google-Smtp-Source: APXvYqz/BXoO3SUK3pNuT4dB/BaZXVnRsd7tF37Y3p3dMF1ZMIc3IFu7sJT6G2xv7afzbM2H4foUQQ== X-Received: by 2002:adf:d0c1:: with SMTP id z1mr27385784wrh.371.1579027436890; Tue, 14 Jan 2020 10:43:56 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id l3sm18813708wrt.29.2020.01.14.10.43.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:43:56 -0800 (PST) Message-Id: <413a87bd798296844ebec0c1aad579044da56194.1579027433.git.gitgitgadget@gmail.com> In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:45 +0000 Subject: [PATCH v4 02/10] built-in add -p: support interactive.diffFilter Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin The Perl version supports post-processing the colored diff (that is generated in addition to the uncolored diff, intended to offer a prettier user experience) by a command configured via that config setting, and now the built-in version does that, too. Signed-off-by: Johannes Schindelin --- add-interactive.c | 12 ++++++++++++ add-interactive.h | 3 +++ add-patch.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/add-interactive.c b/add-interactive.c index a5bb14f2f4..1786ea29c4 100644 --- a/add-interactive.c +++ b/add-interactive.c @@ -52,6 +52,17 @@ void init_add_i_state(struct add_i_state *s, struct repository *r) diff_get_color(s->use_color, DIFF_FILE_OLD)); init_color(r, s, "new", s->file_new_color, diff_get_color(s->use_color, DIFF_FILE_NEW)); + + FREE_AND_NULL(s->interactive_diff_filter); + git_config_get_string("interactive.difffilter", + &s->interactive_diff_filter); +} + +void clear_add_i_state(struct add_i_state *s) +{ + FREE_AND_NULL(s->interactive_diff_filter); + memset(s, 0, sizeof(*s)); + s->use_color = -1; } /* @@ -1149,6 +1160,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps) strbuf_release(&print_file_item_data.worktree); strbuf_release(&header); prefix_item_list_clear(&commands); + clear_add_i_state(&s); return res; } diff --git a/add-interactive.h b/add-interactive.h index b2f23479c5..46c73867ad 100644 --- a/add-interactive.h +++ b/add-interactive.h @@ -15,9 +15,12 @@ struct add_i_state { char context_color[COLOR_MAXLEN]; char file_old_color[COLOR_MAXLEN]; char file_new_color[COLOR_MAXLEN]; + + char *interactive_diff_filter; }; void init_add_i_state(struct add_i_state *s, struct repository *r); +void clear_add_i_state(struct add_i_state *s); struct repository; struct pathspec; diff --git a/add-patch.c b/add-patch.c index 46c6c183d5..78bde41df0 100644 --- a/add-patch.c +++ b/add-patch.c @@ -398,6 +398,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) if (want_color_fd(1, -1)) { struct child_process colored_cp = CHILD_PROCESS_INIT; + const char *diff_filter = s->s.interactive_diff_filter; setup_child_process(s, &colored_cp, NULL); xsnprintf((char *)args.argv[color_arg_index], 8, "--color"); @@ -407,6 +408,24 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) argv_array_clear(&args); if (res) return error(_("could not parse colored diff")); + + if (diff_filter) { + struct child_process filter_cp = CHILD_PROCESS_INIT; + + setup_child_process(s, &filter_cp, + diff_filter, NULL); + filter_cp.git_cmd = 0; + filter_cp.use_shell = 1; + strbuf_reset(&s->buf); + if (pipe_command(&filter_cp, + colored->buf, colored->len, + &s->buf, colored->len, + NULL, 0) < 0) + return error(_("failed to run '%s'"), + diff_filter); + strbuf_swap(colored, &s->buf); + } + strbuf_complete_line(colored); colored_p = colored->buf; colored_pend = colored_p + colored->len; @@ -531,6 +550,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) colored_pend - colored_p); if (colored_eol) colored_p = colored_eol + 1; + else if (p != pend) + /* colored shorter than non-colored? */ + goto mismatched_output; else colored_p = colored_pend; @@ -555,6 +577,15 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) */ hunk->splittable_into++; + /* non-colored shorter than colored? */ + if (colored_p != colored_pend) { +mismatched_output: + error(_("mismatched output from interactive.diffFilter")); + advise(_("Your filter must maintain a one-to-one correspondence\n" + "between its input and output lines.")); + return -1; + } + return 0; } @@ -1612,6 +1643,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode, parse_diff(&s, ps) < 0) { strbuf_release(&s.plain); strbuf_release(&s.colored); + clear_add_i_state(&s.s); return -1; } @@ -1630,5 +1662,6 @@ int run_add_p(struct repository *r, enum add_p_mode mode, strbuf_release(&s.buf); strbuf_release(&s.plain); strbuf_release(&s.colored); + clear_add_i_state(&s.s); return 0; } From patchwork Tue Jan 14 18:43:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver via GitGitGadget X-Patchwork-Id: 11332759 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9354E921 for ; Tue, 14 Jan 2020 18:44:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 68A8124658 for ; Tue, 14 Jan 2020 18:44:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NFpW6oM/" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728670AbgANSoF (ORCPT ); Tue, 14 Jan 2020 13:44:05 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:42619 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728765AbgANSn7 (ORCPT ); Tue, 14 Jan 2020 13:43:59 -0500 Received: by mail-wr1-f65.google.com with SMTP id q6so13198923wro.9 for ; Tue, 14 Jan 2020 10:43:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=Wts3H8nhhEz2jG17zS1qC1FJL1l+mQIfLvzo4D7CRNg=; b=NFpW6oM/h1wN24Ch8sDQQAVZ7EFWjp9RsdSlIAOAT0/Uex6i9PhRqHU5ibnHHNVgJv XtUn9Nt9oYSCMegn2bc+RK8MfEZHHcYy0C32Y+MAzEUCcQyMgiFT7SG301FvNG3C75NJ F7tb2Ft/YRnn8sJw4R9w1Hig0i9BNfXKl/IXRmB+d4cqg3/B6dgMwoWMZB86a0uzcKMK yl/wvx0QzaKHI5Kg5yYN+z3srxwz2zqf4/ByEUSm29PyqxPUYQ/v654Yfuf3/ODUovJE bqYNCGnrJnaYah6diz8Bk4lzo8XH+AHpa6dioKDs0L4VszQCONQRTanuqtL0tS9Wkj4K XOWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=Wts3H8nhhEz2jG17zS1qC1FJL1l+mQIfLvzo4D7CRNg=; b=lgTMmHxLcFLr1+01T9zjDGfaWMGIDG6i1c/NUX8SmBL/GR1E3+ahyG8SbDbfdZAmeW 2PWNQORz1fecrcQm9/16WqnDFR7P5LI8+DxYxVCRDHJusPlEC694AGHcFxq2rzZYPRx0 Z5Ur7TTB5iAkbeqTnTjJRC0OWSbQVlr8g25My6BTCeoOJku1/pLXcF7Cipd6rfVcmD0R N0UXdHYYTTTjUREQVtdtXEpeuHQv1r4heqI8CsBZNr0KeII21izMkDZ1t2X/yijUw2h6 XywJg5Kj7e/PrauwNE5N6H/P39fLI0Qke8MNgIzE8H1lxYD2ky6rQ8jFV3Rz0RxfneSS hlIg== X-Gm-Message-State: APjAAAWvvX4/ZAIlA53gOEZrd7RjLKKw6CxSbMUrY9wy51wyi7qmV9ll E7ct8PKZryBBRsmZMRgjlF7k/aOu X-Google-Smtp-Source: APXvYqwDH0OhVgKCLUU/AU1Gxb2EYqGDs83c1dtWPdBwXuxRbnCLYawX7+hKLMv//ItLzUTt8ib8Dg== X-Received: by 2002:a5d:5044:: with SMTP id h4mr26067672wrt.4.1579027437599; Tue, 14 Jan 2020 10:43:57 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id d8sm21240953wre.13.2020.01.14.10.43.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:43:57 -0800 (PST) Message-Id: <062c6245477b23b9c13a6324e677e7a2be62dd65.1579027433.git.gitgitgadget@gmail.com> In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:46 +0000 Subject: [PATCH v4 03/10] built-in add -p: handle diff.algorithm Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin The Perl version of `git add -p` reads the config setting `diff.algorithm` and if set, uses it to generate the diff using the specified algorithm. This patch ports that functionality to the C version. Note: just like `git-add--interactive.perl`, we do _not_ respect this config setting in `git add -i`'s `diff` command, but _only_ in the `patch` command. Signed-off-by: Johannes Schindelin --- add-interactive.c | 5 +++++ add-interactive.h | 2 +- add-patch.c | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/add-interactive.c b/add-interactive.c index 1786ea29c4..9e4bcb382c 100644 --- a/add-interactive.c +++ b/add-interactive.c @@ -56,11 +56,16 @@ void init_add_i_state(struct add_i_state *s, struct repository *r) FREE_AND_NULL(s->interactive_diff_filter); git_config_get_string("interactive.difffilter", &s->interactive_diff_filter); + + FREE_AND_NULL(s->interactive_diff_algorithm); + git_config_get_string("diff.algorithm", + &s->interactive_diff_algorithm); } void clear_add_i_state(struct add_i_state *s) { FREE_AND_NULL(s->interactive_diff_filter); + FREE_AND_NULL(s->interactive_diff_algorithm); memset(s, 0, sizeof(*s)); s->use_color = -1; } diff --git a/add-interactive.h b/add-interactive.h index 46c73867ad..923efaf527 100644 --- a/add-interactive.h +++ b/add-interactive.h @@ -16,7 +16,7 @@ struct add_i_state { char file_old_color[COLOR_MAXLEN]; char file_new_color[COLOR_MAXLEN]; - char *interactive_diff_filter; + char *interactive_diff_filter, *interactive_diff_algorithm; }; void init_add_i_state(struct add_i_state *s, struct repository *r); diff --git a/add-patch.c b/add-patch.c index 78bde41df0..8f2ee8688b 100644 --- a/add-patch.c +++ b/add-patch.c @@ -360,6 +360,7 @@ static int is_octal(const char *p, size_t len) static int parse_diff(struct add_p_state *s, const struct pathspec *ps) { struct argv_array args = ARGV_ARRAY_INIT; + const char *diff_algorithm = s->s.interactive_diff_algorithm; struct strbuf *plain = &s->plain, *colored = NULL; struct child_process cp = CHILD_PROCESS_INIT; char *p, *pend, *colored_p = NULL, *colored_pend = NULL, marker = '\0'; @@ -369,6 +370,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) int res; argv_array_pushv(&args, s->mode->diff_cmd); + if (diff_algorithm) + argv_array_pushf(&args, "--diff-algorithm=%s", diff_algorithm); if (s->revision) { struct object_id oid; argv_array_push(&args, From patchwork Tue Jan 14 18:43:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver via GitGitGadget X-Patchwork-Id: 11332763 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2D3C8921 for ; Tue, 14 Jan 2020 18:44:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0BAAE24658 for ; Tue, 14 Jan 2020 18:44:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Bx0SWYgk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728799AbgANSoD (ORCPT ); Tue, 14 Jan 2020 13:44:03 -0500 Received: from mail-wr1-f66.google.com ([209.85.221.66]:36201 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728774AbgANSoA (ORCPT ); Tue, 14 Jan 2020 13:44:00 -0500 Received: by mail-wr1-f66.google.com with SMTP id z3so13268330wru.3 for ; Tue, 14 Jan 2020 10:43:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=SoINhosxY8bQOCleNIF9uXXAb4CbGyczHohOpNqVWPc=; b=Bx0SWYgkLeUeyvxylLXa4/bxK0H3ThHOPQNHZ8bH3+ZBg0vyhMWCtKne3ER2Thiycg v8kMoIkG/YRLAt61hZ2iA6zMYIhAyD6ydjASAp5ek1VDVQphqfjQD3pjpH13jVQH/8Uf z1pvJMAmNFf6+uUWjiKu5wWsRvo0leC+1fPoK6bgsqfz/0HcL4b8gLoIhJbJTYpKbkXM 1bMgbmfUl/lLJlCz2YsAkGhdKOq8kDyPsmetVTx/VWfbozCAhjxUs0b+FwqqEIXYXuRo vnOtsDi1kxJ8CnDjYpdBzTzSi7XeaBmLK2Bl1aocRZDOhY1BaLzyJp67T+lkzojBQBnd jlnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=SoINhosxY8bQOCleNIF9uXXAb4CbGyczHohOpNqVWPc=; b=Sj1BisqYaqjqT8jlR2kCnQfwttGhl9ib7miabO67ZhpXLeqt1Pjm5EfVWIrPebYFym yPetXFttaTgHLUUGOSdsnRNGHNOfFf+SRBMsDkw04B/3cd0AEXL/u48UViVVBSxZlVHX F2PfG4+odJI3OBAcabsIUc9Ztg8oySzFPQz8lEKWvY6njWvzLXK1zszgzruSXpgZ953Y z1ynLOXXdQKxRenGScZsS67ZsISPgmFaCem60+KCPd/QBcWKQdBP8qBmWr7q74AAuW1S OdDQOXgBvGtRBKWAIYWS54lxp2zm0t14ymu6J3W2v6fqpbHI2BEWZMlMnPXSbVyxrw6f gasQ== X-Gm-Message-State: APjAAAWb6VUW0LTocQqpD9BmwJ8DqFXi16pD/xwjkZs0DtHjQxd5hIju urnswgifazM4FkSbu7KRDIsIg5r6 X-Google-Smtp-Source: APXvYqzMEArxym/TFx7SviywV+7HzkXwPXvUb3SUsyaOxgB2bpcPEPjstE6q0SwEyDC7nmuklCFpzw== X-Received: by 2002:adf:d4ca:: with SMTP id w10mr25438598wrk.53.1579027438380; Tue, 14 Jan 2020 10:43:58 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id d16sm22081582wrg.27.2020.01.14.10.43.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:43:57 -0800 (PST) Message-Id: <09a8946303720f8abd168d0590d421c1dbbbd71a.1579027433.git.gitgitgadget@gmail.com> In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:47 +0000 Subject: [PATCH v4 04/10] terminal: make the code of disable_echo() reusable Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin We are about to introduce the function `enable_non_canonical()`, which shares almost the complete code with `disable_echo()`. Let's prepare for that, by refactoring out that shared code. Signed-off-by: Johannes Schindelin --- compat/terminal.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index fa13ee672d..1fb40b3a0a 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -32,7 +32,7 @@ static void restore_term(void) term_fd = -1; } -static int disable_echo(void) +static int disable_bits(tcflag_t bits) { struct termios t; @@ -43,7 +43,7 @@ static int disable_echo(void) old_term = t; sigchain_push_common(restore_term_on_signal); - t.c_lflag &= ~ECHO; + t.c_lflag &= ~bits; if (!tcsetattr(term_fd, TCSAFLUSH, &t)) return 0; @@ -53,6 +53,11 @@ static int disable_echo(void) return -1; } +static int disable_echo(void) +{ + return disable_bits(ECHO); +} + #elif defined(GIT_WINDOWS_NATIVE) #define INPUT_PATH "CONIN$" @@ -72,7 +77,7 @@ static void restore_term(void) hconin = INVALID_HANDLE_VALUE; } -static int disable_echo(void) +static int disable_bits(DWORD bits) { hconin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, @@ -82,7 +87,7 @@ static int disable_echo(void) GetConsoleMode(hconin, &cmode); sigchain_push_common(restore_term_on_signal); - if (!SetConsoleMode(hconin, cmode & (~ENABLE_ECHO_INPUT))) { + if (!SetConsoleMode(hconin, cmode & ~bits)) { CloseHandle(hconin); hconin = INVALID_HANDLE_VALUE; return -1; @@ -91,6 +96,12 @@ static int disable_echo(void) return 0; } +static int disable_echo(void) +{ + return disable_bits(ENABLE_ECHO_INPUT); +} + + #endif #ifndef FORCE_TEXT From patchwork Tue Jan 14 18:43:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver via GitGitGadget X-Patchwork-Id: 11332751 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1DE8313BD for ; Tue, 14 Jan 2020 18:44:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F17D324673 for ; Tue, 14 Jan 2020 18:44:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aiFQaWOl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728809AbgANSoE (ORCPT ); Tue, 14 Jan 2020 13:44:04 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:32814 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727102AbgANSoA (ORCPT ); Tue, 14 Jan 2020 13:44:00 -0500 Received: by mail-wr1-f67.google.com with SMTP id b6so13285183wrq.0 for ; Tue, 14 Jan 2020 10:43:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=Pd7gm9sA8KWwnCXzcqZeBD0/pHyKhrgKove5Fa6H3tg=; b=aiFQaWOlI0osu2RNLcQFNdRRG89HK1dxr9uKI6/ofE7QzcpRqWHs2o5FSVSvG10KuM v+D8A7v3GkMQy0QaYtrDJJEWhF3Moge1Km42TAtLFYO4OyYoe/SEYd9QwHWiNHM5ntwb 5nPf1J6LABCie1jjvMGQ8ouCSa7ArjkUtSBUeb5vc2qJmPFPxyUVxbeBSDnUoj9XHX3n RgWQgNr6ZAwIS8Is+l9BCJ1kQotXC6YVHbSuOBKMxS8FJchTAaOvHTbD8T+KnX3puEeE iKAFrCes3KxgYpJljhaKeNzJxEWy9SfZydiE6Z2Z3WjC5TyuL6lP4pi8qLuXpiDdt7VF zoQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=Pd7gm9sA8KWwnCXzcqZeBD0/pHyKhrgKove5Fa6H3tg=; b=FNRwBGE/WCE6t81SuYi5/cb4H10Bxz5agQowpsBgWt0H5+ntX3Rcuaa1MW5PPJ+jF+ BL4DCxFFMe5dWxwLKNI/Xa1Kqrs5XgezyHkAmtmOx7Z0jgFGndP7WKb2OKxEHZkQF0NP AI6T3ekLxL82cZ0sqs7EZc5eeyIIinG/D+NVzGWCcxB97rh+8AOAu+Gha8aFwwnvxNb3 iaOmqKSsRK/WIZF/SjdUmJGPcswHJ8sD2Xb5H89Jy4xRih1j80808FG74ix8OBfZdeda LWAGWDPrGJ7OLTFN0dFtXyYNQlbZPBLJ3Ar7n3BWRWC4iQ3bmybIBmooIU7OrhZn3fu2 ndMA== X-Gm-Message-State: APjAAAWHGFO8tT7tmi0Okimzwt7iaGpHJyiHkLtf0yE6jvOXkPn60OI+ vG2wxi+5oniOw9vSchBe0ZFu8gNQ X-Google-Smtp-Source: APXvYqzkOL4KEu4g4uEtOAe7YhABiSZ+5vAGnp8kN4+AiRpTHmPvAzDFsIzqHcpYayCHiPmHN/zI3g== X-Received: by 2002:adf:ec41:: with SMTP id w1mr25421419wrn.212.1579027439115; Tue, 14 Jan 2020 10:43:59 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id d8sm20281663wrx.71.2020.01.14.10.43.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:43:58 -0800 (PST) Message-Id: In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:48 +0000 Subject: [PATCH v4 05/10] terminal: accommodate Git for Windows' default terminal Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin Git for Windows' Git Bash runs in MinTTY by default, which does not have a Win32 Console instance, but uses MSYS2 pseudo terminals instead. This is a problem, as Git for Windows does not want to use the MSYS2 emulation layer for Git itself, and therefore has no direct way to interact with that pseudo terminal. As a workaround, use the `stty` utility (which is included in Git for Windows, and which *is* an MSYS2 program, so it knows how to deal with the pseudo terminal). Note: If Git runs in a regular CMD or PowerShell window, there *is* a regular Win32 Console to work with. This is not a problem for the MSYS2 `stty`: it copes with this scenario just fine. Also note that we introduce support for more bits than would be necessary for a mere `disable_echo()` here, in preparation for the upcoming `enable_non_canonical()` function. Signed-off-by: Johannes Schindelin --- compat/terminal.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/compat/terminal.c b/compat/terminal.c index 1fb40b3a0a..16e9949da1 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -2,6 +2,8 @@ #include "compat/terminal.h" #include "sigchain.h" #include "strbuf.h" +#include "run-command.h" +#include "string-list.h" #if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE) @@ -64,11 +66,28 @@ static int disable_echo(void) #define OUTPUT_PATH "CONOUT$" #define FORCE_TEXT "t" +static int use_stty = 1; +static struct string_list stty_restore = STRING_LIST_INIT_DUP; static HANDLE hconin = INVALID_HANDLE_VALUE; static DWORD cmode; static void restore_term(void) { + if (use_stty) { + int i; + struct child_process cp = CHILD_PROCESS_INIT; + + if (stty_restore.nr == 0) + return; + + argv_array_push(&cp.args, "stty"); + for (i = 0; i < stty_restore.nr; i++) + argv_array_push(&cp.args, stty_restore.items[i].string); + run_command(&cp); + string_list_clear(&stty_restore, 0); + return; + } + if (hconin == INVALID_HANDLE_VALUE) return; @@ -79,6 +98,37 @@ static void restore_term(void) static int disable_bits(DWORD bits) { + if (use_stty) { + struct child_process cp = CHILD_PROCESS_INIT; + + argv_array_push(&cp.args, "stty"); + + if (bits & ENABLE_LINE_INPUT) { + string_list_append(&stty_restore, "icanon"); + argv_array_push(&cp.args, "-icanon"); + } + + if (bits & ENABLE_ECHO_INPUT) { + string_list_append(&stty_restore, "echo"); + argv_array_push(&cp.args, "-echo"); + } + + if (bits & ENABLE_PROCESSED_INPUT) { + string_list_append(&stty_restore, "-ignbrk"); + string_list_append(&stty_restore, "intr"); + string_list_append(&stty_restore, "^c"); + argv_array_push(&cp.args, "ignbrk"); + argv_array_push(&cp.args, "intr"); + argv_array_push(&cp.args, ""); + } + + if (run_command(&cp) == 0) + return 0; + + /* `stty` could not be executed; access the Console directly */ + use_stty = 0; + } + hconin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); From patchwork Tue Jan 14 18:43:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver via GitGitGadget X-Patchwork-Id: 11332761 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0E178921 for ; Tue, 14 Jan 2020 18:44:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E139F24676 for ; Tue, 14 Jan 2020 18:44:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aC5LYuk/" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728803AbgANSoD (ORCPT ); Tue, 14 Jan 2020 13:44:03 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:51720 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728787AbgANSoB (ORCPT ); Tue, 14 Jan 2020 13:44:01 -0500 Received: by mail-wm1-f68.google.com with SMTP id d73so15044134wmd.1 for ; Tue, 14 Jan 2020 10:44:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=piNb8ps1Uqk/dtptwShlXphncXbdxXOUBitj8rIWJ6o=; b=aC5LYuk/0hYGsicrYyBsHuPx3FhdZEM9zqUx5LXeYch3R/lG4G3N0RyZC+8xY5TKeq z3mhkQ+VAJH99gKIPj6yKH0WWtN5O0DKRebpW2hH29mBrG7PpxikujYDm87MGYrp3Mah /FVIM/ubPRZl+CPmMTe7EuIJBgIaJUo+2B54erkIwktU8KnPyV07XmQuxDnViPf+fgBD vtHNxezYIcDaCHzA34JL5901DY1hChuz1gzPgZOy8mLWjK8X9Yxob/9t3tbj7ZCd+tzL Td0mM5OQc5QsCKK34W7qAjbhI2oNix7RflodSDBbNiagyWo6YRZ2Ddo7AtnwO1/ziatW UipQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=piNb8ps1Uqk/dtptwShlXphncXbdxXOUBitj8rIWJ6o=; b=niTEXLPVRk1zKIcOnE/vSlCa2GS5iTh5UtTdb9tzNXv4ynnFmZElI53rkm3UxTB6s+ apQ2QjOi7ax1/lKzZR5jzyXMIDATo9a6bbZC1I9Xe6Cz95LKlLz/5kyMHCpQRggRDSTt chOn8sowjBUb7K9KaLWYRwd7qQZ6HIj236l3zjl7fGyCjJepilXdyCUdgbBH1b4yG63e rahCfs0XflOFmnmAJqur2kXIEkhldZyeubpqgK+r2qv6gN1w8nmsGPaHB17AhuBqDTJ+ PCYNeYRo7K8IyA/oOxeejiX0XsgJju8SjDBKG/4x2h4AlpLmCbpNx3QQhocVLN/osPYe dMYA== X-Gm-Message-State: APjAAAXy9WKaTpsivaLCjZAzrk6rQH18zlOCrb0hW8OET9emUKqtsJRs rLXoI1ggpcDZiiS/2hSYlSSxxsQ7 X-Google-Smtp-Source: APXvYqwz1gtx4elFsv5KGLaobfFzQl8ybln6zArtmn6gc/U+bTgppJOZLF/eVMzKPRKNKEB9Le+hiA== X-Received: by 2002:a05:600c:2409:: with SMTP id 9mr27037830wmp.109.1579027439997; Tue, 14 Jan 2020 10:43:59 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id l7sm20978096wrq.61.2020.01.14.10.43.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:43:59 -0800 (PST) Message-Id: <8d9c703f3b02cd784025dec5c0be682ea25811de.1579027433.git.gitgitgadget@gmail.com> In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:49 +0000 Subject: [PATCH v4 06/10] terminal: add a new function to read a single keystroke Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin Typically, input on the command-line is line-based. It is actually not really easy to get single characters (or better put: keystrokes). We provide two implementations here: - One that handles `/dev/tty` based systems as well as native Windows. The former uses the `tcsetattr()` function to put the terminal into "raw mode", which allows us to read individual keystrokes, one by one. The latter uses `stty.exe` to do the same, falling back to direct Win32 Console access. Thanks to the refactoring leading up to this commit, this is a single function, with the platform-specific details hidden away in conditionally-compiled code blocks. - A fall-back which simply punts and reads back an entire line. Note that the function writes the keystroke into an `strbuf` rather than a `char`, in preparation for reading Escape sequences (e.g. when the user hit an arrow key). This is also required for UTF-8 sequences in case the keystroke corresponds to a non-ASCII letter. Signed-off-by: Johannes Schindelin --- compat/terminal.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++ compat/terminal.h | 3 +++ 2 files changed, 58 insertions(+) diff --git a/compat/terminal.c b/compat/terminal.c index 16e9949da1..1b2564042a 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -60,6 +60,11 @@ static int disable_echo(void) return disable_bits(ECHO); } +static int enable_non_canonical(void) +{ + return disable_bits(ICANON | ECHO); +} + #elif defined(GIT_WINDOWS_NATIVE) #define INPUT_PATH "CONIN$" @@ -151,6 +156,10 @@ static int disable_echo(void) return disable_bits(ENABLE_ECHO_INPUT); } +static int enable_non_canonical(void) +{ + return disable_bits(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); +} #endif @@ -198,6 +207,33 @@ char *git_terminal_prompt(const char *prompt, int echo) return buf.buf; } +int read_key_without_echo(struct strbuf *buf) +{ + static int warning_displayed; + int ch; + + if (warning_displayed || enable_non_canonical() < 0) { + if (!warning_displayed) { + warning("reading single keystrokes not supported on " + "this platform; reading line instead"); + warning_displayed = 1; + } + + return strbuf_getline(buf, stdin); + } + + strbuf_reset(buf); + ch = getchar(); + if (ch == EOF) { + restore_term(); + return EOF; + } + + strbuf_addch(buf, ch); + restore_term(); + return 0; +} + #else char *git_terminal_prompt(const char *prompt, int echo) @@ -205,4 +241,23 @@ char *git_terminal_prompt(const char *prompt, int echo) return getpass(prompt); } +int read_key_without_echo(struct strbuf *buf) +{ + static int warning_displayed; + const char *res; + + if (!warning_displayed) { + warning("reading single keystrokes not supported on this " + "platform; reading line instead"); + warning_displayed = 1; + } + + res = getpass(""); + strbuf_reset(buf); + if (!res) + return EOF; + strbuf_addstr(buf, res); + return 0; +} + #endif diff --git a/compat/terminal.h b/compat/terminal.h index 97db7cd69d..a9d52b8464 100644 --- a/compat/terminal.h +++ b/compat/terminal.h @@ -3,4 +3,7 @@ char *git_terminal_prompt(const char *prompt, int echo); +/* Read a single keystroke, without echoing it to the terminal */ +int read_key_without_echo(struct strbuf *buf); + #endif /* COMPAT_TERMINAL_H */ From patchwork Tue Jan 14 18:43:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver via GitGitGadget X-Patchwork-Id: 11332757 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5EC4D14B7 for ; Tue, 14 Jan 2020 18:44:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3D92924673 for ; Tue, 14 Jan 2020 18:44:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bLIwtCJt" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728811AbgANSoE (ORCPT ); Tue, 14 Jan 2020 13:44:04 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:40524 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728739AbgANSoC (ORCPT ); Tue, 14 Jan 2020 13:44:02 -0500 Received: by mail-wm1-f68.google.com with SMTP id t14so14962729wmi.5 for ; Tue, 14 Jan 2020 10:44:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=0phmocog8B6q0Tw8zeYRgiTpc3ndWE2xf19kROVrxLg=; b=bLIwtCJtryDoEOpGYa5F+rLnmmroh9/bMKwY7G0kM8f2jFziMEjCCjgdrbPEWikrwc azfAJzfsXkKx9h/PuigMRnh2TzoARVgTXYoQa84Ci7kSOjKI+Fx3f4j3b367Si3mC3wQ LDxgzLvT4p7aXCODngA4eQhcrt1UKfaLW8jXx6g6Ft4xsvMHVUKqmEnirticNOQIhM2/ szPbb9KFUAvSZjo34VRxS/0UjOL3NhLqFgvcvuM4eL2YHEEjXRSmBZHtBHkvAuOV7wsT pYgMfUsv8p1mxhZXc0jS8CWZrQQu2fOfPmVmmNMnowO2vr9dvKR/iu8FxUiGe/Bt174R HW7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=0phmocog8B6q0Tw8zeYRgiTpc3ndWE2xf19kROVrxLg=; b=B3KxHaVtUNc4/wpIMW3qAehGtCKdVeGzzDeAD1BJUFavdPTz/1f04ntcN2heECKcal HFqFQftnJlywsw+QSSCdn36HBg/RcVGKU01Zy/uhSW6OQYY+vJzPMTRG5qJfV7SbB6QK uM9VvLo8IzpF7pOp8ir4QqiwoKLCTL3Yoe0zwMBUuPwpzsVKZNu3NZEN1v97mtv7KyxO DEiTS8pEt2QSJaYhNMEK2dWYb8JU+tVuPrWphFvvJ3ZW75CG+AA1hzTLaioUPpjS4HlY ronHhICSP3hlc0KA+HVEgZGWxAJ4KG3w3RRpygiUwVlR3A3ibySLdd0oXsEOY0OctdVF mCnQ== X-Gm-Message-State: APjAAAWrp80/89vf2yXe2Wc4mmOtqK8wq1MekrG6baqw/GehIaLcqRHO 0/MWU22LzkDlZ2lDroRijSriHvhk X-Google-Smtp-Source: APXvYqxYoAi0dyBBdsHbQg+w3GAomPShh3Qv32OWvfbhODW3aakRgL5MpEcRT7fXpdtYIaGxNst4Fg== X-Received: by 2002:a7b:cbc8:: with SMTP id n8mr28943902wmi.35.1579027440692; Tue, 14 Jan 2020 10:44:00 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 4sm18824491wmg.22.2020.01.14.10.44.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:44:00 -0800 (PST) Message-Id: <8ed4487ae49f5ff416d0dbcfdb7292056c7e3b85.1579027433.git.gitgitgadget@gmail.com> In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:50 +0000 Subject: [PATCH v4 07/10] built-in add -p: respect the `interactive.singlekey` config setting Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin The Perl version of `git add -p` supports this config setting to allow users to input commands via single characters (as opposed to having to press the key afterwards). This is an opt-in feature because it requires Perl packages (Term::ReadKey and Term::Cap, where it tries to handle an absence of the latter package gracefully) to work. Note that at least on Ubuntu, that Perl package is not installed by default (it needs to be installed via `sudo apt-get install libterm-readkey-perl`), so this feature is probably not used a whole lot. In C, we obviously do not have these packages available, but we just introduced `read_single_keystroke()` that is similar to what Term::ReadKey provides, and we use that here. Signed-off-by: Johannes Schindelin --- add-interactive.c | 2 ++ add-interactive.h | 1 + add-patch.c | 21 +++++++++++++++++---- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/add-interactive.c b/add-interactive.c index 9e4bcb382c..39c3896494 100644 --- a/add-interactive.c +++ b/add-interactive.c @@ -60,6 +60,8 @@ void init_add_i_state(struct add_i_state *s, struct repository *r) FREE_AND_NULL(s->interactive_diff_algorithm); git_config_get_string("diff.algorithm", &s->interactive_diff_algorithm); + + git_config_get_bool("interactive.singlekey", &s->use_single_key); } void clear_add_i_state(struct add_i_state *s) diff --git a/add-interactive.h b/add-interactive.h index 923efaf527..693f125e8e 100644 --- a/add-interactive.h +++ b/add-interactive.h @@ -16,6 +16,7 @@ struct add_i_state { char file_old_color[COLOR_MAXLEN]; char file_new_color[COLOR_MAXLEN]; + int use_single_key; char *interactive_diff_filter, *interactive_diff_algorithm; }; diff --git a/add-patch.c b/add-patch.c index 8f2ee8688b..d8dafa8168 100644 --- a/add-patch.c +++ b/add-patch.c @@ -6,6 +6,7 @@ #include "pathspec.h" #include "color.h" #include "diff.h" +#include "compat/terminal.h" enum prompt_mode_type { PROMPT_MODE_CHANGE = 0, PROMPT_DELETION, PROMPT_HUNK, @@ -1149,14 +1150,27 @@ static int run_apply_check(struct add_p_state *s, return 0; } +static int read_single_character(struct add_p_state *s) +{ + if (s->s.use_single_key) { + int res = read_key_without_echo(&s->answer); + printf("%s\n", res == EOF ? "" : s->answer.buf); + return res; + } + + if (strbuf_getline(&s->answer, stdin) == EOF) + return EOF; + strbuf_trim_trailing_newline(&s->answer); + return 0; +} + static int prompt_yesno(struct add_p_state *s, const char *prompt) { for (;;) { color_fprintf(stdout, s->s.prompt_color, "%s", _(prompt)); fflush(stdout); - if (strbuf_getline(&s->answer, stdin) == EOF) + if (read_single_character(s) == EOF) return -1; - strbuf_trim_trailing_newline(&s->answer); switch (tolower(s->answer.buf[0])) { case 'n': return 0; case 'y': return 1; @@ -1396,9 +1410,8 @@ static int patch_update_file(struct add_p_state *s, _(s->mode->prompt_mode[prompt_mode_type]), s->buf.buf); fflush(stdout); - if (strbuf_getline(&s->answer, stdin) == EOF) + if (read_single_character(s) == EOF) break; - strbuf_trim_trailing_newline(&s->answer); if (!s->answer.len) continue; From patchwork Tue Jan 14 18:43:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver via GitGitGadget X-Patchwork-Id: 11332753 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 208C213BD for ; Tue, 14 Jan 2020 18:44:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F327B24673 for ; Tue, 14 Jan 2020 18:44:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="EcePuJkD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728819AbgANSoG (ORCPT ); Tue, 14 Jan 2020 13:44:06 -0500 Received: from mail-wr1-f47.google.com ([209.85.221.47]:38770 "EHLO mail-wr1-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727083AbgANSoD (ORCPT ); Tue, 14 Jan 2020 13:44:03 -0500 Received: by mail-wr1-f47.google.com with SMTP id y17so13273166wrh.5 for ; Tue, 14 Jan 2020 10:44:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=ocI02bHKxI6bqqVjgkc/ET4PWDrishuZmL3FurmFRns=; b=EcePuJkDO3pTnQgIWlEOZw9xYx8Fyfiofo0GYeCzl5SdrkzyC5BpmTAHKFPP6XOOW2 Ivo8q3fBrs+VE9poX9WWw+BzTMo0FxR3KufA36op+vr+CbFLNGXKD7n43PanrPNoV93s u5bPbyCjO0LlFm8s44PATwsRKCiPdisg59jQA9wUK+7LXnhxwlFmM3GUnBhzXbeaDw07 8FYVpVqd2G74HLtdDDJOUGn8OCwCtA1amvcdq6DuykF07yBdyfjv+HIq6vE27ZluRhqs /i2H3gC0cWr0cTK0XdXgWqVmIWFPsAfd+zqXneoRYM82oyq98fNJGtF5jUwRY2VRog2k i9Xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=ocI02bHKxI6bqqVjgkc/ET4PWDrishuZmL3FurmFRns=; b=mltjC0E/uG97O55DQaG5vXqhLebKd+TJBPVwEDqekdDzfGk5dUxKM3mz3sgY+pU5XA jpp48tkkYUP3nmZo2CxoLUYR52k6VHoDkuD0V2leJ5t2QG5AElP2YOpih2CgeddMtOfQ k/w+8vfRxxCmu4WRcEPsHeMxavSD7ibh/xrYmhG44499CPKNKWeA1YuDrDCU4/ju1Qx/ Fxe0GUuNeAlQwbHU6CWwr+U72hjmhaGM/4n3rvHKoh6SuDwGsiv/h4UlTsNj6vcJFaiz 2JzH8fPd5LuDttAVq94KFXPy4rvztLDu7wOQjcBSthzX4B2YJIhI4AiaAAQnwmLZan+o Xb0w== X-Gm-Message-State: APjAAAXUSAuhDJdR+fACSh88j1+O4VOuNUlajEn28mfn4kI6HK4tgDWs kNSa/81jLRQZ11EUQauAODpAZkPU X-Google-Smtp-Source: APXvYqyV0mBqhgXiWoSRXLP2iYHEWbFv8GYIFPPaIX/kyCdWmd8mbtMRd3VmwIBm7sQupD2JhYNAyg== X-Received: by 2002:adf:ffc5:: with SMTP id x5mr26873959wrs.92.1579027441419; Tue, 14 Jan 2020 10:44:01 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a9sm18971769wmm.15.2020.01.14.10.44.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:44:01 -0800 (PST) Message-Id: In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:51 +0000 Subject: [PATCH v4 08/10] built-in add -p: handle Escape sequences in interactive.singlekey mode Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin This recapitulates part of b5cc003253c8 (add -i: ignore terminal escape sequences, 2011-05-17): add -i: ignore terminal escape sequences On the author's terminal, the up-arrow input sequence is ^[[A, and thus fat-fingering an up-arrow into 'git checkout -p' is quite dangerous: git-add--interactive.perl will ignore the ^[ and [ characters and happily treat A as "discard everything". As a band-aid fix, use Term::Cap to get all terminal capabilities. Then use the heuristic that any capability value that starts with ^[ (i.e., \e in perl) must be a key input sequence. Finally, given an input that starts with ^[, read more characters until we have read a full escape sequence, then return that to the caller. We use a timeout of 0.5 seconds on the subsequent reads to avoid getting stuck if the user actually input a lone ^[. Since none of the currently recognized keys start with ^[, the net result is that the sequence as a whole will be ignored and the help displayed. Note that we leave part for later which uses "Term::Cap to get all terminal capabilities", for several reasons: 1. it is actually not really necessary, as the timeout of 0.5 seconds should be plenty sufficient to catch Escape sequences, 2. it is cleaner to keep the change to special-case Escape sequences separate from the change that reads all terminal capabilities to speed things up, and 3. in practice, relying on the terminal capabilities is a bit overrated, as the information could be incomplete, or plain wrong. For example, in this developer's tmux sessions, the terminal capabilities claim that the "cursor up" sequence is ^[M, but the actual sequence produced by the "cursor up" key is ^[[A. Signed-off-by: Johannes Schindelin --- compat/terminal.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/compat/terminal.c b/compat/terminal.c index 1b2564042a..b7f58d1781 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -161,6 +161,37 @@ static int enable_non_canonical(void) return disable_bits(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); } +/* + * Override `getchar()`, as the default implementation does not use + * `ReadFile()`. + * + * This poses a problem when we want to see whether the standard + * input has more characters, as the default of Git for Windows is to start the + * Bash in a MinTTY, which uses a named pipe to emulate a pty, in which case + * our `poll()` emulation calls `PeekNamedPipe()`, which seems to require + * `ReadFile()` to be called first to work properly (it only reports 0 + * available bytes, otherwise). + * + * So let's just override `getchar()` with a version backed by `ReadFile()` and + * go our merry ways from here. + */ +static int mingw_getchar(void) +{ + DWORD read = 0; + unsigned char ch; + + if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &read, NULL)) + return EOF; + + if (!read) { + error("Unexpected 0 read"); + return EOF; + } + + return ch; +} +#define getchar mingw_getchar + #endif #ifndef FORCE_TEXT @@ -228,8 +259,31 @@ int read_key_without_echo(struct strbuf *buf) restore_term(); return EOF; } - strbuf_addch(buf, ch); + + if (ch == '\033' /* ESC */) { + /* + * We are most likely looking at an Escape sequence. Let's try + * to read more bytes, waiting at most half a second, assuming + * that the sequence is complete if we did not receive any byte + * within that time. + * + * Start by replacing the Escape byte with ^[ */ + strbuf_splice(buf, buf->len - 1, 1, "^[", 2); + + for (;;) { + struct pollfd pfd = { .fd = 0, .events = POLLIN }; + + if (poll(&pfd, 1, 500) < 1) + break; + + ch = getchar(); + if (ch == EOF) + return 0; + strbuf_addch(buf, ch); + } + } + restore_term(); return 0; } From patchwork Tue Jan 14 18:43:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver via GitGitGadget X-Patchwork-Id: 11332765 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2D50E13BD for ; Tue, 14 Jan 2020 18:44:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0267924670 for ; Tue, 14 Jan 2020 18:44:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dxOxFDd0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728826AbgANSoM (ORCPT ); Tue, 14 Jan 2020 13:44:12 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:50531 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728754AbgANSoD (ORCPT ); Tue, 14 Jan 2020 13:44:03 -0500 Received: by mail-wm1-f67.google.com with SMTP id a5so15064884wmb.0 for ; Tue, 14 Jan 2020 10:44:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=aIVFmW+ag61G3qpmr5SfVtnq0Qq3IxumTrYFwfEvO/w=; b=dxOxFDd0Mtxo86n81fXPrBtvaQFWx2lNER/ge5BmMo++OnVVdZjPEkUCtWuRPA8Exw z0fuOqixv4MqDjDqaTe17yC4sUPUm6d6api5dPy4ycA7BW/S7QEEzW9ZHqF/hQmEx+Q6 llUbFADgrJH7cCoaj7w7n5lG0LBptQMHDPZMgCnuxdtlUkzEsR3mwZBo5aGhAXJInXIi ejV1Fyk41qNf0L3TKGRZjUZJZ+dMA1s8woDLXGG53CPIHyTvBOC9FgPpHXzm3bzYUD5P 7pgR4RbPdvRX/FEKzu7+rX6ybOKsgwce2DvXgoy5DqHC0Lc4q6iQV1g93Wy7y0ziDA5N c6TA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=aIVFmW+ag61G3qpmr5SfVtnq0Qq3IxumTrYFwfEvO/w=; b=JwaCjdXWtWtE+n4uYZY9Gm1rM/SE/MbH55jzHEw/x003/NzNI0EyYosZP53YLXCrAb kbufp73BKuBSDK97xmLV+ZKRpRezrInPAhWX8OnEKgVzM03DnwL5uprlTs78urunTfC0 mQ3ZvOd9TGdHolqKojWPy136k+7JE+K0I/ZVw3YS7c1rnt6w+7dq86QwP1+p+KD0Mhcs VzG+kxlhZbJWydrwgt/zlqb6e9axHRrHqmQmDU6g+7EHq5Pw0zLwKj+yU97h/iOsecYY 1iahCnlkBInxXUOZV0vhE28kRa7AeVTx3xfcmwOTgg+bcSUHSig2vXG5yOpIIFANYViq /Mkw== X-Gm-Message-State: APjAAAVYBueEaD2ilU0mi5UupKEQoDJLpHaLTPjGPUFSqXDKNwBHeBis 5XeFM/C+QxKzb9PjImtylJe/Wni0 X-Google-Smtp-Source: APXvYqx5uZDV1xEUnq35z1NPe7pkl1W89erRszM4EsWumt6oFlL2Ip98a7tCBIoIADVICRbJjBMLeA== X-Received: by 2002:a1c:a702:: with SMTP id q2mr29424983wme.6.1579027442125; Tue, 14 Jan 2020 10:44:02 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id p18sm19312772wmg.4.2020.01.14.10.44.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:44:01 -0800 (PST) Message-Id: <80b0f2528d360e11f8eea4ca9ee69d1ed570414b.1579027433.git.gitgitgadget@gmail.com> In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:52 +0000 Subject: [PATCH v4 09/10] built-in add -p: handle Escape sequences more efficiently Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin When `interactive.singlekey = true`, we react immediately to keystrokes, even to Escape sequences (e.g. when pressing a cursor key). The problem with Escape sequences is that we do not really know when they are done, and as a heuristic we poll standard input for half a second to make sure that we got all of it. While waiting half a second is not asking for a whole lot, it can become quite annoying over time, therefore with this patch, we read the terminal capabilities (if available) and extract known Escape sequences from there, then stop polling immediately when we detected that the user pressed a key that generated such a known sequence. This recapitulates the remaining part of b5cc003253c8 (add -i: ignore terminal escape sequences, 2011-05-17). Note: We do *not* query the terminal capabilities directly. That would either require a lot of platform-specific code, or it would require linking to a library such as ncurses. Linking to a library in the built-ins is something we try very hard to avoid (we even kicked the libcurl dependency to a non-built-in remote helper, just to shave off a tiny fraction of a second from Git's startup time). And the platform-specific code would be a maintenance nightmare. Even worse: in Git for Windows' case, we would need to query MSYS2 pseudo terminals, which `git.exe` simply cannot do (because it is intentionally *not* an MSYS2 program). To address this, we simply spawn `infocmp -L -1` and parse its output (which works even in Git for Windows, because that helper is included in the end-user facing installations). This is done only once, as in the Perl version, but it is done only when the first Escape sequence is encountered, not upon startup of `git add -i`; This saves on startup time, yet makes reacting to the first Escape sequence slightly more sluggish. But it allows us to keep the terminal-related code encapsulated in the `compat/terminal.c` file. Signed-off-by: Johannes Schindelin --- compat/terminal.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/compat/terminal.c b/compat/terminal.c index b7f58d1781..35bca03d14 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -4,6 +4,7 @@ #include "strbuf.h" #include "run-command.h" #include "string-list.h" +#include "hashmap.h" #if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE) @@ -238,6 +239,71 @@ char *git_terminal_prompt(const char *prompt, int echo) return buf.buf; } +/* + * The `is_known_escape_sequence()` function returns 1 if the passed string + * corresponds to an Escape sequence that the terminal capabilities contains. + * + * To avoid depending on ncurses or other platform-specific libraries, we rely + * on the presence of the `infocmp` executable to do the job for us (failing + * silently if the program is not available or refused to run). + */ +struct escape_sequence_entry { + struct hashmap_entry entry; + char sequence[FLEX_ARRAY]; +}; + +static int sequence_entry_cmp(const void *hashmap_cmp_fn_data, + const struct escape_sequence_entry *e1, + const struct escape_sequence_entry *e2, + const void *keydata) +{ + return strcmp(e1->sequence, keydata ? keydata : e2->sequence); +} + +static int is_known_escape_sequence(const char *sequence) +{ + static struct hashmap sequences; + static int initialized; + + if (!initialized) { + struct child_process cp = CHILD_PROCESS_INIT; + struct strbuf buf = STRBUF_INIT; + char *p, *eol; + + hashmap_init(&sequences, (hashmap_cmp_fn)sequence_entry_cmp, + NULL, 0); + + argv_array_pushl(&cp.args, "infocmp", "-L", "-1", NULL); + if (pipe_command(&cp, NULL, 0, &buf, 0, NULL, 0)) + strbuf_setlen(&buf, 0); + + for (eol = p = buf.buf; *p; p = eol + 1) { + p = strchr(p, '='); + if (!p) + break; + p++; + eol = strchrnul(p, '\n'); + + if (starts_with(p, "\\E")) { + char *comma = memchr(p, ',', eol - p); + struct escape_sequence_entry *e; + + p[0] = '^'; + p[1] = '['; + FLEX_ALLOC_MEM(e, sequence, p, comma - p); + hashmap_entry_init(&e->entry, + strhash(e->sequence)); + hashmap_add(&sequences, &e->entry); + } + if (!*eol) + break; + } + initialized = 1; + } + + return !!hashmap_get_from_hash(&sequences, strhash(sequence), sequence); +} + int read_key_without_echo(struct strbuf *buf) { static int warning_displayed; @@ -271,7 +337,12 @@ int read_key_without_echo(struct strbuf *buf) * Start by replacing the Escape byte with ^[ */ strbuf_splice(buf, buf->len - 1, 1, "^[", 2); - for (;;) { + /* + * Query the terminal capabilities once about all the Escape + * sequences it knows about, so that we can avoid waiting for + * half a second when we know that the sequence is complete. + */ + while (!is_known_escape_sequence(buf->buf)) { struct pollfd pfd = { .fd = 0, .events = POLLIN }; if (poll(&pfd, 1, 500) < 1) From patchwork Tue Jan 14 18:43:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Arver via GitGitGadget X-Patchwork-Id: 11332755 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A9748921 for ; Tue, 14 Jan 2020 18:44:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 886C824673 for ; Tue, 14 Jan 2020 18:44:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZD15EvVk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728767AbgANSoG (ORCPT ); Tue, 14 Jan 2020 13:44:06 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:53437 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728800AbgANSoE (ORCPT ); Tue, 14 Jan 2020 13:44:04 -0500 Received: by mail-wm1-f68.google.com with SMTP id m24so15040953wmc.3 for ; Tue, 14 Jan 2020 10:44:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=prnawxM73KG9YEc4YMrhTFoFBf5A8wYjttJZSeSVNhc=; b=ZD15EvVkwAdd6BlfHe8AI/KRnmzWGQnJNbkXg5/2XH1hWykgE1kjLt4kIIxOXnU7tg dvCuuYyr0jUZYQo1M6fxjRBjfUjHoZIi3J3i9v4HgPqqpFfQuIiEskI9qb3T4GJltGf/ HLRsnazSoJ/A4Xa5UHDgQEk9tneeW2tzodlKbeHYGACzMe/pAuzKsRfMapa/vhgUfb1L UUHlusmHSQf4coA9XbVPjmxSWKoRBHSbxXATyCpM6drgJhEEqxIzTmcjD/DFWo3ID/Sk FknB9IgD7cFhrnDcyDYmqJEsdwn2lFumYuJBlL8D/CYwVNsucubKwrxDVFiRoKT+gj0E eyxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=prnawxM73KG9YEc4YMrhTFoFBf5A8wYjttJZSeSVNhc=; b=DfITWNH6LRu3oMgVu+RYgh5dbP4nIBgrwOR48gNsuasZO7yHpTjvst2BBsAeMFEnRA +9UMeZ5Gq0ipYs8xbO6BmJPV+ZjStE4TtD5BtaJooFXVDUC6q49oQ0JYCKPfJtkP+RYm radbN15sGli5gBoxocKyQBakypYd4mQuPcnmpR2Yl7Ey5c0bBcFYJ+URPwS0iDLNlC3x 9YH+4//s5YmmnwGMzlIepblevtCs5LNyLffU3BhkJKIfQKxUliDep9fvBkYZOfQOKHmx nV73/hGf2y1MWrliozkb/OVsGIk60CHjH9Sh7UNY5PTIGf5EtpqQGtnfid37pY0dz5x0 06Ag== X-Gm-Message-State: APjAAAVWdPy5ADjn7scCjOMqHX7eGEkCE/+hA/UbbvmX336KVBMJ4zoL fxrsJl3uGLi45+wx0NljcxjyNWyY X-Google-Smtp-Source: APXvYqwYwvKYXqSVqqUD7FVWYzacuf6ITTz03xg5mCm4n+gojanZCgsIcJXNOoNaVJXZGFIxMmwVrQ== X-Received: by 2002:a1c:1f51:: with SMTP id f78mr27651277wmf.60.1579027442875; Tue, 14 Jan 2020 10:44:02 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id t8sm21015337wrp.69.2020.01.14.10.44.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 10:44:02 -0800 (PST) Message-Id: <7ab7ec62d0d67c0adbef54d2a363c77a12d689bc.1579027433.git.gitgitgadget@gmail.com> In-Reply-To: References: From: "Johannes Schindelin via GitGitGadget" Date: Tue, 14 Jan 2020 18:43:53 +0000 Subject: [PATCH v4 10/10] ci: include the built-in `git add -i` in the `linux-gcc` job Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin This job runs the test suite twice, once in regular mode, and once with a whole slew of `GIT_TEST_*` variables set. Now that the built-in version of `git add --interactive` is feature-complete, let's also throw `GIT_TEST_ADD_I_USE_BUILTIN` into that fray. Signed-off-by: Johannes Schindelin --- ci/run-build-and-tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh index ff0ef7f08e..4df54c4efe 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -20,6 +20,7 @@ linux-gcc) export GIT_TEST_OE_DELTA_SIZE=5 export GIT_TEST_COMMIT_GRAPH=1 export GIT_TEST_MULTI_PACK_INDEX=1 + export GIT_TEST_ADD_I_USE_BUILTIN=1 make test ;; linux-gcc-4.8)