diff --git a/common/_home_manager/mods/foot.nix b/common/_home_manager/mods/foot.nix index fc37320..29fe6e3 100644 --- a/common/_home_manager/mods/foot.nix +++ b/common/_home_manager/mods/foot.nix @@ -8,7 +8,7 @@ }; alpha = lib.mkOption { type = lib.types.float; - default = 0.9; + default = 0.935; description = "Background opacity for Foot terminal (1.0 = opaque)"; }; }; diff --git a/common/general/shell/branch.func.sh b/common/general/shell/branch.func.sh index ae911d8..3422ce4 100644 --- a/common/general/shell/branch.func.sh +++ b/common/general/shell/branch.func.sh @@ -76,9 +76,17 @@ branch() { git -C "$repo_dir" fetch --all --prune || true local wt_root wt_path + if [ -z "$xdg" ]; then + xdg="${XDG_DATA_HOME:-$HOME/.local/share}" + fi wt_root="$xdg/git_worktrees/${repo_base}_${repo_hash}" wt_path="$wt_root/$branch_name" + # ensure worktree root exists + if [ ! -d "$wt_root" ]; then + mkdir -p "$wt_root" || { echo "Failed to create worktree root: $wt_root" >&2; return 1; } + fi + # If worktree already exists at our expected path, open a shell there if [ -d "$wt_path" ]; then echo "Opening existing worktree at '$wt_path'." @@ -86,11 +94,23 @@ branch() { return 0 fi - local branch_exists branch_from + local branch_exists branch_from local_exists branch_exists=$(git -C "$repo_dir" ls-remote --heads origin "$branch_name" | wc -l) + # check if a local branch exists + if git -C "$repo_dir" show-ref --verify --quiet "refs/heads/$branch_name"; then + local_exists=1 + else + local_exists=0 + fi + branch_from="$default_branch" if [ "$branch_exists" -eq 0 ]; then - echo "Branch '$branch_name' does not exist on remote; creating from '$branch_from'." + if [ "$local_exists" -eq 1 ]; then + branch_from="$branch_name" + echo "Branch '$branch_name' exists locally; creating worktree from local branch." + else + echo "Branch '$branch_name' does not exist on remote; creating from '$branch_from'." + fi else branch_from="origin/$branch_name" echo "Branch '$branch_name' exists on remote; creating worktree tracking it." @@ -99,9 +119,16 @@ branch() { echo "Creating new worktree for branch '$branch_name' at '$wt_path'." # Try to add or update worktree from the resolved ref. Use a fallback path if needed. - if git -C "$repo_dir" worktree add -b "$branch_name" "$wt_path" "$branch_from" 2>/dev/null; then - cd "$wt_path" || return 1 - return 0 + if [ "$local_exists" -eq 1 ]; then + if git -C "$repo_dir" worktree add "$wt_path" "$branch_name" 2>/dev/null; then + cd "$wt_path" || return 1 + return 0 + fi + else + if git -C "$repo_dir" worktree add -b "$branch_name" "$wt_path" "$branch_from" 2>/dev/null; then + cd "$wt_path" || return 1 + return 0 + fi fi # Fallback: try to resolve a concrete SHA and create the branch ref locally, then add worktree diff --git a/common/general/shell/branchd.func.sh b/common/general/shell/branchd.func.sh index 7fc296c..98ed5f5 100644 --- a/common/general/shell/branchd.func.sh +++ b/common/general/shell/branchd.func.sh @@ -1,5 +1,7 @@ branchdel() { - # branchd — remove current branch worktree (function form) + # branchdel — remove a branch worktree (optional branch arg) + local branch_arg + branch_arg="$1" local wt_path wt_path=$(pwd) local common_dir repo_dir @@ -16,40 +18,76 @@ branchdel() { return 1 fi - if [ "$repo_dir" = "$wt_path" ]; then - echo "Inside the root directory of repo, will not delete." >&2 - return 1 - fi - - local current default_branch + # determine current branch in this worktree + local current default_branch branch target_wt current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || { echo "Not inside a git repository." >&2; return 1; } default_branch=$(getdefault) - if [ "$current" = "$default_branch" ] || [ "$current" = "default" ]; then - echo "Already on default branch ($default_branch). Won't remove." - return 0 - fi - - echo "Switching to default branch '$default_branch'..." - # Use branch function if available, otherwise checkout directly in repo - if declare -f branch >/dev/null 2>&1; then - branch default || { echo "Failed to switch to default branch" >&2; return 1; } + # choose branch: provided arg or current + if [ -z "$branch_arg" ]; then + branch="$current" else - git -C "$repo_dir" checkout "$default_branch" || { echo "Failed to checkout default branch" >&2; return 1; } + branch="$branch_arg" + fi + # normalize branch name if refs/heads/ was provided + branch="${branch#refs/heads/}" + + # don't remove default + if [ "$branch" = "$default_branch" ] || [ "$branch" = "default" ]; then + echo "Refusing to remove default branch worktree ($default_branch)." >&2 + return 1 fi - echo "Removing worktree at: $wt_path" - if git -C "$repo_dir" worktree remove "$wt_path" 2>/dev/null; then - echo "Removed worktree: $wt_path" + # find the worktree path for the requested branch + target_wt=$(git -C "$repo_dir" worktree list --porcelain 2>/dev/null | awk -v b="refs/heads/$branch" ' + $1=="worktree" { w=$2 } + $1=="branch" && $2==b { print w; exit } + ') + + # if not found in worktree list, check main worktree branch + if [ -z "$target_wt" ]; then + local main_branch + main_branch=$(git -C "$repo_dir" rev-parse --abbrev-ref HEAD 2>/dev/null || true) + if [ "$main_branch" = "$branch" ]; then + target_wt="$repo_dir" + fi + fi + + if [ -z "$target_wt" ]; then + echo "No worktree found for branch '$branch'." >&2 + return 1 + fi + + if [ "$target_wt" = "$repo_dir" ]; then + echo "Branch '$branch' is the main worktree at '$repo_dir'. Will not delete main worktree." >&2 + return 1 + fi + + # if we're currently in that branch/worktree, switch to default and cd to repo root first + if [ "$current" = "$branch" ]; then + echo "Currently on branch '$branch' in '$wt_path'. Switching to default branch '$default_branch' in main worktree..." + if declare -f branch >/dev/null 2>&1; then + branch default || { echo "Failed to switch to default branch" >&2; return 1; } + else + git -C "$repo_dir" checkout "$default_branch" || { echo "Failed to checkout default branch" >&2; return 1; } + fi + cd "$repo_dir" || { echo "Failed to change directory to repo root: $repo_dir" >&2; return 1; } + fi + + echo "Removing worktree at: $target_wt" + if git -C "$repo_dir" worktree remove "$target_wt" 2>/dev/null; then + rm -rf -- "$target_wt" 2>/dev/null || true + echo "Removed worktree: $target_wt" return 0 fi # try with --force as a fallback - if git -C "$repo_dir" worktree remove --force "$wt_path" 2>/dev/null; then - echo "Removed worktree (forced): $wt_path" + if git -C "$repo_dir" worktree remove --force "$target_wt" 2>/dev/null; then + rm -rf -- "$target_wt" 2>/dev/null || true + echo "Removed worktree (forced): $target_wt" return 0 fi - echo "Failed to remove worktree: $wt_path" >&2 + echo "Failed to remove worktree: $target_wt" >&2 return 1 } diff --git a/hosts/lio/flake.lock b/hosts/lio/flake.lock index 4a2d843..fd514d0 100644 --- a/hosts/lio/flake.lock +++ b/hosts/lio/flake.lock @@ -1206,11 +1206,11 @@ "rust-overlay": "rust-overlay_2" }, "locked": { - "lastModified": 1757952613, - "narHash": "sha256-+oe+sRXenNMSP5O9ux0EF808JxoLbUneTV06/ILRPMA=", + "lastModified": 1757954114, + "narHash": "sha256-1Y6+uiLicKPARiiIjYY32asP9oKBW9z1LEBRYOR6ajI=", "ref": "refs/heads/master", - "rev": "4022513b5d59433b9ab0c273c384b664d6d17457", - "revCount": 302, + "rev": "f1487458ea787031e00230b604e652464fd44139", + "revCount": 303, "type": "git", "url": "https://git.joshuabell.xyz/ringofstorms/nvim" },