diff --git a/lib/colorls/git.rb b/lib/colorls/git.rb index ab37d3c..366f638 100644 --- a/lib/colorls/git.rb +++ b/lib/colorls/git.rb @@ -14,17 +14,10 @@ module ColorLS git_status = Hash.new { |hash, key| hash[key] = Set.new } - git_subdir_status(repo_path) do |output| - while (status_line = output.gets "\x0") - mode, file = status_line.chomp("\x0").split(' ', 2) + git_subdir_status(repo_path) do |mode, file| + path = Pathname.new(file).relative_path_from(prefix) - path = Pathname.new(file).relative_path_from(prefix) - - git_status[path.descend.first.cleanpath.to_s].add(mode) - - # skip the next \x0 separated original path for renames, issue #185 - output.gets("\x0") if mode.start_with? 'R' - end + git_status[path.descend.first.cleanpath.to_s].add(mode) end warn "git status failed in #{repo_path}" unless $CHILD_STATUS.success? @@ -61,10 +54,19 @@ module ColorLS end def git_subdir_status(repo_path) - yield IO.popen( + IO.popen( ['git', '-C', repo_path, 'status', '--porcelain', '-z', '-unormal', '--ignored', '.'], external_encoding: Encoding::ASCII_8BIT - ) + ) do |output| + while (status_line = output.gets "\x0") + mode, file = status_line.chomp("\x0").split(' ', 2) + + yield mode, file + + # skip the next \x0 separated original path for renames, issue #185 + output.gets("\x0") if mode.start_with? 'R' + end + end end end end diff --git a/spec/color_ls/git_spec.rb b/spec/color_ls/git_spec.rb index d3c3b8d..0f6daab 100644 --- a/spec/color_ls/git_spec.rb +++ b/spec/color_ls/git_spec.rb @@ -8,21 +8,17 @@ RSpec.describe ColorLS::Git do expect($CHILD_STATUS).to be_success # rubocop:todo RSpec/ExpectInHook end - def git_status(*entries) - StringIO.new entries.map { |line| "#{line}\u0000" }.join - end - context 'with file in repository root' do it 'returns `M`' do allow(subject).to receive(:git_prefix).with('/repo/').and_return(['', true]) - allow(subject).to receive(:git_subdir_status).and_yield(git_status(' M foo.txt')) + allow(subject).to receive(:git_subdir_status).and_yield('M', 'foo.txt') expect(subject.status('/repo/')).to include('foo.txt' => Set['M']) end it 'returns `??`' do allow(subject).to receive(:git_prefix).with('/repo/').and_return(['', true]) - allow(subject).to receive(:git_subdir_status).and_yield(git_status('?? foo.txt')) + allow(subject).to receive(:git_subdir_status).and_yield('??', 'foo.txt') expect(subject.status('/repo/')).to include('foo.txt' => Set['??']) end @@ -31,14 +27,14 @@ RSpec.describe ColorLS::Git do context 'with file in subdir' do it 'returns `M` for subdir' do allow(subject).to receive(:git_prefix).with('/repo/').and_return(['', true]) - allow(subject).to receive(:git_subdir_status).and_yield(git_status(' M subdir/foo.txt')) + allow(subject).to receive(:git_subdir_status).and_yield('M', 'subdir/foo.txt') expect(subject.status('/repo/')).to include('subdir' => Set['M']) end it 'returns `M` and `D` for subdir' do allow(subject).to receive(:git_prefix).with('/repo/').and_return(['', true]) - allow(subject).to receive(:git_subdir_status).and_yield(git_status(' M subdir/foo.txt', 'D subdir/other.c')) + allow(subject).to receive(:git_subdir_status).and_yield('M', 'subdir/foo.txt').and_yield('D', 'subdir/other.c') expect(subject.status('/repo/')).to include('subdir' => Set['M', 'D']) end