chúng tôi đang tránh vấn đề này trong thời gian tới với:
1) tất cả mọi người sử dụng một trình soạn thảo dùng để tách phần đuôi khoảng trắng, và chúng tôi lưu tất cả các file với LF.
2) nếu 1) không (nó có thể - ai đó vô tình lưu nó trong CRLF vì lý do gì), chúng tôi có một kịch bản pre-cam kết để kiểm tra cho chars 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 --
kịch bản này sử dụng GNU grep, và hoạt động trên Mac OS X, tuy nhiên cần phải kiểm tra trước khi sử dụng trên các nền tảng khác (chúng tôi gặp sự cố với Cygwin và BSD grep)
3) Trong trường hợp chúng tôi tìm thấy bất kỳ lỗi nào, chúng tôi sử dụng tập lệnh sau trên tệp sai:
#!/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;
}
?>
Điều này thật tuyệt vời! Tuy nhiên, tập lệnh của bạn có vấn đề với khoảng trống trong tên tệp. Tôi đã làm một cái gì đó như thế này: tìm. - type f -print0 -a \ (-name '*. [hc]' -o -name '* .p [yl]' \) | xargs -0 fromdos – Enno
Đồng ý rằng điều này thật tuyệt vời. Tuy nhiên, một câu hỏi: Cách tiếp cận ở đây chỉ định rõ ràng các phần mở rộng tệp để loại bỏ CR.Tôi muốn biết nếu nó có thể thay vì dải CRs từ tất cả và chỉ những bản sửa lỗi mà chẩn đoán phát hiện văn bản của git sẽ xem xét văn bản. (Git của heuristics nhìn vào nội dung tập tin thực tế, không tên tập tin.) Thoạt nhìn, có vẻ như nó sẽ chơi tốt hơn với core.autocrlf = true. – Chris
Không hoàn toàn là những gì tôi đã hỏi, nhưng http://stackoverflow.com/a/3092511 đưa ra cách tiếp cận sử dụng lệnh "tệp" unix để cố phân biệt văn bản với các tệp không phải văn bản. – Chris