Class: RightGit::Git::BranchCollection

Inherits:
Object
  • Object
show all
Includes:
BelongsToRepository
Defined in:
lib/right_git/git/branch_collection.rb

Overview

A collection of Git branches. Acts a bit like an Array, allowing it to be mapped, sorted and compared as such.

Constant Summary collapse

HEAD_REF =

Regexp matching (and capturing) the output of ‘git symbolic-ref’; used to determine which branch is currently checked out.

%r{^refs/heads/(#{Branch::BRANCH_NAME})$}
NO_HEAD_REF =

The output of ‘git symbolic-ref’ when the HEAD ref is not on any branch.

/^HEAD is not a symbolic ref$/
NO_BRANCH =

The output of the ‘git branch’ command when the HEAD ref is not on any branch. This is not useful to RightGit, so we must filter it out of Git’s output when we see it.

'* (no branch)'

Instance Attribute Summary

Attributes included from BelongsToRepository

#repo

Instance Method Summary collapse

Methods included from BelongsToRepository

#logger

Constructor Details

#initialize(repo, branches = nil) ⇒ BranchCollection

Create a new BranchCollection. Don’t pass in a branches parameter unless you really know what you’re doing; it’s intended more for internal use than anything else.

Parameters:

  • repo (Repository)

    to host branch collection

  • optional (Array)

    branches an array of Branch objects, or nil to auto-populate this collection with ALL branches



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/right_git/git/branch_collection.rb', line 50

def initialize(repo, branches=nil)
  @repo = repo

  if branches
    # Use an arbitrary set of branches that was passed in
    @branches = branches
  else
    @branches = []

    # Initialize ourselves with all branches in the repository
    git_args = ['branch', '-a']
    @repo.git_output(git_args).lines.each do |line|
      line.strip!

      if line == NO_BRANCH
        #no-op; ignore this one
      else
        @branches << Branch.new(@repo, line)
      end
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object

Dispatch to the underlying Array of Branch objects, allowing the branch collection to act a bit like an Array.

If the dispatched-to method returns an Array, it is wrapped in another BranchCollection object before returning to the caller. This allows array-like method calls to be chained together without losing the BranchCollection-ness of the underlying object.



172
173
174
175
176
177
178
179
180
# File 'lib/right_git/git/branch_collection.rb', line 172

def method_missing(meth, *args, &block)
  result = @branches.__send__(meth, *args, &block)

  if result.is_a?(::Array)
    BranchCollection.new(@repo, result)
  else
    result
  end
end

Instance Method Details

#[](argument) ⇒ Object

Accessor that acts like either a Hash or Array accessor



156
157
158
159
160
161
162
163
164
# File 'lib/right_git/git/branch_collection.rb', line 156

def [](argument)
  case argument
  when String
    target = Branch.new(@repo, argument)
    @branches.detect { |b| b == target }
  else
    @branches.__send__(:[], argument)
  end
end

#currentBranch

Return a Branch object representing whichever branch is currently checked out, IF AND ONLY IF that branch is a member of the collection. If the current branch isn’t part of the collection or HEAD refers to something other than a branch, return nil.

Returns:

  • (Branch)

    the current branch if any, nil otherwise



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/right_git/git/branch_collection.rb', line 89

def current
  lines = @repo.git_output(['symbolic-ref', 'HEAD'], :raise_on_failure => false).lines

  if lines.size == 1
    line = lines.first.strip
    if (match = HEAD_REF.match(line))
      @branches.detect { |b| b.fullname == match[1] }
    elsif line == NO_HEAD_REF
      nil
    end
  else
    raise GitError, "Unexpected output from 'git symbolic-ref'; need 1 lines, got #{lines.size}"
  end
end

#inspectObject

Provide a programmer-friendly representation of this collection.



80
81
82
# File 'lib/right_git/git/branch_collection.rb', line 80

def inspect
  '#<%s:%s>' % [self.class.name, @branches.inspect]
end

#localBranchCollection

Return another collection that contains only the local branches in this collection.

Returns:



107
108
109
110
111
112
113
114
115
# File 'lib/right_git/git/branch_collection.rb', line 107

def local
  local = []

  @branches.each do |branch|
    local << branch unless branch.remote?
  end

  BranchCollection.new(@repo, local)
end

#merged(revision) ⇒ BranchCollection

Queries and filters on branches reachable from the given revision, if any.

Parameters:

  • revision (String)

    for listing reachable merged branches

Returns:



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/right_git/git/branch_collection.rb', line 135

def merged(revision)
  # By hand, build a list of all branches known to be merged into master
  git_args = ['branch', '-a', '--merged', revision]
  all_merged = []
  @repo.git_output(git_args).lines.each do |line|
    line.strip!
    all_merged << Branch.new(@repo, line)
  end

  # Filter the contents of this collection according to the big list
  merged = []
  @branches.each do |candidate|
    # For some reason Set#include? does not play nice with our overridden comparison operators
    # for branches, so we need to do this the hard way :(
    merged << candidate if all_merged.detect { |b| candidate == b }
  end

  BranchCollection.new(@repo, merged)
end

#remoteBranchCollection

Return another collection that contains only the local branches in this collection.

Returns:



120
121
122
123
124
125
126
127
128
# File 'lib/right_git/git/branch_collection.rb', line 120

def remote
  remote = []

  @branches.each do |branch|
    remote << branch if branch.remote?
  end

  BranchCollection.new(@repo, remote)
end

#respond_to?(meth) ⇒ Boolean

Polite implementation of #respond_to that honors our #method_missing.

Returns:

  • (Boolean)


183
184
185
# File 'lib/right_git/git/branch_collection.rb', line 183

def respond_to?(meth)
  super || @branches.respond_to?(meth)
end

#to_sObject

Provide a String representation of this collection, depicting it as a comma-separated list of branch names.



75
76
77
# File 'lib/right_git/git/branch_collection.rb', line 75

def to_s
  @branches.join(',')
end