require 'spec_helper' describe Gitlab::Git::Attributes, seed_helper: true do let(:path) do File.join(SEED_STORAGE_PATH, 'with-git-attributes.git') end subject { described_class.new(path) } describe '#attributes' do context 'using a path with attributes' do it 'returns the attributes as a Hash' do expect(subject.attributes('test.txt')).to eq({ 'text' => true }) end it 'returns a Hash containing multiple attributes' do expect(subject.attributes('test.sh')). to eq({ 'eol' => 'lf', 'gitlab-language' => 'shell' }) end it 'returns a Hash containing attributes for a file with multiple extensions' do expect(subject.attributes('test.haml.html')). to eq({ 'gitlab-language' => 'haml' }) end it 'returns a Hash containing attributes for a file in a directory' do expect(subject.attributes('foo/bar.txt')).to eq({ 'foo' => true }) end it 'returns a Hash containing attributes with query string parameters' do expect(subject.attributes('foo.cgi')). to eq({ 'key' => 'value?p1=v1&p2=v2' }) end it 'returns a Hash containing the attributes for an absolute path' do expect(subject.attributes('/test.txt')).to eq({ 'text' => true }) end it 'returns a Hash containing the attributes when a pattern is defined using an absolute path' do # When a path is given without a leading slash it should still match # patterns defined with a leading slash. expect(subject.attributes('foo.png')). to eq({ 'gitlab-language' => 'png' }) expect(subject.attributes('/foo.png')). to eq({ 'gitlab-language' => 'png' }) end it 'returns an empty Hash for a defined path without attributes' do expect(subject.attributes('bla/bla.txt')).to eq({}) end context 'when the "binary" option is set for a path' do it 'returns true for the "binary" option' do expect(subject.attributes('test.binary')['binary']).to eq(true) end it 'returns false for the "diff" option' do expect(subject.attributes('test.binary')['diff']).to eq(false) end end end context 'using a path without any attributes' do it 'returns an empty Hash' do expect(subject.attributes('test.foo')).to eq({}) end end end describe '#patterns' do it 'parses a file with entries' do expect(subject.patterns).to be_an_instance_of(Hash) end it 'parses an entry that uses a tab to separate the pattern and attributes' do expect(subject.patterns[File.join(path, '*.md')]). to eq({ 'gitlab-language' => 'markdown' }) end it 'stores patterns in reverse order' do first = subject.patterns.to_a[0] expect(first[0]).to eq(File.join(path, 'bla/bla.txt')) end # It's a bit hard to test for something _not_ being processed. As such we'll # just test the number of entries. it 'ignores any comments and empty lines' do expect(subject.patterns.length).to eq(10) end it 'does not parse anything when the attributes file does not exist' do expect(File).to receive(:exist?). with(File.join(path, 'info/attributes')). and_return(false) expect(subject.patterns).to eq({}) end end describe '#parse_attributes' do it 'parses a boolean attribute' do expect(subject.parse_attributes('text')).to eq({ 'text' => true }) end it 'parses a negated boolean attribute' do expect(subject.parse_attributes('-text')).to eq({ 'text' => false }) end it 'parses a key-value pair' do expect(subject.parse_attributes('foo=bar')).to eq({ 'foo' => 'bar' }) end it 'parses multiple attributes' do input = 'boolean key=value -negated' expect(subject.parse_attributes(input)). to eq({ 'boolean' => true, 'key' => 'value', 'negated' => false }) end it 'parses attributes with query string parameters' do expect(subject.parse_attributes('foo=bar?baz=1')). to eq({ 'foo' => 'bar?baz=1' }) end end describe '#each_line' do it 'iterates over every line in the attributes file' do args = [String] * 14 # the number of lines in the file expect { |b| subject.each_line(&b) }.to yield_successive_args(*args) end it 'does not yield when the attributes file does not exist' do expect(File).to receive(:exist?). with(File.join(path, 'info/attributes')). and_return(false) expect { |b| subject.each_line(&b) }.not_to yield_control end it 'does not yield when the attributes file has an unsupported encoding' do path = File.join(SEED_STORAGE_PATH, 'with-invalid-git-attributes.git') attrs = described_class.new(path) expect { |b| attrs.each_line(&b) }.not_to yield_control end end end