stiamo evitare questo problema in futuro con:
1) tutti usano un editor che mette a nudo spazi bianchi finali, e noi salvare tutti i file con LF.
2) se 1) fallisce (il possibile - qualcuno salva accidentalmente in CRLF per qualsiasi motivo) abbiamo uno script pre-commit che verifica la presenza di caratteri CRLF:
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by git-commit with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit" and set executable bit
# original by Junio C Hamano
# modified by Barnabas Debreceni to disallow CR characters in commits
if git rev-parse --verify HEAD 2>/dev/null
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
crlf=0
IFS="
"
for FILE in `git diff-index --cached $against`
do
fhash=`echo $FILE | cut -d' ' -f4`
fname=`echo $FILE | cut -f2`
if git show $fhash | grep -EUIlq $'\r$'
then
echo $fname contains CRLF characters
crlf=1
fi
done
if [ $crlf -eq 1 ]
then
echo Some files have CRLF line endings. Please fix it to be LF and try committing again.
exit 1
fi
exec git diff-index --check --cached $against --
Questo script utilizza GNU grep, e funziona su Mac OS X, tuttavia dovrebbe essere testato prima dell'uso su altre piattaforme (abbiamo avuto problemi con Cygwin e BSD grep)
3) Nel caso in cui troviamo errori di spazi bianchi, utilizziamo il seguente script su file errati:
#!/usr/bin/env php
<?php
// Remove various whitespace errors and convert to LF from CRLF line endings
// written by Barnabas Debreceni
// licensed under the terms of WFTPL (http://en.wikipedia.org/wiki/WTFPL)
// handle no args
if($argc <2) die("nothing to do");
// blacklist
$bl = array('smarty' . DIRECTORY_SEPARATOR . 'templates_c' . DIRECTORY_SEPARATOR . '.*');
// whitelist
$wl = array( '\.tpl', '\.php', '\.inc', '\.js', '\.css', '\.sh', '\.html', '\.txt', '\.htc', '\.afm',
'\.cfm', '\.cfc', '\.asp', '\.aspx', '\.ascx' ,'\.lasso', '\.py', '\.afp', '\.xml',
'\.htm', '\.sql', '\.as', '\.mxml', '\.ini', '\.yaml', '\.yml' );
// remove $argv[0]
array_shift($argv);
// make file list
$files = getFileList($argv);
// sort files
sort($files);
// filter them for blacklist and whitelist entries
$filtered = preg_grep('#(' . implode('|', $wl) . ')$#', $files);
$filtered = preg_grep('#(' . implode('|', $bl) . ')$#', $filtered, PREG_GREP_INVERT);
// fix whitespace errors
fix_whitespace_errors($filtered);
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
// whitespace error fixer
function fix_whitespace_errors($files) {
foreach($files as $file) {
// read in file
$rawlines = file_get_contents($file);
// remove \r
$lines = preg_replace("/(\r\n)|(\n\r)/m", "\n", $rawlines);
$lines = preg_replace("/\r/m", "\n", $lines);
// remove spaces from before tabs
$lines = preg_replace("/\040+\t/m", "\t", $lines);
// remove spaces from line endings
$lines = preg_replace("/[\040\t]+$/m", "", $lines);
// remove tabs from line endings
$lines = preg_replace("/\t+$/m", "", $lines);
// remove EOF newlines
$lines = preg_replace("/\n+$/", "", $lines);
// write file if changed and set old permissions
if(strlen($lines) != strlen($rawlines)){
$perms = fileperms($file);
// Uncomment to save original files
//rename($file, $file.".old");
file_put_contents($file, $lines);
chmod($file, $perms);
echo "${file}: FIXED\n";
} else {
echo "${file}: unchanged\n";
}
}
}
// get file list from argument array
function getFileList($argv) {
$files = array();
foreach($argv as $arg) {
// is a direcrtory
if(is_dir($arg)) {
$files = array_merge($files, getDirectoryTree($arg));
}
// is a file
if(is_file($arg)) {
$files[] = $arg;
}
}
return $files;
}
// recursively scan directory
function getDirectoryTree($outerDir){
$outerDir = preg_replace(':' . DIRECTORY_SEPARATOR . '$:', '', $outerDir);
$dirs = array_diff(scandir($outerDir), array(".", ".."));
$dir_array = array();
foreach($dirs as $d){
if(is_dir($outerDir . DIRECTORY_SEPARATOR . $d)) {
$otherdir = getDirectoryTree($outerDir . DIRECTORY_SEPARATOR . $d);
$dir_array = array_merge($dir_array, $otherdir);
}
else $dir_array[] = $outerDir . DIRECTORY_SEPARATOR . $d;
}
return $dir_array;
}
?>
È fantastico! Tuttavia, il tuo script ha problemi con gli spazi nei nomi dei file. Ho fatto qualcosa di simile invece: trovare. -type f -print0 -a \ (-name '*. [hc]' -o -name '* .p [yl]' \) | xargs -0 fromdos – Enno
D'accordo che è fantastico. Un Q, però: l'approccio qui specifica esplicitamente quali estensioni di file rimuovere da CR.Mi piacerebbe sapere se è possibile invece eliminare i CR da tutti e solo quelle correzioni che l'euristica di rilevamento del testo di Git considererebbe il testo. (L'euristica di Git guarda il contenuto reale del file, non i nomi dei file.) A prima vista, comunque, sembra che giochi ancora meglio con core.autocrlf = true. – Chris
Non proprio quello che stavo chiedendo, ma http://stackoverflow.com/a/3092511 fornisce un approccio che usa il comando "file" di unix per cercare di distinguere tra testo e file non di testo. – Chris