Module: Git::Parsers::Branch Private
- Defined in:
- lib/git/parsers/branch.rb
Overview
This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.
Parser for git branch command output
Handles parsing of git branch --list and git branch --delete output
into structured data objects.
Design Note: Namespace Organization
This parser creates and returns BranchInfo and BranchDeleteResult
objects, which live at the top-level Git:: namespace rather than within
Git::Parsers::. This is intentional:
- Parsers are infrastructure - marked
@api private, users shouldn't interact with them directly - Info/Result classes are public API - returned by commands and used throughout the codebase
- Info classes are domain entities - represent core git concepts (branches as data)
- Result classes are operation outcomes - represent command results, not parsing details
Keeping Info/Result classes at Git:: improves discoverability and correctly
reflects their role as public types rather than parser internals.
Constant Summary collapse
- FORMAT_STRING =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Format string for git branch --format
Fields (pipe-delimited):
- refname - full ref name (e.g., refs/heads/main, refs/remotes/origin/main)
- objectname - full SHA of the commit the branch points to
- HEAD - '*' if current branch, empty otherwise
- worktreepath - path if checked out in another worktree, empty otherwise
- symref - target ref if symbolic reference, empty otherwise
- upstream - full upstream ref (e.g., refs/remotes/origin/main), empty if none
'%(refname)|%(objectname)|%(HEAD)|%(worktreepath)|%(symref)|%(upstream)'- FIELD_DELIMITER =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Delimiter used in format output
'|'- DELETED_BRANCH_REGEX =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Regex to parse successful deletion lines from stdout Matches: Deleted branch branchname (was abc123). Matches: Deleted remote-tracking branch origin/branchname (was abc123). Uses non-greedy match to capture branch names containing spaces
/^Deleted (?:remote-tracking )?branch (.+?) \(was/- ERROR_BRANCH_REGEX =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Regex to parse error messages from stderr Matches: error: branch 'branchname' not found.
/^error: branch '([^']+)'(.*)$/
Class Method Summary collapse
-
.build_branch_info(fields) ⇒ Git::BranchInfo
private
Build a BranchInfo from parsed fields.
-
.build_delete_result(requested_names, existing_branches, deleted_names, error_map) ⇒ Git::BranchDeleteResult
private
Build the BranchDeleteResult from parsed data.
-
.build_upstream_info(upstream_ref) ⇒ Git::BranchInfo?
private
Build upstream BranchInfo from upstream refname.
-
.in_other_worktree?(worktreepath, current) ⇒ Boolean
private
Check if the branch is checked out in another worktree.
-
.non_branch_entry?(refname) ⇒ Boolean
private
Check if the refname represents a detached HEAD state or non-branch entry.
-
.normalize_refname(refname) ⇒ String
private
Normalize a full refname to the expected format.
-
.parse_branch_line(line) ⇒ Git::BranchInfo?
private
Parse a single formatted branch line.
-
.parse_deleted_branches(stdout) ⇒ Array<String>
private
Parse deleted branch names from stdout.
-
.parse_error_messages(stderr) ⇒ Hash<String, String>
private
Parse error messages from stderr into a map.
-
.parse_list(stdout) ⇒ Array<Git::BranchInfo>
private
Parse git branch --list output into BranchInfo objects.
-
.presence(value) ⇒ String?
private
Return value if non-empty, nil otherwise.
Class Method Details
.build_branch_info(fields) ⇒ Git::BranchInfo
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Build a BranchInfo from parsed fields
100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/git/parsers/branch.rb', line 100 def build_branch_info(fields) raw_refname, objectname, head, worktreepath, symref, upstream = fields current = head == '*' Git::BranchInfo.new( refname: normalize_refname(raw_refname), target_oid: presence(objectname), current: current, worktree: in_other_worktree?(worktreepath, current), symref: presence(symref), upstream: build_upstream_info(upstream) ) end |
.build_delete_result(requested_names, existing_branches, deleted_names, error_map) ⇒ Git::BranchDeleteResult
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Build the BranchDeleteResult from parsed data
230 231 232 233 234 235 236 237 238 239 |
# File 'lib/git/parsers/branch.rb', line 230 def build_delete_result(requested_names, existing_branches, deleted_names, error_map) deleted = deleted_names.filter_map { |name| existing_branches[name] } not_deleted = (requested_names - deleted_names).map do |name| = error_map[name] || "branch '#{name}' could not be deleted" Git::BranchDeleteFailure.new(name: name, error_message: ) end Git::BranchDeleteResult.new(deleted: deleted, not_deleted: not_deleted) end |
.build_upstream_info(upstream_ref) ⇒ Git::BranchInfo?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Build upstream BranchInfo from upstream refname
164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/git/parsers/branch.rb', line 164 def build_upstream_info(upstream_ref) return nil if upstream_ref.nil? || upstream_ref.empty? Git::BranchInfo.new( refname: normalize_refname(upstream_ref), target_oid: nil, # We don't have upstream's OID from this format current: false, worktree: false, symref: nil, upstream: nil # Upstream branches don't have their own upstream in this context ) end |
.in_other_worktree?(worktreepath, current) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if the branch is checked out in another worktree
worktree is true when the branch is checked out in ANOTHER worktree (worktreepath is non-empty AND it's not the current branch)
153 154 155 156 |
# File 'lib/git/parsers/branch.rb', line 153 def in_other_worktree?(worktreepath, current) has_worktree = !worktreepath.nil? && !worktreepath.empty? has_worktree && !current end |
.non_branch_entry?(refname) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if the refname represents a detached HEAD state or non-branch entry
Git outputs special entries for detached HEAD and non-branch states:
- "(HEAD detached at )" when in detached HEAD state
- "(not a branch)" for non-branch entries
124 125 126 |
# File 'lib/git/parsers/branch.rb', line 124 def non_branch_entry?(refname) refname.match?(/^\(HEAD detached/) || refname.match?(/^\(not a branch\)/) end |
.normalize_refname(refname) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Normalize a full refname to the expected format
Converts:
- refs/heads/main -> main
- refs/remotes/origin/main -> remotes/origin/main
138 139 140 |
# File 'lib/git/parsers/branch.rb', line 138 def normalize_refname(refname) refname.sub(%r{^refs/heads/}, '').sub(%r{^refs/}, '') end |
.parse_branch_line(line) ⇒ Git::BranchInfo?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Parse a single formatted branch line
86 87 88 89 90 91 92 |
# File 'lib/git/parsers/branch.rb', line 86 def parse_branch_line(line) fields = line.split(FIELD_DELIMITER, 6) return nil if non_branch_entry?(fields[0]) build_branch_info(fields) end |
.parse_deleted_branches(stdout) ⇒ Array<String>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Parse deleted branch names from stdout
197 198 199 |
# File 'lib/git/parsers/branch.rb', line 197 def parse_deleted_branches(stdout) stdout.scan(DELETED_BRANCH_REGEX).flatten end |
.parse_error_messages(stderr) ⇒ Hash<String, String>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Parse error messages from stderr into a map
211 212 213 214 215 216 |
# File 'lib/git/parsers/branch.rb', line 211 def (stderr) stderr.each_line.with_object({}) do |line, hash| match = line.match(ERROR_BRANCH_REGEX) hash[match[1]] = line.strip if match end end |
.parse_list(stdout) ⇒ Array<Git::BranchInfo>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Parse git branch --list output into BranchInfo objects
76 77 78 |
# File 'lib/git/parsers/branch.rb', line 76 def parse_list(stdout) stdout.split("\n").filter_map { |line| parse_branch_line(line) } end |
.presence(value) ⇒ String?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return value if non-empty, nil otherwise
183 184 185 |
# File 'lib/git/parsers/branch.rb', line 183 def presence(value) value.nil? || value.empty? ? nil : value end |