Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .delphi/manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# MINOR something new that existing clones need nothing for
# MAJOR clones need cleanup (MINOR while 0.x): add .delphi/migrations/<version>-<slug>.sh, which
# setup.sh runs once per workspace in each clone (rules in Delphi's CLAUDE.md)
version: 2.1.0
version: 2.1.1
files: # repo-relative paths; a trailing / means everything under it
- .delphi/manifest.yml
- .delphi/.gitattributes
Expand Down
11 changes: 9 additions & 2 deletions .delphi/new-worktree.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
# .delphi/new-worktree.sh <repo> <branch> [<base>]: create or reuse worktrees/<repo>/<branch> from
# the bare store .delphi/setup.sh made at worktrees/<repo>/.bare (never the clone at repos/<repo>), and
# print its path. An existing branch (local or on origin) is checked out; a new one starts from <base>
# (default: origin's default branch). Runs on bash 3.2 and Git Bash.
# (default: origin's default branch; a <base> only on origin is used as origin/<base>), and the script
# fails unless the worktree ends up on <branch>. Runs on bash 3.2 and Git Bash.
set -euo pipefail
# shellcheck source-path=SCRIPTDIR source=paths.sh
. "$(dirname "$0")/paths.sh"
Expand All @@ -18,7 +19,13 @@ elif g rev-parse -q --verify "refs/heads/$branch" >/dev/null; then
g worktree add -q "$dest" "$branch"
elif g rev-parse -q --verify "refs/remotes/origin/$branch" >/dev/null; then
g worktree add -q --track -b "$branch" "$dest" "origin/$branch"
else
else # a <base> only on origin goes as origin/<base>: given the bare name, Git 2.43 checks out <base>, not -b
if ! g rev-parse -q --verify "$base^{commit}" >/dev/null && g rev-parse -q --verify "refs/remotes/origin/$base" >/dev/null; then
base=origin/$base
fi
g worktree add -q --no-track -b "$branch" "$dest" "$base"
fi
on=$(git -C "$dest" branch --show-current)
[ "$on" = "$branch" ] || { echo "new-worktree: worktrees/$repo/$branch is on '${on:-a detached HEAD}', not '$branch';" \
"remove it (git -C worktrees/$repo/.bare worktree remove ../$branch) and rerun" >&2 && exit 1; }
echo "$dest"
1 change: 1 addition & 0 deletions .delphi/versions
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
1.2.0 d139aaf9f4a5 worktrees come from their own bare store, worktrees/<name>/.bare, separate from the plain clone at repos/<name>; setup.sh makes the store and the default-branch worktree again; an older bare store at repos/<name> is left as it is
2.0.0 750acf945979 a bare repos/<name> from before 1.1.0 becomes the worktree store, worktrees/<name>/.bare, with its worktrees, and repos/<name> is cloned normally (migration; skipped with a message if it has no origin or work not on origin)
2.1.0 84b00128fc22 add a harness-independent per-command workspace bootstrap for Codex
2.1.1 66714104d7a3 new-worktree.sh passes a <base> only on origin as origin/<base> (Git 2.43 checked out <base> instead of -b) and fails unless the worktree is on <branch> (#85)
9 changes: 8 additions & 1 deletion tests/e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1073,11 +1073,18 @@ nw code feat >/dev/null && [ "$(git -C "$w/worktrees/code/feat" rev-parse HEAD)"
[ "$(git -C "$w/worktrees/code/feat" rev-parse --abbrev-ref '@{u}')" = origin/feat ] || fail "existing branch not tracking origin"
nw code 2-dev origin/develop >/dev/null && [ "$(git -C "$w/worktrees/code/2-dev" rev-parse HEAD)" = "$(git -C "$t/code" rev-parse develop)" ] ||
fail "<base> ignored"
! git -C "$w/worktrees/code/.bare" rev-parse -q --verify refs/heads/develop >/dev/null || fail "store already has a local develop"
nw code 3-dev develop >/dev/null && [ "$(git -C "$w/worktrees/code/3-dev" branch --show-current)" = 3-dev ] &&
[ "$(git -C "$w/worktrees/code/3-dev" rev-parse HEAD)" = "$(git -C "$t/code" rev-parse develop)" ] || fail "<base> only on origin: not on the new branch"
! git -C "$w/worktrees/code/.bare" rev-parse -q --verify refs/heads/develop >/dev/null || fail "<base> only on origin: left a local develop"
git -C "$w/worktrees/code/.bare" worktree add -q --detach "$w/worktrees/code/4-off" origin/develop
! nw code 4-off >/dev/null 2>"$t/err" || fail "worktree off its branch not refused"
grep -q "is on 'a detached HEAD', not '4-off'" "$t/err" || fail "worktree off its branch refusal unexplained: $(cat "$t/err")"
[ "$(nw code feat)" = "$w/worktrees/code/feat" ] || fail "rerun did not reuse"
[ "$(git -C "$w/worktrees/code/$def" branch --show-current)" = "$def" ] || fail "default worktree left its branch"
{ [ "$(git -C "$w/repos/code" branch --show-current)" = "$def" ] && [ "$(git -C "$w/repos/code" worktree list | wc -l | tr -d " ")" = 1 ] &&
! git -C "$w/repos/code" rev-parse -q --verify refs/heads/1-new >/dev/null; } || fail "new-worktree touched the clone at repos/code"
ok "new-worktree.sh makes new branches from the default or <base>, checks out existing ones, reuses on rerun, never touching repos/<repo>"
ok "new-worktree.sh makes new branches from the default or <base> (local or only on origin), checks out existing ones, reuses on rerun, refuses a worktree off its branch, never touching repos/<repo>"
# skill scripts read the workspace from $DELPHI_ROOT (the session hook evals paths.sh's export line) and every folder from paths.sh
(. "$w/.delphi/paths.sh" && [ "$DELPHI_ROOT" = "$w" ] && [ "$DELPHI_REPOS" = "$w/repos" ] &&
[ "$DELPHI_WORKTREES" = "$w/worktrees" ] && [ "$DELPHI_REFERENCES" = "$w/references" ] && [ "$DELPHI_WORKSPACES" = "$w/workspaces" ]) ||
Expand Down
Loading