aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2026-01-05 14:17:11 +0000
committerMark Johnston <markj@FreeBSD.org>2026-01-05 14:17:11 +0000
commit684c762485d31d769b9e1ebeaababa31f684d2de (patch)
tree06ed6ab858bd10acf19b0e30cfb4b3039e0c3168
parent4a1b69ade6b5e8665dfb4d0cb683854705192a68 (diff)
git-arc: Try to make patching more useful
Add a raw mode, which fetches the patch file and applies it manually rather than using arc patch. This is handy because arc patch will always try to fetch your remotes if it can't find the base commit in your repo (even if you ask it not to make a commit). This is basically unusable in some of my workspaces where I have 20+ remotes configured, some of which may be unreachable. Add a stack mode, which causes git-arc to recursively apply parent revisions, going up the patch stack. Thus, to apply a full patch stack, just apply the final patch with -s. Reviewed by: ngie Differential Revision: https://reviews.freebsd.org/D54403
-rwxr-xr-xtools/tools/git/git-arc.sh79
1 files changed, 70 insertions, 9 deletions
diff --git a/tools/tools/git/git-arc.sh b/tools/tools/git/git-arc.sh
index 98d29809d636..bff9b0607761 100755
--- a/tools/tools/git/git-arc.sh
+++ b/tools/tools/git/git-arc.sh
@@ -59,7 +59,7 @@ Usage: git arc [-vy] <command> <arguments>
Commands:
create [-l] [-r <reviewer1>[,<reviewer2>...]] [-s subscriber[,...]] [<commit>|<commit range>]
list <commit>|<commit range>
- patch [-bc] <diff1> [<diff2> ...]
+ patch [-bcrs] <diff1> [<diff2> ...]
stage [-b branch] [<commit>|<commit range>]
update [-l] [-m message] [<commit>|<commit range>]
@@ -226,6 +226,20 @@ diff2phid()
jq -r "select(.response != []) | .response.${diff}.phid"
}
+phid2diff()
+{
+ local diff phid
+
+ phid=$1
+ if ! expr "$phid" : 'PHID-DREV-[0-9A-Za-z]*$' >/dev/null; then
+ err "invalid diff PHID $phid"
+ fi
+ diff=$(echo '{"constraints": {"phids": ["'"$phid"'"]}}' |
+ arc_call_conduit -- differential.revision.search |
+ jq -r '.response.data[0].id')
+ echo "D${diff}"
+}
+
diff2status()
{
local diff tmp status summary
@@ -244,6 +258,19 @@ diff2status()
printf "%-14s %s\n" "${status}" "${summary}"
}
+diff2parents()
+{
+ local dep dependencies diff parents phid
+
+ diff=$1
+ phid=$(diff2phid "$diff")
+ for dep in $(echo '{"phids": ["'"$phid"'"]}' |
+ arc_call_conduit -- differential.query |
+ jq -r '.response[0].auxiliary."phabricator:depends-on"[]'); do
+ echo $(phid2diff $dep)
+ done
+}
+
log2diff()
{
local diff
@@ -651,13 +678,46 @@ patch_commit()
git commit --author "${author}" --file "$tmp"
}
+apply_rev()
+{
+ local commit parent parents raw rev stack
+
+ rev=$1
+ commit=$2
+ raw=$3
+ stack=$4
+
+ if $stack; then
+ parents=$(diff2parents "$rev")
+ for parent in $parents; do
+ echo "Applying parent ${parent}..."
+ if ! apply_rev $parent $commit $raw $stack; then
+ return 1
+ fi
+ done
+ fi
+
+ if $raw; then
+ fetch -o /dev/stdout "https://reviews.freebsd.org/${rev}.diff" | git apply --index
+ else
+ arc patch --skip-dependencies --nobranch --nocommit --force $rev
+ fi
+
+ if ${commit}; then
+ patch_commit $rev
+ fi
+ return 0
+}
+
gitarc__patch()
{
- local branch commit rev
+ local branch commit o raw rev stack
branch=false
commit=false
- while getopts bc o; do
+ raw=false
+ stack=false
+ while getopts bcrs o; do
case "$o" in
b)
require_clean_work_tree "patch -b"
@@ -667,6 +727,12 @@ gitarc__patch()
require_clean_work_tree "patch -c"
commit=true
;;
+ r)
+ raw=true
+ ;;
+ s)
+ stack=true
+ ;;
*)
err_usage
;;
@@ -682,13 +748,8 @@ gitarc__patch()
patch_branch "$@"
fi
for rev in "$@"; do
- if ! arc patch --skip-dependencies --nobranch --nocommit --force "$rev"; then
- break
- fi
echo "Applying ${rev}..."
- if ${commit}; then
- patch_commit $rev
- fi
+ apply_rev $rev $commit $raw $stack
done
}