#!/usr/bin/env bash # git_auto_commit_dirty — Si el repo tiene cambios sin commitear, hace git add -A # y git commit con mensaje generado o el que se pase como argumento. # Stdout: subject del commit creado, vacio si no habia cambios. # Salta sin commitear si el repo es ~/.password-store (pass gestiona sus propios commits). git_auto_commit_dirty() { local repo_dir="${1:-.}" local message="${2:-}" if [[ ! -d "$repo_dir/.git" ]]; then echo "git_auto_commit_dirty: '$repo_dir' no es un repo git" >&2 return 1 fi # Normalizar path local abs_repo abs_repo="$(cd "$repo_dir" && pwd)" # Saltear ~/.password-store — pass gestiona sus propios commits local pass_dir pass_dir="${PASSWORD_STORE_DIR:-$HOME/.password-store}" pass_dir="$(cd "$pass_dir" 2>/dev/null && pwd)" || true if [[ -n "$pass_dir" && "$abs_repo" == "$pass_dir"* ]]; then # No commitear — pass se autocommitea return 0 fi # Comprobar si hay cambios local status status=$(git -C "$abs_repo" status --porcelain) if [[ -z "$status" ]]; then # Nada que commitear return 0 fi # Saltear si hay merge conflicts sin resolver (UU, AA, DD, AU, UA, DU, UD). # git add -A los aceptaria como resueltos y commitearia los markers — no. if echo "$status" | grep -qE '^(UU|AA|DD|AU|UA|DU|UD) '; then echo "git_auto_commit_dirty: '$abs_repo' tiene conflictos sin resolver — skipped" >&2 return 0 fi # Generar mensaje automatico si no se proporciono if [[ -z "$message" ]]; then message="$(_git_auto_commit_dirty_generate_message "$abs_repo" "$status")" fi # Commitear git -C "$abs_repo" add -A local commit_output commit_output=$(git -C "$abs_repo" commit \ -m "$message" \ -m "Co-Authored-By: Claude Opus 4.7 (1M context) " \ 2>&1) local exit_code=$? if [[ $exit_code -ne 0 ]]; then echo "git_auto_commit_dirty: fallo al commitear en '$abs_repo'" >&2 echo "$commit_output" >&2 return 1 fi # Imprimir subject del commit echo "$message" | head -1 } # Funcion auxiliar: genera mensaje de commit automatico _git_auto_commit_dirty_generate_message() { local repo_dir="$1" local status="$2" # Contar tipos de cambios local n_modified n_added n_deleted n_modified=$(echo "$status" | grep -c '^ M\| M\|MM\|AM\|CM\|RM' 2>/dev/null || true) n_added=$(echo "$status" | grep -c '^??\|^A ' 2>/dev/null || true) n_deleted=$(echo "$status" | grep -c '^ D\|^D ' 2>/dev/null || true) # Extraer paths (sin el prefijo de status) local paths paths=$(echo "$status" | awk '{print $NF}') # Detectar patron comun: todos bajo python/functions// local py_dom py_dom=$(echo "$paths" | grep -oE '^python/functions/[^/]+' | sort -u) if [[ $(echo "$py_dom" | wc -l) -eq 1 && -n "$py_dom" ]]; then local dom dom=$(echo "$py_dom" | sed 's|python/functions/||') local n_total n_total=$(echo "$paths" | wc -l) echo "feat($dom): auto-commit con $n_total cambios" return fi # Detectar patron: todos bajo dev/issues/ if echo "$paths" | grep -q '^dev/issues/' && ! echo "$paths" | grep -qv '^dev/issues/'; then echo "chore(issues): auto-commit" return fi # Detectar patron: todos bajo functions// (Go) local go_dom go_dom=$(echo "$paths" | grep -oE '^functions/[^/]+' | sort -u) if [[ $(echo "$go_dom" | wc -l) -eq 1 && -n "$go_dom" ]]; then local dom dom=$(echo "$go_dom" | sed 's|functions/||') local n_total n_total=$(echo "$paths" | wc -l) echo "feat($dom): auto-commit con $n_total cambios" return fi # Detectar patron: todos bajo bash/functions// local bash_dom bash_dom=$(echo "$paths" | grep -oE '^bash/functions/[^/]+' | sort -u) if [[ $(echo "$bash_dom" | wc -l) -eq 1 && -n "$bash_dom" ]]; then local dom dom=$(echo "$bash_dom" | sed 's|bash/functions/||') local n_total n_total=$(echo "$paths" | wc -l) echo "feat($dom): auto-commit con $n_total cambios" return fi # Caso general: cambios dispersos local n_total n_total=$(echo "$paths" | wc -l) local subject="chore: auto-commit ($n_total archivos)" # Listar hasta 10 paths en el body (se anade como segundo -m) local body body=$(echo "$paths" | head -10 | awk '{print "- "$0}') if [[ $(echo "$paths" | wc -l) -gt 10 ]]; then body="$body"$'\n'"- ..." fi echo "$subject"$'\n\n'"$body" } if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then git_auto_commit_dirty "$@" fi