diff --git a/tools/hooks/README.md b/tools/hooks/README.md new file mode 100644 index 0000000..b525609 --- /dev/null +++ b/tools/hooks/README.md @@ -0,0 +1,249 @@ +# Git Hooks - Orni Attack + +Este directorio contiene los **git hooks** versionados para el proyecto Orni Attack. + +Los hooks permiten ejecutar automáticamente verificaciones de calidad de código antes de hacer commits. + +--- + +## 📦 Instalación + +### Instalación automática (recomendada) + +Ejecuta el script de instalación desde la raíz del proyecto: + +```bash +./tools/hooks/install.sh +``` + +### Instalación manual + +```bash +cp tools/hooks/pre-commit .git/hooks/ +chmod +x .git/hooks/pre-commit +``` + +--- + +## 🔍 Hooks disponibles + +### `pre-commit` + +**Se ejecuta automáticamente antes de cada commit.** + +Realiza dos verificaciones en los archivos `.cpp` y `.hpp` modificados: + +#### 1. 🎨 clang-format (formato de código) + +- **Acción**: Formatea automáticamente el código según `.clang-format` +- **Comportamiento**: Si encuentra problemas de formato, los arregla automáticamente y añade los cambios al commit +- **Resultado**: Código siempre bien formateado sin esfuerzo manual + +#### 2. 🔍 clang-tidy (análisis estático) + +- **Acción**: Verifica el código según las reglas de `.clang-tidy` +- **Comportamiento**: + - ✅ Si no hay errores → commit permitido + - ❌ Si hay errores → commit **bloqueado** y muestra los errores +- **Resultado**: Previene commits con problemas de calidad + +--- + +## 📋 Ejemplo de uso + +```bash +# 1. Modificas código +vim source/game/entities/nau.cpp + +# 2. Añades al staging +git add source/game/entities/nau.cpp + +# 3. Intentas commit +git commit -m "feat: añadir nueva funcionalidad" + +# → El hook se ejecuta automáticamente: +🔍 Pre-commit hook: verificando código... +📝 Archivos a revisar: source/game/entities/nau.cpp + +🎨 Ejecutando clang-format... + ✏️ Formateado: source/game/entities/nau.cpp +✅ Archivos formateados automáticamente y añadidos al commit + +🔍 Ejecutando clang-tidy... + ✅ source/game/entities/nau.cpp + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +✅ Pre-commit hook: TODO OK +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + 🎨 clang-format: OK (archivos formateados) + 🔍 clang-tidy: OK (sin errores) + +[main abc1234] feat: añadir nueva funcionalidad + 1 file changed, 10 insertions(+) +``` + +--- + +## ❌ ¿Qué pasa si hay errores? + +Si clang-tidy encuentra errores, el hook **bloquea el commit** y te muestra: + +```bash +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +❌ COMMIT BLOQUEADO: clang-tidy encontró errores +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +❌ Errores en source/game/entities/nau.cpp: +source/game/entities/nau.cpp:42:10: error: method 'getPosition' can be made const + ^ + const + +💡 Soluciones: + 1. Corrige los errores manualmente + 2. O ejecuta: make tidy (aplica fixes automáticos) + 3. Luego: git add && git commit + +⚠️ Si necesitas saltarte el hook (NO RECOMENDADO): + git commit --no-verify +``` + +### Soluciones + +**Opción 1: Arreglar manualmente** + +Edita el archivo y corrige los errores que muestra clang-tidy. + +**Opción 2: Auto-fix con make tidy** + +```bash +make tidy # Aplica fixes automáticos +git add . # Añade los cambios +git commit -m "..." # Intenta commit de nuevo +``` + +**Opción 3: Saltar el hook (NO RECOMENDADO)** + +```bash +git commit --no-verify -m "mensaje" +``` + +⚠️ **Solo usa `--no-verify` en casos excepcionales**, ya que permite commits con código de baja calidad. + +--- + +## 🚀 Ventajas + +✅ **Solo código nuevo**: Revisa únicamente archivos modificados (rápido) +✅ **Automático**: No tienes que acordarte de ejecutar clang-tidy +✅ **Formato automático**: clang-format arregla el código por ti +✅ **Bloquea errores**: Previene commits con problemas de calidad +✅ **No ralentiza compilación**: Solo se ejecuta en commits, no en `make` +✅ **Excluye código externo**: Ignora automáticamente `audio/` y `legacy/` + +--- + +## 🔧 Configuración + +Los hooks usan las configuraciones del proyecto: + +- **`.clang-format`**: Reglas de formato de código +- **`.clang-tidy`**: Reglas de análisis estático +- **`CMakeLists.txt`**: Exclusiones de directorios (audio/, legacy/) + +Si modificas estas configuraciones, los hooks aplicarán automáticamente las nuevas reglas. + +--- + +## 🗑️ Desinstalación + +Para desinstalar el hook: + +```bash +rm .git/hooks/pre-commit +``` + +O para deshabilitarlo temporalmente: + +```bash +mv .git/hooks/pre-commit .git/hooks/pre-commit.disabled +``` + +Para volver a habilitarlo: + +```bash +mv .git/hooks/pre-commit.disabled .git/hooks/pre-commit +``` + +--- + +## 📚 Más información + +- **clang-format**: https://clang.llvm.org/docs/ClangFormat.html +- **clang-tidy**: https://clang.llvm.org/extra/clang-tidy/ +- **Git hooks**: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks + +--- + +## ⚠️ Nota para desarrolladores + +Los hooks de git están en `.git/hooks/` y **no se versionan automáticamente**. Por eso este directorio `tools/hooks/` contiene copias versionadas que se pueden instalar fácilmente. + +**Cada nuevo desarrollador debe ejecutar el instalador** al clonar el repositorio: + +```bash +git clone +cd orni +./tools/hooks/install.sh +``` + +--- + +## 🐛 Troubleshooting + +### "clang-format: command not found" + +Instala clang-format: + +```bash +# macOS +brew install clang-format + +# Ubuntu/Debian +sudo apt install clang-format + +# Arch Linux +sudo pacman -S clang +``` + +### "clang-tidy: command not found" + +Instala clang-tidy: + +```bash +# macOS +brew install llvm +export PATH="/opt/homebrew/opt/llvm/bin:$PATH" + +# Ubuntu/Debian +sudo apt install clang-tidy + +# Arch Linux +sudo pacman -S clang +``` + +### Hook no se ejecuta + +Verifica que el hook tiene permisos de ejecución: + +```bash +ls -la .git/hooks/pre-commit +chmod +x .git/hooks/pre-commit +``` + +### Errores en macOS sobre SDK + +El hook detecta automáticamente el SDK de macOS usando `xcrun --show-sdk-path`. Si falla, asegúrate de tener Command Line Tools instaladas: + +```bash +xcode-select --install +``` diff --git a/tools/hooks/install.sh b/tools/hooks/install.sh new file mode 100755 index 0000000..c7b4331 --- /dev/null +++ b/tools/hooks/install.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# Script de instalación de git hooks para desarrollo de Orni Attack +# Copia los hooks desde tools/hooks/ a .git/hooks/ y los hace ejecutables + +set -e + +# Obtener raíz del repositorio +REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".") + +# Colores para output +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "🔧 Instalando Git Hooks para Orni Attack" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +# Verificar que estamos en un repositorio git +if [ ! -d "$REPO_ROOT/.git" ]; then + echo "❌ Error: No se encontró el directorio .git" + echo " Ejecuta este script desde la raíz del repositorio" + exit 1 +fi + +# Verificar que existe el directorio de hooks versionados +if [ ! -d "$REPO_ROOT/tools/hooks" ]; then + echo "❌ Error: No se encontró el directorio tools/hooks/" + exit 1 +fi + +# Instalar pre-commit hook +if [ -f "$REPO_ROOT/tools/hooks/pre-commit" ]; then + echo "📦 Instalando pre-commit hook..." + cp "$REPO_ROOT/tools/hooks/pre-commit" "$REPO_ROOT/.git/hooks/pre-commit" + chmod +x "$REPO_ROOT/.git/hooks/pre-commit" + echo -e " ${GREEN}✅ pre-commit instalado${NC}" +else + echo -e " ${YELLOW}⚠️ pre-commit no encontrado, saltando...${NC}" +fi + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo -e "${GREEN}✅ Instalación completada${NC}" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo "📋 Hooks instalados:" +echo " • pre-commit: Ejecuta clang-format + clang-tidy en cada commit" +echo "" +echo "💡 Próximos pasos:" +echo " 1. Haz cambios en el código" +echo " 2. git add " +echo " 3. git commit -m \"mensaje\"" +echo " 4. El hook verificará automáticamente tu código" +echo "" +echo "⚙️ Para desinstalar:" +echo " rm .git/hooks/pre-commit" +echo "" + +exit 0 diff --git a/tools/hooks/pre-commit b/tools/hooks/pre-commit new file mode 100644 index 0000000..23a6a3c --- /dev/null +++ b/tools/hooks/pre-commit @@ -0,0 +1,133 @@ +#!/bin/bash +# Pre-commit hook: ejecuta clang-format y clang-tidy en archivos modificados +# Para instalarlo: cp tools/hooks/pre-commit .git/hooks/ && chmod +x .git/hooks/pre-commit +# O ejecuta: tools/hooks/install.sh + +set -e # Salir si hay error + +echo "🔍 Pre-commit hook: verificando código..." + +# Obtener raíz del repositorio +REPO_ROOT=$(git rev-parse --show-toplevel) + +# Obtener archivos staged (solo .cpp y .hpp) +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(cpp|hpp)$' || true) + +if [ -z "$STAGED_FILES" ]; then + echo "✅ No hay archivos C++ para revisar" + exit 0 +fi + +# Excluir directorios audio/ y legacy/ (igual que CMakeLists.txt) +FILTERED_FILES="" +for file in $STAGED_FILES; do + # Excluir si está en audio/ o legacy/ + if [[ ! "$file" =~ audio/ ]] && [[ ! "$file" =~ legacy/ ]]; then + # Solo incluir si el archivo existe (no fue eliminado) + if [ -f "$file" ]; then + FILTERED_FILES="$FILTERED_FILES $file" + fi + fi +done + +if [ -z "$FILTERED_FILES" ]; then + echo "✅ No hay archivos C++ para revisar (excluidos audio/ y legacy/)" + exit 0 +fi + +echo "📝 Archivos a revisar:$FILTERED_FILES" + +# ============================================ +# PASO 1: Ejecutar clang-format (auto-format) +# ============================================ +echo "" +echo "🎨 Ejecutando clang-format..." + +FORMAT_CHANGED=false +for file in $FILTERED_FILES; do + # Ejecutar clang-format in-place + clang-format --style=file -i "$file" + + # Verificar si el archivo cambió + if ! git diff --quiet "$file"; then + echo " ✏️ Formateado: $file" + FORMAT_CHANGED=true + # Añadir cambios de formato al staging + git add "$file" + fi +done + +if [ "$FORMAT_CHANGED" = true ]; then + echo "✅ Archivos formateados automáticamente y añadidos al commit" +else + echo "✅ Formato correcto (sin cambios)" +fi + +# ============================================ +# PASO 2: Ejecutar clang-tidy (verificación) +# ============================================ +echo "" +echo "🔍 Ejecutando clang-tidy..." + +# Configurar SDK de macOS (igual que CMakeLists.txt) +MACOS_SDK=$(xcrun --show-sdk-path 2>/dev/null || echo "") + +TIDY_FAILED=false +TIDY_OUTPUT="" + +for file in $FILTERED_FILES; do + # Ejecutar clang-tidy con configuración del proyecto + if [ -n "$MACOS_SDK" ]; then + TIDY_RESULT=$(clang-tidy "$file" \ + --extra-arg=-std=c++20 \ + --extra-arg=-isysroot"$MACOS_SDK" \ + --extra-arg=-I"$REPO_ROOT"/source \ + --extra-arg=-I"$REPO_ROOT"/build \ + -- 2>&1 || echo "TIDY_ERROR") + else + TIDY_RESULT=$(clang-tidy "$file" \ + --extra-arg=-std=c++20 \ + --extra-arg=-I"$REPO_ROOT"/source \ + --extra-arg=-I"$REPO_ROOT"/build \ + -- 2>&1 || echo "TIDY_ERROR") + fi + + # Verificar si hubo errores (ignorar warnings de headers del sistema) + ERROR_COUNT=$(echo "$TIDY_RESULT" | grep -E "error:|warning:" | grep -v "in non-user code" | wc -l | tr -d ' ') + + if [ "$ERROR_COUNT" -gt 0 ]; then + TIDY_FAILED=true + TIDY_OUTPUT="$TIDY_OUTPUT\n\n❌ Errores en $file:\n$TIDY_RESULT" + else + echo " ✅ $file" + fi +done + +# Si clang-tidy encontró errores, bloquear commit +if [ "$TIDY_FAILED" = true ]; then + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "❌ COMMIT BLOQUEADO: clang-tidy encontró errores" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo -e "$TIDY_OUTPUT" + echo "" + echo "💡 Soluciones:" + echo " 1. Corrige los errores manualmente" + echo " 2. O ejecuta: make tidy (aplica fixes automáticos)" + echo " 3. Luego: git add && git commit" + echo "" + echo "⚠️ Si necesitas saltarte el hook (NO RECOMENDADO):" + echo " git commit --no-verify" + echo "" + exit 1 +fi + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "✅ Pre-commit hook: TODO OK" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo " 🎨 clang-format: OK (archivos formateados)" +echo " 🔍 clang-tidy: OK (sin errores)" +echo "" + +exit 0