Class: Twig::Branch

Inherits:
Object
  • Object
show all
Defined in:
lib/twig/branch.rb

Overview

Represents a Git branch.

Defined Under Namespace

Classes: EmptyPropertyNameError, MissingPropertyError

Constant Summary collapse

PARENT_PROPERTY =
'diff-branch'
PROPERTY_NAME_FROM_GIT_CONFIG =
/^branch\.[^.]+\.([^=]+)=.*$/
RESERVED_BRANCH_PROPERTY_NAMES =
%w[branch merge property rebase remote]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, attrs = {}) ⇒ Branch

Returns a new instance of Branch.

Raises:

  • (ArgumentError)


66
67
68
69
70
71
# File 'lib/twig/branch.rb', line 66

def initialize(name, attrs = {})
  self.name = name
  raise ArgumentError, '`name` is required' if name.empty?

  self.last_commit_time = attrs[:last_commit_time]
end

Instance Attribute Details

#last_commit_timeObject

Returns the value of attribute last_commit_time.



18
19
20
# File 'lib/twig/branch.rb', line 18

def last_commit_time
  @last_commit_time
end

#nameObject

Returns the value of attribute name.



18
19
20
# File 'lib/twig/branch.rb', line 18

def name
  @name
end

Class Method Details

.all_branch_namesObject



36
37
38
# File 'lib/twig/branch.rb', line 36

def self.all_branch_names
  @_all_branch_names ||= all_branches.map { |branch| branch.name }
end

.all_branchesObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/twig/branch.rb', line 20

def self.all_branches
  @_all_branches ||= begin
    branch_tuples = Twig.
      run(%{git for-each-ref #{ REF_PREFIX } --format="#{ REF_FORMAT }"}).
      split("\n")

    branch_tuples.inject([]) do |result, branch_tuple|
      name, time_string = branch_tuple.split(REF_FORMAT_SEPARATOR)
      time        = Time.parse(time_string)
      commit_time = Twig::CommitTime.new(time)
      branch      = Branch.new(name, :last_commit_time => commit_time)
      result << branch
    end
  end
end

.all_property_namesObject



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/twig/branch.rb', line 40

def self.all_property_names
  @_all_property_names ||= begin
    config_lines = Twig.run('git config --list').split("\n")

    properties = config_lines.map do |line|
      # Split by rightmost `=`, allowing branch names to contain `=`
      match_data = line.match(/(.+)=(.+)/)
      key, value = match_data[1..2] if match_data
      next unless key

      key_parts = key.split('.')
      key_parts.last if key_parts[0] == 'branch' && key_parts.size > 2
    end.compact

    properties.uniq.sort - RESERVED_BRANCH_PROPERTY_NAMES
  end
end

.shellescape_property_value(property_value) ⇒ Object



62
63
64
# File 'lib/twig/branch.rb', line 62

def self.shellescape_property_value(property_value)
  Shellwords.escape(property_value).gsub('\\ ', ' ')
end

.validate_property_name(property_name) ⇒ Object



58
59
60
# File 'lib/twig/branch.rb', line 58

def self.validate_property_name(property_name)
  raise EmptyPropertyNameError if property_name.empty?
end

Instance Method Details

#escaped_property_names(property_names) ⇒ Object



91
92
93
94
95
96
97
# File 'lib/twig/branch.rb', line 91

def escaped_property_names(property_names)
  property_names.map do |property_name|
    property_name = sanitize_property(property_name)
    Branch.validate_property_name(property_name)
    Regexp.escape(property_name)
  end
end

#get_properties(property_names) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/twig/branch.rb', line 99

def get_properties(property_names)
  return {} if property_names.empty?

  property_names_regexp = escaped_property_names(property_names).join('|')
  git_config_regexp     = "branch\.#{Shellwords.escape(name)}\.(#{ property_names_regexp })$"
  cmd = %{git config --get-regexp "#{git_config_regexp}"}

  git_result = Twig.run(cmd) || ''
  git_result_lines = git_result.split("\n")

  git_result_lines.inject({}) do |properties, line|
    match_data = line.match(/^branch\.#{Regexp.escape(name)}\.([^\s]+)\s+(.*)$/)

    if match_data
      property_name = match_data[1]
      property_value = match_data[2]
    else
      property_value = ''
    end

    if property_value.empty?
      properties
    else
      properties.merge(property_name => property_value)
    end
  end
end

#get_property(property_name) ⇒ Object



127
128
129
130
# File 'lib/twig/branch.rb', line 127

def get_property(property_name)
  property_name = sanitize_property(property_name)
  get_properties([property_name])[property_name]
end

#parent_nameObject



83
84
85
# File 'lib/twig/branch.rb', line 83

def parent_name
  get_property(PARENT_PROPERTY)
end

#sanitize_property(property_name) ⇒ Object



87
88
89
# File 'lib/twig/branch.rb', line 87

def sanitize_property(property_name)
  property_name.gsub(/[ _]+/, '')
end

#set_property(property_name, value) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/twig/branch.rb', line 132

def set_property(property_name, value)
  property_name = sanitize_property(property_name)
  value = value.to_s.strip
  Branch.validate_property_name(property_name)

  if RESERVED_BRANCH_PROPERTY_NAMES.include?(property_name)
    raise ArgumentError,
      %{Can't modify the reserved property "#{property_name}".}
  elsif value.empty?
    raise ArgumentError,
      %{Can't set a branch property to an empty string.}
  else
    git_config = "branch.#{name.shellescape}.#{property_name}"
    escaped_value = Branch.shellescape_property_value(value)
    Twig.run(%{git config #{git_config} "#{escaped_value}"})
    result_body = %{property "#{property_name}" as "#{value}" for branch "#{name}".}
    if $?.success?
      "Saved #{result_body}"
    else
      raise RuntimeError, "Could not save #{result_body}"
    end
  end
end

#to_hash(property_names) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/twig/branch.rb', line 75

def to_hash(property_names)
  {
    'name' => name,
    'last-commit-time' => last_commit_time.iso8601,
    'properties' => get_properties(property_names)
  }
end

#to_sObject



73
# File 'lib/twig/branch.rb', line 73

def to_s ; name ; end

#unset_property(property_name) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/twig/branch.rb', line 156

def unset_property(property_name)
  property_name = sanitize_property(property_name)
  Branch.validate_property_name(property_name)

  value = get_property(property_name)

  if value
    git_config = "branch.#{name.shellescape}.#{property_name}"
    Twig.run(%{git config --unset #{git_config}})
    %{Removed property "#{property_name}" for branch "#{name}".}
  else
    raise MissingPropertyError,
      %{The branch "#{name}" does not have the property "#{property_name}".}
  end
end