debian-mirror-gitlab/lib/gitlab/git/attributes_parser.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

116 lines
2.9 KiB
Ruby
Raw Normal View History

2019-02-15 15:39:39 +05:30
# frozen_string_literal: true
2017-08-17 22:00:37 +05:30
module Gitlab
module Git
# Class for parsing Git attribute files and extracting the attributes for
# file patterns.
2018-03-17 18:26:18 +05:30
class AttributesParser
2018-10-15 14:42:47 +05:30
def initialize(attributes_data = "")
2018-03-17 18:26:18 +05:30
@data = attributes_data || ""
2017-08-17 22:00:37 +05:30
end
# Returns all the Git attributes for the given path.
#
2018-03-17 18:26:18 +05:30
# file_path - A path to a file for which to get the attributes.
2017-08-17 22:00:37 +05:30
#
# Returns a Hash.
2018-03-17 18:26:18 +05:30
def attributes(file_path)
absolute_path = File.join('/', file_path)
2017-08-17 22:00:37 +05:30
patterns.each do |pattern, attrs|
2018-03-17 18:26:18 +05:30
return attrs if File.fnmatch?(pattern, absolute_path)
2017-08-17 22:00:37 +05:30
end
{}
end
# Returns a Hash containing the file patterns and their attributes.
def patterns
2018-10-15 14:42:47 +05:30
@patterns ||= parse_data
2017-08-17 22:00:37 +05:30
end
# Parses an attribute string.
#
# These strings can be in the following formats:
#
# text # => { "text" => true }
# -text # => { "text" => false }
# key=value # => { "key" => "value" }
#
# string - The string to parse.
#
# Returns a Hash containing the attributes and their values.
def parse_attributes(string)
values = {}
dash = '-'
equal = '='
binary = 'binary'
string.split(/\s+/).each do |chunk|
# Data such as "foo = bar" should be treated as "foo" and "bar" being
# separate boolean attributes.
next if chunk == equal
key = chunk
# Input: "-foo"
if chunk.start_with?(dash)
key = chunk.byteslice(1, chunk.length - 1)
value = false
# Input: "foo=bar"
elsif chunk.include?(equal)
key, value = chunk.split(equal, 2)
# Input: "foo"
else
value = true
end
values[key] = value
# When the "binary" option is set the "diff" option should be set to
# the inverse. If "diff" is later set it should overwrite the
# automatically set value.
values['diff'] = false if key == binary && value
end
values
end
# Iterates over every line in the attributes file.
def each_line
2018-03-17 18:26:18 +05:30
@data.each_line do |line|
break unless line.valid_encoding?
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
yield line.strip
2017-08-17 22:00:37 +05:30
end
2020-05-24 23:13:21 +05:30
# Catch invalid byte sequences
rescue ArgumentError
2017-08-17 22:00:37 +05:30
end
private
2018-10-15 14:42:47 +05:30
# Parses the Git attributes file contents.
def parse_data
2017-08-17 22:00:37 +05:30
pairs = []
comment = '#'
each_line do |line|
next if line.start_with?(comment) || line.empty?
pattern, attrs = line.split(/\s+/, 2)
parsed = attrs ? parse_attributes(attrs) : {}
2018-03-17 18:26:18 +05:30
absolute_pattern = File.join('/', pattern)
pairs << [absolute_pattern, parsed]
2017-08-17 22:00:37 +05:30
end
# Newer entries take precedence over older entries.
pairs.reverse.to_h
end
end
end
end