Merge branch 'zj-info-attributes' into 'master'
Client implementation for InfoAttributes See merge request gitlab-org/gitlab-ce!18261
This commit is contained in:
commit
b2f57a561f
7 changed files with 46 additions and 114 deletions
|
@ -3,12 +3,8 @@ module Gitlab
|
|||
# Class for parsing Git attribute files and extracting the attributes for
|
||||
# file patterns.
|
||||
class AttributesParser
|
||||
def initialize(attributes_data)
|
||||
def initialize(attributes_data = "")
|
||||
@data = attributes_data || ""
|
||||
|
||||
if @data.is_a?(File)
|
||||
@patterns = parse_file
|
||||
end
|
||||
end
|
||||
|
||||
# Returns all the Git attributes for the given path.
|
||||
|
@ -28,7 +24,7 @@ module Gitlab
|
|||
|
||||
# Returns a Hash containing the file patterns and their attributes.
|
||||
def patterns
|
||||
@patterns ||= parse_file
|
||||
@patterns ||= parse_data
|
||||
end
|
||||
|
||||
# Parses an attribute string.
|
||||
|
@ -91,8 +87,8 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
# Parses the Git attributes file.
|
||||
def parse_file
|
||||
# Parses the Git attributes file contents.
|
||||
def parse_data
|
||||
pairs = []
|
||||
comment = '#'
|
||||
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
# Gitaly note: JV: not sure what to make of this class. Why does it use
|
||||
# the full disk path of the repository to look up attributes This is
|
||||
# problematic in Gitaly, because Gitaly hides the full disk path to the
|
||||
# repository from gitlab-ce.
|
||||
|
||||
module Gitlab
|
||||
module Git
|
||||
# Parses gitattributes at `$GIT_DIR/info/attributes`
|
||||
#
|
||||
# Unlike Rugged this parser only needs a single IO call (a call to `open`),
|
||||
# vastly reducing the time spent in extracting attributes.
|
||||
#
|
||||
# This class _only_ supports parsing the attributes file located at
|
||||
# `$GIT_DIR/info/attributes` as GitLab doesn't use any other files
|
||||
# (`.gitattributes` is copied to this particular path).
|
||||
#
|
||||
# Basic usage:
|
||||
#
|
||||
# attributes = Gitlab::Git::InfoAttributes.new(some_repo.path)
|
||||
#
|
||||
# attributes.attributes('README.md') # => { "eol" => "lf }
|
||||
class InfoAttributes
|
||||
delegate :attributes, :patterns, to: :parser
|
||||
|
||||
# path - The path to the Git repository.
|
||||
def initialize(path)
|
||||
@repo_path = File.expand_path(path)
|
||||
end
|
||||
|
||||
def parser
|
||||
@parser ||= begin
|
||||
if File.exist?(attributes_path)
|
||||
File.open(attributes_path, 'r') do |file_handle|
|
||||
AttributesParser.new(file_handle)
|
||||
end
|
||||
else
|
||||
AttributesParser.new("")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def attributes_path
|
||||
@attributes_path ||= File.join(@repo_path, 'info/attributes')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -105,7 +105,6 @@ module Gitlab
|
|||
)
|
||||
@path = File.join(storage_path, @relative_path)
|
||||
@name = @relative_path.split("/").last
|
||||
@attributes = Gitlab::Git::InfoAttributes.new(path)
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
|
@ -993,11 +992,32 @@ module Gitlab
|
|||
raise InvalidRef
|
||||
end
|
||||
|
||||
def info_attributes
|
||||
return @info_attributes if @info_attributes
|
||||
|
||||
content =
|
||||
gitaly_migrate(:get_info_attributes) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_repository_client.info_attributes
|
||||
else
|
||||
attributes_path = File.join(File.expand_path(@path), 'info', 'attributes')
|
||||
|
||||
if File.exist?(attributes_path)
|
||||
File.read(attributes_path)
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@info_attributes = AttributesParser.new(content)
|
||||
end
|
||||
|
||||
# Returns the Git attributes for the given file path.
|
||||
#
|
||||
# See `Gitlab::Git::Attributes` for more information.
|
||||
def attributes(path)
|
||||
@attributes.attributes(path)
|
||||
info_attributes.attributes(path)
|
||||
end
|
||||
|
||||
def gitattribute(path, name)
|
||||
|
|
|
@ -50,6 +50,15 @@ module Gitlab
|
|||
GitalyClient.call(@storage, :repository_service, :apply_gitattributes, request)
|
||||
end
|
||||
|
||||
def info_attributes
|
||||
request = Gitaly::GetInfoAttributesRequest.new(repository: @gitaly_repo)
|
||||
|
||||
response = GitalyClient.call(@storage, :repository_service, :get_info_attributes, request)
|
||||
response.each_with_object("") do |message, attributes|
|
||||
attributes << message.attributes
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_remote(remote, ssh_auth:, forced:, no_tags:, timeout:, prune: true)
|
||||
request = Gitaly::FetchRemoteRequest.new(
|
||||
repository: @gitaly_repo, remote: remote, force: forced,
|
||||
|
|
|
@ -66,18 +66,6 @@ describe Gitlab::Git::AttributesParser, seed_helper: true do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when attributes data is a file handle' do
|
||||
subject do
|
||||
File.open(attributes_path, 'r') do |file_handle|
|
||||
described_class.new(file_handle)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the attributes as a Hash' do
|
||||
expect(subject.attributes('test.txt')).to eq({ 'text' => true })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when attributes data is nil' do
|
||||
let(:data) { nil }
|
||||
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Git::InfoAttributes, 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 an empty Hash for a defined path without attributes' do
|
||||
expect(subject.attributes('bla/bla.txt')).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#parser' do
|
||||
it 'parses a file with entries' do
|
||||
expect(subject.patterns).to be_an_instance_of(Hash)
|
||||
expect(subject.patterns["/*.txt"]).to eq({ 'text' => true })
|
||||
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
|
||||
|
||||
it 'does not parse attributes files with unsupported encoding' do
|
||||
path = File.join(SEED_STORAGE_PATH, 'with-invalid-git-attributes.git')
|
||||
subject = described_class.new(path)
|
||||
|
||||
expect(subject.patterns).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
|
@ -84,6 +84,17 @@ describe Gitlab::GitalyClient::RepositoryService do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#info_attributes' do
|
||||
it 'reads the info attributes' do
|
||||
expect_any_instance_of(Gitaly::RepositoryService::Stub)
|
||||
.to receive(:get_info_attributes)
|
||||
.with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
|
||||
.and_return([])
|
||||
|
||||
client.info_attributes
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_local_branches?' do
|
||||
it 'sends a has_local_branches message' do
|
||||
expect_any_instance_of(Gitaly::RepositoryService::Stub)
|
||||
|
|
Loading…
Reference in a new issue