atributo git usando filter smudge / clean para procesar files .cpp a través del script de shell sin encontrar el nombre del file

Quería configurar el formatting del estilo del código para todos los files .cpp antes de que se hayan comprometido con git.

Hice un pequeño script (llamado codeformat) para hacer esto, (también intenté replaying% f con $ 1)

#! /bin/bash clang-format -style=file %f | diff %f -** if [ $? -ne 0 ]; then echo "ERROR: codeformat not correct" exit 1 fi 

configuró git config y actualizó .gitattributes con * .cpp filter = codeformat,

 git config --global filter.codeformat.clean codeformat git config --global filter.codeformat.smudge codeformat 

parece que se está ejecutando el script, pero no está obteniendo el nombre del file. ¿Por qué es esto?

Tienes la directiva %f en el lugar equivocado.

Como se muestra en la documentation de gitattributes (search %f ):

La secuencia "% f" en la línea de command del filter se reemplaza con el nombre del file en el que está trabajando el filter. Un filter puede usar esto en la sustitución de palabra key. Por ejemplo:

 [filter "p4"] clean = git-p4-filter --clean %f smudge = git-p4-filter --smudge %f 

Por lo tanto, para get el nombre de ruta del file, deberá establecer, por ejemplo, filter.codeformat.clean a codeformat %f .

En este punto, también necesitará modificar su script bash, ya que su syntax para la sustitución de arguments es de hecho $1 . Sin embargo, lea el próximo párrafo inmediato de la documentation de gitattributes:

Tenga en count que "% f" es el nombre de la ruta en la que se está trabajando. Dependiendo de la versión que se está filtrando, el file correspondiente en el disco puede no existir o puede tener diferentes contenidos. Por lo tanto, los commands de borrado y borrado no deben intentar acceder al file en el disco, sino que solo actúan como filters en el contenido que se les proporciona en la input estándar.

El énfasis aquí es mío, pero esto te dice que no puedes simplemente abrir el file del disco y leerlo. Debe filtrar solo la input estándar, proporcionando salida estándar.

( Como resulta, el formatting clang está diseñado para hacer exactamente eso. Dif, sin embargo, no lo es).


Editar para agregar un ejemplo de trabajo:

 $ cat ~/scripts/dotest #! /bin/sh echo "dotest run with $# arguments:" >>/tmp/dotest_log for i do printf '%s\n' "$i" done >>/tmp/dotest_log cat $ which dotest [path edited]/scripts/dotest $ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [filter "testfilter"] clean = dotest %f smudge = dotest %f $ cat .gitattributes *.test filter=testfilter $ echo 'bar.test' > bar.test $ git add bar.test $ cat /tmp/dotest_log dotest run with 1 arguments: bar.test 

%f es interpretado por git y debe estar en gitconfig . En el script de shell use $1 :

 git config --global filter.codeformat.clean 'codeformat %f' git config --global filter.codeformat.smudge 'codeformat %f' #! /bin/bash clang-format -style=file $1 | diff $1 -** if [ $? -ne 0 ]; then echo "ERROR: codeformat not correct" exit 1 fi 

eso significa que nunca puedo get el nombre del file ?, intenté% f con la configuration de git y cambié la secuencia de commands para usar $ 1, sin embargo, no obtiene el nombre del file.

 cat ~/.gitconfig [filter "codeformat"] clean = codeformat %f smudge = codeformat %f cat .gitattributes #clang code style format *.cpp filter=codeformat cat codeformat #! /bin/bash clang-format -i -style=file $1 - echo "file/path accessed is _____ $1 ____" > log_output 2>&1 git add src/sample.cpp cat log_output file/path accessed is _____ ____ 

mismo command (a continuación) si ejecuto en command-line funciona bien,

 clang-format -i -style=file src/sample.cpp 

Con git add no se puede get el nombre de file y, por lo tanto, otro error con error: no se puede usar -i cuando se lee desde stdin.

nota esta vez, eliminé el command diff, usé -i para replace el file fuente directamente "