Skip to content

Commit f43743b

Browse files
harmjanbloksds
authored andcommitted
Added pre-commit hook to check for line endings
Depending on the configured representation, this hook will verify if only unix line endings (LF) or only windows line endings (CRLF) are used.
1 parent 80766b4 commit f43743b

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

config/default.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff 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'
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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\nline\r\nendings\r\n" }
35+
36+
it { should fail_hook }
37+
end
38+
39+
context 'when file contains \n endings' do
40+
let(:contents) { "LF\nline\nendings\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\nline\r\nendings\r\n" }
51+
52+
it { should pass }
53+
end
54+
55+
context 'when file contains \n line endings' do
56+
let(:contents) { "LF\nline\nendings\n" }
57+
58+
it { should fail_hook }
59+
end
60+
end
61+
end

0 commit comments

Comments
 (0)