#!/usr/bin/env bash # ensure_project_gitignore — Garantiza de forma idempotente que el .gitignore de # un directorio de project (projects//) contiene las lineas canonicas que # excluyen del repo del project el contenido de sus sub-repos hijos (apps y # analyses son repos Gitea independientes) y sus vaults (datos fuera de git). # # Esto evita que al hacer push del project se trackee por error el contenido de # los hijos (doble-tracking). Ver .claude/rules/apps_subrepo.md y # .claude/rules/projects.md. # # Uso: # ensure_project_gitignore # # Salida: # stdout vacio. A stderr informa de la accion realizada (created / updated / ok). ensure_project_gitignore() { local project_dir="$1" if [[ -z "$project_dir" ]]; then echo "ensure_project_gitignore: se requiere project_dir" >&2 return 1 fi if [[ ! -d "$project_dir" ]]; then echo "ensure_project_gitignore: directorio '$project_dir' no existe" >&2 return 1 fi local gitignore="$project_dir/.gitignore" # Lineas canonicas que deben estar presentes (orden de referencia). local -a canonical=( "apps/*/" "analysis/*/" "vaults/*" "!vaults/.gitkeep" "!vaults/vault.yaml" ) # Caso 1: el .gitignore no existe — crearlo con el contenido canonico. if [[ ! -f "$gitignore" ]]; then printf '%s\n' "${canonical[@]}" > "$gitignore" echo "ensure_project_gitignore: created $gitignore" >&2 return 0 fi # Caso 2: existe — anadir solo las lineas que falten (comparacion linea-exacta), # preservando el contenido y el orden existentes. # Si el archivo no termina en newline, anadir uno antes de apendar para no # pegar la primera linea nueva al final de la ultima existente. if [[ -s "$gitignore" && -n "$(tail -c 1 "$gitignore")" ]]; then printf '\n' >> "$gitignore" fi local line added=0 for line in "${canonical[@]}"; do # grep -F -x: match literal de linea completa, sin interpretar metacaracteres. if ! grep -Fxq -- "$line" "$gitignore"; then printf '%s\n' "$line" >> "$gitignore" added=$((added + 1)) fi done if [[ $added -gt 0 ]]; then echo "ensure_project_gitignore: updated: anadidas $added lineas a $gitignore" >&2 else echo "ensure_project_gitignore: ok: ya completo $gitignore" >&2 fi return 0 } # Si se invoca como script (no source), ejecutar la funcion. if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then ensure_project_gitignore "$@" fi