- Simplified command cases by removing unnecessary semicolons.
- Improved error handling in rebuild.nix for clarity and consistency.
This commit is contained in:
@ -18,33 +18,35 @@
|
|||||||
|
|
||||||
# --- Help text ---
|
# --- Help text ---
|
||||||
print_help = ''
|
print_help = ''
|
||||||
echo "NixOS CLI Utility -- version 2.1.3"
|
print_help() {
|
||||||
echo ""
|
echo "NixOS CLI Utility -- version 2.1.3"
|
||||||
echo "Usage: ncli [command]"
|
echo ""
|
||||||
echo ""
|
echo "Usage: ncli [command]"
|
||||||
echo "System Commands:"
|
echo ""
|
||||||
echo " rebuild - Rebuild the NixOS system configuration."
|
echo "System Commands:"
|
||||||
echo " update - Update the flake and rebuild the system."
|
echo " rebuild - Rebuild the NixOS system configuration."
|
||||||
echo ""
|
echo " update - Update the flake and rebuild the system."
|
||||||
echo "Maintenance Commands:"
|
echo ""
|
||||||
echo " cleanup - Clean up old system generations. Can specify a number to keep."
|
echo "Maintenance Commands:"
|
||||||
echo " diag - Create a system diagnostic report (saves to ~/diag.txt)."
|
echo " cleanup - Clean up old system generations. Can specify a number to keep."
|
||||||
echo " list-gens - List user and system generations."
|
echo " diag - Create a system diagnostic report (saves to ~/diag.txt)."
|
||||||
echo " trim - Trim filesystems to improve SSD performance."
|
echo " list-gens - List user and system generations."
|
||||||
echo ""
|
echo " trim - Trim filesystems to improve SSD performance."
|
||||||
echo "Git Commands:"
|
echo ""
|
||||||
echo " commit [msg] - Add all changes and commit with message."
|
echo "Git Commands:"
|
||||||
echo " push - Push changes to origin."
|
echo " commit [msg] - Add all changes and commit with message."
|
||||||
echo " pull - Pull latest changes from origin."
|
echo " push - Push changes to origin."
|
||||||
echo " status - Show git status."
|
echo " pull - Pull latest changes from origin."
|
||||||
echo ""
|
echo " status - Show git status."
|
||||||
echo "Development Commands:"
|
echo ""
|
||||||
echo " dev - Initialize a Nix development environment (flake.nix + direnv)."
|
echo "Development Commands:"
|
||||||
echo " dev track - Remove assume-unchanged flag from flake files."
|
echo " dev - Initialize a Nix development environment (flake.nix + direnv)."
|
||||||
echo " dev untrack - Mark flake files as assume-unchanged in a directory."
|
echo " dev track - Remove assume-unchanged flag from flake files."
|
||||||
echo ""
|
echo " dev untrack - Mark flake files as assume-unchanged in a directory."
|
||||||
echo " help - Show this help message."
|
echo ""
|
||||||
echo ""
|
echo " help - Show this help message."
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
pkgs.writeShellScriptBin "ncli" ''
|
pkgs.writeShellScriptBin "ncli" ''
|
||||||
@ -70,6 +72,7 @@ in
|
|||||||
${lib.print_success}
|
${lib.print_success}
|
||||||
${lib.print_error}
|
${lib.print_error}
|
||||||
${lib.print_info}
|
${lib.print_info}
|
||||||
|
${print_help}
|
||||||
|
|
||||||
# --- Main Logic ---
|
# --- Main Logic ---
|
||||||
if [ "$#" -eq 0 ]; then
|
if [ "$#" -eq 0 ]; then
|
||||||
@ -122,7 +125,7 @@ in
|
|||||||
${dev.dev_case}
|
${dev.dev_case}
|
||||||
;;
|
;;
|
||||||
help)
|
help)
|
||||||
${print_help}
|
print_help
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Invalid command '$1'" >&2
|
echo "Error: Invalid command '$1'" >&2
|
||||||
|
|||||||
@ -1,367 +1,364 @@
|
|||||||
# ncli/commands/dev.nix — dev init / track / untrack
|
# ncli/commands/dev.nix — dev init / track / untrack
|
||||||
lib:
|
lib: {
|
||||||
|
|
||||||
{
|
|
||||||
dev_case = ''
|
dev_case = ''
|
||||||
# Only flake files need assume-unchanged (Nix requires them in the index).
|
# Only flake files need assume-unchanged (Nix requires them in the index).
|
||||||
# .envrc and .direnv are handled via .git/info/exclude instead.
|
# .envrc and .direnv are handled via .git/info/exclude instead.
|
||||||
DEV_FILES=(flake.nix flake.lock)
|
DEV_FILES=(flake.nix flake.lock)
|
||||||
DIRENV_LOCAL_FILES=(.envrc .direnv)
|
DIRENV_LOCAL_FILES=(.envrc .direnv)
|
||||||
|
|
||||||
_dev_resolve_dir() {
|
_dev_resolve_dir() {
|
||||||
read -rp " Enter target directory [./]: " TARGET_DIR
|
read -rp " Enter target directory [./]: " TARGET_DIR
|
||||||
TARGET_DIR="''${TARGET_DIR:-./}"
|
TARGET_DIR="''${TARGET_DIR:-./}"
|
||||||
if [[ ! -d "$TARGET_DIR" ]]; then
|
if [[ ! -d "$TARGET_DIR" ]]; then
|
||||||
print_error "Directory '$TARGET_DIR' does not exist."
|
print_error "Directory '$TARGET_DIR' does not exist."
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
|
|
||||||
if ! git -C "$TARGET_ABS" rev-parse --git-dir > /dev/null 2>&1; then
|
|
||||||
print_error "No Git repository found at '$TARGET_ABS'."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_add_local_excludes() {
|
|
||||||
local repo_abs="$1"
|
|
||||||
local git_dir exclude_file
|
|
||||||
git_dir="$(git -C "$repo_abs" rev-parse --git-dir)"
|
|
||||||
exclude_file="$git_dir/info/exclude"
|
|
||||||
mkdir -p "$(dirname "$exclude_file")"
|
|
||||||
touch "$exclude_file"
|
|
||||||
|
|
||||||
for entry in "''${DIRENV_LOCAL_FILES[@]}"; do
|
|
||||||
if ! grep -qxF "$entry" "$exclude_file" 2>/dev/null; then
|
|
||||||
echo "$entry" >> "$exclude_file"
|
|
||||||
print_success "$entry → ignored via .git/info/exclude (local only)"
|
|
||||||
else
|
|
||||||
print_info "$entry already in .git/info/exclude, skipping."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
_remove_local_excludes() {
|
|
||||||
local repo_abs="$1"
|
|
||||||
local git_dir exclude_file tmp_file
|
|
||||||
git_dir="$(git -C "$repo_abs" rev-parse --git-dir)"
|
|
||||||
exclude_file="$git_dir/info/exclude"
|
|
||||||
|
|
||||||
[[ -f "$exclude_file" ]] || return 0
|
|
||||||
|
|
||||||
tmp_file="$(mktemp)"
|
|
||||||
cp "$exclude_file" "$tmp_file"
|
|
||||||
|
|
||||||
for entry in "''${DIRENV_LOCAL_FILES[@]}"; do
|
|
||||||
if grep -qxF "$entry" "$tmp_file" 2>/dev/null; then
|
|
||||||
grep -vxF "$entry" "$tmp_file" > "''${tmp_file}.new" || true
|
|
||||||
mv "''${tmp_file}.new" "$tmp_file"
|
|
||||||
print_success "$entry → removed from .git/info/exclude"
|
|
||||||
else
|
|
||||||
print_info "$entry not present in .git/info/exclude, skipping."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
mv "$tmp_file" "$exclude_file"
|
|
||||||
}
|
|
||||||
|
|
||||||
case "''${2:-init}" in
|
|
||||||
|
|
||||||
untrack)
|
|
||||||
echo ""
|
|
||||||
echo -e "''${BLUE}--- Dev: Track Files (assume-unchanged) ---''${NOCOLOR}"
|
|
||||||
echo ""
|
|
||||||
_dev_resolve_dir
|
|
||||||
|
|
||||||
acted=false
|
|
||||||
for f in "''${DEV_FILES[@]}"; do
|
|
||||||
full="$TARGET_ABS/$f"
|
|
||||||
if [[ ! -f "$full" ]]; then
|
|
||||||
print_info "$f not found in $TARGET_ABS — skipping."
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if ! git -C "$TARGET_ABS" ls-files --error-unmatch "$f" > /dev/null 2>&1; then
|
|
||||||
git -C "$TARGET_ABS" add --intent-to-add "$f"
|
|
||||||
fi
|
|
||||||
git -C "$TARGET_ABS" update-index --assume-unchanged "$f"
|
|
||||||
print_success "$f → untracked (assume-unchanged)"
|
|
||||||
acted=true
|
|
||||||
done
|
|
||||||
|
|
||||||
_add_local_excludes "$TARGET_ABS"
|
|
||||||
|
|
||||||
if ! $acted; then
|
|
||||||
print_info "No dev files found in '$TARGET_ABS' to track."
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
track)
|
|
||||||
echo ""
|
|
||||||
echo -e "''${BLUE}--- Dev: Untrack Files (remove assume-unchanged) ---''${NOCOLOR}"
|
|
||||||
echo ""
|
|
||||||
_dev_resolve_dir
|
|
||||||
|
|
||||||
acted=false
|
|
||||||
for f in "''${DEV_FILES[@]}"; do
|
|
||||||
if git -C "$TARGET_ABS" ls-files -v "$f" 2>/dev/null | grep -q "^h "; then
|
|
||||||
git -C "$TARGET_ABS" update-index --no-assume-unchanged "$f"
|
|
||||||
print_success "$f → tracked (assume-unchanged removed)"
|
|
||||||
acted=true
|
|
||||||
else
|
|
||||||
print_info "$f is not marked assume-unchanged — skipping."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
_remove_local_excludes "$TARGET_ABS"
|
|
||||||
|
|
||||||
if ! $acted; then
|
|
||||||
print_info "No files in '$TARGET_ABS' had the assume-unchanged bit set."
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
init|*)
|
|
||||||
SOURCE_FLAKE="$HOME/${lib.project}/other/dev-template.nix"
|
|
||||||
|
|
||||||
if [[ ! -f "$SOURCE_FLAKE" ]]; then
|
|
||||||
print_error "Source flake template not found: $SOURCE_FLAKE"
|
|
||||||
echo "Please ensure dev-template.nix exists in $HOME/${lib.project}/other/"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
|
||||||
print_header
|
if ! git -C "$TARGET_ABS" rev-parse --git-dir > /dev/null 2>&1; then
|
||||||
|
print_error "No Git repository found at '$TARGET_ABS'."
|
||||||
# ---- Step 1: Target Directory ----
|
|
||||||
echo -e "''${YELLOW}Step 1/5: Target Directory''${NOCOLOR}"
|
|
||||||
echo ""
|
|
||||||
read -p " Enter target directory [./]: " TARGET_DIR
|
|
||||||
|
|
||||||
if [[ -z "$TARGET_DIR" ]]; then
|
|
||||||
TARGET_DIR="./"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d "$TARGET_DIR" ]]; then
|
|
||||||
print_error "Directory '$TARGET_DIR' does not exist. Exiting."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
print_success "Target directory: $TARGET_DIR"
|
_add_local_excludes() {
|
||||||
echo ""
|
local repo_abs="$1"
|
||||||
|
local git_dir exclude_file
|
||||||
|
git_dir="$(git -C "$repo_abs" rev-parse --git-dir)"
|
||||||
|
exclude_file="$git_dir/info/exclude"
|
||||||
|
mkdir -p "$(dirname "$exclude_file")"
|
||||||
|
touch "$exclude_file"
|
||||||
|
|
||||||
# ---- Check for existing flake ----
|
for entry in "''${DIRENV_LOCAL_FILES[@]}"; do
|
||||||
if [[ -f "$TARGET_DIR/flake.nix" ]]; then
|
if ! grep -qxF "$entry" "$exclude_file" 2>/dev/null; then
|
||||||
echo ""
|
echo "$entry" >> "$exclude_file"
|
||||||
print_error "A flake.nix already exists in '$TARGET_DIR'!"
|
print_success "$entry → ignored via .git/info/exclude (local only)"
|
||||||
echo ""
|
|
||||||
read -p " Would you like to just place the .envrc instead? [y/N]: " ENVRC_ONLY
|
|
||||||
ENVRC_ONLY="''${ENVRC_ONLY:-N}"
|
|
||||||
|
|
||||||
if [[ "$ENVRC_ONLY" =~ ^[Yy]$ ]]; then
|
|
||||||
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
|
|
||||||
echo ""
|
|
||||||
print_info "Placing .envrc only..."
|
|
||||||
if ! grep -qxF "use flake" "$TARGET_ABS/.envrc" 2>/dev/null; then
|
|
||||||
echo "use flake" >> "$TARGET_ABS/.envrc"
|
|
||||||
print_success ".envrc created at $TARGET_ABS/"
|
|
||||||
else
|
|
||||||
print_info ".envrc already contains 'use flake', nothing to do."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
print_info "Next steps:"
|
|
||||||
echo " cd $TARGET_DIR"
|
|
||||||
echo " direnv allow"
|
|
||||||
echo ""
|
|
||||||
exit 0
|
|
||||||
else
|
else
|
||||||
print_info "Aborting. No files were changed."
|
print_info "$entry already in .git/info/exclude, skipping."
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
fi
|
done
|
||||||
|
}
|
||||||
|
|
||||||
# ---- Step 2: Project Name ----
|
_remove_local_excludes() {
|
||||||
echo -e "''${YELLOW}Step 2/5: Project Name''${NOCOLOR}"
|
local repo_abs="$1"
|
||||||
echo ""
|
local git_dir exclude_file tmp_file
|
||||||
read -p " Enter development environment name [devShell]: " PROJECT_NAME
|
git_dir="$(git -C "$repo_abs" rev-parse --git-dir)"
|
||||||
|
exclude_file="$git_dir/info/exclude"
|
||||||
|
|
||||||
if [[ -z "$PROJECT_NAME" ]]; then
|
[[ -f "$exclude_file" ]] || return 0
|
||||||
PROJECT_NAME="devShell"
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_success "Project name: $PROJECT_NAME"
|
tmp_file="$(mktemp)"
|
||||||
echo ""
|
cp "$exclude_file" "$tmp_file"
|
||||||
|
|
||||||
# ---- Step 3: Select template ----
|
for entry in "''${DIRENV_LOCAL_FILES[@]}"; do
|
||||||
echo -e "''${YELLOW}Step 3/5: Select Template''${NOCOLOR}"
|
if grep -qxF "$entry" "$tmp_file" 2>/dev/null; then
|
||||||
echo ""
|
grep -vxF "$entry" "$tmp_file" > "''${tmp_file}.new" || true
|
||||||
echo " 1) Empty - Basic shell, add packages yourself"
|
mv "''${tmp_file}.new" "$tmp_file"
|
||||||
echo " 2) Python - Python 3, pip, venv setup"
|
print_success "$entry → removed from .git/info/exclude"
|
||||||
echo " 3) Node.js - Node.js, npm"
|
else
|
||||||
echo " 4) Rust - Rustc, cargo, rust-analyzer"
|
print_info "$entry not present in .git/info/exclude, skipping."
|
||||||
echo " 5) Go - Go, gopls, golangci-lint"
|
fi
|
||||||
echo " 6) C/C++ - GCC, CMake, GDB, pkg-config"
|
done
|
||||||
echo " 7) Java - JDK 21, Maven"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p " Select template [1-7] (default: 1): " TEMPLATE_CHOICE
|
mv "$tmp_file" "$exclude_file"
|
||||||
|
}
|
||||||
|
|
||||||
case "$TEMPLATE_CHOICE" in
|
case "''${2:-init}" in
|
||||||
2)
|
|
||||||
TEMPLATE="python3"
|
|
||||||
PACKAGES="python3 python3Packages.pip python3Packages.virtualenv"
|
|
||||||
BUILD_INPUTS=""
|
|
||||||
SHELL_HOOK_EXTRA="
|
|
||||||
if [ ! -d .venv ]; then
|
|
||||||
echo 'Creating Python virtual environment...'
|
|
||||||
python3 -m venv .venv
|
|
||||||
fi
|
|
||||||
source .venv/bin/activate
|
|
||||||
echo 'Python venv activated.'
|
|
||||||
"
|
|
||||||
;;
|
|
||||||
3)
|
|
||||||
TEMPLATE="node"
|
|
||||||
PACKAGES="nodejs_22"
|
|
||||||
BUILD_INPUTS=""
|
|
||||||
SHELL_HOOK_EXTRA='echo "Node.js $(node --version) ready."'
|
|
||||||
;;
|
|
||||||
4)
|
|
||||||
TEMPLATE="rust"
|
|
||||||
PACKAGES="rustc cargo rust-analyzer"
|
|
||||||
BUILD_INPUTS="openssl pkg-config"
|
|
||||||
SHELL_HOOK_EXTRA='echo "Rust $(rustc --version) ready."'
|
|
||||||
;;
|
|
||||||
5)
|
|
||||||
TEMPLATE="go"
|
|
||||||
PACKAGES="go gopls golangci-lint"
|
|
||||||
BUILD_INPUTS=""
|
|
||||||
SHELL_HOOK_EXTRA='
|
|
||||||
export GOPATH="$PWD/.gopath"
|
|
||||||
export PATH="$GOPATH/bin:$PATH"
|
|
||||||
mkdir -p "$GOPATH"
|
|
||||||
echo "Go $(go version) ready. GOPATH: $GOPATH"
|
|
||||||
'
|
|
||||||
;;
|
|
||||||
6)
|
|
||||||
TEMPLATE="cpp"
|
|
||||||
PACKAGES="gcc gdb cmake gnumake"
|
|
||||||
BUILD_INPUTS="pkg-config"
|
|
||||||
SHELL_HOOK_EXTRA='echo "GCC $(gcc --version | head -1) ready."'
|
|
||||||
;;
|
|
||||||
7)
|
|
||||||
TEMPLATE="java"
|
|
||||||
PACKAGES="jdk21 maven"
|
|
||||||
BUILD_INPUTS=""
|
|
||||||
SHELL_HOOK_EXTRA='echo "Java $(java --version | head -1) ready."'
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
TEMPLATE="empty"
|
|
||||||
PACKAGES=""
|
|
||||||
BUILD_INPUTS=""
|
|
||||||
SHELL_HOOK_EXTRA=""
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
print_success "Selected template: $TEMPLATE"
|
untrack)
|
||||||
echo ""
|
|
||||||
|
|
||||||
# ---- Step 4: Copy and modify flake ----
|
|
||||||
echo -e "''${YELLOW}Step 4/5: Generating flake.nix''${NOCOLOR}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
cp "$SOURCE_FLAKE" "$TARGET_DIR/flake.nix"
|
|
||||||
print_success "Copied flake.nix to $TARGET_DIR/"
|
|
||||||
|
|
||||||
sed -i "s|name = \"replaceNameHere\";|name = \"''${PROJECT_NAME}\";|" "$TARGET_DIR/flake.nix"
|
|
||||||
print_success "Set project name: $PROJECT_NAME"
|
|
||||||
|
|
||||||
if [[ -n "$PACKAGES" ]]; then
|
|
||||||
sed -i "s|# replacePackagesHere|$PACKAGES|" "$TARGET_DIR/flake.nix"
|
|
||||||
print_success "Added packages: $PACKAGES"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$BUILD_INPUTS" ]]; then
|
|
||||||
BUILD_INPUTS_LINE="buildInputs = with pkgs; [ $BUILD_INPUTS ];"
|
|
||||||
sed -i "s|# replaceBuildInputsHere|$BUILD_INPUTS_LINE|" "$TARGET_DIR/flake.nix"
|
|
||||||
print_success "Added build inputs: $BUILD_INPUTS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$SHELL_HOOK_EXTRA" ]]; then
|
|
||||||
awk -v hook="$SHELL_HOOK_EXTRA" '/# replaceShellHookHere/ { print hook; next } { print }' \
|
|
||||||
"$TARGET_DIR/flake.nix" > "$TARGET_DIR/flake.nix.tmp" \
|
|
||||||
&& mv "$TARGET_DIR/flake.nix.tmp" "$TARGET_DIR/flake.nix"
|
|
||||||
print_success "Added template-specific shell hook"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ---- Step 5: Git Integration & .envrc ----
|
|
||||||
echo -e "''${YELLOW}Step 5/5: Git Integration''${NOCOLOR}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
|
|
||||||
|
|
||||||
echo "Creating .envrc for direnv to automatically work!"
|
|
||||||
if ! grep -qxF "use flake" "$TARGET_ABS/.envrc" 2>/dev/null; then
|
|
||||||
echo "use flake" >> "$TARGET_ABS/.envrc"
|
|
||||||
print_success ".envrc created at $TARGET_ABS/"
|
|
||||||
else
|
|
||||||
print_info ".envrc already contains 'use flake', skipping."
|
|
||||||
fi
|
|
||||||
|
|
||||||
if git -C "$TARGET_ABS" rev-parse --git-dir > /dev/null 2>&1; then
|
|
||||||
echo " A Git repository was detected at:"
|
|
||||||
echo " $(git -C "$TARGET_ABS" rev-parse --show-toplevel)"
|
|
||||||
echo ""
|
echo ""
|
||||||
|
echo -e "''${BLUE}--- Dev: Track Files (assume-unchanged) ---''${NOCOLOR}"
|
||||||
|
echo ""
|
||||||
|
_dev_resolve_dir
|
||||||
|
|
||||||
|
acted=false
|
||||||
|
for f in "''${DEV_FILES[@]}"; do
|
||||||
|
full="$TARGET_ABS/$f"
|
||||||
|
if [[ ! -f "$full" ]]; then
|
||||||
|
print_info "$f not found in $TARGET_ABS — skipping."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! git -C "$TARGET_ABS" ls-files --error-unmatch "$f" > /dev/null 2>&1; then
|
||||||
|
git -C "$TARGET_ABS" add --intent-to-add "$f"
|
||||||
|
fi
|
||||||
|
git -C "$TARGET_ABS" update-index --assume-unchanged "$f"
|
||||||
|
print_success "$f → untracked (assume-unchanged)"
|
||||||
|
acted=true
|
||||||
|
done
|
||||||
|
|
||||||
_add_local_excludes "$TARGET_ABS"
|
_add_local_excludes "$TARGET_ABS"
|
||||||
|
|
||||||
|
if ! $acted; then
|
||||||
|
print_info "No dev files found in '$TARGET_ABS' to track."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
track)
|
||||||
|
echo ""
|
||||||
|
echo -e "''${BLUE}--- Dev: Untrack Files (remove assume-unchanged) ---''${NOCOLOR}"
|
||||||
|
echo ""
|
||||||
|
_dev_resolve_dir
|
||||||
|
|
||||||
|
acted=false
|
||||||
|
for f in "''${DEV_FILES[@]}"; do
|
||||||
|
if git -C "$TARGET_ABS" ls-files -v "$f" 2>/dev/null | grep -q "^h "; then
|
||||||
|
git -C "$TARGET_ABS" update-index --no-assume-unchanged "$f"
|
||||||
|
print_success "$f → tracked (assume-unchanged removed)"
|
||||||
|
acted=true
|
||||||
|
else
|
||||||
|
print_info "$f is not marked assume-unchanged — skipping."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
_remove_local_excludes "$TARGET_ABS"
|
||||||
|
|
||||||
|
if ! $acted; then
|
||||||
|
print_info "No files in '$TARGET_ABS' had the assume-unchanged bit set."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
init|*)
|
||||||
|
SOURCE_FLAKE="$HOME/${lib.project}/other/dev-template.nix"
|
||||||
|
|
||||||
|
if [[ ! -f "$SOURCE_FLAKE" ]]; then
|
||||||
|
print_error "Source flake template not found: $SOURCE_FLAKE"
|
||||||
|
echo "Please ensure dev-template.nix exists in $HOME/${lib.project}/other/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_header
|
||||||
|
|
||||||
|
# ---- Step 1: Target Directory ----
|
||||||
|
echo -e "''${YELLOW}Step 1/5: Target Directory''${NOCOLOR}"
|
||||||
|
echo ""
|
||||||
|
read -p " Enter target directory [./]: " TARGET_DIR
|
||||||
|
|
||||||
|
if [[ -z "$TARGET_DIR" ]]; then
|
||||||
|
TARGET_DIR="./"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "$TARGET_DIR" ]]; then
|
||||||
|
print_error "Directory '$TARGET_DIR' does not exist. Exiting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_success "Target directory: $TARGET_DIR"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo " Nix flakes require flake.nix (and flake.lock) to be Git-tracked."
|
# ---- Check for existing flake ----
|
||||||
echo " This script can stage them as 'assume-unchanged' so Nix sees them,"
|
if [[ -f "$TARGET_DIR/flake.nix" ]]; then
|
||||||
echo " but they will NEVER be committed or show up in git status."
|
|
||||||
echo ""
|
|
||||||
read -p " Set up flake files as tracked-but-invisible to Git? [y/N]: " GIT_CHOICE
|
|
||||||
|
|
||||||
GIT_CHOICE="''${GIT_CHOICE:-N}"
|
|
||||||
|
|
||||||
if [[ "$GIT_CHOICE" =~ ^[Yy]$ ]]; then
|
|
||||||
cat > "$TARGET_ABS/flake.lock" << 'FLAKE_LOCK_EOF'
|
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"root": {}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
||||||
FLAKE_LOCK_EOF
|
|
||||||
print_success "flake.lock ready (Nix will populate it on first run if empty)"
|
|
||||||
|
|
||||||
git -C "$TARGET_ABS" add --intent-to-add flake.nix flake.lock
|
|
||||||
git -C "$TARGET_ABS" update-index --assume-unchanged flake.nix flake.lock
|
|
||||||
print_success "flake.nix + flake.lock → tracked (assume-unchanged)"
|
|
||||||
else
|
|
||||||
print_info "Skipped. You can do this manually later:"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " git -C \"$TARGET_ABS\" add --intent-to-add flake.nix flake.lock"
|
print_error "A flake.nix already exists in '$TARGET_DIR'!"
|
||||||
echo " git -C \"$TARGET_ABS\" update-index --assume-unchanged flake.nix flake.lock"
|
echo ""
|
||||||
|
read -p " Would you like to just place the .envrc instead? [y/N]: " ENVRC_ONLY
|
||||||
|
ENVRC_ONLY="''${ENVRC_ONLY:-N}"
|
||||||
|
|
||||||
|
if [[ "$ENVRC_ONLY" =~ ^[Yy]$ ]]; then
|
||||||
|
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
|
||||||
|
echo ""
|
||||||
|
print_info "Placing .envrc only..."
|
||||||
|
if ! grep -qxF "use flake" "$TARGET_ABS/.envrc" 2>/dev/null; then
|
||||||
|
echo "use flake" >> "$TARGET_ABS/.envrc"
|
||||||
|
print_success ".envrc created at $TARGET_ABS/"
|
||||||
|
else
|
||||||
|
print_info ".envrc already contains 'use flake', nothing to do."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
print_info "Next steps:"
|
||||||
|
echo " cd $TARGET_DIR"
|
||||||
|
echo " direnv allow"
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
print_info "Aborting. No files were changed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---- Step 2: Project Name ----
|
||||||
|
echo -e "''${YELLOW}Step 2/5: Project Name''${NOCOLOR}"
|
||||||
|
echo ""
|
||||||
|
read -p " Enter development environment name [devShell]: " PROJECT_NAME
|
||||||
|
|
||||||
|
if [[ -z "$PROJECT_NAME" ]]; then
|
||||||
|
PROJECT_NAME="devShell"
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_success "Project name: $PROJECT_NAME"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ---- Step 3: Select template ----
|
||||||
|
echo -e "''${YELLOW}Step 3/5: Select Template''${NOCOLOR}"
|
||||||
|
echo ""
|
||||||
|
echo " 1) Empty - Basic shell, add packages yourself"
|
||||||
|
echo " 2) Python - Python 3, pip, venv setup"
|
||||||
|
echo " 3) Node.js - Node.js, npm"
|
||||||
|
echo " 4) Rust - Rustc, cargo, rust-analyzer"
|
||||||
|
echo " 5) Go - Go, gopls, golangci-lint"
|
||||||
|
echo " 6) C/C++ - GCC, CMake, GDB, pkg-config"
|
||||||
|
echo " 7) Java - JDK 21, Maven"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p " Select template [1-7] (default: 1): " TEMPLATE_CHOICE
|
||||||
|
|
||||||
|
case "$TEMPLATE_CHOICE" in
|
||||||
|
2)
|
||||||
|
TEMPLATE="python3"
|
||||||
|
PACKAGES="python3 python3Packages.pip python3Packages.virtualenv"
|
||||||
|
BUILD_INPUTS=""
|
||||||
|
SHELL_HOOK_EXTRA="
|
||||||
|
if [ ! -d .venv ]; then
|
||||||
|
echo 'Creating Python virtual environment...'
|
||||||
|
python3 -m venv .venv
|
||||||
|
fi
|
||||||
|
source .venv/bin/activate
|
||||||
|
echo 'Python venv activated.'
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
TEMPLATE="node"
|
||||||
|
PACKAGES="nodejs_22"
|
||||||
|
BUILD_INPUTS=""
|
||||||
|
SHELL_HOOK_EXTRA='echo "Node.js $(node --version) ready."'
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
TEMPLATE="rust"
|
||||||
|
PACKAGES="rustc cargo rust-analyzer"
|
||||||
|
BUILD_INPUTS="openssl pkg-config"
|
||||||
|
SHELL_HOOK_EXTRA='echo "Rust $(rustc --version) ready."'
|
||||||
|
;;
|
||||||
|
5)
|
||||||
|
TEMPLATE="go"
|
||||||
|
PACKAGES="go gopls golangci-lint"
|
||||||
|
BUILD_INPUTS=""
|
||||||
|
SHELL_HOOK_EXTRA='
|
||||||
|
export GOPATH="$PWD/.gopath"
|
||||||
|
export PATH="$GOPATH/bin:$PATH"
|
||||||
|
mkdir -p "$GOPATH"
|
||||||
|
echo "Go $(go version) ready. GOPATH: $GOPATH"
|
||||||
|
'
|
||||||
|
;;
|
||||||
|
6)
|
||||||
|
TEMPLATE="cpp"
|
||||||
|
PACKAGES="gcc gdb cmake gnumake"
|
||||||
|
BUILD_INPUTS="pkg-config"
|
||||||
|
SHELL_HOOK_EXTRA='echo "GCC $(gcc --version | head -1) ready."'
|
||||||
|
;;
|
||||||
|
7)
|
||||||
|
TEMPLATE="java"
|
||||||
|
PACKAGES="jdk21 maven"
|
||||||
|
BUILD_INPUTS=""
|
||||||
|
SHELL_HOOK_EXTRA='echo "Java $(java --version | head -1) ready."'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
TEMPLATE="empty"
|
||||||
|
PACKAGES=""
|
||||||
|
BUILD_INPUTS=""
|
||||||
|
SHELL_HOOK_EXTRA=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
print_success "Selected template: $TEMPLATE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ---- Step 4: Copy and modify flake ----
|
||||||
|
echo -e "''${YELLOW}Step 4/5: Generating flake.nix''${NOCOLOR}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
cp "$SOURCE_FLAKE" "$TARGET_DIR/flake.nix"
|
||||||
|
print_success "Copied flake.nix to $TARGET_DIR/"
|
||||||
|
|
||||||
|
sed -i "s|name = \"replaceNameHere\";|name = \"''${PROJECT_NAME}\";|" "$TARGET_DIR/flake.nix"
|
||||||
|
print_success "Set project name: $PROJECT_NAME"
|
||||||
|
|
||||||
|
if [[ -n "$PACKAGES" ]]; then
|
||||||
|
sed -i "s|# replacePackagesHere|$PACKAGES|" "$TARGET_DIR/flake.nix"
|
||||||
|
print_success "Added packages: $PACKAGES"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$BUILD_INPUTS" ]]; then
|
||||||
|
BUILD_INPUTS_LINE="buildInputs = with pkgs; [ $BUILD_INPUTS ];"
|
||||||
|
sed -i "s|# replaceBuildInputsHere|$BUILD_INPUTS_LINE|" "$TARGET_DIR/flake.nix"
|
||||||
|
print_success "Added build inputs: $BUILD_INPUTS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$SHELL_HOOK_EXTRA" ]]; then
|
||||||
|
awk -v hook="$SHELL_HOOK_EXTRA" '/# replaceShellHookHere/ { print hook; next } { print }' \
|
||||||
|
"$TARGET_DIR/flake.nix" > "$TARGET_DIR/flake.nix.tmp" \
|
||||||
|
&& mv "$TARGET_DIR/flake.nix.tmp" "$TARGET_DIR/flake.nix"
|
||||||
|
print_success "Added template-specific shell hook"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---- Step 5: Git Integration & .envrc ----
|
||||||
|
echo -e "''${YELLOW}Step 5/5: Git Integration''${NOCOLOR}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
|
||||||
|
|
||||||
|
echo "Creating .envrc for direnv to automatically work!"
|
||||||
|
if ! grep -qxF "use flake" "$TARGET_ABS/.envrc" 2>/dev/null; then
|
||||||
|
echo "use flake" >> "$TARGET_ABS/.envrc"
|
||||||
|
print_success ".envrc created at $TARGET_ABS/"
|
||||||
|
else
|
||||||
|
print_info ".envrc already contains 'use flake', skipping."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if git -C "$TARGET_ABS" rev-parse --git-dir > /dev/null 2>&1; then
|
||||||
|
echo " A Git repository was detected at:"
|
||||||
|
echo " $(git -C "$TARGET_ABS" rev-parse --show-toplevel)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
_add_local_excludes "$TARGET_ABS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo " Nix flakes require flake.nix (and flake.lock) to be Git-tracked."
|
||||||
|
echo " This script can stage them as 'assume-unchanged' so Nix sees them,"
|
||||||
|
echo " but they will NEVER be committed or show up in git status."
|
||||||
|
echo ""
|
||||||
|
read -p " Set up flake files as tracked-but-invisible to Git? [y/N]: " GIT_CHOICE
|
||||||
|
|
||||||
|
GIT_CHOICE="''${GIT_CHOICE:-N}"
|
||||||
|
|
||||||
|
if [[ "$GIT_CHOICE" =~ ^[Yy]$ ]]; then
|
||||||
|
cat > "$TARGET_ABS/flake.lock" << 'FLAKE_LOCK_EOF'
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"root": {}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
|
FLAKE_LOCK_EOF
|
||||||
|
print_success "flake.lock ready (Nix will populate it on first run if empty)"
|
||||||
|
|
||||||
|
git -C "$TARGET_ABS" add --intent-to-add flake.nix flake.lock
|
||||||
|
git -C "$TARGET_ABS" update-index --assume-unchanged flake.nix flake.lock
|
||||||
|
print_success "flake.nix + flake.lock → tracked (assume-unchanged)"
|
||||||
|
else
|
||||||
|
print_info "Skipped. You can do this manually later:"
|
||||||
|
echo ""
|
||||||
|
echo " git -C \"$TARGET_ABS\" add --intent-to-add flake.nix flake.lock"
|
||||||
|
echo " git -C \"$TARGET_ABS\" update-index --assume-unchanged flake.nix flake.lock"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_info "No Git repository detected — skipping Git integration."
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
print_info "No Git repository detected — skipping Git integration."
|
# ---- Done ----
|
||||||
|
echo -e "''${GREEN}==============================================''${NOCOLOR}"
|
||||||
|
echo -e "''${GREEN} Done! Your flake is ready at:''${NOCOLOR}"
|
||||||
|
echo -e "''${GREEN} $TARGET_DIR/flake.nix''${NOCOLOR}"
|
||||||
|
echo -e "''${GREEN}==============================================''${NOCOLOR}"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
print_info "Next steps:"
|
||||||
|
echo " cd $TARGET_DIR"
|
||||||
|
echo " direnv allow # Trust the .envrc so direnv auto-activates"
|
||||||
|
echo " nix develop # Or just: cd out and back in"
|
||||||
|
echo ""
|
||||||
|
;;
|
||||||
|
|
||||||
# ---- Done ----
|
esac
|
||||||
echo -e "''${GREEN}==============================================''${NOCOLOR}"
|
|
||||||
echo -e "''${GREEN} Done! Your flake is ready at:''${NOCOLOR}"
|
|
||||||
echo -e "''${GREEN} $TARGET_DIR/flake.nix''${NOCOLOR}"
|
|
||||||
echo -e "''${GREEN}==============================================''${NOCOLOR}"
|
|
||||||
echo ""
|
|
||||||
print_info "Next steps:"
|
|
||||||
echo " cd $TARGET_DIR"
|
|
||||||
echo " direnv allow # Trust the .envrc so direnv auto-activates"
|
|
||||||
echo " nix develop # Or just: cd out and back in"
|
|
||||||
echo ""
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
# ncli/commands/git.nix — commit, push, pull, status, format
|
# ncli/commands/git.nix — commit, push, pull, status, format
|
||||||
lib:
|
lib: let
|
||||||
|
|
||||||
let
|
|
||||||
inherit (lib) project;
|
inherit (lib) project;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
commit_case = ''
|
commit_case = ''
|
||||||
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
|
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
|
||||||
if [ "$#" -lt 2 ]; then
|
if [ "$#" -lt 2 ]; then
|
||||||
@ -20,29 +17,24 @@ in
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
git add -A && git commit -m "$commit_msg"
|
git add -A && git commit -m "$commit_msg"
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
push_case = ''
|
push_case = ''
|
||||||
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
|
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
|
||||||
git push origin $(git branch --show-current)
|
git push origin $(git branch --show-current)
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
pull_case = ''
|
pull_case = ''
|
||||||
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
|
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
|
||||||
git pull origin $(git branch --show-current)
|
git pull origin $(git branch --show-current)
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
status_case = ''
|
status_case = ''
|
||||||
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
|
cd "$HOME/${project}" || { echo "Error: Could not change to $HOME/${project}"; exit 1; }
|
||||||
git status
|
git status
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
format_case = ''
|
format_case = ''
|
||||||
nix fmt .
|
nix fmt .
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
# ncli/commands/maintenance.nix — cleanup, diag, list-gens, trim, home-backups
|
# ncli/commands/maintenance.nix — cleanup, diag, list-gens, trim, home-backups
|
||||||
lib:
|
lib: let
|
||||||
|
|
||||||
let
|
|
||||||
inherit (lib) project;
|
inherit (lib) project;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
cleanup_case = ''
|
cleanup_case = ''
|
||||||
echo "Warning! This will remove old generations of your system."
|
echo "Warning! This will remove old generations of your system."
|
||||||
read -p "How many generations to keep (default: all)? " keep_count
|
read -p "How many generations to keep (default: all)? " keep_count
|
||||||
@ -33,7 +30,6 @@ in
|
|||||||
echo "Cleaning up old log files..." >> "$LOG_FILE"
|
echo "Cleaning up old log files..." >> "$LOG_FILE"
|
||||||
find "$LOG_DIR" -type f -mtime +3 -name "*.log" -delete >> "$LOG_FILE" 2>&1
|
find "$LOG_DIR" -type f -mtime +3 -name "*.log" -delete >> "$LOG_FILE" 2>&1
|
||||||
echo "Cleanup process logged to $LOG_FILE"
|
echo "Cleanup process logged to $LOG_FILE"
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
diag_case = ''
|
diag_case = ''
|
||||||
@ -50,7 +46,6 @@ in
|
|||||||
echo ""
|
echo ""
|
||||||
} > "$HOME/diag.txt"
|
} > "$HOME/diag.txt"
|
||||||
echo "Diagnostic report saved to $HOME/diag.txt"
|
echo "Diagnostic report saved to $HOME/diag.txt"
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
list_gens_case = ''
|
list_gens_case = ''
|
||||||
@ -59,7 +54,6 @@ in
|
|||||||
echo ""
|
echo ""
|
||||||
echo "--- System Generations ---"
|
echo "--- System Generations ---"
|
||||||
nix profile history --profile /nix/var/nix/profiles/system | cat || echo "Could not list system generations."
|
nix profile history --profile /nix/var/nix/profiles/system | cat || echo "Could not list system generations."
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
trim_case = ''
|
trim_case = ''
|
||||||
@ -73,11 +67,9 @@ in
|
|||||||
else
|
else
|
||||||
echo "Trim operation cancelled."
|
echo "Trim operation cancelled."
|
||||||
fi
|
fi
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
home_backups_case = ''
|
home_backups_case = ''
|
||||||
ls -a ~ | grep backup
|
ls -a ~ | grep backup
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
# ncli/commands/rebuild.nix — Rebuild + Update logic
|
# ncli/commands/rebuild.nix — Rebuild + Update logic
|
||||||
lib:
|
lib: let
|
||||||
|
|
||||||
let
|
|
||||||
inherit (lib) host project handle_backups handle_build_error;
|
inherit (lib) host project handle_backups handle_build_error;
|
||||||
in
|
in rec {
|
||||||
{
|
|
||||||
# Shared rebuild snippet used by both `rebuild` and `update`
|
# Shared rebuild snippet used by both `rebuild` and `update`
|
||||||
rebuild_logic = ''
|
rebuild_logic = ''
|
||||||
handle_backups
|
handle_backups
|
||||||
@ -21,7 +18,10 @@ in
|
|||||||
${rebuild_logic}
|
${rebuild_logic}
|
||||||
echo -e "Starting NixOS rebuild for current host: ${host} on generation: $YELLOW$geno$NOCOLOR"
|
echo -e "Starting NixOS rebuild for current host: ${host} on generation: $YELLOW$geno$NOCOLOR"
|
||||||
|
|
||||||
sudo nixos-rebuild switch --flake . ; _rebuild_exit=$?
|
set +e
|
||||||
|
sudo nixos-rebuild switch --flake .
|
||||||
|
_rebuild_exit=$?
|
||||||
|
set -e
|
||||||
if [ "$_rebuild_exit" -eq 0 ]; then
|
if [ "$_rebuild_exit" -eq 0 ]; then
|
||||||
echo "✓ Rebuild finished successfully for ${host}"
|
echo "✓ Rebuild finished successfully for ${host}"
|
||||||
|
|
||||||
@ -38,7 +38,6 @@ in
|
|||||||
echo "✗ Rebuild failed for ${host}" >&2
|
echo "✗ Rebuild failed for ${host}" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
update_case = ''
|
update_case = ''
|
||||||
@ -110,7 +109,10 @@ in
|
|||||||
echo "Rebuilding system... Staying on current specialization"
|
echo "Rebuilding system... Staying on current specialization"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo nixos-rebuild switch --flake . ; _rebuild_exit=$?
|
set +e
|
||||||
|
sudo nixos-rebuild switch --flake .
|
||||||
|
_rebuild_exit=$?
|
||||||
|
set -e
|
||||||
if [ "$_rebuild_exit" -eq 0 ]; then
|
if [ "$_rebuild_exit" -eq 0 ]; then
|
||||||
echo "✓ Update and rebuild finished successfully for ${host}"
|
echo "✓ Update and rebuild finished successfully for ${host}"
|
||||||
|
|
||||||
@ -127,6 +129,5 @@ in
|
|||||||
echo "✗ Update and rebuild failed for ${host}" >&2
|
echo "✗ Update and rebuild failed for ${host}" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
# ncli/commands/switch.nix — Specialization switching
|
# ncli/commands/switch.nix — Specialization switching
|
||||||
lib:
|
lib: {
|
||||||
|
|
||||||
{}:
|
|
||||||
|
|
||||||
{
|
|
||||||
switch_case = ''
|
switch_case = ''
|
||||||
current=""
|
current=""
|
||||||
if [ -f /etc/nixos-tags ]; then
|
if [ -f /etc/nixos-tags ]; then
|
||||||
@ -35,6 +31,5 @@ lib:
|
|||||||
echo "To switch to a specialization, run: 'ncli switch <tag>'"
|
echo "To switch to a specialization, run: 'ncli switch <tag>'"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,3 @@
|
|||||||
# ncli/default.nix — Entry point
|
|
||||||
# Usage in your flake:
|
|
||||||
# ncli = import ./ncli { inherit pkgs host project; };
|
|
||||||
# environment.systemPackages = [ ncli ];
|
|
||||||
{
|
{
|
||||||
pkgs,
|
pkgs,
|
||||||
host,
|
host,
|
||||||
|
|||||||
@ -13,64 +13,76 @@ in
|
|||||||
|
|
||||||
# --- Backup helper ---
|
# --- Backup helper ---
|
||||||
handle_backups = ''
|
handle_backups = ''
|
||||||
if [ ''${#BACKUP_FILES[@]} -eq 0 ]; then
|
handle_backups() {
|
||||||
echo "No backup files configured to check."
|
echo "Checking for backup files to remove..."
|
||||||
return
|
found=0
|
||||||
fi
|
for file_path in "''${BACKUP_FILES[@]}"; do
|
||||||
|
full_path="$HOME/$file_path"
|
||||||
echo "Checking for backup files to remove..."
|
if [ -f "$full_path" ]; then
|
||||||
for file_path in "''${BACKUP_FILES[@]}"; do
|
echo "Removing stale backup file: $full_path"
|
||||||
full_path="$HOME/$file_path"
|
rm "$full_path"
|
||||||
if [ -f "$full_path" ]; then
|
found=1
|
||||||
echo "Removing stale backup file: $full_path"
|
fi
|
||||||
rm "$full_path"
|
done
|
||||||
|
if [ "$found" -eq 0 ]; then
|
||||||
|
echo "No stale backup files found."
|
||||||
fi
|
fi
|
||||||
done
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# --- OOM / build error handler ---
|
# --- OOM / build error handler ---
|
||||||
handle_build_error = ''
|
handle_build_error = ''
|
||||||
local exit_code=$?
|
handle_build_error() {
|
||||||
if [ "$exit_code" -eq 137 ]; then
|
local exit_code=$?
|
||||||
echo ""
|
if [ "$exit_code" -eq 137 ]; then
|
||||||
echo -e "''${RED}╔══════════════════════════════════════════════════════════╗''${NOCOLOR}"
|
echo ""
|
||||||
echo -e "''${RED}║ BUILD KILLED — Signal 9 (SIGKILL) detected ║''${NOCOLOR}"
|
echo -e "''${RED}╔══════════════════════════════════════════════════════════╗''${NOCOLOR}"
|
||||||
echo -e "''${RED}╚══════════════════════════════════════════════════════════╝''${NOCOLOR}"
|
echo -e "''${RED}║ BUILD KILLED — Signal 9 (SIGKILL) detected ║''${NOCOLOR}"
|
||||||
echo ""
|
echo -e "''${RED}╚══════════════════════════════════════════════════════════╝''${NOCOLOR}"
|
||||||
echo -e "''${YELLOW}What happened:''${NOCOLOR}"
|
echo ""
|
||||||
echo " The build process was forcefully terminated by the OS."
|
echo -e "''${YELLOW}What happened:''${NOCOLOR}"
|
||||||
echo " This is almost always the Linux kernel OOM killer running out"
|
echo " The build process was forcefully terminated by the OS."
|
||||||
echo " of RAM + swap during Nix evaluation or compilation."
|
echo " This is almost always the Linux kernel OOM killer running out"
|
||||||
echo ""
|
echo " of RAM + swap during Nix evaluation or compilation."
|
||||||
echo -e "''${YELLOW}Suggested fixes (try in order):''${NOCOLOR}"
|
echo ""
|
||||||
echo ""
|
echo -e "''${YELLOW}Suggested fixes (try in order):''${NOCOLOR}"
|
||||||
echo -e " ''${GREEN}1. Reduce parallel jobs''${NOCOLOR} (lowest RAM usage):"
|
echo ""
|
||||||
echo " sudo nixos-rebuild switch --flake . --max-jobs 1 --cores 1"
|
echo -e " ''${GREEN}1. Reduce parallel jobs''${NOCOLOR} (lowest RAM usage):"
|
||||||
echo ""
|
echo " sudo nixos-rebuild switch --flake . --max-jobs 1 --cores 1"
|
||||||
echo -e " ''${GREEN}2. Confirm OOM killer fired:''${NOCOLOR}"
|
echo ""
|
||||||
echo " journalctl -k --since '5 minutes ago' | grep -i oom"
|
echo -e " ''${GREEN}2. Confirm OOM killer fired:''${NOCOLOR}"
|
||||||
echo ""
|
echo " journalctl -k --since '5 minutes ago' | grep -i oom"
|
||||||
fi
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# --- Print helpers (used by dev init) ---
|
# --- Print helpers (used by dev init) ---
|
||||||
print_header = ''
|
print_header = ''
|
||||||
echo ""
|
print_header() {
|
||||||
echo -e "''${BLUE}==============================================''${NOCOLOR}"
|
echo ""
|
||||||
echo -e "''${BLUE} Nix Flake Development Environment Initializer''${NOCOLOR}"
|
echo -e "''${BLUE}==============================================''${NOCOLOR}"
|
||||||
echo -e "''${BLUE}==============================================''${NOCOLOR}"
|
echo -e "''${BLUE} Nix Flake Development Environment Initializer''${NOCOLOR}"
|
||||||
echo ""
|
echo -e "''${BLUE}==============================================''${NOCOLOR}"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
print_success = ''
|
print_success = ''
|
||||||
echo -e "''${GREEN}[OK]''${NOCOLOR} $1"
|
print_success() {
|
||||||
|
echo -e "''${GREEN}[OK]''${NOCOLOR} $1"
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
print_error = ''
|
print_error = ''
|
||||||
echo -e "''${RED}[ERR]''${NOCOLOR} $1"
|
print_error() {
|
||||||
|
echo -e "''${RED}[ERR]''${NOCOLOR} $1"
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
print_info = ''
|
print_info = ''
|
||||||
echo -e "''${YELLOW}[->]''${NOCOLOR} $1"
|
print_info() {
|
||||||
|
echo -e "''${YELLOW}[->]''${NOCOLOR} $1"
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user