2010-10-21 3 views
16

Je souhaite que mon référentiel distant refuse toutes les poussées contenant un fichier contenant un onglet, mais seulement si le fichier appartient à une certaine classe (basée sur le nom de fichier). Est-ce possible?
J'ai regardé un peu au update hook dans les githooks, et je pense que c'est la bonne.Empêcher les push to git contenant des tabulations dans certains fichiers (par exemple * .cpp, * .h, CMakeLists.txt)

Donc en bref, un coup de pouce doit être rejetée si:

  1. il y a un fichier des types énumérés (*.cpp, *.h, CMakeLists.txt)
  2. qui contient un ou plusieurs caractères de tabulation.
+0

Demandez-vous de l'aide pour écrire le crochet, ou si un crochet de mise à jour fonctionnera dans ce but? – Cascabel

+0

Les deux en fait :) J'ai été très surpris que ce ne soit pas facilement trouvable et téléchargeable, j'ai donc le sentiment que ce n'est pas trivial. Un exemple de la façon dont un tel crochet pourrait ressembler aiderait beaucoup. –

Répondre

15

Euh oh, cette question semble avoir glissé à travers les fissures. J'espère que vous êtes toujours là-bas, Esben!

Vous recherchez un update hook, qui est exécuté une fois pour chaque réf mis à jour. Les arguments sont le nom de l'arbitre, le nom de l'ancien objet (commit SHA1) et le nouveau nom de l'objet. Donc, tout ce que vous devez vraiment faire est de vérifier le diff entre l'ancien et le nouveau et assurez-vous qu'il répond à vos normes. Ce n'est pas totalement simple, bien sûr, mais c'est tout à fait gérable. Voici ce que je ferais:

Enregistrez le script suivant sur .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 

qui répertorie tous les fichiers qui diffèrent entre les anciens et nouveaux, greps pour tous ceux désirés, obtient la diff pour eux (avec zéro lignes de contexte, étant donné que nous ne nous soucions pas), et pour greps une ligne ajoutée (commençant par +) contenant une tabulation. Le grep quitte le succès s'il en trouve un, ce qui laissera le && exécuter exit 1, provoquant l'échec de l'accrochage et l'abandon de la mise à jour! Notez que ceci est légèrement différent de vos besoins - il vérifie si le diff ajoute des caractères de tabulation. C'est probablement mieux à long terme; Une fois que vous avez vérifié que votre code existant est correct, c'est la même chose, sauf beaucoup plus rapide car il n'a pas à chercher tout le contenu.

+0

C'est parfait. Je revenais en fait ici pour télécharger ma solution, et c'est très proche ... sauf que j'utilise - $ (git ls-files ....) pour filtrer les types de fichiers. C'est un grand confort de voir que ma solution correspond aux experts :) –

+0

J'ai juste essayé ceci avec un commit qui ne contenait aucun * .cpp, * .h ou CMakeLists.txt (juste un peu aléatoire .txt avec un autre nom). xargs exécute alors 'git diff -U0 $ old $ new --' qui ne diffuse que le commit entier. La commande xargs devrait être: 'xargs -r -d '\ git diff -U0 $ old $ new --' pour l'empêcher de s'exécuter sur des entrées vides. – ancow

3

Vous pouvez configurer un pre-push hook, mais ce n'est pas vraiment dans l'esprit du mécanisme de publication git.

Je préfère aller avec:

  • un pre-commit hook, ce qui empêche toute commettras avec le mauvais contenu
  • ou filter driver que vous pouvez facilement associer les bons types de fichiers, et qui peut fixer ou d'un rapport tout contenu inapproprié.
+0

Dans ce cas, il semble plus probable que l'OP souhaite un hook de mise à jour plutôt qu'un hook de pré-push; s'il s'agit de garder le mauvais contenu hors du repo public, vous voulez probablement mettre un barrage routier sur le repo central, plutôt que de compter sur les développeurs qui s'installent toujours correctement. Je suis avec vous sur le crochet pré-commit, cependant. Je préférerais de loin savoir s'il y a un problème avec mon code quand je commets que quand je publie. – Cascabel

+0

@Jefromi: d'accord. Je trouve qu'il est préférable de détecter les problèmes plus tôt dans le cycle de vie du développement;) – VonC

+0

J'ai déjà écrit le hook pré-commit. Mais c'était relativement facile. le crochet de mise à jour semble beaucoup plus compliqué. Un exemple de ce qui pourrait être la bonne direction serait très apprécié. Et oui, j'ai l'intention d'avoir les deux: pré-commettre pour aider les devs contre eux-mêmes et mettre à jour pour aider les uns contre les autres. L'onglet Devs wanted a déjà un script qu'il utilise pour convertir d'avant en arrière lors de la validation/validation. –

1

Basé sur benprew's travail, voici un crochet de pré-script qui affiche une erreur si des caractères de tabulation ont été ajoutés, ainsi que le numéro de ligne correspondant. Enregistrez ce qui suit dans .git/hooks/pre-commit.

() Remarque: pre-commit est le nom du fichier.Il ne devrait pas y avoir de prolongation .)

#!/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); 
' 

Ce n'est pas exactement que vous avez demandé, car il ne fait pas de vérification de nom de fichier, mais nous espérons qu'il aide peu importe.

Questions connexes