Module: Git::Parsers::Worktree Private
- Defined in:
- lib/git/parsers/worktree.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.
Known limitation: git C-quotes a lock or prune reason that contains
unusual characters such as a newline or a non-ASCII byte (see the
--porcelain description in the git-worktree documentation). The reason
is returned as git prints it, quotes and escapes included; it is not
unquoted.
Parser for git worktree command output
Handles parsing of git worktree list --porcelain output into structured
data objects.
Design Note: Namespace Organization
This parser creates and returns WorktreeInfo 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 classes are public API - returned by commands and used throughout the codebase
- Info classes are domain entities - represent core git concepts (worktrees as data)
Keeping Info classes at Git:: improves discoverability and correctly
reflects their role as public types rather than parser internals.
Constant Summary collapse
- LINE_PATTERN =
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.
Pattern splitting a porcelain line into its key and optional value
The key is everything before the first space and the value is everything after it, so a path or reason that contains spaces is kept intact. The pattern matches every line; a line with no space has a nil value.
/\A(?<key>[^ ]*)(?: (?<value>.*))?\z/- DEFAULT_ATTRS =
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.
Attribute values for a worktree with no flags set
{ head: nil, branch: nil, bare: false, detached: false, locked: false, lock_reason: nil, prunable: false, prune_reason: nil }.freeze
Class Method Summary collapse
-
.line_attrs(line, stdout) ⇒ Hash{Symbol => Object}
private
Map one porcelain line to the WorktreeInfo attributes it sets.
-
.parse_list(stdout) ⇒ Array<Git::WorktreeInfo>
private
Parse git worktree list --porcelain output into WorktreeInfo objects.
-
.parse_record(lines, stdout) ⇒ Git::WorktreeInfo
private
Parse one record into a WorktreeInfo.
-
.record_attrs(lines, stdout) ⇒ Hash{Symbol => Object}
private
Collect the attributes set by the lines that follow the
worktreeline. -
.records(stdout) ⇒ Array<Array<String>>
private
Split the output into records, each an array of chomped non-blank lines.
-
.split_line(line) ⇒ Array(String, String), Array(String, nil)
private
Split a porcelain line into its key and optional value.
-
.unexpected_line_error(stdout, line, reason) ⇒ String
private
Generate the error message for a line the parser cannot handle.
Class Method Details
.line_attrs(line, stdout) ⇒ Hash{Symbol => Object}
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.
Map one porcelain line to the WorktreeInfo attributes it sets
136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/git/parsers/worktree.rb', line 136 def line_attrs(line, stdout) key, value = split_line(line) case key when 'HEAD' then { head: value } when 'branch' then { branch: value } when 'bare' then { bare: true } when 'detached' then { detached: true } when 'locked' then { locked: true, lock_reason: value } when 'prunable' then { prunable: true, prune_reason: value } else raise Git::UnexpectedResultError, unexpected_line_error(stdout, line, 'unrecognized key') end end |
.parse_list(stdout) ⇒ Array<Git::WorktreeInfo>
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 worktree list --porcelain output into WorktreeInfo objects
Records are separated by a blank line. Each record starts with a
worktree <path> line followed by any of HEAD <sha>, branch <ref>,
bare, detached, locked [<reason>], and prunable <reason>.
74 75 76 |
# File 'lib/git/parsers/worktree.rb', line 74 def parse_list(stdout) records(stdout).map { |lines| parse_record(lines, stdout) } end |
.parse_record(lines, stdout) ⇒ Git::WorktreeInfo
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 one record into a WorktreeInfo
102 103 104 105 106 107 108 109 110 |
# File 'lib/git/parsers/worktree.rb', line 102 def parse_record(lines, stdout) key, path = split_line(lines.first) unless key == 'worktree' && path raise Git::UnexpectedResultError, unexpected_line_error(stdout, lines.first, 'expected a record to start with "worktree <path>"') end Git::WorktreeInfo.new(path: path, **DEFAULT_ATTRS, **record_attrs(lines.drop(1), stdout)) end |
.record_attrs(lines, stdout) ⇒ Hash{Symbol => Object}
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.
Collect the attributes set by the lines that follow the worktree line
122 123 124 |
# File 'lib/git/parsers/worktree.rb', line 122 def record_attrs(lines, stdout) lines.each_with_object({}) { |line, attrs| attrs.merge!(line_attrs(line, stdout)) } end |
.records(stdout) ⇒ Array<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.
Split the output into records, each an array of chomped non-blank lines
Blank lines separate records. chunk drops every run of lines whose
block value is :_separator, so only the non-blank runs are returned.
87 88 89 |
# File 'lib/git/parsers/worktree.rb', line 87 def records(stdout) stdout.each_line(chomp: true).chunk { |line| line.empty? ? :_separator : true }.map { |_, lines| lines } end |
.split_line(line) ⇒ Array(String, String), Array(String, nil)
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.
Split a porcelain line into its key and optional value
157 158 159 160 |
# File 'lib/git/parsers/worktree.rb', line 157 def split_line(line) match = LINE_PATTERN.match(line) [match[:key], match[:value]] end |
.unexpected_line_error(stdout, line, reason) ⇒ 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.
Generate the error message for a line the parser cannot handle
172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/git/parsers/worktree.rb', line 172 def unexpected_line_error(stdout, line, reason) <<~ERROR Unexpected line in output from `git worktree list --porcelain`: #{reason} Line: "#{line}" Full output: #{stdout.gsub("\n", "\n ")} ERROR end |