2010-10-21 11 views
16

Me gustaría que mi repositorio remoto rechace cualquier inserción que contenga un archivo que contenga una pestaña, pero solo si el el archivo pertenece a cierta clase (basado en el nombre del archivo). ¿Es eso posible?
Miré un poco el update hook en githooks, y creo que es el correcto.Prevenir los intentos de inserción de pestañas en ciertos archivos (p. Ej. * .cpp, * .h, CMakeLists.txt)

Así que en resumen, un empuje debe ser rechazada si:

  1. hay un archivo de los tipos enumerados (*.cpp, *.h, CMakeLists.txt)
  2. que contiene uno o más caracteres de tabulación.
+0

¿Está pidiendo ayuda para escribir el gancho, o si un gancho de actualización funcionará para este propósito? – Cascabel

+0

Ambos en realidad :) Me sorprendió mucho que esto no fuera fácil de encontrar y descargar, así que tengo la sensación de que no es trivial. Un ejemplo de cómo podría ser ese gancho ayudaría mucho. –

Respuesta

15

Uh, oh, esta pregunta parece haber resuelto las grietas. Espero que sigas ahí afuera, Esben!

Está buscando una update hook, que se ejecuta una vez por cada ref actualizada. Los argumentos son el nombre de la referencia, el nombre del objeto anterior (confirmación SHA1) y el nuevo nombre del objeto.

Por lo tanto, todo lo que necesita hacer es verificar la diferencia entre lo viejo y lo nuevo y asegurarse de que cumpla con sus estándares. Esto no es totalmente sencillo, por supuesto, pero es totalmente manejable. Esto es lo que haría:

Guarde la siguiente secuencia de comandos en .git/hooks/update.

old=$2 
new=$3 

# that's a literal tab, because (ba)sh turns \t into t, not a tab 
# make sure your editor doesn't expand it to spaces 
git diff --name-only $old $new | egrep '(\.(cpp|h)$)|^CMakeLists.txt$' | xargs -d'\n' git diff -U0 $old $new -- | grep -q '^+.* ' && exit 1 

que muestra todos los archivos que difieren entre las viejas y nuevas, greps para todos los deseados, obtiene el diff para ellos (con cero líneas de contexto, ya que no nos importa), y para greps una línea adicional (comenzando con +) que contiene una pestaña. El grep sale exitoso si encuentra uno, lo que permitirá que && ejecute exit 1, haciendo que el gancho salga de falla y aborte la actualización.

Tenga en cuenta que esto es ligeramente diferente de sus requisitos: comprueba si el diff agrega caracteres de pestañas. Esto es probablemente mejor a largo plazo; una vez que se haya asegurado de que su código actual está bien, es lo mismo, excepto mucho más rápido, ya que no tiene que buscar todo el contenido.

+0

Eso es perfecto. De hecho, volvía aquí para cargar mi solución, y está muy cerca ... excepto que uso - $ (git ls-files ....) para filtrar los tipos de archivo. Es una gran comodidad ver que mi solución coincide con los expertos :) –

+0

Acabo de probar esto con una confirmación que no contenía ningún * .cpp, * .h o CMakeLists.txt (solo algunos .txt aleatorios con otro nombre). xargs luego ejecuta 'git diff -U0 $ old $ new --' que simplemente diffiste la confirmación completa. El comando xargs debe ser: 'xargs -r -d '\ n' git diff -U0 $ old $ new --' para evitar que se ejecute en entradas vacías. – ancow

3

Puede configurar un pre-push hook, pero esto no está realmente en el espíritu del mecanismo de publicación de git.

preferiría ir con:

  • un pre-commit hook, evitando comprometerse con el contenido equivocado
  • o una filter driver que se pueden asociar fácilmente con el tipo correcto de archivo, y que se puede fijar o informe cualquier contenido inapropiado
+0

En este caso, parece más probable que el OP desee un gancho de actualización que un gancho de pre-push; si se trata de mantener el contenido incorrecto fuera del repositorio público, es probable que desee colocar una barricada en el repositorio central, en lugar de confiar en que los desarrolladores siempre se configuren correctamente. Sin embargo, estoy contigo en el gancho de precompromiso. Prefiero descubrir que hay un problema con mi código cuando me estoy comprometiendo que cuando publico. – Cascabel

+0

@Jefromi: de acuerdo. Me parece mejor detectar problemas más temprano en el ciclo de vida de desarrollo;) – VonC

+0

Ya he escrito el enganche previo a la confirmación. Pero eso fue relativamente fácil; el gancho de actualización parece mucho más complicado. Un ejemplo de lo que podría ser la dirección correcta sería muy apreciado. Y sí, tengo la intención de tener ambas cosas: comprometerse previamente para ayudar a los desarrolladores en su contra y actualizar para ayudarse unos contra otros. Los desarrolladores querían que la pestaña ya tenga una secuencia de comandos que usa para convertir de ida y vuelta al momento del pago/confirmación. –

1

Según el trabajo benprew's, aquí hay un gancho de preguión que muestra un error si se han agregado caracteres de pestañas, así como el número de línea correspondiente. Guarde lo siguiente en .git/hooks/pre-commit.

(Nota: pre-commit es el nombre de archivo.No debería haber ninguna extensión .)

#!/bin/sh 

if git rev-parse --verify HEAD 2>/dev/null 
then 
    git diff-index -p -M --cached HEAD 
else 
    : 
fi | 
perl -e ' 
    my $found_bad = 0; 
    my $filename; 
    my $reported_filename = ""; 
    my $lineno; 
    sub bad_line { 
     my ($why, $line) = @_; 
     if (!$found_bad) { 
      print STDERR "*\n"; 
      print STDERR "* You have some suspicious patch lines:\n"; 
      print STDERR "*\n"; 
      $found_bad = 1; 
     } 
     if ($reported_filename ne $filename) { 
      print STDERR "* In $filename\n"; 
      $reported_filename = $filename; 
     } 
     print STDERR "* $why (line $lineno)\n"; 
     print STDERR "$filename:$lineno:$line\n"; 
    } 
    while (<>) { 
     if (m|^diff --git a/(.*) b/\1$|) { 
      $filename = $1; 
      next; 
     } 
     if (/^@@ -\S+ \+(\d+)/) { 
      $lineno = $1 - 1; 
      next; 
     } 
     if (/^ /) { 
      $lineno++; 
      next; 
     } 
     if (s/^\+//) { 
      $lineno++; 
      chomp; 
      if (/ /) { 
       bad_line("TAB character", $_); 
      } 
     } 
    } 
    exit($found_bad); 
' 

No es exactamente lo que pidieron, ya que no hace ninguna comprobación de nombre de archivo, pero espero que ayuda a tener en cuenta.

Cuestiones relacionadas