Skip to content

Commit 51a541d

Browse files
ChandraChaansds
andauthored
Read .overcommit.yml as UTF-8 in the hook template (#910)
Fixes #868. Every hook in `template-dir/hooks` starts by reading `.overcommit.yml` to look for a `gemfile:` setting: ```ruby File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ ``` `File.read` without an encoding uses `Encoding.default_external`. Under a non-UTF-8 locale such as `LANG=C` that is US-ASCII, so if `.overcommit.yml` contains any non-ASCII character (even in a comment) the match raises `ArgumentError: invalid byte sequence in US-ASCII` before Overcommit loads, and every git hook fails. This passes `encoding: 'UTF-8'` in all 10 hook copies (the template directory spec requires them to be byte-identical). The regression spec in `spec/integration/template_dir_spec.rb` initializes a temporary repository using the hook templates and writes a `.overcommit.yml` containing a non-ASCII comment. It runs the installed `pre-commit` hook with `LC_ALL=C LANG=C` and `-E US-ASCII`, then checks for a successful exit and output from the configured `AuthorName` check. This verifies that the hook actually runs instead of passing on an unrelated startup failure or an early exit. The encoding is set explicitly because the CI runners use a UTF-8 locale by default. Initial validation of the original spec on the fork: - Spec only, without the fix: [Tests](https://github.com/ChandraChaan/overcommit/actions/runs/41726596528) fails on every Ruby from 2.6 to 4.0 with a single failure out of 1667 examples, `template_dir_spec.rb:31`, `expected "…/template-dir/hooks/pre-commit:30:in '<main>': invalid byte s…" not to include "invalid byte sequence"`. - Spec with the fix: [Tests](https://github.com/ChandraChaan/overcommit/actions/runs/41726604340) passes on all eight Ruby versions (`1667 examples, 0 failures`), and Lint passes. The original fix commit is the squashed form of the fix branch; a separate follow-up commit strengthens the regression test. I left `CHANGELOG.md` alone since it looks like it is written when a version is cut. Follow-up validation: [Tests](https://github.com/sds/overcommit/actions/runs/41934884255) passes on all eight Ruby versions (2.6–4.0), and [Lint](https://github.com/sds/overcommit/actions/runs/41934884375) passes. The strengthened spec also passes locally on Ruby 2.6 and fails both without the encoding fix and with hook execution disabled. The full local suite has four macOS timestamp precision failures, all reproduced on the original PR commit. --------- Co-authored-by: Shane da Silva <[email protected]>
1 parent 50f3e86 commit 51a541d

11 files changed

Lines changed: 37 additions & 10 deletions

File tree

‎spec/integration/template_dir_spec.rb‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require 'spec_helper'
44
require 'fileutils'
5+
require 'open3'
56

67
describe 'template directory' do
78
let(:template_dir) { File.join(Overcommit::HOME, 'template-dir') }
@@ -26,6 +27,32 @@
2627
end
2728
end
2829

30+
it 'reads a non-ASCII .overcommit.yml when the default external encoding is ASCII' do
31+
repo(template_dir: template_dir) do
32+
config = <<~YAML
33+
# caf\u00e9
34+
gemfile: false
35+
PreCommit:
36+
ALL:
37+
enabled: false
38+
AuthorName:
39+
enabled: true
40+
quiet: false
41+
YAML
42+
File.write('.overcommit.yml', config, encoding: 'UTF-8')
43+
44+
stdout, stderr, status = Open3.capture3(
45+
{ 'LC_ALL' => 'C', 'LANG' => 'C' },
46+
RbConfig.ruby, '-E', 'US-ASCII', '-I', File.join(Overcommit::HOME, 'lib'),
47+
File.join('.git', 'hooks', 'pre-commit'),
48+
stdin_data: ''
49+
)
50+
51+
expect(status.exitstatus).to eq(0), stdout + stderr
52+
stdout.should include('AuthorName')
53+
end
54+
end
55+
2956
it 'contains no symlinks' do
3057
Overcommit::Utils.supported_hook_types.each do |hook_type|
3158
Overcommit::Utils::FileUtils.symlink?(File.join(hooks_dir, hook_type)).should == false

‎template-dir/hooks/commit-msg‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook'
2727
end
2828

2929
# Check if Overcommit should invoke a Bundler context for loading gems
30-
File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
30+
File.read('.overcommit.yml', encoding: 'UTF-8') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
3131
gemfile = Regexp.last_match(1)
3232

3333
if gemfile

‎template-dir/hooks/overcommit-hook‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook'
2727
end
2828

2929
# Check if Overcommit should invoke a Bundler context for loading gems
30-
File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
30+
File.read('.overcommit.yml', encoding: 'UTF-8') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
3131
gemfile = Regexp.last_match(1)
3232

3333
if gemfile

‎template-dir/hooks/post-checkout‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook'
2727
end
2828

2929
# Check if Overcommit should invoke a Bundler context for loading gems
30-
File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
30+
File.read('.overcommit.yml', encoding: 'UTF-8') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
3131
gemfile = Regexp.last_match(1)
3232

3333
if gemfile

‎template-dir/hooks/post-commit‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook'
2727
end
2828

2929
# Check if Overcommit should invoke a Bundler context for loading gems
30-
File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
30+
File.read('.overcommit.yml', encoding: 'UTF-8') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
3131
gemfile = Regexp.last_match(1)
3232

3333
if gemfile

‎template-dir/hooks/post-merge‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook'
2727
end
2828

2929
# Check if Overcommit should invoke a Bundler context for loading gems
30-
File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
30+
File.read('.overcommit.yml', encoding: 'UTF-8') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
3131
gemfile = Regexp.last_match(1)
3232

3333
if gemfile

‎template-dir/hooks/post-rewrite‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook'
2727
end
2828

2929
# Check if Overcommit should invoke a Bundler context for loading gems
30-
File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
30+
File.read('.overcommit.yml', encoding: 'UTF-8') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
3131
gemfile = Regexp.last_match(1)
3232

3333
if gemfile

‎template-dir/hooks/pre-commit‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook'
2727
end
2828

2929
# Check if Overcommit should invoke a Bundler context for loading gems
30-
File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
30+
File.read('.overcommit.yml', encoding: 'UTF-8') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
3131
gemfile = Regexp.last_match(1)
3232

3333
if gemfile

‎template-dir/hooks/pre-push‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook'
2727
end
2828

2929
# Check if Overcommit should invoke a Bundler context for loading gems
30-
File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
30+
File.read('.overcommit.yml', encoding: 'UTF-8') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
3131
gemfile = Regexp.last_match(1)
3232

3333
if gemfile

‎template-dir/hooks/pre-rebase‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook'
2727
end
2828

2929
# Check if Overcommit should invoke a Bundler context for loading gems
30-
File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
30+
File.read('.overcommit.yml', encoding: 'UTF-8') =~ /gemfile: (?:false|['"]?(.*)['"]?)/
3131
gemfile = Regexp.last_match(1)
3232

3333
if gemfile

0 commit comments

Comments
 (0)