Refactor git_subdir_status

Instead of simply returning the opened pipe, consume the output
and yield the `mode, file` tuple to the given block.
This commit is contained in:
Claudio Bley 2021-01-14 22:19:29 +01:00
parent 373fb67003
commit 2eeb30fc44
2 changed files with 18 additions and 20 deletions

View file

@ -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

View file

@ -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