diff --git a/scripts/edit-os b/scripts/edit-os new file mode 100755 index 0000000..01fe8f5 --- /dev/null +++ b/scripts/edit-os @@ -0,0 +1,250 @@ +#!/usr/bin/env bash + +# Exit immediately if a command exits with a non-zero status. +set -e +# Treat unset variables as an error when substituting. +set -u +# Pipestatus +set -o pipefail + +# --- Configuration --- +: "${NIX_CONFIG_DIR:=/etc/nix-darwin}" # Path to your Nix configuration directory +: "${GIT_REMOTE_NAME:=origin}" +GIT_BRANCH_NAME_CMD="git -C \"$NIX_CONFIG_DIR\" rev-parse --abbrev-ref HEAD" +: "${GIT_BRANCH_NAME:=$(eval "$GIT_BRANCH_NAME_CMD" 2>/dev/null || echo main)}" + +# Ollama configuration +: "${OLLAMA_MODEL:=deepseek-r1:1.5b}" # Ollama model +: "${OLLAMA_HOST:=http://localhost:11434}" # Default Ollama API host + +# Hardcoded Nix switch command +NIX_SWITCH_COMMAND="sudo darwin-rebuild switch" +# If your flake requires a specific attribute, modify it here, e.g.: +# NIX_SWITCH_COMMAND="sudo darwin-rebuild switch --flake .#yourDarwinConfigName" +# --- End Configuration --- + +# Function to check if a command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Check for dependencies +if ! command_exists ollama; then + echo "❌ Error: ollama CLI not found. Please install Ollama." + exit 1 +fi +if ! command_exists jq; then + echo "❌ Error: jq not found. Please install jq." + exit 1 +fi +if ! command_exists code; then + echo "❌ Error: 'code' (VSCode CLI) not found. Please ensure it's in your PATH." + echo " You might need to install it from within VSCode (View -> Command Palette -> 'Shell Command: Install code command in PATH')." + exit 1 +fi +if ! command_exists sudo; then + echo "❌ Error: 'sudo' command not found. This script requires sudo for 'darwin-rebuild switch'." + exit 1 +fi +if ! command_exists darwin-rebuild; then + echo "❌ Error: 'darwin-rebuild' command not found. Please ensure Nix-Darwin is installed correctly." + exit 1 +fi + + +# --- VSCode Integration --- +echo "Nix config directory: $NIX_CONFIG_DIR" +echo "-----------------------------------------------------" +echo "💻 Opening VSCode to edit Nix configuration at $NIX_CONFIG_DIR..." +echo " The script will continue after you close VSCode." + +if ! code --wait "$NIX_CONFIG_DIR"; then + echo "❌ Error: 'code --wait \"$NIX_CONFIG_DIR\"' failed." + echo " Please ensure VSCode is installed correctly and the 'code' command with '--wait' works." + exit 1 +fi +echo "✅ VSCode closed. Proceeding with the script..." +echo "-----------------------------------------------------" +# --- End VSCode Integration --- + + +# Function to generate commit message using Ollama +generate_commit_message() { + local diff_content + diff_content=$(git -C "$NIX_CONFIG_DIR" diff --staged) + + if [ -z "$diff_content" ]; then + echo "chore: No changes to commit" + return + fi + + local max_diff_lines=150 + local truncated_diff + truncated_diff=$(echo "$diff_content" | head -n "$max_diff_lines") + if [ "$(echo "$diff_content" | wc -l)" -gt "$max_diff_lines" ]; then + truncated_diff+=$'\n\n... (diff truncated) ...' + fi + + local prompt + prompt=$(cat <(): + +[optional body] + +[optional footer] + +Allowed types: +- feat: A new feature or package addition +- fix: A bug fix in the configuration +- docs: Documentation changes +- style: Code style changes (formatting, whitespace) +- refactor: Code changes that neither fix a bug nor add a feature +- perf: A code change that improves performance +- test: Adding missing tests or correcting existing tests +- build: Changes that affect the build system or external dependencies +- ci: Changes to CI configuration files and scripts +- chore: Other changes that don't modify source or test files + +Consider these for Nix configurations: +- Adding a new package: 'feat' or 'feat(pkg)' or 'feat(darwin)' +- Updating flake inputs: 'build(deps): update flake inputs' or 'chore(deps): update flake inputs' +- Modifying system settings: 'refactor(system)' or 'fix(system)' +- Changing themes or appearances: 'style(theme)' +- General maintenance or minor tweaks: 'chore' or 'refactor' + +Focus on a short, descriptive subject line (max 50-70 chars). +If no specific scope is obvious, you can omit it. +If the changes are minor, 'chore' or 'refactor' are good defaults. + +Git Diff: +--- +$truncated_diff +--- + +Generate ONLY the commit message. Do not include any other explanatory text. +EOF +) + + echo "🧠 Generating commit message with Ollama ($OLLAMA_MODEL)..." + local ollama_response + ollama_response=$(curl -s --fail "$OLLAMA_HOST/api/generate" -d '{ + "model": "'"$OLLAMA_MODEL"'", + "prompt": "'"${prompt//\"/\\\"}"'", + "stream": false, + "options": { + "temperature": 0.3, + "num_predict": 150 + } + }') + + if [ -z "$ollama_response" ]; then + echo "❌ Ollama request failed or returned empty. Using default commit message." + echo "chore: Automated Nix config update $(date +'%Y-%m-%d %H:%M:%S')" + return + fi + + local generated_message + generated_message=$(echo "$ollama_response" | jq -r '.response | sub("^\\s*"; "") | sub("\\s*$"; "")') + + if [ -z "$generated_message" ] || [[ "$generated_message" == "null" ]]; then + echo "⚠️ Ollama did not return a valid message. Using default commit message." + echo "chore: Automated Nix config update $(date +'%Y-%m-%d %H:%M:%S')" + else + if [[ "$generated_message" =~ ^[a-z]+(\([a-zA-Z0-9_-]+\))?!?: ]]; then + echo "$generated_message" + else + echo "⚠️ Ollama message doesn't look like a conventional commit. Prepending 'chore: '." + echo "chore: $generated_message" + fi + fi +} + + +echo "Current effective configuration:" +echo "Nix config directory: $NIX_CONFIG_DIR" +echo "Nix switch command to run: $NIX_SWITCH_COMMAND" +echo "Git remote: $GIT_REMOTE_NAME" +echo "Git branch: $GIT_BRANCH_NAME" +echo "Ollama model: $OLLAMA_MODEL" +echo "-----------------------------------------------------" + +# 1. Navigate to the Nix config Git repository using pushd +# This is done *before* the switch command so darwin-rebuild finds flake.nix +echo "🔄 Changing directory to $NIX_CONFIG_DIR using pushd..." +if ! pushd "$NIX_CONFIG_DIR" > /dev/null; then + echo "❌ Failed to pushd into $NIX_CONFIG_DIR. Is the path correct and accessible?" + exit 1 +fi +echo "✅ Successfully changed to $NIX_CONFIG_DIR (current directory: $PWD)." +echo "-----------------------------------------------------" + +# Ensure we popd at the end, even if errors occur. +# A trap is more robust, but for now, manual popd before exits and at the end. +_cleanup() { + echo "🔄 Returning to original directory using popd..." + if ! popd > /dev/null; then + echo "⚠️ Failed to popd. Current directory ($PWD) might not be the original one." + fi +} +# trap _cleanup EXIT # Uncomment this for more robust cleanup on any exit + +# 2. Run the Nix switch command +echo "🚀 Starting Nix switch: $NIX_SWITCH_COMMAND" +echo " This command will be run from: $PWD" +# The '|| echo ...' construct ensures the script continues even if the command fails, +# due to 'set -e'. A warning will be printed on failure. +# Using 'eval' to correctly handle the command string if it contains spaces and needs sudo. +eval "$NIX_SWITCH_COMMAND" || echo "⚠️ Nix switch command exited with a non-zero status. Continuing as requested..." +echo "ℹ️ Nix switch command execution finished. Proceeding..." +echo "-----------------------------------------------------" + +# 3. Check for changes +echo "🔍 Checking for Git changes in current directory ($PWD)..." +if git diff --quiet && git diff --staged --quiet; then + echo "ℹ️ No changes detected in $NIX_CONFIG_DIR. Nothing to commit or push." + _cleanup # Call cleanup function + exit 0 +fi +echo "✅ Changes detected." +echo "-----------------------------------------------------" + +# 4. Add changes +echo "💾 Staging all changes in current directory ($PWD)..." +git add . +echo "-----------------------------------------------------" + +# 5. Generate Commit Message +COMMIT_MESSAGE=$(generate_commit_message) # generate_commit_message uses git -C "$NIX_CONFIG_DIR" +echo "💬 Generated commit message:" +echo "$COMMIT_MESSAGE" +echo "-----------------------------------------------------" + +# 6. Commit and Push +echo "✍️ Committing to local repository in current directory ($PWD)..." +if printf '%s\n' "$COMMIT_MESSAGE" | git commit -F - ; then + echo "✅ Commit successful." +else + echo "❌ Git commit failed. Please check the repository status and the generated message." + echo " Ensure you have commit permissions for $NIX_CONFIG_DIR." + _cleanup # Call cleanup function + exit 1 +fi + +echo "📡 Pushing to $GIT_REMOTE_NAME $GIT_BRANCH_NAME from current directory ($PWD)..." +if ! git push "$GIT_REMOTE_NAME" "$GIT_BRANCH_NAME"; then + echo "⚠️ Git push failed. The commit was made locally, but not pushed." + echo " Please check your remote connection, permissions, and push manually if needed." +else + echo "✅ Push successful." +fi +echo "-----------------------------------------------------" + +_cleanup # Call cleanup function +echo "🎉 All done!" +