Module: Ace::Git::Atoms::PrIdentifierParser
- Defined in:
- lib/ace/git/atoms/pr_identifier_parser.rb
Overview
Parse PR identifiers into structured format
Supports three formats:
-
Simple number: “123”
-
Qualified reference: “owner/repo#456”
-
GitHub URL: “github.com/owner/repo/pull/789”
Consolidated from ace-bundle PrIdentifierParser
Defined Under Namespace
Classes: ParseResult
Constant Summary collapse
- MAX_IDENTIFIER_LENGTH =
Parse a PR identifier string
Returns nil for nil/empty input (no PR specified), raises ArgumentError for invalid formats. This design allows callers to distinguish between “no PR” (nil input -> nil result) and “invalid PR” (bad format -> exception).
Maximum length for PR identifier to prevent ReDoS attacks GitHub URLs are typically under 200 chars, this provides generous margin
256
Class Method Summary collapse
Class Method Details
.parse(input) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/ace/git/atoms/pr_identifier_parser.rb', line 49 def self.parse(input) return nil if input.nil? input_str = input.to_s.strip return nil if input_str.empty? # Validate length to prevent ReDoS attacks on regex patterns if input_str.length > MAX_IDENTIFIER_LENGTH raise ArgumentError, "PR identifier too long (max #{MAX_IDENTIFIER_LENGTH} characters)" end case input_str when /^(\d+)$/ # Simple PR number: "123" number = ::Regexp.last_match(1) # Reject zero: GitHub PR numbers are positive integers starting from 1 raise ArgumentError, "Invalid PR identifier format: #{input_str}" if number.to_i.zero? # Normalize to canonical form (strip leading zeros) for consistent gh_format canonical_number = number.to_i.to_s ParseResult.new(number: canonical_number, repo: nil, gh_format: canonical_number) when /^(?<repo>[a-zA-Z0-9_\-.]+\/[a-zA-Z0-9_\-.]+)#(?<number>\d+)$/ # Qualified reference: "owner/repo#456" # GitHub owner/repo names: alphanumeric, hyphens, underscores, dots only match = ::Regexp.last_match ParseResult.new(number: match[:number], repo: match[:repo], gh_format: "#{match[:repo]}##{match[:number]}") when %r{github\.com/(?<repo>[^/]+/[^/]+)/pull/(?<number>\d+)} # GitHub URL: "https://github.com/owner/repo/pull/789" match = ::Regexp.last_match ParseResult.new(number: match[:number], repo: match[:repo], gh_format: "#{match[:repo]}##{match[:number]}") else raise ArgumentError, "Invalid PR identifier format: #{input_str}" end end |