From patchwork Thu Aug 15 13:14:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13764786 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7DA6B19DF74 for ; Thu, 15 Aug 2024 13:14:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727660; cv=none; b=Q9ZJbP6qBVSqRGeWxI9PMbAu79OWKB4rA7GB9Z2zYCHwMX46GG5fJ1EtVgtMkwP+8UeJyNqOQBiMQT8UVt6Cx81hPXIsM5eseguMN5DS3naRpZT83rUknwlzM/Zc02vVtvrMAvmucXaaSJmQHT3ElD1vdqUgmC93INkhjbkvYXc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727660; c=relaxed/simple; bh=sipFw1dJc1zbv6tyF/MqIbyJnlnjC/BLxSZ5WN2aGTs=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=r2JZ3Q3VE81xNWSCssDQhDSCsga+AujsCZvJ6VwnvrHAMeqGz3hBrgygKZ/jEIPW9VeibFJO3YGboaKJDfzV7rijYohi69YTxwWJB3sdB4ffmixx69LLc5aGgJTs2YriHzcY5D15ueTX0XhsPuCMgn1x9vYi42YUAdp1DglsHNM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=M4x4N2IM; arc=none smtp.client-ip=209.85.128.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="M4x4N2IM" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-42816ca782dso6022605e9.2 for ; Thu, 15 Aug 2024 06:14:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723727656; x=1724332456; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=6FG3uwywf17nE7MKTAyfOz2NJswUr1C/H8jKjMZ6nbM=; b=M4x4N2IM/BC9HG+0qT9+ydLJuL+vUfek8xPTNnb32HpPzYii49Rk992BPqh70EnOEg vjLcZHWNtY85DZDpsCvdZwV6HFofVysHzK5ZrLSAaBtXJg6yRcJLhFmZcWMJLEX5aAaQ HPjGUloK+mS2JJy0tN0aLfbu2N8Kl+7VAQcvp1nBgc/FJQtz4+wWC/KxlFri7jRnyOOp mriz/9KgaW5st46FO8Af+TklCo36EGl8WDODe3jfkAaHHCWOSDgtG0FVnuSKNFzVV5hN 9OcAfatIwhp6K3WMdJSXy28Ix1JqNkCzU1GsypfpdnjbFsCTsC5qVeKC2QFFURgrbfYt ic+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723727656; x=1724332456; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6FG3uwywf17nE7MKTAyfOz2NJswUr1C/H8jKjMZ6nbM=; b=oIPSo5UFuOdLTQ/ERfuGDzHg4CDl/0XtgVhZ67TUmjjxqN3nFxY4lsG+6s6qciFYTE 0XOBtl+d2VKlleeRdoukxqCHi/ppY/lsJ+qYZwMNIGCv6s1hGkmRpWDTkQUr9pwGMdFE aEA6nZZIlLDoIEaJuVAsvixtccPLOwZABtKm/As/PBI5lxZPLN2oIhG9Jq+t9VvFppqr sFht1ZXuBrVYHw+SMDw/eeF9RW8ZsVe3oWKB9djk2XTqzAByClIOZr68aBrdJg6LxUqF RDIKWg1KimYXqfG8Vrd1CpvTuoymk5AKGmcso2t936/43Y7P407smLlilNRcqz9inNAS 8dIg== X-Gm-Message-State: AOJu0YyM8oYtSWBdKzRJh4xnmyFI2gsypVHg5bcAIMwb0cV9Yzwnv1jh 4oh3t3265ZZ2tyON3mnG/nO+TJhUIg8Kl6JMPWfJK9rKJsjp8RybHT3TRA== X-Google-Smtp-Source: AGHT+IFjIWNi6YwkXeyswpS3VrlGdpzjoEszcKrHNck4Zb9EuL4nd+eHMrAWNI0dSAeYVMBu4D024A== X-Received: by 2002:a5d:456d:0:b0:368:3717:10aa with SMTP id ffacd0b85a97d-37177761400mr3684985f8f.11.1723727656029; Thu, 15 Aug 2024 06:14:16 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3718983a57asm1532642f8f.2.2024.08.15.06.14.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Aug 2024 06:14:15 -0700 (PDT) Message-Id: <9ce5ddadf0bb13229461d67451094a373348771e.1723727653.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Aug 2024 13:14:06 +0000 Subject: [PATCH v2 1/8] git-prompt: use here-doc instead of here-string Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "brian m. carlson" , Avi Halachmi , "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" Here-documend is standard, and works in all shells. Both here-string and here-doc add final newline, which is important in this case, because $output is without final newline, but we do want "read" to succeed on the last line as well. Shells which support here-string: - bash, zsh, mksh, ksh93, yash (non-posix-mode). shells which don't, and got fixed: - ash-derivatives (dash, free/net bsd sh, busybox-ash). - pdksh, openbsd sh. - All Schily Bourne shell variants. Signed-off-by: Avi Halachmi (:avih) --- contrib/completion/git-prompt.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 5330e769a72..ebf2e30d684 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -137,7 +137,9 @@ __git_ps1_show_upstream () upstream_type=svn+git # default upstream type is SVN if available, else git ;; esac - done <<< "$output" + done <<-OUTPUT + $output + OUTPUT # parse configuration values local option From patchwork Thu Aug 15 13:14:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13764787 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4CEDB19DF8C for ; Thu, 15 Aug 2024 13:14:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727661; cv=none; b=hP3iJ0/AOfuO+V1/op/QS76Do5A0GefOTUo3fYIYgegHefkkYELUyOFHubIEr0fqHox3tUh3b+Y29JFGqbMUF0rTAJ4X7oh5Os6jsNlsy++UUvEyTivr5gfaKugEJevmyVVtd4QSGk5iEQg8roTjP091fGDUmsIZHaChhR9ggKY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727661; c=relaxed/simple; bh=PeWD7Xzsyt+Jh9Nqsn4TpYWX2egoJFqBtWAUMS9nZWQ=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=QOKQPbnKZpOvE34caXL0UsHMNSKh7bryInspq1yyBSvAqMGAIb+P7Lyv0Q1KXBjBK51nJa2kVGffEX1sHO4Jxs7mhCg5VNtmx3oFrSnLC6Pz5IlNItYRmTo19HPPKhArwSqAD9NgOoz7vG2TZSLoOm53rA737/lfUiZX4kSQO1M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=jjSLJa8W; arc=none smtp.client-ip=209.85.128.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jjSLJa8W" Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-429e29933aaso5902875e9.0 for ; Thu, 15 Aug 2024 06:14:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723727657; x=1724332457; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=bffUfw/AShNzuPzmr6Fl68h5i7kGOyEHgnQZYZFtG8Q=; b=jjSLJa8WLQXudrgBHXPxSeCfAX6Fav+fA8cChCKVWmSAiGq/duDsbm6FvBLKpQDP6v N1MKLM9AbqlG7CphTzj9vZLya63CUafBv+BaZqvQsbSCG3LiDTT9eUKRq6m1R9iHulPI 7l1WqwsGi1I1w+Sl66qv0CXwtCcoL2RGvZ9ZCEuDUPVHK2EUXHnNj+E3RTukHirZ7uaO ULfxKH2Hc/hFkRIeKrerR/CnWWdFmeIygQARdf1SQS3GFn3pyrLE6NxMKPTkvBvcnVSP vOie0SRA87GRrZEXtNIF77Q0lWc9TXA8MM8RdctSZQIP5NkfP6C1HRmaahKcnWSZq/Ta YPHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723727657; x=1724332457; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bffUfw/AShNzuPzmr6Fl68h5i7kGOyEHgnQZYZFtG8Q=; b=X9H9Cp9xK6QByaIgbyLRtUNrG37j2CyIcxAC3kS9BRxC5guwKRn40M7uGy9/l/PyuO yueV478ByxmjqlSWpY6831RcouUO90y3okUhcOPVLLWwYwTdpvKB0pTcgf253L9MoRuS Oxj6wUrhAnhv+/2eb3adj4ulwFFCKH043DxGllK9FmZzH09788WRVj2yzU9P/GcgmI+R OjiLdxeyHZkI6qVIgpmCGrnGsqeFcfmj0NM7PBkEMm0wjzN7PvPksqfuBZhVmh6+pSqc Ck+dQ9dAKXbC43vrR1yUavWLZWnQEZVUQ6iyFQ7R5t+jygfyOuFXrlsY9tIUxQ3NemqN eypg== X-Gm-Message-State: AOJu0YyBBzG/XnMmGTDtNJfjjxQFff2cBBsXD9o7gnwLfdWzAUoOfLrE 3Fr6JD8BR5ei1jyPE4wrhA6UA/Fsn+t/LT18TKO0hSbHYFWVCS9k0Ch7sA== X-Google-Smtp-Source: AGHT+IEgG8IQrbmwsQAYNToY7AVRpTmLEL+vsE45LEXebX07QUflQXnidlBHocB+I9nWJfmaew5OVQ== X-Received: by 2002:a05:600c:1e23:b0:426:6e86:f82 with SMTP id 5b1f17b1804b1-429dd248517mr41803165e9.22.1723727656894; Thu, 15 Aug 2024 06:14:16 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429e7bfd917sm19737715e9.8.2024.08.15.06.14.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Aug 2024 06:14:16 -0700 (PDT) Message-Id: <680ecb524040c64f886c4e484a64f0d17b512e27.1723727653.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Aug 2024 13:14:07 +0000 Subject: [PATCH v2 2/8] git-prompt: fix uninitialized variable Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "brian m. carlson" , Avi Halachmi , "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" First use is in the form: local var; ...; var=$var$whatever... If the variable was unset (as bash and others do after "local x"), then it would error if set -u is in effect. Also, many shells inherit the existing value after "local var" without init, but in this case it's unlikely to have a prior value. Now we initialize it. (local var= is enough, but local var="" is the custom in this file) Signed-off-by: Avi Halachmi (:avih) --- contrib/completion/git-prompt.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index ebf2e30d684..4cc2cf91bb6 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -116,7 +116,7 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1 __git_ps1_show_upstream () { local key value - local svn_remote svn_url_pattern count n + local svn_remote svn_url_pattern="" count n local upstream_type=git legacy="" verbose="" name="" svn_remote=() From patchwork Thu Aug 15 13:14:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13764788 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 08DC219DF9C for ; Thu, 15 Aug 2024 13:14:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727661; cv=none; b=pZAXmZ5kIVp2g+HlPEFBFhTihkjrZAaNlZytVBpEnh42W0el0JpBmIBuS+7/8hrKcSdJxb3yoVhbRyS2fpoTmXSJ1VSpnForv+QQK5yRhxTlWny6AgWpBaifWbYr9IrxORdllSVpPPc/cJ7U75vmxeckCyE3TG2rxa9hMZpnbNg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727661; c=relaxed/simple; bh=p/jqA9gX8l00DDL8hIGrnZJ3zN3+zLxdtSLBkGRh4Gs=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=TbAxAX6Ei3gycRdK9hjKm8KgOOijep9aJGkmaWywapmzAsX8DZACimLHLbfzKKeLkhIru/C2q/g8FSBZtY0FNJ6PZbmYJwIEBzoyJ7VISfhqbZVYMCWZrvKMTtffW3lPEIgnHKRrTpN4IWavPh+MDyN9io2r4Hf8J5JkS8EtKVc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=EujOy0dK; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="EujOy0dK" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-428243f928cso5977425e9.3 for ; Thu, 15 Aug 2024 06:14:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723727658; x=1724332458; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=scQQcYhZj7QegWybZvw4rIUqVDfa3YFL+8LLt/4ZwzY=; b=EujOy0dKu1yLD2O3sdFCQy7xBrX0nrDPoNzAIHDiInny8pzcPBb25A8ujCH24HAExR peMEUvVyeVD5vXFMZuYqoBGwUidRRiuD2EY8AgjbfSgSFYYbiwBA7bDiyd4P31j0LzrM 8YPEaau12wSrH1N5+67Jhe8FdFmpgdhf1VlemDmeyicagcaA8C9amUKegMplUHgq4WQV dLFMSF8TxBcIKnEPNYPKJF0Yq1YGw8mmzs77JceegjM+g9Mk9hCDR1qW8QFkaDL6nkR1 cJ7Mq1OWWepI17jGvUL7XVFae91Ixz76UXDsuIBXym0vX0gWO8iKCEl6a7NhsSl4zQjF MzNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723727658; x=1724332458; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=scQQcYhZj7QegWybZvw4rIUqVDfa3YFL+8LLt/4ZwzY=; b=H0OkVdLUETO5fDJIM+elJiDf3y3pQR3WU4i48MWS5FOW/IrKh7AH70z4eDqHgOE48l zqoa1Xk230+55gM4busfU+enAYw8ft1zyINTEVbnQr3on640ZpRgPD3ACSFGrJp4x3ew feoN+LOjnvRv8EhC7laSy8f8obN01sFJ5KrrmcbXkkWzyzidpVmABa5PXaUzZNxwytd0 DdVC4bgtcGFVaVON12up0it3T95EoMudbBslSAPHNC6FxE87NDHqMvYprLhxp86v0BAu C7Q9nMa85Hd7EDzznIFOKvbVVwVnI7flwM9yskQ5HWj2Dei7LLvCrjN2ocStvap9IWN/ bBig== X-Gm-Message-State: AOJu0YxXxNSGRbQo0MlJemuIxLGorvJ5SCpzR8lPy8DIXliZDTP2Zk1M J8XKLdL3wrLd1AwOCtidhuJoVHXluyxz1YrJUYTp4G9azFBEZ92kr0W/Sg== X-Google-Smtp-Source: AGHT+IHE8/8vRwv6nudsPW+GO0RLW7aoJkgtVqf5MYnfa6C3Hea5a9oxDu6QLdvAlMuvH4yibpwQ7A== X-Received: by 2002:a05:6000:1b83:b0:368:3789:1a2 with SMTP id ffacd0b85a97d-37177771c37mr3908609f8f.21.1723727657661; Thu, 15 Aug 2024 06:14:17 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429e7df64e5sm19984535e9.28.2024.08.15.06.14.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Aug 2024 06:14:17 -0700 (PDT) Message-Id: <7e994eae7bc3dfa021262410c801ddb124ce24f1.1723727653.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Aug 2024 13:14:08 +0000 Subject: [PATCH v2 3/8] git-prompt: don't use shell arrays Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "brian m. carlson" , Avi Halachmi , "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" Arrays only existed in the svn-upstream code, used to: - Keep a list of svn remotes. - Convert commit msg to array of words, extract the 2nd-to-last word. Except bash/zsh, nearly all shells failed load on syntax errors here. Now: - The svn remotes are a list of newline-terminated values. - The 2nd-to-last word is extracted using standard shell substrings. - All shells can digest the svn-upstream code. While using shell field splitting to extract the word is simple, and doesn't even need non-standard code, e.g. set -- $(git log -1 ...), it would have the same issues as the old array code: it depends on IFS which we don't control, and it's subject to glob-expansion, e.g. if the message happens to include * or **/* (as this commit message just did), then the array could get huge. This was not great. Now it uses standard shell substrings, and we know the exact delimiter to expect, because it's the match from our grep just one line earlier. The new word extraction code also fixes svn-upstream in zsh, because previously it used arr[len-2], but because in zsh, unlike bash, array subscripts are 1-based, it incorrectly extracted the 3rd-to-last word. symptom: missing upstream status in a git-svn repo: u=, u+N-M, etc. The breakage in zsh is surprising, because it was last touched by commit d0583da838 (prompt: fix show upstream with svn and zsh), claiming to fix exactly that. However, it only mentions syntax fixes. It's unclear if behavior was fixed too. But it was broken, now fixed. Note LF=$'\n' and then using $LF instead of $'\n' few times. A future commit will add fallback for shells without $'...', so this would be the only line to touch instead of replacing every $'\n' . Shells which could run the previous array code: - bash Shells which have arrays but were broken anyway: - zsh: 1-based subscript - ksh93: no "local" (the new code can't fix this part...) - mksh, openbsd sh, pdksh: failed load on syntax error: "for ((...))". More shells which Failed to load due to syntax error: - dash, free/net bsd sh, busybox-ash, Schily Bourne shell, yash. Signed-off-by: Avi Halachmi (:avih) --- contrib/completion/git-prompt.sh | 48 ++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 4cc2cf91bb6..75c3a813fda 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -116,10 +116,10 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1 __git_ps1_show_upstream () { local key value - local svn_remote svn_url_pattern="" count n + local svn_remotes="" svn_url_pattern="" count n local upstream_type=git legacy="" verbose="" name="" + local LF=$'\n' - svn_remote=() # get some config options from git-config local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')" while read -r key value; do @@ -132,7 +132,7 @@ __git_ps1_show_upstream () fi ;; svn-remote.*.url) - svn_remote[$((${#svn_remote[@]} + 1))]="$value" + svn_remotes=${svn_remotes}${value}${LF} # URI\nURI\n... svn_url_pattern="$svn_url_pattern\\|$value" upstream_type=svn+git # default upstream type is SVN if available, else git ;; @@ -156,25 +156,37 @@ __git_ps1_show_upstream () case "$upstream_type" in git) upstream_type="@{upstream}" ;; svn*) - # get the upstream from the "git-svn-id: ..." in a commit message - # (git-svn uses essentially the same procedure internally) - local -a svn_upstream - svn_upstream=($(git log --first-parent -1 \ - --grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null)) - if [[ 0 -ne ${#svn_upstream[@]} ]]; then - svn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]} - svn_upstream=${svn_upstream%@*} - local n_stop="${#svn_remote[@]}" - for ((n=1; n <= n_stop; n++)); do - svn_upstream=${svn_upstream#${svn_remote[$n]}} - done + # successful svn-upstream resolution: + # - get the list of configured svn-remotes ($svn_remotes set above) + # - get the last commit which seems from one of our svn-remotes + # - confirm that it is from one of the svn-remotes + # - use $GIT_SVN_ID if set, else "git-svn" - if [[ -z "$svn_upstream" ]]; then + # get upstream from "git-svn-id: UPSTRM@N HASH" in a commit message + # (git-svn uses essentially the same procedure internally) + local svn_upstream="$( + git log --first-parent -1 \ + --grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null + )" + + if [ -n "$svn_upstream" ]; then + # extract the URI, assuming --grep matched the last line + svn_upstream=${svn_upstream##*$LF} # last line + svn_upstream=${svn_upstream#*: } # UPSTRM@N HASH + svn_upstream=${svn_upstream%@*} # UPSTRM + + case ${LF}${svn_remotes} in + *"${LF}${svn_upstream}${LF}"*) + # grep indeed matched the last line - it's our remote # default branch name for checkouts with no layout: upstream_type=${GIT_SVN_ID:-git-svn} - else + ;; + *) + # the commit message includes one of our remotes, but + # it's not at the last line. is $svn_upstream junk? upstream_type=${svn_upstream#/} - fi + ;; + esac elif [[ "svn+git" = "$upstream_type" ]]; then upstream_type="@{upstream}" fi From patchwork Thu Aug 15 13:14:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13764789 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 040EB19E7FA for ; Thu, 15 Aug 2024 13:14:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727662; cv=none; b=PC5ZWOCGRgb3xQM6VwDrk0RTPBw9vrSF/ZU7ZWWiCy7g1jZ/Sw+KwKCKlnpg14+DQt/3IvZ+BaVdnr74BJmt55s3vEPBYN4Lqb2Oy6R01T5wh3mt3tcZ/E7Um8sjMb0VniXAg2NSrpCuvp51xD5nrmkY2JK5NzrmebPcNj1BEu8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727662; c=relaxed/simple; bh=Y/eflf72LHbfyadXjodWb8yDEzd6vBwvAvyrlVdBjOc=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=g2tgO5yFg1THLLt6N7QxWFxlDeLDO6FKcebdUdaid0/YXpm2PjfJrQgTzw31QqCgJILG5Nm8mQmqjTDgj2q3k1tCi2ELs49Ynp8viryBMl2WYEMzXrYHbJe9INZJnFYvSSxAP4pBGBFHdwQBIl2eEEX/I/aeF3/mQ3DZcH19OxI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=an54m3NI; arc=none smtp.client-ip=209.85.128.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="an54m3NI" Received: by mail-wm1-f52.google.com with SMTP id 5b1f17b1804b1-428085a3ad1so6433685e9.1 for ; Thu, 15 Aug 2024 06:14:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723727659; x=1724332459; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=VHG2sFf1oXdGYAQiFJCppD/TIS+KE4TS3ITpeGhcpNk=; b=an54m3NIPmXbWCm99pA057pPeUOIW5yjdkIjCVCn4c+YSq5Y/d8NGl9onr3tDFzY3Q 61mg1p0Mu7N3Q03bI0BnXQCS2IrSdjxaPG8SaGWEeh3RrwQ96KkHhyWz5rd082y5SiiV 4d7gwaHoumdgVRfKS+9c82eYnNxJsGf2yCPi6LvpZd9j0L1sjgh5nVenXisX4RkSs+3z kZnCt4vnsbJ7V78+9NL88I+CxhYons3NLmk6t3EaD/SSo6HEsk9DKpWOmgI6bcKegMVF WyxAx0yzN8AvPEy+7xEkEM8M/9K3VaEXkPueOx4VdpUR/oWzw+C8QGaPDq1EW7vwl9Yr 1evg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723727659; x=1724332459; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VHG2sFf1oXdGYAQiFJCppD/TIS+KE4TS3ITpeGhcpNk=; b=WIhnzNkY5iKp6AZBfWBAOSnpoN/4PBqTiTMUWOv4RHh8ZHACO4q20nL0/fShbNCi9w M1LTuroq4MIYXYpUUK9mxEg40k1eUYSPNg0yoO8aQHuzGFMxigL3+1UKBfarhIdO2pfH EYNvlEttXRsfDGnrtchb7Kgi3+9Re4Ijt/TXofC8n+8uOoMj9Y03K/VpL/tAQixooR3B g7EM1f6JDEeh8JC/bVe9rpC7Idv0bamrOAP004a7XQQTWlV8iZ5aLaqGW6k+VPaSVyna fAlzrLcFS38Cc0GwM/UKh54PDBnxaaYIDkolP25PdoiXgTrs55VAww8nnob6Wf4Md7Dr 4wfw== X-Gm-Message-State: AOJu0YzADeU+gKSuxjD/Uu7hyL5SRbsSW/NUqG+bBGtpe0ry4Prodiz5 YZpAmsAp+dDrII7r7jopCItmdKgMhrePO7mttLdMmFqAeSxNS/XwBOQXfg== X-Google-Smtp-Source: AGHT+IEd+yokNVrGXCNw+GQst608zoKOLRvwde4yytWpwsP9d+Qrfx7K26neDMyqT0la9aRmprkSQA== X-Received: by 2002:a05:600c:1c0a:b0:428:14b6:ce32 with SMTP id 5b1f17b1804b1-429dd23b13cmr38845145e9.9.1723727658491; Thu, 15 Aug 2024 06:14:18 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429e7df6248sm19751965e9.25.2024.08.15.06.14.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Aug 2024 06:14:18 -0700 (PDT) Message-Id: <232340902a1feeafe526528eb88b8d0814d11545.1723727653.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Aug 2024 13:14:09 +0000 Subject: [PATCH v2 4/8] git-prompt: replace [[...]] with standard code Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "brian m. carlson" , Avi Halachmi , "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" The existing [[...]] tests were either already valid as standard [...] tests, or only required minimal retouch: Notes: - [[...]] doesn't do field splitting and glob expansion, so $var or $(cmd...) don't need quoting, but [... does need quotes. - [[ X == Y ]] when Y is a string is same as [ X = Y ], but if Y is a pattern, then we need: case X in Y)... ; esac . - [[ ... && ... ]] was replaced with [ ... ] && [ ... ] . - [[ -o ]] requires [[...]], so put it in "eval" and only eval it in zsh, so other shells would not abort on syntax error (posix says [[ has unspecified results, shells allowed to reject it) - ((x++)) was changed into x=$((x+1)) (yeah, not [[...]] ...) Shells which accepted the previous forms: - bash, zsh, ksh93, mksh, openbsd sh, pdksh. Shells which didn't, and now can process it: - dash, free/net bsd sh, busybox-ash, Schily Bourne sh, yash. Signed-off-by: Avi Halachmi (:avih) --- contrib/completion/git-prompt.sh | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 75c3a813fda..4781261f868 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -126,7 +126,7 @@ __git_ps1_show_upstream () case "$key" in bash.showupstream) GIT_PS1_SHOWUPSTREAM="$value" - if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then + if [ -z "${GIT_PS1_SHOWUPSTREAM}" ]; then p="" return fi @@ -187,14 +187,14 @@ __git_ps1_show_upstream () upstream_type=${svn_upstream#/} ;; esac - elif [[ "svn+git" = "$upstream_type" ]]; then + elif [ "svn+git" = "$upstream_type" ]; then upstream_type="@{upstream}" fi ;; esac # Find how many commits we are ahead/behind our upstream - if [[ -z "$legacy" ]]; then + if [ -z "$legacy" ]; then count="$(git rev-list --count --left-right \ "$upstream_type"...HEAD 2>/dev/null)" else @@ -206,8 +206,8 @@ __git_ps1_show_upstream () for commit in $commits do case "$commit" in - "<"*) ((behind++)) ;; - *) ((ahead++)) ;; + "<"*) behind=$((behind+1)) ;; + *) ahead=$((ahead+1)) ;; esac done count="$behind $ahead" @@ -217,7 +217,7 @@ __git_ps1_show_upstream () fi # calculate the result - if [[ -z "$verbose" ]]; then + if [ -z "$verbose" ]; then case "$count" in "") # no upstream p="" ;; @@ -243,7 +243,7 @@ __git_ps1_show_upstream () *) # diverged from upstream upstream="|u+${count#* }-${count% *}" ;; esac - if [[ -n "$count" && -n "$name" ]]; then + if [ -n "$count" ] && [ -n "$name" ]; then __git_ps1_upstream_name=$(git rev-parse \ --abbrev-ref "$upstream_type" 2>/dev/null) if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then @@ -265,7 +265,7 @@ __git_ps1_show_upstream () # their own color. __git_ps1_colorize_gitstring () { - if [[ -n ${ZSH_VERSION-} ]]; then + if [ -n "${ZSH_VERSION-}" ]; then local c_red='%F{red}' local c_green='%F{green}' local c_lblue='%F{blue}' @@ -417,7 +417,7 @@ __git_ps1 () # incorrect.) # local ps1_expanded=yes - [ -z "${ZSH_VERSION-}" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no + [ -z "${ZSH_VERSION-}" ] || eval '[[ -o PROMPT_SUBST ]]' || ps1_expanded=no [ -z "${BASH_VERSION-}" ] || shopt -q promptvars || ps1_expanded=no local repo_info rev_parse_exit_code @@ -502,11 +502,13 @@ __git_ps1 () return $exit fi - if [[ $head == "ref: "* ]]; then + case $head in + "ref: "*) head="${head#ref: }" - else + ;; + *) head="" - fi + esac ;; *) head="$(git symbolic-ref HEAD 2>/dev/null)" @@ -542,8 +544,8 @@ __git_ps1 () fi local conflict="" # state indicator for unresolved conflicts - if [[ "${GIT_PS1_SHOWCONFLICTSTATE-}" == "yes" ]] && - [[ $(git ls-files --unmerged 2>/dev/null) ]]; then + if [ "${GIT_PS1_SHOWCONFLICTSTATE-}" = "yes" ] && + [ "$(git ls-files --unmerged 2>/dev/null)" ]; then conflict="|CONFLICT" fi From patchwork Thu Aug 15 13:14:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13764790 Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A425419EED2 for ; Thu, 15 Aug 2024 13:14:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727663; cv=none; b=sENrhGO/kFPX3MIbklxMCwLRNrfzCMMBYk5RwBugs46RM/rXYq2zrw1wn622g36mQnAFxyIWekK9oC414SIRTd+cs6Cd41DGONL2ox7e+3af8gpSlkAza+Rq/2SA7yL+O5tAdg/ppbzp7AUuxLekhYf6QItUazqCgDTcAKZk1qY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727663; c=relaxed/simple; bh=6w00k9+c3G9p0OFCKpTfLoJYrHe7xtK6Q68P4pNSGFM=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=hsOywskMWzv8ADp3d+9OCEkjnO7W11zqcPpszpuBMqm60LMJX9O0YYnOKjvFiIHN06Zw3QeozHZYmLIEBY6p1pkoq7JjiKRi7joFltPMBkptg8Du0CKvrLHZ4tQocw1/ZBbvgUPn8/y2t5L8531+cM0YoMKeF0vpN2nkiUE+dD8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=mkAWhc9s; arc=none smtp.client-ip=209.85.221.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mkAWhc9s" Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-369f68f63b1so529482f8f.2 for ; Thu, 15 Aug 2024 06:14:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723727659; x=1724332459; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=mRA+5SmsjtaOpQD+SKfEoxPR3u9Wix32fAl2ggOOZmo=; b=mkAWhc9sGiyg6/c6J71R5QIYSbzjMdp5wsFQ5G7XlKQH7ADHDH5cJKGAAHfyTMt9o+ YyPuuBzMwnkoLfUQ70S02yWDdYjnWeY5ZdVwpf+OAlzISkp6RqG2g9D0j0mqTyFAIM46 IWova5W6xK7NWP9cCh9i8iths1sdRAO/9qgQJV0h7nuh3CG7gy4InjaZbfoiyLMcOM86 jR7ELwpSbFHNEqmUEflw1y4IfyJj4K03WqXZ8NdnVJb4v5Dwx7shRSDCXkImTNOFWRX+ DAo4K0BYQAPFO7LkRdgKwOCY7HRrfd+ijmSDo6bKsEtHTw1FN+VeGQYhPFAyfYa4o5fj XEcg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723727659; x=1724332459; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mRA+5SmsjtaOpQD+SKfEoxPR3u9Wix32fAl2ggOOZmo=; b=WfgoBvh9Kiy3dN+S3E9O6TohGQsSd3/UoTUCD8ZBBGHidxMy7klUKMhAAEpRD1w5fu 5Z7Ti/0S1EhepMVM7R8VwuC0gEYoVufpXxBEOFnZWILhgXkQ+8TDAVOxXedMaWGLpzRV CMZKOloO8uIqY35kRlrsvpPeJZWRODW0fgq/XPj6hxwtHmjjm0AbayYMjZNKW9C6u9Bl 2/Pl4mtQn/scNVK9+cYGuOpFWeLODK290SxpyDL3HC5cYoUYZO1P1ojAeMud5eGKn0ZA i+fy+Zng1pX9b3BPpH21hvKz2sXlvBlat829wmdsO0OQ8IZ4uao3ORxcUDzp2fUfvp3S tfSQ== X-Gm-Message-State: AOJu0YzhWBWjxSDNoovJnvblSbuKZhyZ15hoAsSo3dWcZMMKjkkS2s68 0YLxSA+Xjk9TBrf0bd7zjRahXQIQ0Bcvmr+VZpq4vLL6sFCmP9/Sw1tacw== X-Google-Smtp-Source: AGHT+IFVPmBcSXBMppT2CSsIuTEZxVReGjLIH6TrZIpiwrUymnfj84s7NsRp5d+65h57zyay3Vzhkw== X-Received: by 2002:adf:c784:0:b0:364:6c08:b9b2 with SMTP id ffacd0b85a97d-371778091a3mr4551688f8f.45.1723727659238; Thu, 15 Aug 2024 06:14:19 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429ded29fcfsm49424485e9.20.2024.08.15.06.14.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Aug 2024 06:14:18 -0700 (PDT) Message-Id: <4f77b7eb7f1110e47201b8c97c34a0cbcd14e24f.1723727653.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Aug 2024 13:14:10 +0000 Subject: [PATCH v2 5/8] git-prompt: add some missing quotes Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "brian m. carlson" , Avi Halachmi , "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" The issues which this commit fixes are unlikely to be broken in real life, but the fixes improve correctness, and would prevent bugs in some uncommon cases, such as weird IFS values. Listing some portability guideline here for future reference. I'm leaving it to someone else to decide whether to include it in the file itself, place is as a new file, or not. --------- The command "local" is non standard, but is allowed in this file: - Quote initialization if it can expand (local x="$y"). See below. - Don't assume initial value after "local x". Either initialize it (local x=..), or set before first use (local x;.. x=..; ). (between shells, "local x" can unset x, or inherit it, or do x= ) Other non-standard features beyond "local" are to be avoided. Use the standard "test" - [...] instead of non-standard [[...]] . -------- Quotes (some portability things, but mainly general correctness): Quotes prevent tilde-expansion of some unquoted literal tildes (~). If the expansion is undesirable, quotes would ensure that. Tilds expanded: a=~user:~/ ; echo ~user ~/dir not expanded: t="~"; a=${t}user b=\~foo~; echo "~user" $t/dir But the main reason for quoting is to prevent IFS field splitting (which also coalesces IFS chars) and glob expansion after parameter expansion or command substitution. In _command-arguments_, expanded/substituted values must be quoted: Good: [ "$mode" = yes ]; local s="*" x="$y" e="$?" z="$(cmd ...)" Bad: [ $mode = yes ]; local s=* x=$y e=$? z=$(cmd...) Still in _agumemts_, no need to quote non-expandable values: Good: local x= y=yes; echo OK OK, but not required: local x="" y="yes"; echo "OK" But completely empty (NULL) arguments must be quoted: foo "" is not the same as: foo Assignments in simple commands - with or without an actual command, don't need quoting becase there's no IFS split or glob expansion: Good: s=* a=$b c=$(cmd...)${x# foo }${y- } [cmd ...] It's also OK to use double quotes, but not required. This behavior (no IFS/glob) is called "assignment context", and "local" does not behave with assignment context in some shells, hence we require quotes when using "local" - for compatibility. First value in 'case...' doesn't IFS-split/glob, doesn't need quotes: Good: case * $foo $(cmd...) in ... ; esac identical: case "* $foo $(cmd...)" in ... ; esac Nested quotes in command substitution are fine, often necessary: Good: echo "$(foo... "$x" "$(bar ...)")" Nested quotes in substring ops are legal, and sometimes needed to prevent interpretation as a pattern, but not the most readable: Legal: foo "${x#*"$y" }" Nested quotes in "maybe other value" subst are invalid, unnecessary: Good: local x="${y- }"; foo "${z:+ $a }" Bad: local x="${y-" "}"; foo "${z:+" $a "}" Outer/inner quotes in "maybe other value" have different use cases: "${x-$y}" always one quoted arg: "$x" if x is set, else "$y". ${x+"$x"} one quoted arg "$x" if x is set, else no arg at all. Unquoted $x is similar to the second case, but it would get split into few arguments if it includes any of the IFS chars. Assignments don't need the outer quotes, and the braces delimit the value, so nested quotes can be avoided, for readability: a=$(foo "$x") a=${x#*"$y" } c=${y- }; bar "$a" "$b" "$c" Signed-off-by: Avi Halachmi (:avih) --- contrib/completion/git-prompt.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 4781261f868..5d7f236fe48 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -246,7 +246,7 @@ __git_ps1_show_upstream () if [ -n "$count" ] && [ -n "$name" ]; then __git_ps1_upstream_name=$(git rev-parse \ --abbrev-ref "$upstream_type" 2>/dev/null) - if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then + if [ "$pcmode" = yes ] && [ "$ps1_expanded" = yes ]; then upstream="$upstream \${__git_ps1_upstream_name}" else upstream="$upstream ${__git_ps1_upstream_name}" @@ -278,12 +278,12 @@ __git_ps1_colorize_gitstring () local c_lblue=$'\001\e[1;34m\002' local c_clear=$'\001\e[0m\002' fi - local bad_color=$c_red - local ok_color=$c_green + local bad_color="$c_red" + local ok_color="$c_green" local flags_color="$c_lblue" local branch_color="" - if [ $detached = no ]; then + if [ "$detached" = no ]; then branch_color="$ok_color" else branch_color="$bad_color" @@ -360,7 +360,7 @@ __git_sequencer_status () __git_ps1 () { # preserve exit status - local exit=$? + local exit="$?" local pcmode=no local detached=no local ps1pc_start='\u@\h:\w ' @@ -379,7 +379,7 @@ __git_ps1 () ;; 0|1) printf_format="${1:-$printf_format}" ;; - *) return $exit + *) return "$exit" ;; esac @@ -427,7 +427,7 @@ __git_ps1 () rev_parse_exit_code="$?" if [ -z "$repo_info" ]; then - return $exit + return "$exit" fi local short_sha="" @@ -449,7 +449,7 @@ __git_ps1 () [ "$(git config --bool bash.hideIfPwdIgnored)" != "false" ] && git check-ignore -q . then - return $exit + return "$exit" fi local sparse="" @@ -499,7 +499,7 @@ __git_ps1 () case "$ref_format" in files) if ! __git_eread "$g/HEAD" head; then - return $exit + return "$exit" fi case $head in @@ -597,10 +597,10 @@ __git_ps1 () fi fi - local z="${GIT_PS1_STATESEPARATOR-" "}" + local z="${GIT_PS1_STATESEPARATOR- }" b=${b##refs/heads/} - if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then + if [ "$pcmode" = yes ] && [ "$ps1_expanded" = yes ]; then __git_ps1_branch_name=$b b="\${__git_ps1_branch_name}" fi @@ -612,7 +612,7 @@ __git_ps1 () local f="$h$w$i$s$u$p" local gitstring="$c$b${f:+$z$f}${sparse}$r${upstream}${conflict}" - if [ $pcmode = yes ]; then + if [ "$pcmode" = yes ]; then if [ "${__git_printf_supports_v-}" != yes ]; then gitstring=$(printf -- "$printf_format" "$gitstring") else @@ -623,5 +623,5 @@ __git_ps1 () printf -- "$printf_format" "$gitstring" fi - return $exit + return "$exit" } From patchwork Thu Aug 15 13:14:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13764791 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8B8F719F498 for ; Thu, 15 Aug 2024 13:14:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727664; cv=none; b=btAGd82B99MFRFjO9Xst70PsRYDzB5JUFRYexld3Nt37/nmb1FcaCtpOtel3ErbxYbrKHPWASIXT9Uc0DfFgfz+pwuMHXWsTlaiW9AgGy63bN+hi2BJ1S42YPnthkkeNvYGqlFupVuDUgCWpiCG+Kp6yNqnpWwg15M+5Wfkkezs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727664; c=relaxed/simple; bh=+OzamXJet4poQcDjfbocCqRQTImWRURbURYBdomHj0o=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=ASmFQuFjlFc3zifkHgMHg7+sIZGRCKhocWjcyVK2867iAt0kZWA+cy99SoZwzWqgvsHE/b7k/05BS7H+xIFVRYFzOY2khmvMbXfDfZMm+wSHo2ydLMBQTgeo+hK9j5js0rTsHoSYobq3Bj4pKpzxNECtD6FgKnEEkzqKz+ONapU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QmDDl0q5; arc=none smtp.client-ip=209.85.128.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QmDDl0q5" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-428e0d184b4so5789675e9.2 for ; Thu, 15 Aug 2024 06:14:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723727660; x=1724332460; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=QUEdTvj/rTiuXZmr7VJNrLRqDEkcl3gCFHL3SGDS+Mc=; b=QmDDl0q5RwGPvTWqR6HAwPjIZUTf6gO5QqhboCbq9vwfitdm5ncmWycJw64+nJYICt mv9tfv0m+n4PisDjBHW7CijIx3AypHzSIU1ttPc5BK4TUNzMhG8fzD3q7RjEO18htWKj jrGGMAfyhQ+HsD+a7KIcwfJD/crbdGpa8I2HG78dd+B8a3TeC0JyRuh8him3/KyqQmZr wamjE2BgYtv2OVaET9P1HZGF4WPxYGfUvF0YzYRXeApB0/hVx9AIPpNKdfCx+fb5DQt9 z2IBi8epXvFHch4c5JHUK8XfNRgX4Q7K7KEvoDrTDYspY4geO5OBBPU5Xu3ZLhMqaIRY DTzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723727660; x=1724332460; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QUEdTvj/rTiuXZmr7VJNrLRqDEkcl3gCFHL3SGDS+Mc=; b=EnYzlpb0nVTmIPOOvv/3AOSAa3z0sdx5pqRrUjfnQFKz776aclOUpmoXcdrFKi+0YZ qzYVZtN/eZCDSkopDKbeixnWoa6cuxdUnSlD3oFhSdsjxaZQccgaUD/AfFiVzqo6p+8y R2ouwGGjLsCN/kVYc+RjbddYjVWGNsuYU0GnGqZcraoDbk4J/Gin2o0r1LSvy3XSMSlD MKs6NZ0Ou0bzfKOa5Jd03sOxzNWXPk21wZzm7C+yBY9sjeY18sZ2U0oItQaR0WZxXZaC osJU8gPHfBX2NKO+uah1L+/+GtIVND0uR0pf8bL6i7A17iyZhKJpkTxzANT4lGrWwOP5 oNYg== X-Gm-Message-State: AOJu0YwOp6sWnkVHuxVamiiFidqsStYkL4JJotyuCxLhuoWZT+wANUfh 7MBJE7IDvzliajL6YWN4uWY7L9FUE8cvAWJj1um9mrmEJNBiRhRLGZGE3A== X-Google-Smtp-Source: AGHT+IHiA3lGHKuO+SkA5QX2y5tflX8bK0KOdKjgBAA44Vu+ROlG6WPURl2UPZA9339pNTJxVioaEg== X-Received: by 2002:a5d:6c6e:0:b0:368:4bc0:9211 with SMTP id ffacd0b85a97d-3717778ad57mr4497486f8f.17.1723727660024; Thu, 15 Aug 2024 06:14:20 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429e7e10ddcsm19577055e9.32.2024.08.15.06.14.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Aug 2024 06:14:19 -0700 (PDT) Message-Id: <363b7015763a0203771780d3af63eea903228d43.1723727653.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Aug 2024 13:14:11 +0000 Subject: [PATCH v2 6/8] git-prompt: don't use shell $'...' Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "brian m. carlson" , Avi Halachmi , "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" $'...' is new in POSIX (2024), and some shells support it in recent versions, while others have had it for decades (bash, zsh, ksh93). However, there are still enough shells which don't support it, and it's cheap to use an alternative form which works in all shells, so let's do that instead of dismissing it as "it's compliant". It was agreed to use one form rather than $'...' where supported and fallback otherwise. shells where $'...' works: - bash, zsh, ksh93, mksh, busybox-ash, dash master, free/net bsd sh. shells where it doesn't work, but the new fallback works: - all dash releases (up to 0.5.12), older versions of free/net bsd sh, openbsd sh, pdksh, all Schily Bourne sh variants, yash. Signed-off-by: Avi Halachmi (:avih) --- contrib/completion/git-prompt.sh | 47 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 5d7f236fe48..c3dd38f847c 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -111,6 +111,12 @@ __git_printf_supports_v= printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1 +# like __git_SOH=$'\001' etc but works also in shells without $'...' +eval "$(printf ' + __git_SOH="\001" __git_STX="\002" __git_ESC="\033" + __git_LF="\n" __git_CRLF="\r\n" +')" + # stores the divergence from upstream in $p # used by GIT_PS1_SHOWUPSTREAM __git_ps1_show_upstream () @@ -118,7 +124,7 @@ __git_ps1_show_upstream () local key value local svn_remotes="" svn_url_pattern="" count n local upstream_type=git legacy="" verbose="" name="" - local LF=$'\n' + local LF="$__git_LF" # get some config options from git-config local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')" @@ -271,12 +277,16 @@ __git_ps1_colorize_gitstring () local c_lblue='%F{blue}' local c_clear='%f' else - # Using \001 and \002 around colors is necessary to prevent - # issues with command line editing/browsing/completion! - local c_red=$'\001\e[31m\002' - local c_green=$'\001\e[32m\002' - local c_lblue=$'\001\e[1;34m\002' - local c_clear=$'\001\e[0m\002' + # \001 (SOH) and \002 (STX) are 0-width substring markers + # which bash/readline identify while calculating the prompt + # on-screen width - to exclude 0-screen-width esc sequences. + local c_pre="${__git_SOH}${__git_ESC}[" + local c_post="m${__git_STX}" + + local c_red="${c_pre}31${c_post}" + local c_green="${c_pre}32${c_post}" + local c_lblue="${c_pre}1;34${c_post}" + local c_clear="${c_pre}0${c_post}" fi local bad_color="$c_red" local ok_color="$c_green" @@ -312,7 +322,7 @@ __git_ps1_colorize_gitstring () # variable, in that order. __git_eread () { - test -r "$1" && IFS=$'\r\n' read -r "$2" <"$1" + test -r "$1" && IFS=$__git_CRLF read -r "$2" <"$1" } # see if a cherry-pick or revert is in progress, if the user has committed a @@ -430,19 +440,20 @@ __git_ps1 () return "$exit" fi + local LF="$__git_LF" local short_sha="" if [ "$rev_parse_exit_code" = "0" ]; then - short_sha="${repo_info##*$'\n'}" - repo_info="${repo_info%$'\n'*}" + short_sha="${repo_info##*$LF}" + repo_info="${repo_info%$LF*}" fi - local ref_format="${repo_info##*$'\n'}" - repo_info="${repo_info%$'\n'*}" - local inside_worktree="${repo_info##*$'\n'}" - repo_info="${repo_info%$'\n'*}" - local bare_repo="${repo_info##*$'\n'}" - repo_info="${repo_info%$'\n'*}" - local inside_gitdir="${repo_info##*$'\n'}" - local g="${repo_info%$'\n'*}" + local ref_format="${repo_info##*$LF}" + repo_info="${repo_info%$LF*}" + local inside_worktree="${repo_info##*$LF}" + repo_info="${repo_info%$LF*}" + local bare_repo="${repo_info##*$LF}" + repo_info="${repo_info%$LF*}" + local inside_gitdir="${repo_info##*$LF}" + local g="${repo_info%$LF*}" if [ "true" = "$inside_worktree" ] && [ -n "${GIT_PS1_HIDE_IF_PWD_IGNORED-}" ] && From patchwork Thu Aug 15 13:14:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13764792 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7C76419FA90 for ; Thu, 15 Aug 2024 13:14:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727665; cv=none; b=dA2d36fUb55f3nnLCiLS9b1kmSA2RNl4bLd6zuzb1riYInxvhgSZeCHRa0fkSW789HiQ6RZMVKYgwYZB0GxruXWbMsfVv5+pOarrvqQU/AWogxavYlyZiEzyOqJeAwiZ73nrC75yK9yUhvt4YaHEEXSW1qVJOXG2jdUj+q5pW2E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727665; c=relaxed/simple; bh=gH9B24is8SQhLK5rY5yQAUkz/w2jM26CevbBiWLH/tg=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=azvI1lfPcOG4gNsWgBNb6gGsF2UKOSJYq7TTqkQu6OEmZAccWbY3A+piXvS7bZx/ycNhbPq38p8oUVCJZlqcQgMWEhErsgxMh4JWDuuQ+CiiGeejQP2i2AZRuL2UEUi1Hzhlw+z3RwDkEG+qtPPIhyy4g+NuoBbX9dgEIq/mf9I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Kl7+CDAb; arc=none smtp.client-ip=209.85.221.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Kl7+CDAb" Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-367963ea053so604860f8f.2 for ; Thu, 15 Aug 2024 06:14:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723727661; x=1724332461; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=LhSnxW7lIJKEstF6VbFlbb1yLro61xm8GM1hpiBvOns=; b=Kl7+CDAbyI9FZYWuRwlcrJmre9tHACJruFHHVdwyfwkucVirKRUyQmA6AYOqPcLc6H 0tcyvBhEA5na9RDZkRDs68uOgKXcTYqhsAdm2dpUT3hLKifrootqvyvsy/1QN1TZdfZc tEyHgnus28BbfBoFvGuEYENfZg3Nj0USsP9dJOtzL5/02CcydWXxy0EHUiLsJK5mU58M oCdDGL3EPQIdi+RQXblUyr7l5KgW90CXJkzW6rJPUYxwPoal2W5mhL5d6G6VnGxFN0Ja SeG0CnfzcVryO5cYWMRLVlPHRiJBCmPBmNBg8lI7+MuD03vK71qctaz4KUxvdvngrV1X O8og== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723727661; x=1724332461; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LhSnxW7lIJKEstF6VbFlbb1yLro61xm8GM1hpiBvOns=; b=ur02GEfs8SlAydlh7LsWfPmR5r6mkTmPA/r+Zl5lMCavhE1rob8xBeosYUSe0RaBOx V0+Tpz6NDEB9s8YOqu7amMqu5cp8ylqCF3YjRn71BY/ou83n+0dFbnEBOlVOYYl7DQHl QH9717V4dxftxHauIc92tHEgU3lxOPFdsFzhpeWdyADwp6DDJqtAwRj5/ic3vq451PR4 MwYSocUK7dEmFhygo2sbbojOf5rrhC1gWBiCi9O6rLQx4L8wHuV3bQmimZsURvKWzBpV KsT+5y2tD4PNs8I+XT6BCOk54W+sSPwTxoxqcLZSrjgA2sT/hhNfIz7lzY3+qZ2HE6zM nxqA== X-Gm-Message-State: AOJu0Yyk1AcMQrviAvP0yq2qjNoGGfHVu5YT30ouYHTkTh/aOQ8bKTLg yYW1jRzKR6grWZ9xB3pXmuWnlOxAFeQzbiNzjR/awwQZOEQWKk4zq8PYRA== X-Google-Smtp-Source: AGHT+IHsz8xU0v6CcH/0t2G3IE6k9swL5PevBFIM5B/jGLmyYMEEQY3tTu2SP1Uh3WCiLJ1RLH2ngA== X-Received: by 2002:a5d:6248:0:b0:368:7943:8b1f with SMTP id ffacd0b85a97d-371777e1238mr5457057f8f.43.1723727660843; Thu, 15 Aug 2024 06:14:20 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-37189897066sm1522752f8f.76.2024.08.15.06.14.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Aug 2024 06:14:20 -0700 (PDT) Message-Id: <4aa75cdb5dddca0fa2a4817e856d26f724cb43eb.1723727653.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 15 Aug 2024 13:14:12 +0000 Subject: [PATCH v2 7/8] git-prompt: ta-da! document usage in other shells Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "brian m. carlson" , Avi Halachmi , "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" With one big exception, git-prompt.sh should now be both almost posix compliant, and also compatible with most (posix-ish) shells. That exception is the use of "local" vars in functions, which happens extensively in the current code, and is not simple to replace with posix compliant code (but also not impossible). Luckily, almost all shells support "local" as used by the current code, with the notable exception of ksh93[u+m], but also the Schily minimal posix sh (pbosh), and yash in posix mode. See assessment below that "local" is likely the only blocker in those. So except mainly ksh93, git-prompt.sh now works in most shells: - bash, zsh, dash since at least 0.5.8, free/net bsd sh, busybox-ash, mksh, openbsd sh, pdksh(!), Schily extended Bourne sh (bosh), yash. which is quite nice. As an anecdote, replacing the 1st line in __git_ps1() (local exit=$?) with these 2 makes it work in all tested shells, even without "local": # handles only 0/1 args for simplicity. needs +5 LOC for any $# __git_e=$?; local exit="$__git_e" 2>/dev/null || {(eval 'local() { export "$@"; }'; __git_ps1 "$@"); return "$__git_e"; } Explanation: If the shell doesn't have the command "local", define our own function "local" which instead does plain (global) assignents. Then use __git_ps1 in a subshell to not clober the caller's vars. This happens to work because currently there are no name conflicts (shadow) at the code, initial value is not assumed (i.e. always doing either 'local x=...' or 'local x;... x=...'), and assigned initial values are quoted (local x="$y"), preventing word split and glob expansion (i.e. assignment context is not assumed). The last two (always init, quote values) seem to be enough to use "local" portably if supported, and otherwise shells indeed differ. Uses "eval", else shells with "local" may reject it during parsing. We don't need "export", but it's smaller than writing our own loop. While cute, this approach is not really sustainable because all the vars become global, which is hard to maintain without conflicts (but hey, it currently has no conflicts - without even trying...). However, regardless of being an anecdote, it provides some support to the assessment that "local" is the only blocker in those shells. Signed-off-by: Avi Halachmi (:avih) --- contrib/completion/git-prompt.sh | 33 ++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index c3dd38f847c..75f272daa21 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -8,8 +8,8 @@ # To enable: # # 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh). -# 2) Add the following line to your .bashrc/.zshrc: -# source ~/.git-prompt.sh +# 2) Add the following line to your .bashrc/.zshrc/.profile: +# . ~/.git-prompt.sh # dot path/to/this-file # 3a) Change your PS1 to call __git_ps1 as # command-substitution: # Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' @@ -30,6 +30,8 @@ # Optionally, you can supply a third argument with a printf # format string to finetune the output of the branch status # +# See notes below about compatibility with other shells. +# # The repository status will be displayed only if you are currently in a # git repository. The %s token is the placeholder for the shown status. # @@ -106,6 +108,33 @@ # directory is set up to be ignored by git, then set # GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the # repository level by setting bash.hideIfPwdIgnored to "false". +# +# Conpatibility with other shells (beyond bash/zsh): +# +# We require posix-ish shell plus "local" support, which is most +# shells (even pdksh), but excluding ksh93 (because no "local"). +# +# Prompt integration might differ between shells, but the gist is +# to load it once on shell init with '. path/to/git-prompt.sh', +# set GIT_PS1* vars once as needed, and either place $(__git_ps1..) +# inside PS1 once (0/1 args), or, before each prompt is displayed, +# call __git_ps1 (2/3 args) which sets PS1 with the status embedded. +# +# Many shells support the 1st method of command substitution, +# though some might need to first enable cmd substitution in PS1. +# +# When using colors, each escape sequence is wrapped between byte +# values 1 and 2 (control chars SOH, STX, respectively), which are +# invisible at the output, but for bash/readline they mark 0-width +# strings (SGR color sequences) when calculating the on-screen +# prompt width, to maintain correct input editing at the prompt. +# +# Currently there's no support for different markers, so if editing +# behaves weird when using colors in __git_ps1, then the solution +# is either to disable colors, or, in some shells which only care +# about the width of the last prompt line (e.g. busybox-ash), +# ensure the git output is not at the last line, maybe like so: +# PS1='\n\w \u@\h$(__git_ps1 " (%s)")\n\$ ' # check whether printf supports -v __git_printf_supports_v= From patchwork Thu Aug 15 13:14:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13764793 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 02B651A01D4 for ; Thu, 15 Aug 2024 13:14:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727666; cv=none; b=nIVDZOXLnLvH3nM+zfVgz/Q+EEX1wtrFXLakGo9pH6ZcvCLRlWr56teych2pVN2Q4Yh+sEvvwnPfX/8/a8NHfvFDJQMaHQnCSHHx4tM/ZxXgSGCQOJgDo3+21v89AsiakXeUO1/gFo24U/cScxhCzTOW3FwtFv2BX5wBdt9NhMc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723727666; c=relaxed/simple; bh=v+jMPc8z8nEbTUtYnZtSs+t993RhPfq1zuufwrejIis=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=TJ0y1CG248cOJwmiGayht9ZCAUkQqfxoTZzc06szhO4zK0akpJeQp4Y1NRyStWN5zrIcayhw/Y1Zf9dHmyxzo0WnA4mzdAVTa9aKWQiGWJLliHyDfI91uEnRGOvrBypGuoYr7Btv2bdz/dPbbpgeVlL3HmcB/9GJete1bAy/dLY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bnOiL2nC; arc=none smtp.client-ip=209.85.128.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bnOiL2nC" Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-42808071810so6053535e9.1 for ; Thu, 15 Aug 2024 06:14:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723727662; x=1724332462; darn=vger.kernel.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=4YF7YjmYcjoTfiyty4/qVcE6d/YtaHOgwJiFDBZrqMM=; b=bnOiL2nCfxwnPXZqNgChKMXf4r7lE2zCCVqoILF87f3xuTlG1we86EAD6NRGorYHzO yxxpd1HthkSNXzwaybDdigGVXDPiBcN+PMLM47MPEbCHsC8rbNC07EcseYhw61h8BAvh oFkQf34CfmcFSRC+VUS1sRzroS0ACOyLi8CGrvmrPTrza/6Vefq+lHiMsVKEfnd98l1a b5iWXsJoLmMcjT87Ci3JJB/P3XMbhMJLA9tb8LEC5/I53DQGx7NljJuBPT65uAnHl1M4 WaGPPk1MuSylOaVr1hm2U9zxIMlMGEpSe38bSfYxoOxQD5NYjlaKCCwj9Q0il5+fRiOw N1vA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723727662; x=1724332462; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4YF7YjmYcjoTfiyty4/qVcE6d/YtaHOgwJiFDBZrqMM=; b=Fdge4Uck66ltad+hgJWvZPA4x8/LuEBDoXVhfs33vYJ0eBC1Dsv5xByRBDabVzI6pB db965NXLcbQ+/7qyP4FQ85i5Kmof2dfu06SgcWNdoo0Dk2tTiqaIo2N6o6QvdkaPQUag 9lJM/WK6IyEyQSDc+uKVgWYIDLMMZHE9PfiWRqVUTUXlvVlf+6JCiL0z0/7fEY5+gEap uG3bVM3/MPKieKXhJxndayQ6GHgiWAiK7V+jqY0uCWEpLBDfbw1e0GpcEPF+YRuhuVYt Gw2H9KKltu+ESLRqo7G1yBOQBPOtE7pSzL7IYcx0bfUjQVJ+iT2gxIjx9F7+elfeucV9 UcbA== X-Gm-Message-State: AOJu0YwWQ8gOuRCeNQhRbVsAwXPzXTEcVC8WZesCe0j97xyukg2qpbQ2 1U58I8lYHZjUgPDTdTzAkcJkbbjv0AXaEf2DMB5hpar859B2RaB+HxMHcA== X-Google-Smtp-Source: AGHT+IEMjZcfhq15pG0YsiZPPLOeFIjQJTcIawrcn1p9MTawwnARjWMc3Zafde7ClFwAdqx+UwtU8g== X-Received: by 2002:a05:600c:4590:b0:428:141b:ddfc with SMTP id 5b1f17b1804b1-429dd2684b0mr47246045e9.31.1723727661517; Thu, 15 Aug 2024 06:14:21 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429ded71dfasm48697895e9.38.2024.08.15.06.14.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Aug 2024 06:14:21 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Thu, 15 Aug 2024 13:14:13 +0000 Subject: [PATCH v2 8/8] git-prompt: support custom 0-width PS1 markers Fcc: Sent Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To: git@vger.kernel.org Cc: "brian m. carlson" , Avi Halachmi , "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" From: "Avi Halachmi (:avih)" When using colors, the shell needs to identify 0-width substrings in PS1 - such as color escape sequences - when calculating the on-screen width of the prompt. Until now, we used the form %F{} in zsh - which it knows is 0-width, or otherwise use standard SGR esc sequences wrapped between byte values 1 and 2 (SOH, STX) as 0-width start/end markers, which bash/readline identify as such. But now that more shells are supported, the standard SGR sequences typically work, but the SOH/STX markers might not be identified. This commit adds support for vars GIT_PS1_COLOR_{PRE,POST} which set custom 0-width markers or disable the markers. Signed-off-by: Avi Halachmi (:avih) --- contrib/completion/git-prompt.sh | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 75f272daa21..5c43981aa11 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -129,11 +129,16 @@ # strings (SGR color sequences) when calculating the on-screen # prompt width, to maintain correct input editing at the prompt. # -# Currently there's no support for different markers, so if editing -# behaves weird when using colors in __git_ps1, then the solution -# is either to disable colors, or, in some shells which only care -# about the width of the last prompt line (e.g. busybox-ash), -# ensure the git output is not at the last line, maybe like so: +# To replace or disable the 0-width markers, set GIT_PS1_COLOR_PRE +# and GIT_PS1_COLOR_POST to other markers, or empty (nul) to not +# use markers. For instance, some shells support '\[' and '\]' as +# start/end markers in PS1 - when invoking __git_ps1 with 3/4 args, +# but it may or may not work in command substitution mode. YMMV. +# +# If the shell doesn't support 0-width markers and editing behaves +# incorrectly when using colors in __git_ps1, then, other than +# disabling color, it might be solved using multi-line prompt, +# where the git status is not at the last line, e.g.: # PS1='\n\w \u@\h$(__git_ps1 " (%s)")\n\$ ' # check whether printf supports -v @@ -309,8 +314,8 @@ __git_ps1_colorize_gitstring () # \001 (SOH) and \002 (STX) are 0-width substring markers # which bash/readline identify while calculating the prompt # on-screen width - to exclude 0-screen-width esc sequences. - local c_pre="${__git_SOH}${__git_ESC}[" - local c_post="m${__git_STX}" + local c_pre="${GIT_PS1_COLOR_PRE-$__git_SOH}${__git_ESC}[" + local c_post="m${GIT_PS1_COLOR_POST-$__git_STX}" local c_red="${c_pre}31${c_post}" local c_green="${c_pre}32${c_post}"