Compare commits
4 commits
fdbba0d508
...
951dd38e9d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
951dd38e9d | ||
|
|
186e8db249 | ||
|
|
752310e386 | ||
|
|
8bbc0f7825 |
8 changed files with 334 additions and 45 deletions
105
common/general/shell/branch.func.sh
Normal file
105
common/general/shell/branch.func.sh
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
branch() {
|
||||
local branch_name=${1:-}
|
||||
if [ -z "$branch_name" ]; then
|
||||
echo "Usage: branch <name>" >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
# branch <name> — create or open a worktree for <name>
|
||||
# This function will change directory into the selected worktree so the
|
||||
# caller's shell is moved into it.
|
||||
|
||||
local xdg=${XDG_DATA_HOME:-$HOME/.local/share}
|
||||
|
||||
local common_dir
|
||||
if ! common_dir=$(git rev-parse --git-common-dir 2>/dev/null); then
|
||||
echo "Not inside a git repository." >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "${common_dir#/}" = "$common_dir" ]; then
|
||||
common_dir="$(pwd)/$common_dir"
|
||||
fi
|
||||
local repo_dir="${common_dir%%/.git*}"
|
||||
if [ -z "$repo_dir" ]; then
|
||||
echo "Unable to determine repository root." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local repo_base repo_hash default_branch
|
||||
repo_base=$(basename "$repo_dir")
|
||||
repo_hash=$(printf "%s" "$repo_dir" | sha1sum | awk '{print $1}')
|
||||
|
||||
default_branch=$(getdefault)
|
||||
|
||||
# Special-case: jump to the main working tree on the default branch
|
||||
if [ "$branch_name" = "default" ] || [ "$branch_name" = "master" ] || [ "$branch_name" = "$default_branch" ]; then
|
||||
if [ "$repo_dir" = "$PWD" ]; then
|
||||
echo "Already in the main working tree on branch '$default_branch'."
|
||||
return 0
|
||||
fi
|
||||
echo "Switching to main working tree on branch '$default_branch'."
|
||||
cd "$repo_dir" || return 1
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If a worktree for this branch is already registered elsewhere, open a shell there
|
||||
local existing
|
||||
existing=$(git -C "$repo_dir" worktree list --porcelain 2>/dev/null | awk -v b="$branch_name" 'BEGIN{RS="";FS="\n"} $0 ~ "refs/heads/"b{for(i=1;i<=NF;i++) if ($i ~ /^worktree /){ sub(/^worktree /,"",$i); print $i }}')
|
||||
if [ -n "$existing" ]; then
|
||||
echo "Opening existing worktree for branch '$branch_name' at '$existing'."
|
||||
cd "$existing" || return 1
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Ensure we have up-to-date remote info
|
||||
git -C "$repo_dir" fetch --all --prune || true
|
||||
|
||||
local wt_root wt_path
|
||||
wt_root="$xdg/git_worktrees/${repo_base}_${repo_hash}"
|
||||
wt_path="$wt_root/$branch_name"
|
||||
|
||||
# If worktree already exists at our expected path, open a shell there
|
||||
if [ -d "$wt_path" ]; then
|
||||
echo "Opening existing worktree at '$wt_path'."
|
||||
cd "$wt_path" || return 1
|
||||
return 0
|
||||
fi
|
||||
|
||||
local branch_exists branch_from
|
||||
branch_exists=$(git -C "$repo_dir" ls-remote --heads origin "$branch_name" | wc -l)
|
||||
branch_from="$default_branch"
|
||||
if [ "$branch_exists" -eq 0 ]; then
|
||||
echo "Branch '$branch_name' does not exist on remote; creating from '$branch_from'."
|
||||
else
|
||||
branch_from="origin/$branch_name"
|
||||
echo "Branch '$branch_name' exists on remote; creating worktree tracking it."
|
||||
fi
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
# Fallback: try to resolve a concrete SHA and create the branch ref locally, then add worktree
|
||||
local start_sha
|
||||
if start_sha=$(git -C "$repo_dir" rev-parse --verify "$branch_from" 2>/dev/null); then
|
||||
if git -C "$repo_dir" branch "$branch_name" "$start_sha" 2>/dev/null; then
|
||||
if git -C "$repo_dir" worktree add "$wt_path" "$branch_name" 2>/dev/null; then
|
||||
cd "$wt_path" || return 1
|
||||
return 0
|
||||
else
|
||||
git -C "$repo_dir" branch -D "$branch_name" 2>/dev/null || true
|
||||
rmdir "$wt_path" 2>/dev/null || true
|
||||
echo "Failed to add worktree after creating branch ref." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Failed to add worktree for branch '$branch_name'." >&2
|
||||
rmdir "$wt_path" 2>/dev/null || true
|
||||
return 1
|
||||
}
|
||||
55
common/general/shell/branchd.func.sh
Normal file
55
common/general/shell/branchd.func.sh
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
branchdel() {
|
||||
# branchd — remove current branch worktree (function form)
|
||||
local wt_path
|
||||
wt_path=$(pwd)
|
||||
local common_dir repo_dir
|
||||
if ! common_dir=$(git rev-parse --git-common-dir 2>/dev/null); then
|
||||
echo "Not inside a git repository." >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "${common_dir#/}" = "$common_dir" ]; then
|
||||
common_dir="$(pwd)/$common_dir"
|
||||
fi
|
||||
repo_dir="${common_dir%%/.git*}"
|
||||
if [ -z "$repo_dir" ]; then
|
||||
echo "Unable to determine repository root." >&2
|
||||
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
|
||||
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; }
|
||||
else
|
||||
git -C "$repo_dir" checkout "$default_branch" || { echo "Failed to checkout 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"
|
||||
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"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Failed to remove worktree: $wt_path" >&2
|
||||
return 1
|
||||
}
|
||||
|
|
@ -46,7 +46,6 @@ with lib;
|
|||
cl = "clear";
|
||||
|
||||
# git
|
||||
branch = "git checkout -b";
|
||||
status = "git status";
|
||||
diff = "git diff";
|
||||
branches = "git branch -a";
|
||||
|
|
@ -59,6 +58,11 @@ with lib;
|
|||
rgf = "rg --files --glob '!/nix/store/**' 2>/dev/null | rg";
|
||||
};
|
||||
|
||||
environment.shellInit = builtins.readFile ./common.sh;
|
||||
environment.shellInit = lib.concatStringsSep "\n\n" [
|
||||
(builtins.readFile ./common.sh)
|
||||
(builtins.readFile ./branch.func.sh)
|
||||
(builtins.readFile ./branchd.func.sh)
|
||||
(builtins.readFile ./link_ignored.func.sh)
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ getdefault () {
|
|||
}
|
||||
|
||||
master () {
|
||||
git stash
|
||||
branch $(getdefault)
|
||||
git checkout $(getdefault)
|
||||
pull
|
||||
}
|
||||
|
|
@ -129,12 +129,6 @@ prunel () {
|
|||
done;
|
||||
}
|
||||
|
||||
checkout () {
|
||||
git fetch
|
||||
git checkout $1
|
||||
pull
|
||||
}
|
||||
|
||||
from_master () {
|
||||
git checkout $(getdefault) $@
|
||||
}
|
||||
|
|
|
|||
152
common/general/shell/link_ignored.func.sh
Normal file
152
common/general/shell/link_ignored.func.sh
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
link_ignored() {
|
||||
local DRY_RUN=0
|
||||
local USE_FZF=1
|
||||
local -a PATTERNS=()
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=1; shift ;;
|
||||
--no-fzf) USE_FZF=0; shift ;;
|
||||
-h|--help) link_ignored_usage; return 0 ;;
|
||||
--) shift; break ;;
|
||||
*) PATTERNS+=("$1"); shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
link_ignored_usage() {
|
||||
cat <<EOF
|
||||
Usage: link_ignored [--dry-run] [--no-fzf] [pattern ...]
|
||||
|
||||
Interactively or non-interactively create symlinks in the current worktree
|
||||
for files/dirs that exist in the main repository root but are git-ignored /
|
||||
untracked.
|
||||
EOF
|
||||
}
|
||||
|
||||
# Determine the main repo root using git-common-dir (handles worktrees)
|
||||
local common_dir repo_root
|
||||
if ! common_dir=$(git rev-parse --git-common-dir 2>/dev/null); then
|
||||
echo "Error: not in a git repository." >&2
|
||||
return 2
|
||||
fi
|
||||
if [ "${common_dir#/}" = "$common_dir" ]; then
|
||||
common_dir="$(pwd)/$common_dir"
|
||||
fi
|
||||
repo_root="${common_dir%%/.git*}"
|
||||
if [ -z "$repo_root" ]; then
|
||||
echo "Error: unable to determine repository root." >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
local -a candidates
|
||||
IFS=$'\0' read -r -d '' -a candidates < <(git -C "$repo_root" ls-files --others --ignored --exclude-standard -z || true)
|
||||
|
||||
if [ ${#candidates[@]} -eq 0 ]; then
|
||||
echo "No untracked/ignored files found in $repo_root"
|
||||
return 0
|
||||
fi
|
||||
|
||||
declare -A _seen
|
||||
local -a tops=()
|
||||
for c in "${candidates[@]}"; do
|
||||
c="${c%/}"
|
||||
local top="${c%%/*}"
|
||||
[ -z "$top" ] && continue
|
||||
if [ -z "${_seen[$top]:-}" ]; then
|
||||
_seen[$top]=1
|
||||
tops+=("$top")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#tops[@]} -eq 0 ]; then
|
||||
echo "No top-level ignored/untracked entries found in $repo_root"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local -a filtered
|
||||
if [ ${#PATTERNS[@]} -gt 0 ]; then
|
||||
for t in "${tops[@]}"; do
|
||||
for p in "${PATTERNS[@]}"; do
|
||||
if [[ "$t" == *"$p"* ]]; then
|
||||
filtered+=("$t")
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
else
|
||||
filtered=("${tops[@]}")
|
||||
fi
|
||||
|
||||
if [ ${#filtered[@]} -eq 0 ]; then
|
||||
echo "No candidates match the provided patterns." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
local -a chosen
|
||||
if command -v fzf >/dev/null 2>&1 && [ "$USE_FZF" -eq 1 ]; then
|
||||
local selected
|
||||
selected=$(printf "%s\n" "${filtered[@]}" | fzf --multi --height=40% --border --prompt="Select files to link: " --preview "if [ -f '$repo_root'/{} ]; then bat --color always --paging=never --style=plain '$repo_root'/{}; else ls -la '$repo_root'/{}; fi")
|
||||
if [ -z "$selected" ]; then
|
||||
echo "No files selected." && return 0
|
||||
fi
|
||||
IFS=$'\n' read -r -d '' -a chosen < <(printf "%s\n" "$selected" && printf '\0')
|
||||
else
|
||||
chosen=("${filtered[@]}")
|
||||
fi
|
||||
|
||||
local worktree_root
|
||||
worktree_root=$(pwd)
|
||||
|
||||
echo "Repository root: $repo_root"
|
||||
echo "Worktree root : $worktree_root"
|
||||
|
||||
local -a created=()
|
||||
local -a skipped=()
|
||||
local -a errors=()
|
||||
|
||||
for rel in "${chosen[@]}"; do
|
||||
rel=${rel%%$'\n'}
|
||||
local src="${repo_root}/${rel}"
|
||||
local dst="${worktree_root}/${rel}"
|
||||
|
||||
if [ ! -e "$src" ]; then
|
||||
errors+=("$rel (source missing)")
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -L "$dst" ]; then
|
||||
echo "Skipping $rel (already symlink)"
|
||||
skipped+=("$rel")
|
||||
continue
|
||||
fi
|
||||
if [ -e "$dst" ]; then
|
||||
echo "Skipping $rel (destination exists)"
|
||||
skipped+=("$rel")
|
||||
continue
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$dst")"
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
echo "DRY RUN: ln -s '$src' '$dst'"
|
||||
else
|
||||
if ln -s "$src" "$dst"; then
|
||||
echo "Linked: $rel"
|
||||
created+=("$rel")
|
||||
else
|
||||
echo "Failed to link: $rel" >&2
|
||||
errors+=("$rel (link failed)")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "Summary:"
|
||||
echo " Linked: ${#created[@]}"
|
||||
[ ${#created[@]} -gt 0 ] && printf ' %s\n' "${created[@]}"
|
||||
echo " Skipped: ${#skipped[@]}"
|
||||
[ ${#skipped[@]} -gt 0 ] && printf ' %s\n' "${skipped[@]}"
|
||||
echo " Errors: ${#errors[@]}"
|
||||
[ ${#errors[@]} -gt 0 ] && printf ' %s\n' "${errors[@]}"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
@ -211,6 +211,7 @@
|
|||
"2c:cf:67:6a:45:47,HOMEASSISTANT,10.12.14.22"
|
||||
"2a:d0:ec:fa:b9:7e,PIXEL-6,10.12.14.31"
|
||||
"a8:29:48:94:23:dd,TL-SG1428PE,10.12.16.2"
|
||||
"00:23:a4:0b:3b:be,TMREM00004335,10.12.14.181"
|
||||
];
|
||||
|
||||
enable-ra = lib.mkIf config.networking.enableIPv6 true;
|
||||
|
|
|
|||
43
hosts/lio/flake.lock
generated
43
hosts/lio/flake.lock
generated
|
|
@ -29,22 +29,17 @@
|
|||
"inputs": {
|
||||
"home-manager": "home-manager",
|
||||
"nix-flatpak": "nix-flatpak",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"ragenix": "ragenix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1757006046,
|
||||
"narHash": "sha256-DSPEc465ijE7hVDFpuMDF0LTBIAa0N7V6YFdBfS9XL0=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "307bf34c8c24a7b2b599bd22facae5ec5090c8bd",
|
||||
"revCount": 639,
|
||||
"type": "git",
|
||||
"url": "https://git.joshuabell.xyz/ringofstorms/dotfiles"
|
||||
"path": "../../common",
|
||||
"type": "path"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.joshuabell.xyz/ringofstorms/dotfiles"
|
||||
}
|
||||
"path": "../../common",
|
||||
"type": "path"
|
||||
},
|
||||
"parent": []
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
|
|
@ -194,22 +189,6 @@
|
|||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1757347588,
|
||||
"narHash": "sha256-tLdkkC6XnsY9EOZW9TlpesTclELy8W7lL2ClL+nma8o=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b599843bad24621dcaa5ab60dac98f9b0eb1cabe",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1741379970,
|
||||
"narHash": "sha256-Wh7esNh7G24qYleLvgOSY/7HlDUzWaL/n4qzlBePpiw=",
|
||||
|
|
@ -225,7 +204,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1755471983,
|
||||
"narHash": "sha256-axUoWcm4cNQ36jOlnkD9D40LTfSQgk8ExfHSRm3rTtg=",
|
||||
|
|
@ -241,7 +220,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1755648324,
|
||||
"narHash": "sha256-+2TxwJEXWXGC7JBsRGUHtmQ66lRGPcDI2kFKTTU5e2s=",
|
||||
|
|
@ -1141,7 +1120,7 @@
|
|||
"agenix": "agenix",
|
||||
"crane": "crane",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
|
|
@ -1161,14 +1140,14 @@
|
|||
"root": {
|
||||
"inputs": {
|
||||
"common": "common",
|
||||
"nixpkgs": "nixpkgs_4",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"ros_neovim": "ros_neovim"
|
||||
}
|
||||
},
|
||||
"ros_neovim": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_5",
|
||||
"nixpkgs": "nixpkgs_4",
|
||||
"nvim_plugin-Almo7aya/openingh.nvim": "nvim_plugin-Almo7aya/openingh.nvim",
|
||||
"nvim_plugin-CopilotC-Nvim/CopilotChat.nvim": "nvim_plugin-CopilotC-Nvim/CopilotChat.nvim",
|
||||
"nvim_plugin-JoosepAlviste/nvim-ts-context-commentstring": "nvim_plugin-JoosepAlviste/nvim-ts-context-commentstring",
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
|
||||
# Use relative to get current version for testing
|
||||
# common.url = "path:../../common";
|
||||
common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles";
|
||||
common.url = "path:../../common";
|
||||
# common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles";
|
||||
|
||||
ros_neovim.url = "git+https://git.joshuabell.xyz/ringofstorms/nvim";
|
||||
};
|
||||
|
|
@ -75,6 +75,7 @@
|
|||
appimage-run
|
||||
nodejs_24
|
||||
foot
|
||||
vlc
|
||||
];
|
||||
# Also allow this key to work for root user, this will let us use this as a remote builder easier
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
|
|
@ -117,11 +118,9 @@
|
|||
"dev.vencord.Vesktop"
|
||||
"md.obsidian.Obsidian"
|
||||
"com.spotify.Client"
|
||||
"org.videolan.VLC"
|
||||
"com.bitwarden.desktop"
|
||||
"org.openscad.OpenSCAD"
|
||||
"org.blender.Blender"
|
||||
"im.riot.Riot"
|
||||
"com.rustdesk.RustDesk"
|
||||
"com.google.Chrome"
|
||||
];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue