From nobody Tue Aug 25 20:48:48 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hV0Hp0FFWz6q1fZ for ; Tue, 25 Aug 2026 20:48:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hV0Hn6f1Hz3NLH for ; Tue, 25 Aug 2026 20:48:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787690933; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QFs/QX7R4juBJNBW3WLyeZNp7Rn9l0HgSxDNo6+NQ/k=; b=dfk09Yp0m61iqY9lvyEkwok5EGk0SYUpcjbsXQnTbk0A5VCRVKtyPIbl4qfSszu3zV5EMy xmsOd0JQgg+8f3cuN+zKgUzOR3sl0K8wEPqFnTUKXDFvz9ruUp21OsuRc3fspuOsc20Yzl 9203PyqkxiqkrdWob2kxXi+wDbOrjArgd6WDD2MGf/Tr0QRNZpzoRB5X0RKjT77ex/jj27 OQZTT3+wGukgPYRzNKWmh7xD07KpXUdFo/qpvwM0x9J1Kn1+1nF0NalsqN1V7AJ8RMxZIr 0b0MLyweuMbEbTQr762CxzPbry5e0De099H/1zPPlf1QcM10lphLgBuSfwb0LA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787690933; a=rsa-sha256; cv=none; b=qf/CkAdBXo1rzdUpaccu0J7xXkMZoMoqkPQF/3Bv1AdXqmhdFMZaHGf5JN7EAIm9OFhJhh f7FPV7itOgymQORtZryB8gqq+wITyUbMe3WD2OSLnej2nvRzxeXmH4MQl6W+oPBEmrKI3k GPH1if5WEO8IT66j/DmfpKOk7Aj1ycGjPBALZspF37zrRiliz4bL/WCXbRWbU0WagCDFIM 4UFghLx/lGyuVm21+UT+gED263Wnhkx8RZrk2LgLXV2ruHTzH42Lmv4z/hQu1o8UGMWTl0 FoBmUp9hSXSNrW1JC8C7G5guPmRt/SUIUzmZvzCLpTvVWrY7rRzQeAAsLolrKg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787690933; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QFs/QX7R4juBJNBW3WLyeZNp7Rn9l0HgSxDNo6+NQ/k=; b=tLjPu5344Mnf8HAAqI1zyFgsGKTKMjzQ049CO33VhPz+5+BEJR6qjM1vLx+OsGkCPkiPaH M6H7MvN87o1N0StJkWF3yZDuNAjb48CQRZE2tFXfX4FDToTdJx+89knKxRDP/uJNsyrvJ8 s1izSh2/iBKL/EAEEvJDFdoodKpy9YdKHOsw4sKWgOyCgtcTbHUlntSGSJr7dq50vBi3xI GYs8reYVScf3Xck/b8cruLZItiVedIBKMA7VlteMORNelaoX/TDkjdAyCjQ8G94Wl0bnYk wy0Zw8aqeOgoitTRD3l5N6Vq/OLNc2f6tPu6KYNkMMAZoi+zuWsbHbcVEnaA8A== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hV0Hn5gXnz16TK for ; Tue, 25 Aug 2026 20:48:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1f553 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 25 Aug 2026 20:48:48 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Devin Teske Subject: git: f86c3e6de479 - main - git-arc: Handle -h on subcommands and align usage with the man page List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dteske X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: f86c3e6de4795cb8b44d104635eb39e1f63209b4 Auto-Submitted: auto-generated Date: Tue, 25 Aug 2026 20:48:48 +0000 Message-Id: <6a8dffb0.1f553.6c15e91@gitrepo.freebsd.org> The branch main has been updated by dteske: URL: https://cgit.FreeBSD.org/src/commit/?id=f86c3e6de4795cb8b44d104635eb39e1f63209b4 commit f86c3e6de4795cb8b44d104635eb39e1f63209b4 Author: Devin Teske AuthorDate: 2026-08-25 20:46:32 +0000 Commit: Devin Teske CommitDate: 2026-08-25 20:46:32 +0000 git-arc: Handle -h on subcommands and align usage with the man page git-sh-setup treats -h as help against an empty USAGE, so "git arc create -h" prints "usage: git arc". Handle -h before sourcing it so every subcommand prints the real synopsis. The create, stage, and update synopses showed optional commit-refs while git-arc(1) and the code require them. Advertise -p parent on create; the option was already implemented and documented. Sort create sub-command option-arguments alphabetically in three places: (1) synopsis from tool, (2) man-page synopsis, and (3) man-page description. Check for jq(1) / arc after checking for usage so -h always works. While here, fix missing "local o" in gitarc__stage(). Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D59129 --- tools/tools/git/git-arc.1 | 27 +++--- tools/tools/git/git-arc.sh | 209 ++++++++++++++++++++++++++++++++------------- 2 files changed, 165 insertions(+), 71 deletions(-) diff --git a/tools/tools/git/git-arc.1 b/tools/tools/git/git-arc.1 index 218d852db984..d6b9ed686aaa 100644 --- a/tools/tools/git/git-arc.1 +++ b/tools/tools/git/git-arc.1 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 20, 2026 +.Dd August 23, 2026 .Dt GIT-ARC 1 .Os .Sh NAME @@ -32,28 +32,31 @@ .Nd a wrapper to improve integration between git and arcanist .Sh SYNOPSIS .Nm +.Fl h +.Nm .Cm create -.Op Fl dl +.Op Fl dhl +.Op Fl p Ar parent .Op Fl r Ar reviewer1 Ns Op Cm \&, Ns Ar reviewer2 ... .Op Fl s Ar subscriber1 Ns Op Cm \&, Ns Ar subscriber2 ... .Op Fl t Ar tag1 Ns Op Cm \&, Ns Ar tag2 ... -.Op Fl p Ar parent .Ar commit-ref Op Ar commit-ref ... .Nm -.Cm diff Ar commit-ref Op Ar commit-ref ... +.Cm diff Oo Fl h Oc Ar commit-ref Op Ar commit-ref ... .Nm -.Cm list Ar commit-ref Op Ar commit-ref ... +.Cm list Oo Fl h Oc Ar commit-ref Op Ar commit-ref ... .Nm .Cm patch -.Op Fl bcrs +.Op Fl bchrs .Ar diff1 Op Cm Ar diff2 Op Ar ... .Nm .Cm stage +.Op Fl h .Op Fl b Ar branch .Ar commit-ref Op Ar commit-ref ... .Nm .Cm update -.Op Fl l +.Op Fl hl .Op Fl m Ar message .Ar commit-ref Op Ar commit-ref ... .Sh DESCRIPTION @@ -104,9 +107,15 @@ In this mode, notifications are not sent to reviewers and subscribers until the review is published via the web UI. The draft is still visible to anyone with the URL (or able to guess it), but the review's visibility settings can be modified before publishing. +.It Fl h +Print usage statement and exit. .It Fl l Before processing commit(s) display list of commits to be processed and wait for confirmation. +.It Fl p Ar parent +Specify the parent of the first commit in the list. +This is useful when adding more commits on top of an already existing +stack in Phabricator. .It Fl r Ar reviewer Add one or more reviewers, separated by commas, to revision(s) being created. Each argument must be an existing Phabricator user or group. @@ -123,10 +132,6 @@ Unlike group reviewers, a leading is optional and is added if omitted. Spaces in tag names should be replaced with underscores .Pq e.g., Src_committers for the Do Src Committers Dc tag . -.It Fl p Ar parent -Specify the parent of the first commit in the list. -This is useful when adding more commits on top of an already existing -stack in Phabricator. .El .It Cm diff Show the differences between the specified commits and their associated diff --git a/tools/tools/git/git-arc.sh b/tools/tools/git/git-arc.sh index edaa7a62d846..07ce6539634a 100755 --- a/tools/tools/git/git-arc.sh +++ b/tools/tools/git/git-arc.sh @@ -55,15 +55,16 @@ cleanup() err_usage() { cat >&2 <<__EOF__ -Usage: git arc [-vy] +Usage: git arc [-hvy] Commands: - create [-dl] [-r [,...]] [-s subscriber[,...]] [|] - diff | - list | - patch [-bcrs] [ ...] - stage [-b branch] [|] - update [-l] [-m message] [|] + create [-dhl] [-p parent] [-r [,...]] \\ + [-s subscriber[,...]] [-t tag[,...]] | + diff [-h] | + list [-h] | + patch [-bchrs] [ ...] + stage [-h] [-b branch] | + update [-hl] [-m message] | See git-arc(1) for details. __EOF__ @@ -86,6 +87,65 @@ get_bool_config() test "$(git config --bool --get $1 2>/dev/null || echo $2)" != "false" } +# +# Per-subcommand initialization, invoked only after that sub-command's getopts +# loop and arity check have succeeded. git-sh-setup treats leading -h as help +# against empty USAGE, so must not be sourced until getopts has distinguished +# a usage request from an option argument (for example, "create -t -h"). Same +# delay skips jq(1) / arc checks when user only asked for usage. +# +# Invoke with no arguments because git-sh-setup inspects $1 (only for `-h') +# and sourcing inherits this function's args (empty $1 keeps its help check +# inert). Helpers it defines (require_clean_work_tree, git_pager) available +# only after this returns. +# +setup() +{ + [ -x "${ARC_CMD}" ] || err "arc is required, install devel/arcanist-lib" + which jq >/dev/null 2>&1 || err "jq is required, install textproc/jq" + + if [ "$VERBOSE" ]; then + exec 3>&1 + else + exec 3> /dev/null + fi + + # Pull in some git helper functions. + git_sh_setup=$(git --exec-path)/git-sh-setup + [ -f "$git_sh_setup" ] || err "cannot find git-sh-setup" + SUBDIRECTORY_OK=y + USAGE= + # shellcheck disable=SC1090 + . "$git_sh_setup" + + # git commands use GIT_EDITOR instead of EDITOR, so try to provide consistent + # behaviour. Ditto for PAGER. This makes git-arc play nicer with editor + # plugins like vim-fugitive. + if [ -n "$GIT_EDITOR" ]; then + EDITOR=$GIT_EDITOR + fi + if [ -n "$GIT_PAGER" ]; then + PAGER=$GIT_PAGER + fi + + # Bail if the working tree is unclean, except for "diff", "list" and + # "patch" operations. + case $verb in + diff|list|patch) + ;; + *) + require_clean_work_tree "$verb" + ;; + esac + + if get_bool_config arc.browse false; then + BROWSE=--browse + fi + + GITARC_TMPDIR=$(mktemp -d) || exit 1 + trap cleanup EXIT HUP INT QUIT TRAP USR1 TERM +} + # # Invoke the actual arc command. This allows us to only rely on the # devel/arcanist-lib port, which installs the actual script, rather than @@ -411,6 +471,8 @@ build_commit_list() gitarc__create() { + local OPTIND=1 OPTARG + # NB: reviewers / subscribers / tags not initialized; inheritance allowed. local commit commits doprompt draft list o prev reviewers subscribers local tags @@ -419,9 +481,8 @@ gitarc__create() if get_bool_config arc.list false; then list=1 fi - doprompt=1 draft=0 - while getopts dlp:r:s:t: o; do + while getopts dhlp:r:s:t: o; do case "$o" in d) draft=1 @@ -448,8 +509,17 @@ gitarc__create() done shift $((OPTIND-1)) + # NB: Earlier check of $# in main may have been duped by option-flags. + if [ $# -eq 0 ]; then + warn "Too few arguments" + err_usage + fi + + setup + commits=$(build_commit_list "$@") + doprompt=1 if [ "$list" ]; then for commit in ${commits}; do git --no-pager show --oneline --no-patch "$commit" @@ -479,8 +549,23 @@ gitarc__create() # gitarc__diff() { + local OPTIND=1 OPTARG o local commit commits diff rawdiff rtree + while getopts h o; do + case "$o" in + *) + err_usage + ;; + esac + done + shift $((OPTIND-1)) + + # NB: Earlier check of $# in main enough to ensure sufficient args. + # NB: If any option-flags besides -h are added, add re-check of $#. + + setup + commits=$(build_commit_list "$@") for commit in $commits; do @@ -507,8 +592,23 @@ gitarc__diff() gitarc__list() { + local OPTIND=1 OPTARG o local chash commit commits diff openrevs title + while getopts h o; do + case "$o" in + *) + err_usage + ;; + esac + done + shift $((OPTIND-1)) + + # NB: Earlier check of $# in main enough to ensure sufficient args. + # NB: If any option-flags besides -h are added, add re-check of $#. + + setup + commits=$(build_commit_list "$@") openrevs=$(arc_list --ansi) @@ -731,20 +831,19 @@ apply_rev() gitarc__patch() { + local OPTIND=1 OPTARG local branch commit o raw rev stack branch=false commit=false raw=false stack=false - while getopts bcrs o; do + while getopts bchrs o; do case "$o" in b) - require_clean_work_tree "patch -b" branch=true ;; c) - require_clean_work_tree "patch -c" commit=true ;; r) @@ -760,13 +859,22 @@ gitarc__patch() done shift $((OPTIND-1)) + # NB: Earlier check of $# in main may have been duped by option-flags. if [ $# -eq 0 ]; then + warn "Too few arguments" err_usage fi + setup + if ${branch}; then + require_clean_work_tree "patch -b" patch_branch "$@" fi + if ${commit}; then + require_clean_work_tree "patch -c" + fi + for rev in "$@"; do echo "Applying ${rev}..." apply_rev $rev $commit $raw $stack @@ -775,10 +883,11 @@ gitarc__patch() gitarc__stage() { + local OPTIND=1 OPTARG o local author branch commit commits diff reviewers title tmp branch=main - while getopts b: o; do + while getopts b:h o; do case "$o" in b) branch="$OPTARG" @@ -790,6 +899,14 @@ gitarc__stage() done shift $((OPTIND-1)) + # NB: Earlier check of $# in main may have been duped by option-flags. + if [ $# -eq 0 ]; then + warn "Too few arguments" + err_usage + fi + + setup + commits=$(build_commit_list "$@") if [ "$branch" = "main" ]; then @@ -823,14 +940,15 @@ gitarc__stage() gitarc__update() { + local OPTIND=1 OPTARG + # NB: msg / have_msg not initialized; inheritance allowed. local commit commits diff doprompt have_msg list o msg list= if get_bool_config arc.list false; then list=1 fi - doprompt=1 - while getopts lm: o; do + while getopts hlm: o; do case "$o" in l) list=1 @@ -846,8 +964,17 @@ gitarc__update() done shift $((OPTIND-1)) + # NB: Earlier check of $# in main may have been duped by option-flags. + if [ $# -eq 0 ]; then + warn "Too few arguments" + err_usage + fi + + setup + commits=$(build_commit_list "$@") + doprompt=1 if [ "$list" ]; then for commit in ${commits}; do git --no-pager show --oneline --no-patch "$commit" @@ -886,7 +1013,7 @@ if get_bool_config arc.assume-yes false; then fi VERBOSE= -while getopts vy o; do +while getopts hvy o; do case "$o" in v) VERBOSE=1 @@ -901,21 +1028,17 @@ while getopts vy o; do done shift $((OPTIND-1)) -[ $# -ge 1 ] || err_usage - -[ -x "${ARC_CMD}" ] || err "arc is required, install devel/arcanist-lib" -which jq >/dev/null 2>&1 || err "jq is required, install textproc/jq" - -if [ "$VERBOSE" ]; then - exec 3>&1 -else - exec 3> /dev/null +# NB: Only catches if neither option-flags nor sub-command. +if [ $# -eq 0 ]; then + warn "Too few arguments" + err_usage fi case "$1" in create|diff|list|patch|stage|update) ;; *) + warn "Unrecognized sub-command: $1" err_usage ;; esac @@ -924,42 +1047,8 @@ shift # All subcommands require at least one parameter. if [ $# -eq 0 ]; then + warn "Too few arguments" err_usage fi -# Pull in some git helper functions. -git_sh_setup=$(git --exec-path)/git-sh-setup -[ -f "$git_sh_setup" ] || err "cannot find git-sh-setup" -SUBDIRECTORY_OK=y -USAGE= -# shellcheck disable=SC1090 -. "$git_sh_setup" - -# git commands use GIT_EDITOR instead of EDITOR, so try to provide consistent -# behaviour. Ditto for PAGER. This makes git-arc play nicer with editor -# plugins like vim-fugitive. -if [ -n "$GIT_EDITOR" ]; then - EDITOR=$GIT_EDITOR -fi -if [ -n "$GIT_PAGER" ]; then - PAGER=$GIT_PAGER -fi - -# Bail if the working tree is unclean, except for "diff", "list" and -# "patch" operations. -case $verb in -diff|list|patch) - ;; -*) - require_clean_work_tree "$verb" - ;; -esac - -if get_bool_config arc.browse false; then - BROWSE=--browse -fi - -GITARC_TMPDIR=$(mktemp -d) || exit 1 -trap cleanup EXIT HUP INT QUIT TRAP USR1 TERM - gitarc__"${verb}" "$@"