diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..15780df --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.backup \ No newline at end of file diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..1c380f7 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/nyx/bash/lib/git.sh b/nyx/bash/lib/git.sh new file mode 100644 index 0000000..1f62ff5 --- /dev/null +++ b/nyx/bash/lib/git.sh @@ -0,0 +1,407 @@ +######################################################################## +# Default Variables +######################################################################## +#echo "Debug - git.sh loaded" +setup_git_vars () { + # Enforce dependencies between flags + if [[ "$auto_commit" == "true" ]]; then + if [[ "$auto_stage" != "true" ]]; then + log_warn "autoStage is disabled" + log_debug_warn "auto_stage is $auto_stage" + auto_commit=false + log_warn "Disabling autoCommit" + log_debug_warn "Setting auto_commit to $auto_commit" + log_warn "Please enable autoStage if you want to use this feature" + fi + fi + if [[ "$auto_push" == "true" ]]; then + if [[ "$auto_commit" != "true" ]]; then + log_warn "autoCommit is disabled" + log_debug_warn "auto_stage is $auto_stage" + auto_push=false + log_warn "Disabling autoPush" + log_debug_warn "Setting autoPush to $auto_push" + log_warn "Please enable autoCommit if you want to use this feature" + fi + fi +} + + + +######################################################################## +# Git wrapper +######################################################################## +git_wrapped_git() { + # Local variable for arguments just in case + local args=("$@") + "$git_bin" "${args[@]}" + return $? +} + +######################################################################## +# Layer 1 - No logs or tell out +######################################################################## +git_add_raw() { + local file="$1" + git_wrapped_git add "$file" + return $? +} + +git_commit_raw() { + local message="$1" + git_wrapped_git commit -m "$message" + return $? +} + +git_push_raw() { + git_wrapped_git push + return $? +} + +git_pull_rebase_raw() { + git_wrapped_git pull --rebase + return $? +} +git_pull_raw() { + git_wrapped_git --rebase + return $? +} + +git_reset_raw() { + local mode="${1:-soft}" # default mode: soft + local target="${2:-HEAD}" # default reset target: HEAD + git_wrapped_git reset "--$mode" "$target" + return $? +} + + + +######################################################################## +# Layer 2 - Logs or Tell out - Mainly Debug Logs +######################################################################## + +git_check_autoStage_enabled () { + if [[ "$auto_stage" == "true" ]]; then + log_debug_info "Auto Stage is enabled will execute function further" + return 0 + else + log_debug_warn "Auto Stage is disabled will not execute function further" + return 1 + fi +} + + +git_check_if_file_stage_valid () { + local file="$1" + # note file can also be a folder it was just easier + if [[ -e "$file" ]]; then + log_debug_ok "found file $file" + # check if the file has changes + if git_wrapped_git diff -- "$file" | grep -q .; then + log_debug_ok "file $file has changes" + return 0 + else + log_debug_warn "file $file has no changes and will be skipped" + return 1 + fi + else + log_debug_error "Did not find file $file." + return 1 + fi +} + +git_check_autoCommit_enabled () { + if [[ "$auto_commit" == "true" ]]; then + log_debug_info "Auto Commit is enabled will execute function further" + return 0 + else + log_debug_warn "Auto Commit is disabled will not execute function further" + return 1 + fi +} + +git_check_has_staged_files() { + local staged_files + # git diff --cached --name-only lists staged files + # If no output, there are no staged files to commit + staged_files=$(git_wrapped_git diff --cached --name-only) + if [[ -n "$staged_files" ]]; then + log_debug_ok "Found staged files to commit" + log_debug_info "Staged files:" + log_debug_info "$staged_files" + return 0 + else + log_debug_warn "No staged files found" + return 1 + fi +} + +git_check_autoPush_enabled () { + if [[ "$auto_push" == "true" ]]; then + log_debug_info "Auto Push is enabled will execute function further" + return 0 + else + log_debug_warn "Auto Push is disabled will not execute function further" + return 1 + fi +} + + + +git_check_has_staged_files() { + local staged_files + # git diff --cached --name-only lists staged files + # If no output, there are no staged files to commit + staged_files=$(git_wrapped_git diff --cached --name-only) + if [[ -n "$staged_files" ]]; then + log_debug_warn "Found staged files to commit" + log_debug_info "Staged files:" + log_debug_info "$staged_files" + return 0 + else + log_debug_ok "No staged files found - Nothing uncommitted" + return 1 + fi +} + +# Returns 0 if there are unstaged +git_check_has_unstaged_files() { + local unstaged_files + # git diff --name-only lists unstaged files + staged_files=$(git_wrapped_git diff --name-only) + if [[ -n "$staged_files" ]]; then + log_debug_warn "Unstaged files detected" + log_debug_info "Unstaged files:" + log_debug_info "$unstaged_files" + return 0 + else + log_debug_warn "No unstaged files" + return 1 + fi +} + + +git_check_if_dir_is_in_repo() { + local file="${1:-.}" # defaults to current dir if no file passed + if [[ -e "$file" ]]; then + log_debug_ok "found file $file" + # note file can also be a folder it was just easier to name it like so + if git_wrapped_git -C "$file" rev-parse --is-inside-work-tree >/dev/null 2>&1; then + log_debug_ok "file $file is in git repo" + return 0 + else + log_debug_error "file $file is not in a git repo" + return 1 + fi + else + log_debug_error "Did not find file $file." + return 1 + fi +} + +git_check_necessary_for_rebase() { + # Reuse: first check if we are behind upstream + if ! git_check_if_behind_upstream; then + log_debug_info "No rebase necessary: branch is not behind upstream" + return 1 + fi + + local branch ahead behind + branch=$(git_wrapped_git rev-parse --abbrev-ref HEAD 2>/dev/null) + ahead=$(git_wrapped_git rev-list --count "@{u}..${branch}") + behind=$(git_wrapped_git rev-list --count "${branch}..@{u}") + + if [[ $ahead -gt 0 && $behind -gt 0 ]]; then + log_debug_ok "Branch $branch has diverged (ahead: $ahead, behind: $behind), rebase required" + return 0 + fi + + log_debug_info "Branch $branch has no divergence (ahead: $ahead, behind: $behind)" + return 1 +} + +git_check_if_behind_upstream() { + # First make sure we are in a git repo + if ! git_check_if_dir_is_in_repo; then + log_debug_error "Not inside a git repository" + return 1 + fi + + # Make sure we have a tracking branch + if ! git_wrapped_git rev-parse --abbrev-ref "@{u}" >/dev/null 2>&1; then + log_debug_warn "Current branch has no upstream, cannot check if behind" + return 1 + fi + + git_wrapped_git fetch --quiet + + local behind_count + behind_count=$(git_wrapped_git rev-list --count "HEAD..@{u}") + + if [[ "$behind_count" -gt 0 ]]; then + log_debug_ok "Branch is behind upstream by $behind_count commits" + return 0 + else + log_debug_info "Branch is up to date with upstream" + return 1 + fi +} + + +######################################################################## +# Layer 3 - Logs or Tell out - Also used in Main Script directly +######################################################################## + +git_add () { + local file="$1" + # note file can also be a folder it was just easier + if git_check_autoStage_enabled; then + if git_check_if_file_stage_valid "$file"; then + if git_add_raw "$file"; then + log_ok "Added file: \"$file\"" + return 0 + else + log_error "Failed to add file: \"$file\"" + return 1 + fi + else + log_verbose_warn "Did not Stage: $file" + return 1 + fi + else + return 1 + fi +} + +git_commit () { + local message="$1" + if git_check_autoCommit_enabled; then + if git_check_has_staged_files; then + if git_commit_raw "$message"; then + log_ok "Committed with Message: \"$message\"" + return 0 + else + log_error "Commit failed with Message: \"$message\"" + return 1 + fi + else + log_verbose_warn "Nothing to commit. Would've committed with Message: \"$message\"" + return 1 + fi + else + return 1 + fi +} + +git_push () { + # Check if auto-push is enabled first + if git_check_autoPush_enabled; then + if git_push_raw; then + log_ok "Pushed to remote successfully" + return 0 + else + log_error "Push to remote failed" + return 1 + fi + else + log_verbose_warn "Auto Push disabled, skipping push" + return 1 + fi +} + +git_pull_rebase() { + + # check if current dir is in git repo + if ! git_wrapped_git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + log_error "Not inside a git repository, cannot pull" + return 1 + fi + + if git_check_necessary_for_rebase; then + # Rebase mode: we have local commits and are behind upstream + if git_wrapped_git pull --rebase; then + log_ok "Pulled from remote and rebased successfully" + return 0 + else + log_error "Pull with rebase failed" + return 1 + fi + elif git_check_if_behind_upstream; then + # Behind but no local commits โ†’ simple fast-forward pull + if git_wrapped_git pull; then + log_ok "Pulled from remote successfully (fast-forward)" + return 0 + else + log_error "Pull from remote failed" + return 1 + fi + else + log_info "Branch is already up to date, no pull required" + return 0 + fi +} + +git_reset() { + local mode="${1:-soft}" # default reset mode is soft + local target="${2:-HEAD}" # commit hash, branch, or tag + + log_info "Resetting to target: $target (mode: $mode)" + if git_reset_raw "$mode" "$target"; then + log_ok "Successfully reset to $target with --$mode" + return 0 + else + log_error "Failed to reset to $target" + return 1 + fi +} + + +git_store_starting_commit () { + # Get the current HEAD commit hash + local commit + commit=$(git_wrapped_git rev-parse HEAD 2>/dev/null) + + if [[ $? -eq 0 && -n "$commit" ]]; then + git_starting_commit="$commit" + log_debug_info "Stored starting commit: $git_starting_commit" + return 0 + else + log_debug_error "Unable to retrieve current commit hash" + return 1 + fi +} + +######################################################################## +# COMPILED FUNCTION SUMMARY +# +######################################################################## +# SETUP +######################################################################## +# setup_git_vars() +# Ensures auto_stage / auto_commit / auto_push flags are consistent. +# If dependencies are not satisfied, disables dependent flags and logs warnings. +# +######################################################################## +# LAYER 3: MAIN FUNCTIONS +######################################################################## +# git_add +# Stages file if auto_stage is enabled and file is valid. +# +# git_commit +# Commits staged files if auto_commit is enabled and there are staged files. +# +# git_push +# Pushes current branch if auto_push is enabled. +# +# git_pull_rebase +# Pulls latest changes. Uses rebase if local commits exist and branch has diverged. +# Falls back to fast-forward pull if only behind. Logs appropriately if up to date. +# +######################################################################## +# VARIABLES +######################################################################## +# auto_stage=true +# auto_commit=true +# auto_push=true +# +######################################################################## diff --git a/nyx/bash/lib/logging.sh b/nyx/bash/lib/logging.sh new file mode 100644 index 0000000..d12cc26 --- /dev/null +++ b/nyx/bash/lib/logging.sh @@ -0,0 +1,208 @@ +######################################################################## +# CONFIGURATION +######################################################################## +#echo "Debug - logging.sh loaded" + + +setup_logging_vars () { + local verbosity=${1:-3} # Default to max verbosity if not provided + NYX_VERBOSITY=$verbosity + log_to_file_disable +} +setup_logging_basic () { + + log_info "Log set to $NYX_VERBOSITY" + # Default log directory + log_info "Setting up LogDir in $log_subdir" + mkdir -p "$log_subdir" + + logPath="$log_subdir/log_$(date '+%Y-%m-%d_%H-%M-%S').log" + log_info "Full log is saved under $logPath" +} + + +######################################################################## +# Control whether logs are written to file +######################################################################## +log_to_file_enable () { + if [[ "$log_to_file" == "true" ]]; then + log_debug_info "log_to_file is already true" + log_debug_warn "log_to_file is $log_to_file" + else + log_to_file=true + log_verbose_warn "log_to_file is enabled" + log_debug_warn "log_to_file is $log_to_file" + fi +} + +log_to_file_disable () { + if [[ "$log_to_file" == "true" ]]; then + log_to_file=false + log_verbose_warn "log_to_file is disabled" + log_debug_warn "log_to_file is $log_to_file" + else + log_debug_info "log_to_file is already false" + log_debug_warn "log_to_file is $log_to_file" + fi +} + + +######################################################################## +# Write a log line to the file +######################################################################## +write_log() { + local line="$1" + echo "$line" >> "$logPath" +} + +######################################################################## +# Output with timestamp, level, color, and verbosity +######################################################################## +tell_out() { + local message="$1" + local level="${2:-INFO}" # Default level: INFO + local verbosity_level="${3:-1}" # Default verbosity level for message + local timestamp + timestamp=$(date '+%Y-%m-%d %H:%M:%S') + + # Append diagnostic info for errors + if [[ "$level" == "ERROR" ]]; then + tell_out "$message # $(what_messed_up)" "DEBUG" "3" + fi + + # Fixed width for level display + local level_fmt + local pad + pad=$(( (7 - ${#level}) / 2 )) + printf -v level_fmt "%*s%s%*s" $pad "" "$level" $((7 - pad - ${#level})) "" + + local log_line="[$timestamp] [${level_fmt}] $message" + local line=" [${level_fmt}] $message" + + # Only output messages if verbosity level is sufficient + if [[ $NYX_VERBOSITY -ge $verbosity_level ]]; then + case "$level" in + INFO) echo -e "\033[0;37m$line\033[0m" ;; # Gray + OK) echo -e "\033[0;32m$line\033[0m" ;; # Green + WARN) echo -e "\033[1;33m$line\033[0m" ;; # Yellow + ERROR) echo -e "\033[0;31m$line\033[0m" ;; # Red + CMD) echo -e "\033[0;36m$line\033[0m" ;; # Cyan + OTHER) echo -e "\033[0;35m$line\033[0m" ;; # Magenta + LINE) echo -e "\033[1;30m$line\033[0m" ;; # Dark Gray + *) echo -e "$line" ;; # Default no color + esac + fi + + # Always write to log file if enabled + if [[ "$log_to_file" == "true" ]]; then + write_log "$log_line" + fi +} + + + +######################################################################## +# Separator line for logs +######################################################################## +log_separator() { + local verbosity="${1:-0}" + tell_out "===========================================" "LINE" $verbosity +} + +######################################################################## +# Execute a command with logging and error handling +######################################################################## +execute() { + local command="$1" + local cmd_verbosity="${2:-2}" + + tell_out "Executing: $command" "CMD" "$cmd_verbosity" + tell_out "### Log from $command start ###" "CMD" "$cmd_verbosity" + log_separator "$cmd_verbosity" + + # Use a subshell and a pipe to tee both stdout and stderr to the log + # while preserving the exit code + local status + { + # Redirect stderr to stdout so both are captured + eval "$command" 2>&1 | while IFS= read -r line; do + tell_out "$line" "CMD" "$cmd_verbosity" + done + } + status=${PIPESTATUS[0]} # Capture exit code of eval, not the while loop + + log_separator "$cmd_verbosity" + + tell_out "### Log from $command end ###" "CMD" "$cmd_verbosity" + + # Log success or failure + if (( status == 0 )); then + tell_out "Execution successful: $command" "OK" "$cmd_verbosity" + else + tell_out "Error executing command: $command (exit code $status)" "ERROR" 0 + fi + + return $status +} + +######################################################################## +# Call stack helper for debugging +######################################################################## +what_messed_up() { + local stack=("${FUNCNAME[@]}") + local call_chain="" + #unset 'stack[0]' # remove current function + #unset 'stack[1]' # remove direct caller (log_error etc.) + #unset 'stack[-1]' # remove "main" + + # Join the remaining stack elements with " -> " + for function in "${stack[@]}"; do + if [[ -z "$call_chain" ]]; then + call_chain="$function" + else + call_chain="$call_chain -> $function" + fi + done + + echo "$call_chain" +} + + + +######################################################################## +# Verbosity helper functions +######################################################################## +log_debug_info() { tell_out "$1" "INFO" 3; } +log_debug_warn() { tell_out "$1" "WARN" 3; } +log_debug_ok() { tell_out "$1" "OK" 3; } +log_debug_error() { tell_out "$1" "ERROR" 3; } + + +log_verbose_ok () { tell_out "$1" "OK" 2; } +log_verbose_info () { tell_out "$1" "INFO" 2; } +log_verbose_warn () { tell_out "$1" "WARN" 2; } +log_verbose_error () { tell_out "$1" "ERROR" 2; } +log_verbose_end () { tell_out "$1" "END" 2; } + +log_ok() { tell_out "$1" "OK" 1; } +log_info() { tell_out "$1" "INFO" 1; } +log_warn() { tell_out "$1" "WARN" 1; } +log_error() { tell_out "$1" "ERROR" 0; } +log_end() { tell_out "$1" "END" 0; } + +######################################################################## +# USAGE SUMMARY +# +######################################################################## +# LOGGING FUNCTIONS +######################################################################## +# log_debug_* "Message" # with variations +# log_verbose "Message" # Shown at verbosity 2+ +# log_info "Message" # Standard info message (verbosity 1+) +# log_warn "Message" # Warning message (verbosity 1+) +# log_error "Message" # Error message (always shown) +# +# log_to_file_enable # Enable writing all logs to $logPath +# log_to_file_disable # Disable log file writing +# +######################################################################## diff --git a/nyx/bash/lib/sudo.sh b/nyx/bash/lib/sudo.sh new file mode 100644 index 0000000..d16dcfc --- /dev/null +++ b/nyx/bash/lib/sudo.sh @@ -0,0 +1,56 @@ +#echo "Debug - sudo.sh loaded" + + +check_if_run_with_sudo() { + log_debug_info "Checking if the script is being run with sudo or as root..." + + # Check if running as root + if [[ "$EUID" -eq 0 ]]; then + log_error "This script must NOT be run as root or with sudo." + log_debug_error "Detected EUID=0 (root). Please run as a normal user." + exit 1 + fi + + # Check if running through sudo + if [[ -n "$SUDO_USER" ]]; then + log_error "This script must NOT be run with sudo." + log_debug_error "Detected SUDO_USER='$SUDO_USER'. Run without sudo." + exit 1 + fi + + log_verbose_ok "Sudo/root check passed. Running as a normal user: $USER" + return 0 +} + +get_sudo_ticket() { + log_verbose_info "Checking if sudo rights are already available..." + + # Check if sudo permissions are currently active + if sudo -n true 2>/dev/null; then + log_verbose_ok "Sudo rights are already active. No password required." + return 0 + fi + + log_info "Sudo permissions required. Prompting for password..." + + # Attempt to refresh or request sudo credentials + if sudo -v; then + log_ok "Sudo rights successfully acquired." + return 0 + else + log_error "Failed to acquire sudo permissions. Incorrect password or sudo not available." + return 1 + fi +} + +######################################################################## +# +# Sudo/Root Handling Functions: +# check_if_run_with_sudo +# - Exits if the script is run as root or with sudo. +# +# get_sudo_ticket +# - Checks if sudo permissions are cached. +# - If not, prompts for password to acquire them. +# +######################################################################## \ No newline at end of file diff --git a/nyx/bash/nyx-rebuild.sh b/nyx/bash/nyx-rebuild.sh index 899e997..5637632 100644 --- a/nyx/bash/nyx-rebuild.sh +++ b/nyx/bash/nyx-rebuild.sh @@ -1,387 +1,593 @@ #!/usr/bin/env bash -nyx-rebuild() { - set -euo pipefail - ######################################################################## - # CONFIGURATION (injected by Nix) - ######################################################################## - nix_dir="@NIX_DIR@" - log_dir="@LOG_DIR@" - start_editor="@START_EDITOR@" - enable_formatting="@ENABLE_FORMATTING@" - editor_cmd="@EDITOR@" - formatter_cmd="@FORMATTER@" - git_bin="@GIT_BIN@" - nom_bin="@NOM_BIN@" - auto_push="@AUTO_PUSH@" - version="@VERSION@" +######################################################################## +# CONFIGURATION +######################################################################## +flake_directory="@FLAKE_DIRECTORY@" +log_dir="@LOG_DIR@" +enable_formatting="@ENABLE_FORMATTING@" +formatter_cmd="@FORMATTER@" +git_bin="@GIT_BIN@" +nom_bin="@NOM_BIN@" +auto_stage="@AUTO_STAGE@" +auto_commit="@AUTO_COMMIT@" +auto_push="@AUTO_PUSH@" +auto_repair=true +version="@VERSION@" +rebuild_success=false +nixos_generation="" +git_starting_commit="" - ######################################################################## - # ARGUMENT PARSING - ######################################################################## - do_repair=false - do_update=false - while [[ $# -gt 0 ]]; do - case "$1" in - --repair) do_repair=true; shift;; - --update) do_update=true; shift;; - -h|--help) - cat <" - and remove any unfinished logs (Current-Error*.txt and rebuild-*.log - that are not final nixos-gen_* logs). - --update Before rebuilding, update the flake in nix_dir using: - nix flake update -EOF - return 0 - ;; - *) echo "Unknown argument: $1" >&2; return 2;; - esac - done - ######################################################################## - # COLORS (TTY only) - ######################################################################## - if [[ -t 1 ]]; then - RED=$'\e[31m'; GREEN=$'\e[32m'; YELLOW=$'\e[33m' - BLUE=$'\e[34m'; MAGENTA=$'\e[35m'; CYAN=$'\e[36m' - BOLD=$'\e[1m'; RESET=$'\e[0m' - else - RED=""; GREEN=""; YELLOW="" - BLUE=""; MAGENTA=""; CYAN="" - BOLD=""; RESET="" - fi +######################################################################## +# FORMATTER +######################################################################## +run_formatter() { + if [[ "$enable_formatting" == "true" ]]; then + log_info "Running formatter..." + execute "$formatter_cmd ." "2" + git_add $flake_directory + git_commit "Formatted by $formatter_cmd" + fi +} - ######################################################################## - # LIGHTWEIGHT GIT HELPERS - ######################################################################## - g() { "$git_bin" "$@"; } - git_in_repo() { - local dir="$1" - [[ -d "$dir/.git" ]] || (cd "$dir" && g rev-parse --git-dir >/dev/null 2>&1) - } +######################################################################## +# Repair +######################################################################## +repair_waited_before=false +repair_wait_time=3 - git_has_uncommitted_changes() { - # prints true if there are changes - [[ -n "$(g status --porcelain)" ]] - } +repair_wait () { + if [[ "$auto_repair" == "true" ]]; then + if [[ "$repair_waited_before" == "true" ]]; then + log_debug_info "Waited before so it will start the repair" + else + log_warn "Will repair in $repair_wait_time seconds" + log_warn "Use \"CTRL + C\" to cancel if you don't want that" + for (( waited_time=1; waited_time<=repair_wait_time; waited_time++ )); do + log_info "Will repair in $((repair_wait_time - waited_time + 1))..." + sleep 1 + done + log_warn "Start Repair" + repair_waited_before=true + fi + fi +} - git_pause_if_dirty() { - local attempts=0 - while git_has_uncommitted_changes; do - if (( attempts == 0 )); then - echo "${YELLOW}Uncommitted changes detected!${RESET}" - echo "${RED}Pausing for 5 seconds to allow cancel (Ctrl-C) before attempting repair...${RESET}" - sleep 5 - echo "Attempting repair..." - repair || true # never let a no-op commit kill the script - echo "repair ran" - ((attempts++)) || true - # loop will re-check cleanliness - else - echo "${YELLOW}Uncommitted changes still present after repair.${RESET}" - echo "${RED}Needs manual review. Continuing in 5 seconds...${RESET}" - sleep 5 - break - fi + +check_and_repair () { + + if git_check_has_staged_files; then + log_warn "Repo has uncommitted files" + log_debug_info "auto_commit is $auto_commit" + if [[ "$auto_repair" == "true" ]]; then + log_info "Starting Repair Uncommitted" + if repair_uncommitted; then + log_debug_ok "repair_uncommitted Returned 0 (success)" + else + log_error "I have no Idea but it has sth to do with git_check_has_staged_files in nyx-rebuild.sh" + FATAL + fi + else + log_error "Due to auto_repair being $auto_repair repair not attempted" + log_error "Commit your staged commits or enable \$auto_repair" + FATAL + fi + fi + + + if git_check_has_unstaged_files ; then + log_warn "Repo has unstaged files" + log_debug_warn "auto_stage is $auto_stage" + if [[ "$auto_repair" == "true" ]]; then + log_info "Starting Repair unstaged" + if repair_unstaged; then + log_debug_ok "repair_unstaged Returned 0 (success)" + else + log_error "I have no Idea but it has sth to do with git_check_has_unstaged_files in nyx-rebuild.sh" + fi + else + log_error "Due to auto_repair being $auto_repair repair not attempted" + log_error "Stage your unstaged files or enable \$auto_repair" + FATAL + fi + fi + +} + +repair_unstaged () { + repair_wait + if [[ "$auto_repair" == "true" ]]; then + if [[ "$auto_stage" == "true" ]]; then + log_debug_info "Will attempt to stage files" + git_add $flake_directory + log_info "Added unstaged files" + repair_uncommitted + return 0 + else + log_error "Due to autoStage being disabled repair not attempted" + log_debug_error "Due to auto_stage being $auto_stage repair not attempted" + log_error "Stage your unstaged files or enable autoStage" + FATAL + fi + else + log_error "This shouldn't exist #repair_unstaged" + return 1 + fi + +} + +repair_uncommitted () { + repair_wait + if [[ "$auto_repair" == "true" ]]; then + if [[ "$auto_commit" == "true" ]]; then + log_debug_info "Will attempt to commit" + git_commit "Auto repair commit - $(date '+%Y-%m-%d_%H-%M-%S')" + log_info "Repaired uncommitted changes" + return 0 + else + log_error "Due to autoCommit being disabled repair not attempted" + log_debug_error "Due to auto_commit being $auto_commit repair not attempted" + log_error "Commit your staged commits or enable autoCommit" + FATAL + fi + else + log_error "This shouldn't exist #repair_uncommitted" + return 1 + fi + +} + + + +######################################################################## +# SUDO HANDLING +######################################################################## +ensure_sudo() { + get_sudo_ticket +} + +######################################################################## +# NIXOS REBUILD +######################################################################## +run_nixos_rebuild() { + local tmp_log tmp_status status + tmp_log=$(mktemp /tmp/nyx-tmp-log.XXXXXX) + tmp_status=$(mktemp /tmp/nyx-status.XXXXXX) + + log_debug_info "Running nixos-rebuild command: $*" + log_debug_info "Build log: $build_log" + log_debug_info "Error log: $error_log" + log_debug_info "Using nom binary: $nom_bin" + log_debug_info "Temp log: $tmp_log" + log_debug_info "Temp status file: $tmp_status" + + set -o pipefail + ( + "$@" 2>&1 + echo $? > "$tmp_status" + ) | tee -a "$tmp_log" | "$nom_bin" + + status=$(<"$tmp_status") + execute "rm -f '$tmp_status'" "2" + + log_debug_info "Exit code: $status" + + if [[ $status -eq 0 ]]; then + if grep -Ei -A1 'error|failed' "$tmp_log" >/dev/null; then + log_error "Build reported errors despite successful exit code" + rebuild_success=false + execute "cp '$tmp_log' '$error_log'" "2" + else + log_ok "Build succeeded" + rebuild_success=true + execute "cp '$tmp_log' '$build_log'" "2" + # Populate generation number for finish_rebuild + nixos_generation=$(nixos-rebuild list-generations | grep True | awk '{print $1}') + fi + else + if grep -Ei -A1 'error|failed' "$tmp_log" >/dev/null; then + log_error "Build failed with exit code $status" + rebuild_success=false + execute "cp '$tmp_log' '$error_log'" "2" + else + log_error "Build exited with $status but no explicit error lines found" + rebuild_success=false + execute "cp '$tmp_log' '$error_log'" "2" + fi + fi + + # Send output line by line + while IFS= read -r line; do + tell_out "$line" "CMD" 2 + done < "$tmp_log" + + execute "rm -f '$tmp_log'" "2" + return "$status" +} + + + + + +######################################################################## +# MAIN REBUILD PROCESS +######################################################################## +nyx_rebuild() { + start_time=$(date +%s) + rebuild_success=false + git_store_starting_commit + cd "$flake_directory" || { + log_error "Could not change directory to $flake_directory" + return 1 + } + + # Ensure we are inside a git repo before proceeding + if git_check_if_dir_is_in_repo "$flake_directory"; then + log_debug_info "Passed Git repo check" + else + log_error "Git repo not detected. Aborting rebuild" + return 1 + fi + + check_and_repair + git_pull_rebase + + log_to_file_enable + run_formatter + + log_separator + log_info "Rebuild started: $(date)" + log_separator + + ensure_sudo + + run_nixos_rebuild sudo nixos-rebuild "$rebuild_action" --flake "$flake_directory" + local rebuild_status=$? + + finish_rebuild "$start_time" >/dev/null 2>&1 + + # Only stage/commit logs if rebuild succeeded + if [[ "$rebuild_success" == true ]]; then + logs_stage_and_commit "Rebuild '$rebuild_action' completed successfully" + else + log_error "Rebuild failed" + git_reset "soft" "$git_starting_commit" + logs_stage_and_commit "Error: Rebuild Failed" + finish_rebuild "$start_time" + trap - EXIT + log_debug_info "EXIT trap removed" + exit 1 + fi + + return $rebuild_status +} + + +######################################################################## +# FINISH +######################################################################## +finish_rebuild() { + local start_time=$1 + local duration=$(( $(date +%s) - start_time )) + + # Build failure notes from grep output (one per line) + if [[ "$rebuild_success" != true ]]; then + finish_failure_notes="" + if [[ -f "$error_log" ]]; then + while IFS= read -r line; do + finish_failure_notes+=$'\n'" $line" + done < <(grep -Ei -A1 'error|failed' "$error_log" | tee -a "$error_log" || true) + fi + fi + + log_separator + if [[ "$rebuild_success" == true ]]; then + log_end "###############################################" + log_end " Nyx-Rebuild Completed Successfully" + log_end "###############################################" + log_end "Action: $rebuild_action" + log_end "Flake: $flake_directory" + log_end "Result: Build succeeded" + log_end "Duration: ${duration}s" + log_end "System Generation: $nixos_generation" + [[ -n "$finish_success_notes" ]] && log_end "Notes: $finish_success_notes" + log_end "Build log: $build_log" + log_end "###############################################" + else + log_end "###############################################" + log_end " Nyx-Rebuild Failed" + log_end "###############################################" + log_end "Action: $rebuild_action" + log_end "Flake: $flake_directory" + log_end "Result: Build failed" + log_end "Duration: ${duration}s" + log_end "System Generation: $nixos_generation" + if [[ -n "$finish_failure_notes" ]]; then + log_end "Notes:" + while IFS= read -r note; do + log_end "$note" + done <<< "$finish_failure_notes" + fi + log_end "Error log: $error_log" + log_end "###############################################" + fi + log_separator +} + + +logs_stage_and_commit() { + log_debug_info "logs_stage_and_commit called and is disabling the Logs to Push them" + log_to_file_disable + local message="$1" + git_add "Logs" + git_commit "$message" + git_push +} + + + + + +######################################################################## +# helper: +######################################################################## + +interpret_flags() { + local opt + local verbosity=1 + local action="" + + # Reset OPTIND to handle multiple calls in same shell + OPTIND=1 + + while getopts ":hv:" opt; do + case "$opt" in + h) + print_help + exit 0 + ;; + v) + if [[ "$OPTARG" =~ ^[0-9]+$ ]]; then + verbosity="$OPTARG" + else + echo "Invalid verbosity level: $OPTARG" >&2 + exit 1 + fi + ;; + :) + echo "Option -$OPTARG requires an argument" >&2 + exit 1 + ;; + \?) + echo "Unknown option: -$OPTARG" >&2 + exit 1 + ;; + esac done - } + shift $((OPTIND - 1)) - - git_pull_rebase() { - g pull --rebase - } - - git_add_path() { - g add "$@" - } - - git_commit_if_staged() { - # commit if there is something staged; ignore empty - if ! g diff --cached --quiet; then - g commit -m "$1" || true - fi - } - - git_commit_message() { - local msg="$1" - g commit -m "$msg" - } - - git_push_if_enabled() { - if [[ "${auto_push}" == "true" ]]; then - g push - fi - } - - git_safe_add_commit_push() { - # Convenience: add paths, commit message, optional push - local msg="$1"; shift - git_add_path "$@" - if git_commit_if_staged "$msg"; then - git_push_if_enabled - fi - } - - - ######################################################################## - # REPAIR MODE - ######################################################################## - repair() { - cd "$nix_dir" || { echo "ERROR: Cannot cd into nix_dir: $nix_dir" >&2; return 1; } - - ts="$(date '+%Y-%m-%d_%H-%M-%S')" - echo "Starting repair at ${ts}..." - - # Remove unfinished logs (not final logs) - log_dir_rebuild="${log_dir}/rebuild" - if [[ -d "$log_dir_rebuild" ]]; then - echo "Checking for unfinished logs in: $log_dir_rebuild" - if find "$log_dir_rebuild" -type f \ - ! -name 'nixos-gen_*' \ - \( -name 'rebuild-*.log' -o -name 'Current-Error*.txt' \) | grep -q .; then - echo "Removing unfinished logs..." - find "$log_dir_rebuild" -type f \ - ! -name 'nixos-gen_*' \ - \( -name 'rebuild-*.log' -o -name 'Current-Error*.txt' \) \ - -exec rm -v {} + - echo "Unfinished logs removed." - else - echo "No unfinished logs found." - fi + # First positional arg after options = action + if [[ $# -gt 0 ]]; then + action="$1" + shift else - echo "No rebuild log directory found." + action="test" fi - echo "Staging all changes in $nix_dir..." - g add -A + rebuild_action="$action" + NYX_VERBOSITY="$verbosity" - # Oed; avoid set nly commit if something is stag-e failure on empty commit - if ! g diff --cached --quiet --; then - echo "Committing repair changes..." - g commit -m "rebuild - repair ${ts}" - echo "Repair commit created." + # Any extra args after action can be captured if needed + remaining_args=("$@") +} + + +print_help() { + cat <&1; echo $? > "$tmp" ) | tee -a "$build_log" - local s; s=$(<"$tmp"); rm "$tmp"; return "$s" - } - - run_with_log_rebuild() { - local tmp; tmp=$(mktemp) - ( "$@" 2>&1; echo $? > "$tmp" ) | tee -a "$build_log" | $nom_bin - local s; s=$(<"$tmp"); rm "$tmp"; return "$s" - } - - ######################################################################## - # EARLY REPAIR MODE CHECK - ######################################################################## - if [[ "$do_repair" == true ]]; then - ######################################################################## - # BANNER - ######################################################################## - echo - nyx-tool "Nyx" "nyx-rebuild --repair" "$version" \ - "Smart NixOS configuration repair" \ + #interpret_flags "$@" + + nyx-tool "Nyx" "nyx-rebuild" "$version" \ + "Smart NixOS configuration rebuilder" \ "by Peritia-System" \ "https://github.com/Peritia-System/Nyx-Tools" \ "https://github.com/Peritia-System/Nyx-Tools/issues" \ - "Fixing our mistake... or yours" - echo - repair - rebuild_success=true - return 0 - fi + "Always up to date for you!" - finish_nyx_rebuild() { - stats_duration=$(( $(date +%s) - start_time )) - echo - if [[ "$rebuild_success" == true ]]; then - echo "${GREEN}${BOLD}NixOS Rebuild Complete${RESET}" - echo "${BOLD}${CYAN}Summary:${RESET}" - echo " Started: $start_human" - echo " Duration: ${stats_duration} sec" - echo " Generation: $stats_gen" - else - echo "${RED}${BOLD}NixOS Rebuild Failed${RESET}" - echo "${BOLD}${RED}Error Stats:${RESET}" - echo " Started: $start_human" - echo " Duration: ${stats_duration} sec" - echo " Error lines: ${stats_errors}" - [[ -n "$stats_last_error_lines" ]] && echo -e "${YELLOW}Last few errors:${RESET}$stats_last_error_lines" - fi - } - trap finish_nyx_rebuild EXIT + + - ######################################################################## - # BANNER - ######################################################################## - echo - nyx-tool "Nyx" "nyx-rebuild" "$version" \ - "Smart NixOS configuration rebuilder" \ - "by Peritia-System" \ - "https://github.com/Peritia-System/Nyx-Tools" \ - "https://github.com/Peritia-System/Nyx-Tools/issues" \ - "Always up to date for you!" - echo + # to do make this a flag: verbosity + local verbosity=1 - ######################################################################## - # PREP - ######################################################################## - mkdir -p "$log_dir_rebuild" - cd "$nix_dir" || { echo "Cannot cd into nix_dir: $nix_dir" >&2; exit_code=1; return $exit_code; } - - ######################################################################## - # GIT DIRTY CHECK - ######################################################################## - echo -e "${BOLD}${BLUE}Checking Git status...${RESET}" - git_pause_if_dirty + #source all the files - generated by the .nix file + source_all - ######################################################################## - # NORMAL REBUILD FLOW... - ######################################################################## - - console-log "${BOLD}${BLUE}Pulling latest changes...${RESET}" - if ! run_with_log git pull --rebase; then - exit_code=1; return $exit_code - fi - - ######################################################################## - # OPTIONAL: editor - ######################################################################## - if [[ "$start_editor" == "true" ]]; then - console-log "${BOLD}${BLUE}Opening editor...${RESET}" - console-log "Started editing: $(date)" - run_with_log "$editor_cmd" - console-log "Finished editing: $(date)" - console-log "${BOLD}${CYAN}Changes summary:${RESET}" - run_with_log git diff --compact-summary - fi - - ######################################################################## - # OPTIONAL: formatter - ######################################################################## - if [[ "$enable_formatting" == "true" ]]; then - console-log "${BOLD}${MAGENTA}Running formatter...${RESET}" - run_with_log "$formatter_cmd" . - fi - - ######################################################################## - # REBUILD - ######################################################################## - - # Check if update: - print_line - if [[ "$do_update" == true ]]; then - console-log "${BOLD}${BLUE}Updating flake...${RESET}" - print_line - run_with_log nix flake update --verbose - if git_has_uncommitted_changes; then - git_add_path flake.lock - git_commit_if_staged "flake update: $(date '+%Y-%m-%d %H:%M:%S')" - fi - print_line - fi + # the interger decides verbosity level + setup_logging_vars $verbosity - console-log "${BOLD}${BLUE}Starting system rebuild...${RESET}" + # From now on Logging functions can safely be called: + log_debug_info "Checking that script is NOT run with sudo..." + check_if_run_with_sudo - if find ~ -type f -name '*delme-HMbackup' | grep -q .; then - print_line - console-log "Removing old HM conf" - run_with_log find ~ -type f -name '*delme-HMbackup' -exec rm -v {} + - print_line - fi + # Logging stuff + log_debug_info "Initializing logging..." + log_subdir="${log_dir}/rebuild" + mkdir -p "$log_subdir" + timestamp=$(date '+%Y-%m-%d_%H-%M-%S') + + # lib/logging.sh + log_debug_info "Setting up basic logging (directories, log file)..." + setup_logging_basic + + build_log="${logPath%.log}-rebuild.log" + error_log="${logPath%.log}-Current-Error.txt" - if sudo -n true 2>/dev/null; then - console-log "Sudo rights already available" - else - console-log "Getting sudo ticket (please enter your password)" - run_with_log sudo whoami > /dev/null - fi + # lib/git.sh + log_debug_info "Configuring git-related variables..." + setup_git_vars - print_line - console-log "Rebuild started: $(date)" - print_line + log_debug_info "Configuring nyx-rebuild variables..." + setup_nyxrebuild_vars - run_with_log_rebuild sudo nixos-rebuild switch --flake "$nix_dir" - rebuild_status=$? - if [[ $rebuild_status -ne 0 ]]; then - echo "${RED}Rebuild failed at $(date).${RESET}" > "$error_log" - stats_errors=$(grep -Ei -A 1 'error|failed' "$build_log" | tee -a "$error_log" | wc -l || true) - stats_last_error_lines=$(tail -n 10 "$error_log" || true) - - # capture and push error artifacts - git_add_path "$log_dir_rebuild" - g commit -m "Rebuild failed: errors logged" || true - git_push_if_enabled - - exit_code=1 - return $exit_code - fi - - ######################################################################## - # SUCCESS PATH - ######################################################################## - rebuild_success=true - exit_code=0 - - gen=$(nixos-rebuild list-generations | grep True | awk '{$1=$1};1' || true) - stats_gen=$(echo "$gen" | awk '{printf "%04d", $1}' || echo "0000") - - # Append summary to build log (before rotating file name) - finish_nyx_rebuild >> "$build_log" - - # Commit config changes (if any) - git_add_path -u - if git_commit_if_staged "Rebuild: $gen"; then - echo "${BLUE}Commit message:${RESET}${GREEN}Rebuild: $gen${RESET}" - fi - - # Move and add final log - final_log="$log_dir_rebuild/nixos-gen_${stats_gen}-switch-${timestamp}.log" - mv "$build_log" "$final_log" - git_add_path "$final_log" - git_commit_if_staged "log for $gen" || echo "${YELLOW}No changes in logs to commit.${RESET}" - - git_push_if_enabled && echo "${GREEN}Changes pushed to remote.${RESET}" || true + debug_print_vars + trap trap_on_exit EXIT + nyx_rebuild "$rebuild_action" } -# Execute when sourced as a script -nyx-rebuild "$@" + +main "$@" \ No newline at end of file diff --git a/nyx/default.nix b/nyx/default.nix index b4391b8..a29d1ed 100644 --- a/nyx/default.nix +++ b/nyx/default.nix @@ -25,6 +25,18 @@ with lib; description = "Directory for Nyx logs"; }; + autoStage = mkOption { + type = types.bool; + default = false; + description = "Automatically stage changes after rebuild/cleanup"; + }; + + autoCommit = mkOption { + type = types.bool; + default = false; + description = "Automatically commit changes after rebuild/cleanup"; + }; + autoPush = mkOption { type = types.bool; default = false; diff --git a/nyx/nyx-rebuild.nix b/nyx/nyx-rebuild.nix index 6967326..00cb0c5 100644 --- a/nyx/nyx-rebuild.nix +++ b/nyx/nyx-rebuild.nix @@ -4,46 +4,78 @@ let nyxCfg = config.nyx; cfg = nyxCfg."nyx-rebuild"; + # Function to put a file from lib/ into the Nix store + libFile = file: + builtins.toFile + (builtins.baseNameOf file) + (builtins.readFile ./bash/lib/${file}); + + # List of files you want to source + filesToSource = [ + "git.sh" + "logging.sh" + "sudo.sh" +# "nyx-rebuild-logic.sh" + ]; + + # Build sourcing lines dynamically + sourcingLines = + builtins.concatStringsSep "\n" + (map (f: "source ${libFile f}") filesToSource); + # Read template and inject values rebuiltScript = let - src = builtins.readFile ./bash/nyx-rebuild.sh; # uses @TOKENS@, not ${...} + src = builtins.readFile ./bash/nyx-rebuild.sh; in - builtins.replaceStrings - [ - "@NIX_DIR@" "@LOG_DIR@" "@START_EDITOR@" "@ENABLE_FORMATTING@" - "@EDITOR@" "@FORMATTER@" "@GIT_BIN@" "@NOM_BIN@" "@AUTO_PUSH@" "@VERSION@" - ] - [ - (toString nyxCfg.nixDirectory) - (toString nyxCfg.logDir) - (if cfg.startEditor then "true" else "false") - (if cfg.enableFormatting then "true" else "false") - cfg.editor - cfg.formatter - "${pkgs.git}/bin/git" - "${pkgs.nix-output-monitor}/bin/nom" - (if nyxCfg.autoPush then "true" else "false") - "1.2.0" - ] - src; + builtins.replaceStrings + [ + "@FLAKE_DIRECTORY@" + "@LOG_DIR@" + "@ENABLE_FORMATTING@" + "@FORMATTER@" + "@GIT_BIN@" + "@NOM_BIN@" + "@AUTO_STAGE@" + "@AUTO_COMMIT@" + "@AUTO_PUSH@" + "@VERSION@" + ] + [ + (toString nyxCfg.nixDirectory) + (toString nyxCfg.logDir) + (if cfg.enableFormatting then "true" else "false") + cfg.formatter + "${pkgs.git}/bin/git" + "${pkgs.nix-output-monitor}/bin/nom" + (if nyxCfg.autoStage then "true" else "false") + (if nyxCfg.autoCommit then "true" else "false") + (if nyxCfg.autoPush then "true" else "false") + "1.2.0" + ] + ( + "#!/usr/bin/env bash\n" + + "source_all () {\n" + + sourcingLines + + "\n}\n" + + src + ); + in { options.nyx."nyx-rebuild" = { - enable = lib.mkEnableOption "Enable nyx-rebuild script"; - - editor = lib.mkOption { type = lib.types.str; default = "nvim"; }; - formatter = lib.mkOption { type = lib.types.str; default = "alejandra"; }; - startEditor = lib.mkOption { type = lib.types.bool; default = false; }; - enableFormatting = lib.mkOption { type = lib.types.bool; default = false; }; - enableAlias = lib.mkOption { type = lib.types.bool; default = true; }; + enable = lib.mkEnableOption "Enable nyx-rebuild script"; + formatter = lib.mkOption { type = lib.types.str; default = "alejandra"; }; + enableFormatting = lib.mkOption { type = lib.types.bool; default = false; }; + enableAlias = lib.mkOption { type = lib.types.bool; default = true; }; }; config = lib.mkIf (nyxCfg.enable && cfg.enable) { environment.systemPackages = - lib.optionals (cfg.enableFormatting && cfg.formatter == "alejandra") [ pkgs.alejandra ] + lib.optionals (cfg.enableFormatting && cfg.formatter == "alejandra") [ + pkgs.alejandra + ] ++ [ - # Ensure nyx-tool exists if you call it in the script (pkgs.writeShellScriptBin "nyx-rebuild" rebuiltScript) ]; diff --git a/other/zsh/nyx-cleanup.zsh b/other/zsh/nyx-cleanup.zsh deleted file mode 100644 index 0afb4d8..0000000 --- a/other/zsh/nyx-cleanup.zsh +++ /dev/null @@ -1,108 +0,0 @@ - # Extract cfg values into local variables - nix_dir="${cfg.nixDirectory}" - start_editor="${toString cfg.startEditor}" - enable_formatting="${toString cfg.enableFormatting}" - editor_cmd="${cfg.editor}" - formatter_cmd="${cfg.formatter}" - auto_push="${toString cfg.autoPush}" - source "${scriptTargetPath}" - -function nyx-cleanup() { - ##### ๐Ÿ› ๏ธ CONFIGURATION ##### - local version="1.3.1" - local keep_generations="${keep_generations:-5}" - local start_human=$(date '+%Y-%m-%d %H:%M:%S') - local nix_cleanup_log="nixos-cleanup.log" - local optimize_store="${optimize_store:-false}" - local auto_push="${auto_push:-false}" - - local RED=$'\e[31m'; local GREEN=$'\e[32m'; local YELLOW=$'\e[33m' - local BLUE=$'\e[34m'; local MAGENTA=$'\e[35m'; local CYAN=$'\e[36m' - local BOLD=$'\e[1m'; local RESET=$'\e[0m' - - ##### ๐Ÿ“ PATH SETUP ##### - local timestamp=$(date '+%Y-%m-%d_%H-%M-%S') - local hostname_id=$(hostname) - local log_dir="$nix_dir/Misc/nyx/logs/$hostname_id" - mkdir -p "$log_dir" - local cleanup_log="$log_dir/cleanup-$timestamp.log" - local log_file="$log_dir/nixos-gen-cleanup-$timestamp.log" - - ##### ๐Ÿงฐ HELPERS ##### - console-log() { - echo -e "$@" | tee -a "$cleanup_log" - } - - print_line() { - console-log "${BOLD}$(printf '%*s\n' "${COLUMNS:-40}" '' | tr ' ' '=')${RESET}" - } - - format_bytes() { - num=$1 - echo $(numfmt --to=iec-i --suffix=B "$num") - } - - disk_usage() { - df --output=used /nix/store | tail -1 - } - - ##### ๐Ÿ“˜ TOOL INFO ##### - print_line - nyx-tool "Nyx" "nyx-cleanup" "$version" \ - "Smart NixOS configuration cleanup" \ - "by Peritia-System" \ - "https://github.com/Peritia-System/Nyx-Tools" \ - "https://github.com/Peritia-System/Nyx-Tools/issues" \ - "Always up to date for you!" - echo - echo -e "${BOLD}${CYAN}๐Ÿงผ Nyx Cleanup v$version โ€” Starting...${RESET}" - print_line - - ##### ๐Ÿ“Š STATS: BEFORE ##### - local disk_before=$(disk_usage) - console-log "${CYAN}๐Ÿ“Š Disk used before cleanup: $(format_bytes $disk_before)${RESET}" - - ##### ๐Ÿงน EXECUTION ##### - console-log "\n${BLUE}๐Ÿ—‘๏ธ Collecting Nix garbage...${RESET}" - sudo nix-collect-garbage -d >> "$cleanup_log" 2>&1 - - console-log "\n${BLUE}๐Ÿงน Deleting old generations (keep $keep_generations)...${RESET}" - sudo nix-collect-garbage --delete-older-than "${keep_generations}d" >> "$cleanup_log" 2>&1 - - if [[ "$optimize_store" == "true" ]]; then - console-log "\n${MAGENTA}๐Ÿ”ง Optimizing the Nix store...${RESET}" - sudo nix-store --optimize >> "$cleanup_log" 2>&1 - fi - - ##### ๐Ÿ“Š STATS: AFTER ##### - local disk_after=$(disk_usage) - local space_freed=$((disk_before - disk_after)) - print_line - console-log "${GREEN}${BOLD}โœ… Cleanup Completed Successfully!${RESET}" - console-log "${CYAN}๐Ÿ•’ Finished at: $(date)${RESET}" - console-log "${CYAN}๐Ÿ“Š Disk used after cleanup: $(format_bytes $disk_after)${RESET}" - console-log "${CYAN}๐Ÿ’พ Space freed: $(format_bytes $space_freed)${RESET}" - print_line - - ##### ๐Ÿ“ GIT LOGGING ##### - local gen_nmbr=$(nixos-rebuild list-generations | grep True | awk '{print $1}' | tail -1 | xargs printf "%04d\n") - - cd "$nix_dir" || return 1 - mv "$nix_cleanup_log" "$log_file" - git add "$log_file" - - if ! git diff --cached --quiet; then - git commit -m "Cleanup log on $timestamp" - console-log "${GREEN}โœ… Cleanup log committed.${RESET}" - else - console-log "${YELLOW}โ„น๏ธ No new changes in logs to commit.${RESET}" - fi - - if [[ "$auto_push" == "true" ]]; then - console-log "${BLUE}๐Ÿš€ Auto-push enabled. Pushing to remote...${RESET}" - git push && console-log "${GREEN}โœ… Changes pushed to remote.${RESET}" - fi - - console-log "\n${GREEN}๐ŸŽ‰ Nyx cleanup finished!${RESET}" - print_line -} diff --git a/other/zsh/nyx-rebuild.zsh b/other/zsh/nyx-rebuild.zsh deleted file mode 100644 index 5a74f3a..0000000 --- a/other/zsh/nyx-rebuild.zsh +++ /dev/null @@ -1,204 +0,0 @@ -function nyx-rebuild() { - - #################### ๐Ÿ”ง INITIAL SETUP #################### - local version="1.3.0" - local start_time=$(date +%s) - local start_human=$(date '+%Y-%m-%d %H:%M:%S') - local stats_duration=0 - local stats_gen="?" - local stats_errors=0 - local stats_last_error_lines="" - local rebuild_success=false - local exit_code=1 # default to failure - - trap finish_nyx_rebuild - - #################### ๐ŸŽจ ANSI COLORS #################### - if [[ -t 1 ]]; then - RED=$'\e[31m'; GREEN=$'\e[32m'; YELLOW=$'\e[33m'; BLUE=$'\e[34m' - MAGENTA=$'\e[35m'; CYAN=$'\e[36m'; BOLD=$'\e[1m'; RESET=$'\e[0m' - else - RED=""; GREEN=""; YELLOW=""; BLUE="" - MAGENTA=""; CYAN=""; BOLD=""; RESET="" - fi - - #################### ๐Ÿ“ PATH SETUP #################### - local log_dir="$nix_dir/Misc/nyx/logs/$(hostname)" - mkdir -p "$log_dir" - local timestamp=$(date '+%Y-%m-%d_%H-%M-%S') - local build_log="$log_dir/build-${timestamp}.log" - local error_log="$log_dir/Current-Error-${timestamp}.txt" - - #################### ๐Ÿงฐ HELPERS #################### - console-log() { - echo -e "$@" | tee -a "$build_log" - } - - print_line() { - console-log "${BOLD}$(printf '%*s\n' "${COLUMNS:-40}" '' | tr ' ' '=')${RESET}" - } - - run_with_log() { - local cmd_output - cmd_output=$(mktemp) - ( - "$@" 2>&1 - echo $? > "$cmd_output" - ) | tee -a "$build_log" - local exit_code=$(<"$cmd_output") - rm "$cmd_output" - return "$exit_code" - } - run_with_log_rebuild() { - local cmd_output - cmd_output=$(mktemp) - ( - "$@" 2>&1 - echo $? > "$cmd_output" - ) | tee -a "$build_log" | nom - local exit_code=$(<"$cmd_output") - rm "$cmd_output" - return "$exit_code" - } - - finish_nyx_rebuild() { - stats_duration=$(( $(date +%s) - start_time )) - echo - - if [[ "$rebuild_success" == true ]]; then - echo "${GREEN}${BOLD} -############################## -# โœ… NixOS Rebuild Complete! # -##############################${RESET}" - echo "${BOLD}${CYAN}๐ŸŽฏ Success Stats:${RESET}" - echo " ๐Ÿ•’ Started: $start_human" - echo " โฑ๏ธ Duration: ${stats_duration} sec" - echo " ๐Ÿ“ฆ Gen: $stats_gen" - else - echo "${RED}${BOLD} -############################## -# โŒ NixOS Rebuild Failed! # -##############################${RESET}" - echo "${BOLD}${RED}๐Ÿšจ Error Stats:${RESET}" - echo " ๐Ÿ•’ Started: $start_human" - echo " โฑ๏ธ Duration: ${stats_duration} sec" - echo " โŒ Error lines: ${stats_errors}" - [[ -n "$stats_last_error_lines" ]] && echo "\n${YELLOW}๐Ÿงพ Last few errors:${RESET}\n$stats_last_error_lines" - fi - echo - return $exit_code - } - - #################### ๐Ÿ“˜ TOOL INFO #################### - echo - nyx-tool "Nyx" "nyx-rebuild" "$version" \ - "Smart NixOS configuration rebuilder" \ - "by Peritia-System" \ - "https://github.com/Peritia-System/Nyx-Tools" \ - "https://github.com/Peritia-System/Nyx-Tools/issues" \ - "Always up to date for you!" - echo - - #################### ๐Ÿ“ PROJECT PREP #################### - cd "$nix_dir" || { exit_code=1; return $exit_code; } - - echo "\n${BOLD}${BLUE}๐Ÿ“ Checking Git status...${RESET}" - if [[ -n $(git status --porcelain) ]]; then - echo "${YELLOW}โš ๏ธ Uncommitted changes detected!${RESET}" - echo "${RED}โณ 5s to cancel...${RESET}" - sleep 5 - fi - - #################### ๐Ÿ”„ GIT PULL #################### - console-log "\n${BOLD}${BLUE}โฌ‡๏ธ Pulling latest changes...${RESET}" - if ! run_with_log git pull --rebase; then - exit_code=1; return $exit_code - fi - - #################### ๐Ÿ“ EDIT CONFIG #################### - if [[ "$start_editor" == "true" ]]; then - console-log "\n${BOLD}${BLUE}๐Ÿ“ Editing configuration...${RESET}" - console-log "Started editing: $(date)" - run_with_log $editor_cmd - console-log "Finished editing: $(date)" - fi - - #################### ๐ŸŽจ FORMAT #################### - if [[ "$enable_formatting" == "true" ]]; then - console-log "\n${BOLD}${MAGENTA}๐ŸŽจ Running formatter...${RESET}" - run_with_log $formatter_cmd . - fi - - #################### ๐Ÿงพ GIT DIFF #################### - console-log "\n${BOLD}${CYAN}๐Ÿ” Changes summary:${RESET}" - run_with_log git diff --compact-summary - - #################### ๐Ÿ› ๏ธ SYSTEM REBUILD #################### - console-log "\n${BOLD}${BLUE}๐Ÿ”ง Starting system rebuild...${RESET}" - print_line - console-log "๐Ÿ› ๏ธ Removing old HM conf " - run_with_log find ~ -type f -name '*delme-HMbackup' -exec rm -v {} + - print_line - ### Sudo session ticket: - console-log "Getting an \`sudo\`-\"Ticket\" to use \`nixos-rebuild\` with \"nom\" " - console-log "please enter your sudo credentials:" - run_with_log sudo whoami > /dev/null - ### Now rebuils_ - print_line - console-log "๐Ÿ› ๏ธ Rebuild started: $(date)" - print_line - - run_with_log_rebuild sudo nixos-rebuild switch --flake "$nix_dir" - local rebuild_status=$? - - if [[ $rebuild_status -ne 0 ]]; then - #console-log "\n${BOLD}${RED}โŒ Rebuild failed at $(date). Showing errors:${RESET}" - echo "${RED}โŒ Rebuild failed at $(date).${RESET}" > "$error_log" - stats_errors=$(grep -Ei -A 1 'error|failed' "$build_log" | tee -a "$error_log" | wc -l) - stats_last_error_lines=$(tail -n 10 "$error_log") - finish_nyx_rebuild | tee -a "$error_log" - - git add "$log_dir" - git commit -m "Rebuild failed: errors logged" - if [[ "$auto_push" == "true" ]]; then - run_with_log git push && console-log "${GREEN}โœ… Error log pushed to remote.${RESET}" - fi - exit_code=1 - return $exit_code - fi - - #################### โœ… SUCCESS FLOW #################### - rebuild_success=true - exit_code=0 - - - gen=$(nixos-rebuild list-generations | grep True | awk '{$1=$1};1') - stats_gen=$(echo "$gen" | awk '{printf "%04d\n", $1}') - finish_nyx_rebuild >> $build_log - - git add -u - if ! git diff --cached --quiet; then - git commit -m "Rebuild: $gen" - console-log "${BLUE}๐Ÿ”ง Commit message:${RESET}\n${GREEN}Rebuild: $gen${RESET}" - fi - - local final_log="$log_dir/nixos-gen_${stats_gen}-switch-${timestamp}.log" - mv "$build_log" "$final_log" - git add "$final_log" - - if ! git diff --cached --quiet; then - git commit -m "log for $gen" - echo "${YELLOW}โ„น๏ธ Added changes to git${RESET}" - else - echo "${YELLOW}โ„น๏ธ No changes in logs to commit.${RESET}" - fi - - if [[ "$auto_push" == "true" ]]; then - git push && echo "${GREEN}โœ… Changes pushed to remote.${RESET}" - fi - - echo "\n${GREEN}๐ŸŽ‰ Nyx rebuild completed successfully!${RESET}" - finish_nyx_rebuild - #return $exit_code - -} diff --git a/other/zsh/nyx-tool.zsh b/other/zsh/nyx-tool.zsh deleted file mode 100644 index 577dae0..0000000 --- a/other/zsh/nyx-tool.zsh +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env zsh - -# nyx-tool: reusable metadata banner printer with Base16 theme -function nyx-tool() { - local logo="${1:-Nyx}" - local name="${2:-nix-script}" - local version="${3:-Version Unknown - Please Open Issue}" - local description="${4:-A Nix utility}" - local credit="${5:-Peritia-System}" - local github="${6:-https://github.com/example/repo}" - local issues="${7:-${github}/issues}" - local message="${8:-Use responsibly}" - - # Base16 color palette (using tput for portability or ANSI codes) - local RESET="\033[0m" - local BOLD="\033[1m" - local HEADER="\033[38;5;33m" # Approx base0D (blue) - local LABEL="\033[38;5;70m" # Approx base0B (green) - local VALUE="\033[38;5;250m" # Approx base05 (gray) - local EMPHASIS="\033[38;5;196m" # Approx base08 (red) - - local line - line=$(printf '=%.0s' {1..35}) - - echo "" - echo -e "${HEADER}${line}${RESET}" - echo -e "${HEADER}=====[ ${BOLD}Peritia System Tools${RESET}${HEADER} ]=====${RESET}" - echo -e " - ${VALUE}${BOLD} - -$(figlet -f banner3 "${logo}" | sed 's/#/โ–ˆ/g') ${RESET}${HEADER}by Peritia-System${RESET} - - ${RESET}" - - #cat ../Logo-68px.txt - - echo -e "${HEADER}${line}${RESET}" - echo "" - - echo -e "${LABEL}๐Ÿ› ๏ธ Name: ${VALUE}${name}${RESET}" - echo -e "${LABEL}๐Ÿท๏ธ Version: ${VALUE}${version}${RESET}" - echo -e "${LABEL}๐Ÿ“ Description: ${VALUE}${description}${RESET}" - echo -e "${LABEL}๐Ÿ‘ค Credit: ${VALUE}${credit}${RESET}" - echo -e "${LABEL}๐ŸŒ GitHub: ${VALUE}${github}${RESET}" - echo -e "${LABEL}๐Ÿ› Issues: ${VALUE}${issues}${RESET}" - echo "" - echo -e "${LABEL}๐Ÿ“Œ Message: ${BOLD}${message}${RESET}" - echo "" -} - -nyx-show_spinner() { - local pid=$1 - local spinner_delay=0.1 - local spinstr='|/-\' - local start_time=$(date +%s%3N) - - echo -ne "${CYAN}โณ Starting rebuild...${RESET} " - - ( - while kill -0 "$pid" 2>/dev/null; do - local now=$(date +%s%3N) - local elapsed=$((now - start_time)) - local seconds=$((elapsed / 1000)) - local milliseconds=$((elapsed % 1000)) - local clock_time=$(date +%T) # format: HH:MM:SS - - for i in $(seq 0 3); do - printf "\r${CYAN}โณ [%s] %s [%d.%03ds] ${RESET}" "$clock_time" "${spinstr:$i:1}" "$seconds" "$milliseconds" - sleep $spinner_delay - done - done - ) & - local spinner_pid=$! - - # Wait for the main process - wait "$pid" - local exit_status=$? - - # Kill spinner and wait - kill "$spinner_pid" 2>/dev/null - wait "$spinner_pid" 2>/dev/null - - local end_time=$(date +%s%3N) - local total_elapsed=$((end_time - start_time)) - local total_sec=$((total_elapsed / 1000)) - local total_ms=$((total_elapsed % 1000)) - local end_clock_time=$(date +%T) - - echo -e "\r${GREEN}โœ… Completed at ${end_clock_time}, total: ${total_sec}.${total_ms}s${RESET} " - - return $exit_status -}