From patchwork Tue Jul 23 19:18:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13740303 Received: from mail-ej1-f46.google.com (mail-ej1-f46.google.com [209.85.218.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 32D8D13D504 for ; Tue, 23 Jul 2024 19:18:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762313; cv=none; b=bBXVba65RinKE2GI1tYZMYEcPwR0zwjveLEEXsQ+qaca6ddo4Wn0wbaedgf7TQAgiYuc0u06xdfSvXoZ6Y1WfixRiMZno3bfpQo67Lp1nc/LVlkG9HawuRk0Ef2VjJL7DYArcahqG/QU+un7Nyt0D6iavX3MAA8jTTuw/mk5KK4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762313; c=relaxed/simple; bh=sipFw1dJc1zbv6tyF/MqIbyJnlnjC/BLxSZ5WN2aGTs=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=QT8luX0HcSouJKFSfEz1tPn9Itr49KFmFOm7MUPb5uwPgj4DHVn56T/3oveD+5sPRa9PUEgYjE/NrZiWFEGpEH/psYVCmnXZYqU1cAPxIBII/bx2T1WF3DPbh5Zo+johxw5wBCNboA9UgmjN+M7CYWdAuK6l4jvSFIYmz9QCf3Q= 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=KeHsCvag; arc=none smtp.client-ip=209.85.218.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="KeHsCvag" Received: by mail-ej1-f46.google.com with SMTP id a640c23a62f3a-a79fe8e6282so25363866b.2 for ; Tue, 23 Jul 2024 12:18:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721762310; x=1722367110; 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=KeHsCvagtTKaySFXOp/r61oqpzFK/toNXXKiJpDKqYtRnme5p7Dpm6w3tE6jNI5I3n s/cjXXMRTJKAcm9KzOMK9BkyMbORYeDDNoEGsOTn3KmT+vynLKssEzm/KhwPcJZ3CdQW dBrLyRpK2m7NL2tCxISmF3TspwQ++8cjcNos3QmNc3EfrCHwo90o9G13d9+HUbUDQ+ia yGMpP0NzNdcYsBCB+K6mjEkhQBgZty+6hmGA/0IpbG7q48iO07+Iy0QKNOELl18dwCGg 1jRdMxRBIc7vHBqy0ckMUj1ZhWHhcaVfFHyFUUFd3binURHW+fsykEeACgiJ8RfNDNY1 ccFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721762310; x=1722367110; 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=X/SfIiPZuajmoccGVxqZPmJ1cauZRoWziPw7Oot3k/lkpi2fPiF+sFGZwuAKLiw8HO VbLZnWJ8F5NMI09m32FODX2j0iOTFF+eX5E3YnMwoGdxMd0XpWg4/omyfN8l+uRuq5e2 HzAnII9eXI9MIrfE6cRRfMhW57mX75Q1JewG1VSTjiDO5lwCOiHF+qFWpWaOchE4lxcX +njKGuqtmAPP9pjsRQ7LglSQQeLwVpufqRO/soYWj7gKahlmRadbkE7JhgNcnRxukS1i u6LFVtip7SadcwmRoe4RDyJKaK8RBGoa/zK4eUh1Crq0xxBJJ3Emd0yT7+mdkuP7y/Zn pARQ== X-Gm-Message-State: AOJu0Yz51Sf09A3Aoktf6cRCCFqPymdcRuTgSZKstsb76rixHdEpqAOT uRvDn/9spFECEb+xCN36QEAxcLjmzp8dYgaSVRqAbhbNuUQWwpz88J5LHw== X-Google-Smtp-Source: AGHT+IH+TLo5GcyWN/0gwX6gSBqdDraRISu6/R4J87w8ALklwn3tFMvUOa9ii6F6feghE/qGyC3RWQ== X-Received: by 2002:a17:907:3e1a:b0:a6f:53f9:7974 with SMTP id a640c23a62f3a-a7a4c43d240mr833482566b.52.1721762309790; Tue, 23 Jul 2024 12:18:29 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a7a3c91e052sm567199166b.153.2024.07.23.12.18.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jul 2024 12:18:29 -0700 (PDT) Message-Id: <9ce5ddadf0bb13229461d67451094a373348771e.1721762306.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 23 Jul 2024 19:18:19 +0000 Subject: [PATCH 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: 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 Tue Jul 23 19:18:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13740304 Received: from mail-lj1-f182.google.com (mail-lj1-f182.google.com [209.85.208.182]) (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 EEE5513DDD5 for ; Tue, 23 Jul 2024 19:18:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762314; cv=none; b=UBB0k2Odvd4jhY9SOJtI8lglvCsY+GlpeAtW4HcskJ41G7s+4fSL1iOYHyFoNeVTOtMr2o/CD522ajlkl4yT9vGHXDll4bG0P/16D1txZE0HUBYTS2+oLwkt3NwAmOPRQ+k/p7AiERK7+mB1p9LuADd27cc3GwPQ0A+d4aLkLRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762314; c=relaxed/simple; bh=PeWD7Xzsyt+Jh9Nqsn4TpYWX2egoJFqBtWAUMS9nZWQ=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=i9NImjmSEfNH/Fue0vlqcnL8fM3xNqUosqfkyVN4vfDsOe8k8LeRQtm05klfpRFiPZl+WqUgMqnr1t9mNE09hIk8pak4domTU9oE/M9wZ6LLTj88tsUB8eLMnpp+YHxhlLE9e3uYpHlJsKTIrX39TNPE6ydba6SiULywijHBD7s= 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=hp0Pa4yH; arc=none smtp.client-ip=209.85.208.182 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="hp0Pa4yH" Received: by mail-lj1-f182.google.com with SMTP id 38308e7fff4ca-2ebe40673e8so73369221fa.3 for ; Tue, 23 Jul 2024 12:18:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721762311; x=1722367111; 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=hp0Pa4yHSLEeCP9BYy9sukoNb6RGfkb8RI+GU+AlI6SMMEvIMAki7csgyrlayMrNwI SLfQd+3iMq4gcnxnlXd6argTb+E9ggvCaunarkHXbg9WVcv/XYqPf5uNfVRsksKYQmXe OUjOhMTTnjcn4G8Y5yVgHUNsRhB421x2whlf/xs/3K061F2ibSxM1xD9R84i71brfjDV Z84Iy47HN6YOVaNLW+Baq+3Sc5HMxMACYcXC/NP6OT0i/uzQQI/9svpnmMFL57TYLGis CMJuYXgKudW+6wFAWlZCBXEJAnQxrnmf5AEAhDcJ7PBJCdbXoOqEwu6sF/FkhF0DSdS6 gRLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721762311; x=1722367111; 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=hjA+b6Gv82LX2S+zRa2EdULdjQ+dEBmuHHN+8ev4HApf7gXL7bncpgJ627W0alvhfX L+WJ/cmtWduwkf3TPXk76XVPBX57gRbGZLACJ5zwohbMOWgrMVf0ezpQTp04jmV/CVs/ 3IjEjMX3CoF6HJK0WK2+B7JpYrhDTip55GScmVUr+UHNGuv1un8pmgFj2GQQ93EdvItT atMSG66lojAkBsRCEkDGeTsZ0lL+ezZu30NfTX3/oeCpf/My3JJ33sUGyTFT1pbNI5ey oYOfRwHlq/owCoMJlEpSWrTku7v2GBWzLQbrsblyDeUd7Dd6DQ519TD/6jw3w7Gn175p 2yYQ== X-Gm-Message-State: AOJu0YwJVO3K7TclYv46LlEh0NEVG91WOG47nVepcor61Yk938IfP+eT h8avwIKu19g0piC4zAJzLtCVdQLF/i/TkwEZpgluYPYAvRMOMy1LYvc22A== X-Google-Smtp-Source: AGHT+IFlfxB+74NEDyc3d4YpbJbAEoa5fBrOYjysV/DH5RZ7+iIDRrgRPMPzJZLeoUX9/oG4Pkg4YA== X-Received: by 2002:a2e:9198:0:b0:2ef:265e:bb93 with SMTP id 38308e7fff4ca-2f02b6f52eamr6065991fa.3.1721762310665; Tue, 23 Jul 2024 12:18:30 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5a30a4d7575sm7912214a12.14.2024.07.23.12.18.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jul 2024 12:18:30 -0700 (PDT) Message-Id: <680ecb524040c64f886c4e484a64f0d17b512e27.1721762306.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 23 Jul 2024 19:18:20 +0000 Subject: [PATCH 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: 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 Tue Jul 23 19:18:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13740306 Received: from mail-lf1-f49.google.com (mail-lf1-f49.google.com [209.85.167.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 B292114264C for ; Tue, 23 Jul 2024 19:18:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762317; cv=none; b=lN5rUai8lymLEiKlG5Gd7LYGLX/hKV7RnFCSa1jLAAfDWUNLv06+UBgcYEPI5OqJwhKBmVPqGlfRK90Rd3nZpiZvccmhwZoj2ccS9p+J0DJeztFA1Qim2XqZU8cXE5netjuAA/2VYktY+cQDYcnXEwtnjbQCxsQVWg13qxVaAbQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762317; c=relaxed/simple; bh=p/jqA9gX8l00DDL8hIGrnZJ3zN3+zLxdtSLBkGRh4Gs=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=cPiKQv1stkY1YIxb+tHSNEKvxVp5Z3xdcL1ZOG73l7USGI+pZ7wVJASml03st26RXOmrbjUgLta+dQ+UgeJHM7i4sIINPjDObj0TcNIVUvqGW/BhKoMJXbEGThOCwkGq44NrtijcXYt/qEATNKb2hIV1BWrv/FiuKFa2tJ8FRRI= 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=gVnt1fiL; arc=none smtp.client-ip=209.85.167.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="gVnt1fiL" Received: by mail-lf1-f49.google.com with SMTP id 2adb3069b0e04-52efd08e6d9so4579706e87.1 for ; Tue, 23 Jul 2024 12:18:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721762313; x=1722367113; 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=gVnt1fiLvRMGJe535JK925/d330qNRvLb4pEdA2utmkdkF+pHmffawbxYrd58wyfE0 K0ZeoHQdvQhHWBY48ejGmocBRjaVBOxxnluF5rjbKTb1DrvBAAIsg1AIlTN6R+ZE0nnV REAgmwKypenGinoObXVZbrfrJu20F/r2sjPAPQNZPFZyzjQts6PTSzA/o+/xFUZVpsJu w1KVbB3zGMSzrYl8aHrrkx5j+GajWOpeePIGiIK4Cqsvcw5/LWqnGF0O1CUbOSRicZYo czBQXS3xOCJcgdKjnx41knaGQZcoZnke4sothn11ofgy9gddPZYX+pycNbAzNBJdZTL2 Aw0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721762313; x=1722367113; 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=lpPrhxGEuLZbOwvP2aiXLzlSPTkaF0wzh2+dnzr/6LYVfflMBu8ypb5faxpwHwwHu4 eDrsuzN9pfNytT2oK5RLgnUB2jSYGwTwGcmkbwCkQDWU6pC7HJEleluQxwcwX6HQdSeq kijjiarCy5QGxLxyR0yaOp537a6j8+8grvC5gmqslL74/aEqDPu1AYbMzouNoko5un67 2BkgiA1k7A/vwpW80u5hhNMcM8n3NeTZr3EJVm9rU65cKGhg4OgMWsHTBDYB/pjHac4Z /0VDOWsznNBWhUh2eDGdXzhx0KjW2ptpFUQV9fUQtmYniqCUWJhEjuKv/T8yorhemXkm fGBg== X-Gm-Message-State: AOJu0YwIOBlNGrP7QiGxev0foLFkM1gKjWrPtraZFDJ+jQYZLdWK3M2e 5IrjXYqTRb1hBLdpU5jbEauskzyxzg9mV1dbvHfMlhX3Q34dJpXHvGIM3A== X-Google-Smtp-Source: AGHT+IFL3M1kQRpNAQJp37uQp6vCqY+qJEzy6UrWZ9heXxr4Tj/Z9v9JFEU8QrVJD7nzx/cME/YIXA== X-Received: by 2002:a05:6512:23a3:b0:52e:9619:e26a with SMTP id 2adb3069b0e04-52fc404ba59mr2951510e87.26.1721762313033; Tue, 23 Jul 2024 12:18:33 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a7aa8d8d0cesm31538666b.138.2024.07.23.12.18.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jul 2024 12:18:32 -0700 (PDT) Message-Id: <7e994eae7bc3dfa021262410c801ddb124ce24f1.1721762306.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 23 Jul 2024 19:18:21 +0000 Subject: [PATCH 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: 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 Tue Jul 23 19:18:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13740307 Received: from mail-ej1-f52.google.com (mail-ej1-f52.google.com [209.85.218.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 3E86413DDC6 for ; Tue, 23 Jul 2024 19:18:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762317; cv=none; b=Bcgj3Li73ZU4Fkh8cQ0lmMzhL0xqgbCc1I4p0cAPjI6Jxl1cR8FYiUro8Ca09IBTM1ixedl6AF/fSTZYnuGv3AgiLv8ArtNSRWU7eEEZskfwrxLZMo0YxHeb3F+Idkkv67bIErAajJH8VMngPNEu7jgZLcMKVFguJxix2VPSp4g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762317; c=relaxed/simple; bh=Y/eflf72LHbfyadXjodWb8yDEzd6vBwvAvyrlVdBjOc=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=NxGuG7U3ss0agTTpYvmprmka0jPpkwj1wLj45bj+/iqRnCs2mVmJhcCoSrZWkEaXcRjJ6TXgX2Ocu2HixfpsT2GOQIkGfT8cLB/DYOssp5QYUMLkR7IOTnNG8vDVAOp6YI50qKllR/fd4JyDe7VbZvP0uWVNPvylWXYDzXh6j8s= 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=NPrqLVV5; arc=none smtp.client-ip=209.85.218.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="NPrqLVV5" Received: by mail-ej1-f52.google.com with SMTP id a640c23a62f3a-a7aa4ca9d72so33156666b.0 for ; Tue, 23 Jul 2024 12:18:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721762314; x=1722367114; 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=NPrqLVV56Y11fQ8hwubKi9QJQ5h/8de2zfwyaU9VlM9hKxeVNmJtpuE5wOCOUekq67 DhMps+NBGP0apgU1LvCI1NC+FBzpwmzW1xbaLiLxqQfH3AKueZLbdNmzfmwf6cyj6IVX 5/u68GknDa5NbE0bBcIgTbDw/wPS8Rtf8P0oXIAz7ZMuLBuRt3b1TCm6CEbldsqctU74 3EwA1kU+p2aw9/cZ9gXwnf3/7LHpjr544nUQfBNqhR3excq7lWYRLmyTeghZXzZh397/ hHkHtE1Txc8TgQHwpL02hWhNajqMYN7a9z4eqJyqXbIRjGHcYTeiKWYKHpwxdkF5xbfF lBmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721762314; x=1722367114; 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=DTtNTXJ4v/ZcqotI8lgWJFG91G40IyLIXce2koa/C78tfuIuq4bNRqbk279lvcFZpf GJjpbpAo6Enomi39j1TCNzpU4z44qrW21D5O75G09b1Ckm1UBvNvx+2HOtEmmRLpYi18 42X2DVb9Sbuq7fMh/X2g/bxUzPencVQxzbhrPT4CFelZIgI++ZK9S7hdXcRUzVEXlyVT bL/5mF9NamRCT7/IklaDUbOG+knkq50tWlfWo2YngK6z3AjtiG7t33x6dyTY4g5dOu8T KiKIpFKnSLYAsRejTBKBr7mXm2a83yBrVohYdoffA5XvvXVkwVlek+EjdJcApZsanbjI MdeQ== X-Gm-Message-State: AOJu0Yyx/gfK2WrNl81dAB7tDlq/w+m8/NDbD46yCXDOvaOQ9s8Jj+3b IhsApxcWN0g+04RKS0Jdbe3AhUE1bljijC/QXCQkQJtjrXRZymni/IDdPg== X-Google-Smtp-Source: AGHT+IENQsD1QnAF8VZBpDVAmM4fitwG22Qlepc1OAP4uYlyuYrwInheTh9u2u8IkFjqiZ3AuVjNig== X-Received: by 2002:a17:907:1b22:b0:a7a:9f0f:ab2b with SMTP id a640c23a62f3a-a7a9f0fb5e5mr190115666b.32.1721762313906; Tue, 23 Jul 2024 12:18:33 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a7aaa7a4a76sm24137866b.96.2024.07.23.12.18.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jul 2024 12:18:33 -0700 (PDT) Message-Id: <232340902a1feeafe526528eb88b8d0814d11545.1721762306.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 23 Jul 2024 19:18:22 +0000 Subject: [PATCH 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: 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 Tue Jul 23 19:18:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13740308 Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) (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 1FB7E13DDD5 for ; Tue, 23 Jul 2024 19:18:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762319; cv=none; b=QFcMgZ0jjaCAg1Tb1OKl8bE5xVbT5w5ux9berqrchHfSwxtd2FQo1nCGlnlYn1L0K0gOeIrb6/tFdXKzAAIZKZhL7U8zpIAO+VW+6Zwi6VCmxKCbgA0OSeJARGuYMGJvgFdQAyz6DIoKxkPHFUHfQ64g+O1Y/IC0fwwSLNgTpoQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762319; c=relaxed/simple; bh=6w00k9+c3G9p0OFCKpTfLoJYrHe7xtK6Q68P4pNSGFM=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=JxNLVEmgA7rqDq6y4HG80L/ceeMMkSQJKMkuT5Up3Fq4SKBdtrOCDF+cmkhUzWTnWAtIbGdcaMpqI8+19XF4lFSv2KI/CP/vHhMdnOaVpqGoYDIWumeYwzvSd4XZHigLMg/H0RtM//GwtUvOMCx8nCI43V9d/gcwwhgSwnnH02k= 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=XaGbrvRM; arc=none smtp.client-ip=209.85.208.44 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="XaGbrvRM" Received: by mail-ed1-f44.google.com with SMTP id 4fb4d7f45d1cf-5a309d1a788so5207199a12.3 for ; Tue, 23 Jul 2024 12:18:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721762315; x=1722367115; 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=XaGbrvRMuIsjcj7jbDcpJwUI1yFLNGHFjgYbg9T1bcTwjWs9iVVbpVinBehyKk958A N0b18DxPYtQeRgHmYZQO4zfdlxUM7PdKelM4a4DPqRhpg/n7oLUOnjKCi9YqwJwT0iJK HVnMVLxdOrwxIps7r7C2cBzaaFzpb0rlYsMTEUIKzVWxLgqgtM7el18KHrm/IsQ5PO1v 1Lz1CboNx0lJOm9XpoWDWI0VPy1gK2RGdcNqIB41V4Uo8Ga8zCI4lJ70ZtN7/vNNbZAL iErwt4Q2NZaYg+FUs4HErniz3ikl2L8e+a6K812p8das4kGCRkMKuSBN5FdTnf5V9+Lf XTgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721762315; x=1722367115; 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=sGmMeCOveAmKWMC1G6ed4AhD1mwLm7g0pfWtpp1BuOzoHDzbth3n4NtTY+FE3ry7Zk JwnuzVAu/Z35eLgkqGDmmIwO6rZdWG+X+e/vneclw+Glz0MESwai+QzxaVdBo7ZE44Fp MGV7vb+ODOkjrsjtMg+fAAjmEUsj9UB17yo8VcjtstjO+P4NYfrVZIf6wmhtTUZoEBy3 w2brHNQTEjNtyagwGfC6OIiGYWhhqQn5ac2GPhXzp7/AioK/ZxiulVQDqGNXfCEYmmvL 3p28PqrZt2cxorNOZzHWC7XXYogvLPx8awpvCD4b/eBGaFV99EPQPCgSAZPfxDdAkekV ffYg== X-Gm-Message-State: AOJu0YyF5S7Nfj7hdtfWPtXljE9XM0dTFmp4pni0dVihq0hOAJjl3NQ/ b9XKi33tKB/ORL8ayOgbC0yUcHQOaa7ad9uv3hkYc6MCv16Ndtlsvv2IpA== X-Google-Smtp-Source: AGHT+IHv7RZW/Y0P2jJkEpAWzQxRNZt96rKc9JKeE/KqYEKP3WgD0Ah0kar6PF4RIWrB/EcNhu9b7w== X-Received: by 2002:a50:d6dc:0:b0:5a0:f8a2:9cf5 with SMTP id 4fb4d7f45d1cf-5a3f089d878mr7217660a12.29.1721762314778; Tue, 23 Jul 2024 12:18:34 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5a30a4d6e67sm7920210a12.17.2024.07.23.12.18.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jul 2024 12:18:34 -0700 (PDT) Message-Id: <4f77b7eb7f1110e47201b8c97c34a0cbcd14e24f.1721762306.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 23 Jul 2024 19:18:23 +0000 Subject: [PATCH 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: 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 Tue Jul 23 19:18:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13740309 Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.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 EE7D51428EA for ; Tue, 23 Jul 2024 19:18:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762319; cv=none; b=srkVsr5+7+kr38uwNXZMIT7p8OO/Mog4yETHCaRH3yIyvv747ig6jbB39LJcLFoo1XCW8vJLlBTXHiMIdThfDTcK+Mwt4C8hDH5/3DKVnyC2THAEALr5IIy0WcWoojuM77aqitCNERatv5AzU1fAC+H7znZu2fbTmIhXsPw1qxg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762319; c=relaxed/simple; bh=Q2XHlLPDSA59hcZLR19KMhng2ZRaD9lLdamc7EC/GfY=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=eW0TE63aqmJlXqPugQJUHYtMMgAjc4eV0NPO5MTvbRrp3HR7f5pmvTSs2iWYD7Fxuw0XUaTDTYBp/cSaywq4qRF4HTwJKEplgqarDJydYtc4Tl13woaM1O2bJWVpn525PdNk2jq7vFpNHbEYSOLeGo96HUvZNpHDD4ztr1QOmEs= 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=IYiZ6hzn; arc=none smtp.client-ip=209.85.218.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="IYiZ6hzn" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-a7a9a369055so101080366b.3 for ; Tue, 23 Jul 2024 12:18:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721762315; x=1722367115; 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=U+v+ejSTc6SCQMvsFihFgg/BNnm4VCnNTZNOsUxclIY=; b=IYiZ6hzn4kd2Wd0xtUrgWk6zEtx5K6PXKz7nJrIeysjLGd7FRHty/haosY3OJXt4mE Wb4SeQtTV5annYY/9UcNnZsebzZGG2nuOKeokCr3+6h3dKzYrrOfX1+xxycFEF1Su2TR Nqw00czmFKeqziHEdN5dXvPFExuy0UBV/vJlCiVm8gmVr3JmuJCsYExU6lJKCtKJI23n F6a/HFYprMrWUhVF9qvQvBSlIotZVS8Zo5wHunJU7eJ2p91qx719p9N8swK5fcUc1KdO 1p92L3cjBmMHJWrY5D2usYZVEG/n2+OuJRJEnOJYFCr0nEOgUbywn6wjhXmN1OUGf3Wh HBHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721762315; x=1722367115; 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=U+v+ejSTc6SCQMvsFihFgg/BNnm4VCnNTZNOsUxclIY=; b=ZIzDET3NfSnJxfib3MsefCyYXWZ0JANx4wXw6vaTqSevdNrAwhJUafiuKN0Ai08fmx 8Xh++fK/iLAFrnSzjHPbqdIkM7e/V6GmKtmYEEfEWvQa74pWEoP1cl9q7iCklxR7gzpd bQBy8AvyverhpwxulPdl2ofI2Opz4ejtIdFpSGrQg5o29Epq+7LZcT1raVSh0kImsmzO n+Ea4WRb+MFm3mHoLi1LjV2KLVxNnJ2lcjBExtDa6/ptn/+Jy2nmwXU2uMojCl4KUuAV RD8ljGEgGw6pbzg2JfFMogZX9YOolvVbC5JDXx0qHtCAWL1cxEmL1u06a2rVWIRCnwy6 b/zg== X-Gm-Message-State: AOJu0YyOA/2kF3aob8CZn3IZq7DiutXwlgWmn4m07Ah4be+Tuc5+Mvmz QbihWIlX9vGFPkbhQ1XWlFVrcd96Np3tXT8njTYiiKpXqt2veu4lm7tKdw== X-Google-Smtp-Source: AGHT+IGOmvt+GP8/Q24rPlB36x66ZlbWQyRyoEjAsXChuGSUkdb/h+9qovgcGty2we/nZGYXh4Hc9g== X-Received: by 2002:a17:907:97c4:b0:a79:8149:967a with SMTP id a640c23a62f3a-a7a4c0100c6mr801110066b.16.1721762315522; Tue, 23 Jul 2024 12:18:35 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a7a3c9508d3sm569281866b.204.2024.07.23.12.18.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jul 2024 12:18:35 -0700 (PDT) Message-Id: <1c1b58e20cab6b4989b140282353073165f0067e.1721762306.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 23 Jul 2024 19:18:24 +0000 Subject: [PATCH 6/8] git-prompt: add fallback for shells without $'...' 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: 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 provide a fallback for them, so let's do that instead of dismissing it as "it's compliant". 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 | 52 +++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 5d7f236fe48..bbc16417ac9 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -111,6 +111,17 @@ __git_printf_supports_v= printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1 +__git_SOH=$'\1' __git_STX=$'\2' __git_ESC=$'\33' +__git_LF=$'\n' __git_CRLF=$'\r\n' + +if [ $'\101' != A ]; then # fallback for shells without $'...' + __git_CRLF=$(printf "\r\n\1\2\33") # CR LF SOH STX ESC + __git_ESC=${__git_CRLF#????}; __git_CRLF=${__git_CRLF%?} + __git_STX=${__git_CRLF#???}; __git_CRLF=${__git_CRLF%?} + __git_SOH=${__git_CRLF#??}; __git_CRLF=${__git_CRLF%?} + __git_LF=${__git_CRLF#?} +fi + # stores the divergence from upstream in $p # used by GIT_PS1_SHOWUPSTREAM __git_ps1_show_upstream () @@ -118,7 +129,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 +282,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 +327,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 +445,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 Tue Jul 23 19:18:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13740310 Received: from mail-lj1-f175.google.com (mail-lj1-f175.google.com [209.85.208.175]) (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 BA69C143744 for ; Tue, 23 Jul 2024 19:18:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762321; cv=none; b=l2Pmf5s2GHUozkFUJnKJijvXosUnoJyHDzRH1kyvE4eTA6S95S0Juk6pxFb3PSOfGo0S5l9Xj43NIghoSYjbzJ8XBfJO0sYTzwDXmNeIhtFulgvsP1Uj1AxOp+FAvl65OqjIacUDYz4T9AiDKxSmird3Uefz/Eo44UE/OP7OHKk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762321; c=relaxed/simple; bh=YlO6Rziadwtarg7y+G73ARa7gY76nZonO7yiui1+cWo=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=UUOFiWlx4Btfsf02FaSQ5ns0dKTGefO3nEztOAUzDMVzO1uTVMVe69tjfW9r4tLq8CohTwQW9aTyq9p0lhNNe3CT9o8syseCMFKb4zp7oOpenXR5oFSqXNGBb5tXGBKlfcZuVlaJlBdyx7GEpeXPAUECfOYeJYZdxFBhQNglrE8= 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=ZX8Q9dlT; arc=none smtp.client-ip=209.85.208.175 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="ZX8Q9dlT" Received: by mail-lj1-f175.google.com with SMTP id 38308e7fff4ca-2eeb1ba040aso85027341fa.1 for ; Tue, 23 Jul 2024 12:18:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721762317; x=1722367117; 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=bZu+accr9EvkOwRR3yW09OfJTHbiSshn6eSaoB0Gf6A=; b=ZX8Q9dlTlu4I1/ZiVLbhNBQrtBJ7AD/ZBsvu0nefmKhcDnLh9GfAtvafea14QTQOvk vuYQmYlsE7BoShDeNdzx965f7tHilZQiFYLvGh9PLG5gk/0gjdCtnMb1xQG87o06kTpU GrFufWM7mq/fIyiPBIBzUPftyxq8OUlxoaHrEdWPKs/J3vjL08P6jTe/PsPk91aSn8Ou YIVB8lmfDbI9i76WzoeAm1CxRIzsw1LPwJQUWZBINuuWornoffcBxhbW7PjicW8HLoYC ilNW+c1Nv71nV6uezNeMQYjJJppzFJ5kRsQOJ0NVD3MGeq09vmkPZ5LJKXYeoAHYFvFX ZKoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721762317; x=1722367117; 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=bZu+accr9EvkOwRR3yW09OfJTHbiSshn6eSaoB0Gf6A=; b=TWhci3EM31V+/t6YfiE+RiShURYJYrf16PxRS0l295DK8bqz7Vgawaqe/Zs17juZ7u LhChG/Dm42wG/C2x3+toVvCfjJh1A99L1jh1pciU01thL8NWjojnWM0XRUHgX8mCSKO7 wVPStazxLA0UevCz/O5eLm7ztgqhKX/Vkefj3KbH20tEQ+gAeezoLj5xnmkBDR+Sgw0U uS+3bGpWGAuwrztpa3jEaMH63JXWGmpZ3wCZ949gJdY93B1T9NOjnHP0X3fMzbDgiCX4 Vug7onIb4cf9bFvb51yHT0fH7HCMjcUrx2WlxVknod/6IrGLRKfOHh+H6uqQps84vHTX CUnA== X-Gm-Message-State: AOJu0Yw8lAq3G7ecMpETrJjrEZS+RgG2qc1/nmey1eeNQvA5+JFF58dp wGWlsL0k7qu34QaVD5q6/p7qruPsNVrAMhjrr5KdqbMfVRElC1SQkmFgbQ== X-Google-Smtp-Source: AGHT+IHgiTJVQT5ul7/UVb8G/pp8WtVFTs+FP2L/RE3TSGqtAmpr5Fq7ZlPA6eTJ/IN+eQCWrW1crA== X-Received: by 2002:a05:6512:402a:b0:52c:e326:f4cf with SMTP id 2adb3069b0e04-52fc403d250mr2747993e87.3.1721762317297; Tue, 23 Jul 2024 12:18:37 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5a30c2f869dsm7903772a12.65.2024.07.23.12.18.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jul 2024 12:18:35 -0700 (PDT) Message-Id: <4a086ffc36033301095665530ab8f45cd1c4af36.1721762306.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 23 Jul 2024 19:18:25 +0000 Subject: [PATCH 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: 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 bbc16417ac9..5787eca28db 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 Tue Jul 23 19:18:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: avih X-Patchwork-Id: 13740311 Received: from mail-ej1-f46.google.com (mail-ej1-f46.google.com [209.85.218.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 3918813E03A for ; Tue, 23 Jul 2024 19:18:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762322; cv=none; b=dF2RvQTOm3z5uh6hy9wMEcKscvQ3kHoEzzJAIjIilklL6KEydN7JOSHweZqoJgJxML3Hs6ziyXeA2trv+tf6kwyAWrPxJYaU9T4VIq18SUrYmhcGDcBmQPK6tU37wM1AXdvOR5TUOupp/tNyi6GhKMwG82xAtU4nPzOHZii4/p4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721762322; c=relaxed/simple; bh=C4KixscV5HqK7gXWNomwL24BIhtihamlg4G6dKhrCzQ=; h=Message-Id:In-Reply-To:References:From:Date:Subject:Content-Type: MIME-Version:To:Cc; b=ANhv5D/3nfptHPSXnxg48dCo7k7421gNDEmiUFgHRlA/aR0+LaANWQN6UsZKfj19lG7kOwPmXv4xj1JEJSqxJ5/yQQJdxKkgdSOSCESUTt0kbc1IeMiUfaBLQ9BgLdXZSZlp+UOzsagoQnWyY7w2pIVTYoheeAAcJUhM+zLUq7M= 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=RUSw2w9b; arc=none smtp.client-ip=209.85.218.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="RUSw2w9b" Received: by mail-ej1-f46.google.com with SMTP id a640c23a62f3a-a7a8a4f21aeso29664766b.2 for ; Tue, 23 Jul 2024 12:18:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721762319; x=1722367119; 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=Ehy5/8tJEN9ttSmgFEoZjXY6G4I9WOinFK1xBXmSINo=; b=RUSw2w9bWmYC6HUkr7rpxQ72aqP63CGZYAqaA4/1tSWO4G3VCaIaQHzbX1/QdklVQS 213NlGoV2O9KKWEY1kT2UgN1pHH8wXwI/LcTMdj66xTifz/yWQI2IjNJC/zz35xhYsrF 8jVRBCPgji0N42fU6HDibvVKD7r8CAAjw1pvV9Hwf66JVwZh0O8etess7qp0op06Y2hq BVzMqbOnHq249F7bnTEX3ypQymKxIcQHMtLfhyX6ZwBv3F7RmT2j1QyXv9+dir6y05Ws ffnSTukCIOFJraMmVHvNTzavzJ9D8lSYTqZU4hZ51TsM2toMtKlz2mJ4C6XMaGaMyKMV pWCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721762319; x=1722367119; 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=Ehy5/8tJEN9ttSmgFEoZjXY6G4I9WOinFK1xBXmSINo=; b=GARPfGBCOF9t1U2LDExRp6rHN+VMegjaxoTRoT2KYFP/FdQl+hY4Stvt1HdHlNeXGA lrJVuYIuEIzRYAIN5kTOjMonjR5CFzDjjbsC5ePkQY1JavU9gi70e2aY3hLUIcPuWPcD Hr5RH+ppXuI0k/jCzHDo+zl8/ggUCwt1TCw4BkUAWZJ6uf8PlG+Hq6zvS2iUQLVQ3CrM ffoksdi4zS/R2B0izIBan09tbJ0FcCrlyf0moR6lvwbO4hoHgbr1cbP0/G2gI2PI7y0a 7ZEPhZqIiNwSn4RxPxN19ZiDX2YegKbgr9J/6nMw2IcH1Z+2oTIWZYQllO4EyKlfb/zP S7FA== X-Gm-Message-State: AOJu0Yy6o4pWXeo8T87Fvt1bBl6KZv9Gb9dhR5M+M7mg7UMln1kjo7yt 15TzieWN22KMkzRjiFpswqWHSkkyClGD+64w4NB+aBQcfUWd/SZhlwnymQ== X-Google-Smtp-Source: AGHT+IGwseeqliE2hPNTRRKaZWPZSyreSSXnMVfPNOIJ4kYy+GVVBcB+tU9O1lziTI6VvCY3DP3p/g== X-Received: by 2002:a17:907:d18:b0:a72:8c15:c73e with SMTP id a640c23a62f3a-a7a4c2a32famr685297766b.55.1721762318694; Tue, 23 Jul 2024 12:18:38 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a7a3c9230bdsm576194166b.176.2024.07.23.12.18.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jul 2024 12:18:37 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Tue, 23 Jul 2024 19:18:26 +0000 Subject: [PATCH 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: 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 5787eca28db..60df5cb94fe 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 @@ -314,8 +319,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}"