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
94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/git/parsers/branch.rb', line 94 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
212 213 214 215 216 217 218 219 220 221 |
# File 'lib/git/parsers/branch.rb', line 212 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
153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/git/parsers/branch.rb', line 153 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)
143 144 145 146 |
# File 'lib/git/parsers/branch.rb', line 143 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
117 118 119 |
# File 'lib/git/parsers/branch.rb', line 117 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
130 131 132 |
# File 'lib/git/parsers/branch.rb', line 130 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
81 82 83 84 85 86 87 |
# File 'lib/git/parsers/branch.rb', line 81 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
184 185 186 |
# File 'lib/git/parsers/branch.rb', line 184 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
197 198 199 200 201 202 |
# File 'lib/git/parsers/branch.rb', line 197 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
72 73 74 |
# File 'lib/git/parsers/branch.rb', line 72 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
171 172 173 |
# File 'lib/git/parsers/branch.rb', line 171 def presence(value) value.nil? || value.empty? ? nil : value end |