tipos tener tag sirve remove qué proyecto podemos para oneline nuestros nos mayor log herramienta hacer hace existen etiquetas cuando creamos control git clang-format

git - tener - ¿Puede el formato clang decirme si es necesario realizar cambios de formato?



¿qué herramienta podemos hacer para tener un mayor control de nuestros proyecto en github? (6)

Después de que me inspiré en la publicación de David Ogren, realicé un gancho pre-commit que puede trabajar en los cambios por etapas. Esto asegurará que el enganche de pre-commit funcionará en el código que conformará el contenido del commit y que no podrá ser engañado por una ejecución de clang-format que no se haya realizado.

#!/bin/bash files=() for file in `git diff --cached --name-only --diff-filter=ACMRT | grep -E "/.(cpp|hpp)$"`; do if ! cmp -s <(git show :${file}) <(git show :${file}|clang-format); then files+=("${file}") fi done if [ -n "${files}" ]; then echo Format error within the following files: printf "%s/n" "${files[@]}" exit 1 fi

¿Hay alguna forma de ejecutar clang-format en un modo en el que informe si el archivo cumple con el formato especificado? Un tipo de modo de ejecución en seco en el que informa si se necesita un cambio, pero no lo hace. Idealmente, me gustaría que clang-format devuelva un código de salida distinto de cero si el archivo necesita cambios. O, aún más idealmente, un código de salida distinto de cero y una lista de los archivos que necesitan cambios en la salida estándar.

Estoy tratando de mantener la pregunta genérica, para que más personas puedan responder, pero lo que estoy tratando de hacer es escribir un gancho de pre-confirmación de git que rechace cualquier confirmación que no coincida con el formato .clang esperado. Es fácil ejecutar el formato Clang en la lista de archivos en el índice. Pero es difícil saber si el formato Clang realmente cambió algo.

Tengo una solución potencial basada en -output-replacements-xml (que publicaré como respuesta), pero es un truco y creo que esto debería ser más sencillo. Comentarios / sugerencias, ediciones, diferentes respuestas / enfoques son bienvenidos.



Una de las razones por las que siento que esto debería ser más fácil de lo que es porque -output-replaceements-xml esencialmente me da la respuesta que quiero, simplemente no me la da de una manera fácil de consumir. Sin embargo, dado que la salida, si no se necesitan reemplazos, es muy predecible, el análisis de la salida no es demasiado difícil.

Lo que tengo ahora es

clang-format -style=file -output-replacements-xml | grep -c "<replacement " >/dev/null

En realidad, esto devuelve el inverso del código de salida que quiero, ya que grep devuelve 0 si algo coincide, 1 si nada lo hace. Pero eso es bastante fácil de tratar.

Así que el bit relevante de mi gancho de pre-commit git sería

git diff --cached --name-only --diff-filter=ACMRT | grep "/.[cmh]$" | xargs -n1 clang-format -style=file -output-replacements-xml | grep "<replacement " >/dev/null if [ $? -ne 1 ]; then echo "Commit did not match clang-format" exit 1 fi

  1. Obtenga los nombres de archivo completos de los archivos en el índice (excluyendo los archivos que se están eliminando y otros casos inusuales en los que es posible que no quiera procesar el archivo)
  2. Solo guarde los nombres de archivo de las cosas que quiero comprobar el formato (en mi caso solo los archivos c, m y h)
  3. Ejecute los resultados a través de xargs para esencialmente "para cada" el siguiente comando
  4. Ejecute clang-format con la opción -output-replacements-xml en todos los archivos
  5. Busque un reemplazo (a diferencia de los reemplazos) que indique que clang-format ha encontrado un reemplazo que desea hacer. (Descartar todos los resultados como el XML no será significativo para el usuario).
  6. El último comando sale 1 (grep dice que no encontramos nada), hemos terminado y las cosas están bien.
  7. Si no, muestre un mensaje y salga 1, que cancela la confirmación. Desafortunadamente, no tenemos una manera fácil de decirle al usuario qué archivo fue el problema, pero ellos pueden ejecutar el formato Clang por sí mismos y ver.

Uso el git-clang-format y un script de pre-commit del blog de Mike Rhodes:

#!/bin/python import subprocess output = subprocess.check_output(["git", "clang-format", "--diff"]) if output not in [''no modified files to format/n'', ''clang-format did not modify any files/n'']: print "Run git clang-format, then commit./n" exit(1) else: exit(0)

La secuencia de comandos tiene un pequeño error en que no funciona cuando no hay confirmaciones (tratando de verificar contra HEAD que aún no existe). Para evitar esto, use la --no-verify -n o --no-verify .

Usar -n para omitir la secuencia de comandos de pre-confirmación también puede ser útil cuando ignora la verificación porque puede llevar mucho tiempo para una base de código grande.

La publicación original está aquí: http://www.dx13.co.uk/articles/2015/4/3/Setting-up-git-clang-format.html


Ajusté ligeramente el comentario de phs en esta publicación para llegar a:

find embedded/ -regex ''.*/./(ino/|cpp/|hpp/|cc/|cxx/|h/)'' -exec cat {} /; | diff -u <(find embedded/ -regex ''.*/./(ino/|cpp/|hpp/|cc/|cxx/|h/)'' -exec clang-format-3.9 -style=file {} /;) -

es decir..

  1. cat todos los archivos cpp-ish y canalizaciones que diff ( diff aceptará la stdin porque lo especifico - al final)
  2. use la sustitución de procesos (la sintaxis <( .. ) ) para ejecutar clang-format en esos mismos archivos. No utilice el formato in situ aquí. Esta es la otra mitad que se envía a diff
  3. Si diff sale sin salida, ¡éxito! También puede consultar el código de salida a través de $? - Debería ser cero.

Tengo mi servicio de CI (travis) ejecutando esta línea en un script de bash para asegurarme de que las cosas estén formateadas correctamente. Tengo otro script para ejecutar el formateador en el lugar. Esto me recuerda a una advertencia: debe usar un shell que pueda procesar sub ( el shell de posix no lo hace ).


run-clang-format es un envoltorio simple alrededor clang-format diseñado precisamente para ser usado como un gancho o como un script de integración continua.

El ejemplo dado en la página de inicio habla por sí mismo: