File tree Expand file tree Collapse file tree 3 files changed +117
-0
lines changed
lib/overcommit/hook/pre_commit
spec/overcommit/hook/pre_commit Expand file tree Collapse file tree 3 files changed +117
-0
lines changed Original file line number Diff line number Diff line change @@ -629,6 +629,11 @@ PreCommit:
629629 include :
630630 - ' **/*.html'
631631
632+ LineEndings :
633+ description : ' Check line endings'
634+ enabled : false
635+ eol : " \n "
636+
632637 XmlLint :
633638 enabled : false
634639 description : ' Analyze with xmllint'
Original file line number Diff line number Diff line change 1+ module Overcommit ::Hook ::PreCommit
2+ # Checks for line endings in files.
3+ class LineEndings < Base
4+ def run
5+ messages = [ ]
6+
7+ offending_files . map do |file_name |
8+ file = File . open ( file_name )
9+ file . each_line do |line |
10+ # remove configured line-ending
11+ line . gsub! ( /#{ config [ 'eol' ] } / , '' )
12+
13+ # detect any left over line-ending characters
14+ next unless line . end_with? ( "\n " , "\r " )
15+
16+ messages << Overcommit ::Hook ::Message . new (
17+ :error ,
18+ file_name ,
19+ file . lineno ,
20+ "#{ file_name } :#{ file . lineno } :#{ line . inspect } "
21+ )
22+ end
23+ end
24+
25+ messages
26+ end
27+
28+ private
29+
30+ def offending_files
31+ result = execute ( %w[ git ls-files --eol -z -- ] , args : applicable_files )
32+ raise 'Unable to access git tree' unless result . success?
33+
34+ result . stdout . split ( "\0 " ) . map do |file_info |
35+ i , _w , _attr , path = file_info . split
36+ next if i == 'l/-text' # ignore binary files
37+ next if i == "l/#{ eol } "
38+ path
39+ end . compact
40+ end
41+
42+ def eol
43+ @eol ||= case config [ 'eol' ]
44+ when "\n "
45+ 'lf'
46+ when "\r \n "
47+ 'crlf'
48+ end
49+ end
50+ end
51+ end
Original file line number Diff line number Diff line change 1+ require 'spec_helper'
2+
3+ describe Overcommit ::Hook ::PreCommit ::LineEndings do
4+ let ( :config ) do
5+ Overcommit ::ConfigurationLoader . default_configuration . merge (
6+ Overcommit ::Configuration . new (
7+ 'PreCommit' => {
8+ 'LineEndings' => {
9+ 'eol' => eol
10+ }
11+ }
12+ )
13+ )
14+ end
15+ let ( :context ) { double ( 'context' ) }
16+ subject { described_class . new ( config , context ) }
17+ let ( :eol ) { "\n " }
18+ let ( :staged_file ) { 'filename.txt' }
19+
20+ before do
21+ subject . stub ( :applicable_files ) . and_return ( [ staged_file ] )
22+ end
23+
24+ around do |example |
25+ repo do
26+ File . open ( staged_file , 'w' ) { |f | f . write ( contents ) }
27+ `git add #{ staged_file } `
28+ example . run
29+ end
30+ end
31+
32+ context 'when enforcing \n' do
33+ context 'when file contains \r\n line endings' do
34+ let ( :contents ) { "CR-LF\r \n line\r \n endings\r \n " }
35+
36+ it { should fail_hook }
37+ end
38+
39+ context 'when file contains \n endings' do
40+ let ( :contents ) { "LF\n line\n endings\n " }
41+
42+ it { should pass }
43+ end
44+ end
45+
46+ context 'when enforcing \r\n' do
47+ let ( :eol ) { "\r \n " }
48+
49+ context 'when file contains \r\n line endings' do
50+ let ( :contents ) { "CR-LF\r \n line\r \n endings\r \n " }
51+
52+ it { should pass }
53+ end
54+
55+ context 'when file contains \n line endings' do
56+ let ( :contents ) { "LF\n line\n endings\n " }
57+
58+ it { should fail_hook }
59+ end
60+ end
61+ end
You can’t perform that action at this time.
0 commit comments