Module: Commiti::GitReader
- Defined in:
- lib/services/git/git_reader.rb
Constant Summary collapse
- MAX_DIFF_BYTES =
50_000- TRUNCATION_NOTICE =
"\n# ... diff clipped by Commiti to preserve context under size limit\n"- LOCKFILE_PATTERNS =
[ /Gemfile\.lock/, /package-lock\.json/, /yarn\.lock/, /pnpm-lock\.yaml/, /composer\.lock/, /mix\.lock/, /Cargo\.lock/, /Pipfile\.lock/ ].freeze
Class Method Summary collapse
- .append_notice(clipped_diff, max_bytes:) ⇒ Object
- .branch_diff(base_branch: 'main') ⇒ Object
- .clip_chunks(chunks, max_bytes:) ⇒ Object
- .clip_diff_context(diff, max_bytes:) ⇒ Object
- .clip_single_chunk(lines, max_bytes:) ⇒ Object
- .recent_commits(count: 10) ⇒ Object
-
.split_by_file(diff) ⇒ Object
Returns [{ path: String, lines: Array<String> }].
- .staged_diff ⇒ Object
Class Method Details
.append_notice(clipped_diff, max_bytes:) ⇒ Object
187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/services/git/git_reader.rb', line 187 def self.append_notice(clipped_diff, max_bytes:) safe_clipped = clipped_diff.to_s return safe_clipped if safe_clipped.bytesize >= max_bytes && max_bytes <= TRUNCATION_NOTICE.bytesize return safe_clipped + TRUNCATION_NOTICE if safe_clipped.bytesize + TRUNCATION_NOTICE.bytesize <= max_bytes available = max_bytes - TRUNCATION_NOTICE.bytesize return safe_clipped.byteslice(0, max_bytes) if available <= 0 safe_clipped.byteslice(0, available) + TRUNCATION_NOTICE end |
.branch_diff(base_branch: 'main') ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/services/git/git_reader.rb', line 21 def self.branch_diff(base_branch: 'main') raise 'Invalid branch name.' unless base_branch.match?(%r{\A[a-zA-Z0-9_\-./]+\z}) # Strip context lines using -U0 and filter out binary/lockfile noise diff, status = Open3.capture2('git', 'diff', '-U0', "#{base_branch}...HEAD") raise "Failed to read branch diff against '#{base_branch}'." unless status.success? raise "No diff found against '#{base_branch}'." if diff.strip.empty? filtered_diff = filter_diff_noise(diff) clip_diff_context(filtered_diff, max_bytes: MAX_DIFF_BYTES) end |
.clip_chunks(chunks, max_bytes:) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/services/git/git_reader.rb', line 98 def self.clip_chunks(chunks, max_bytes:) output = +'' chunks.each do |chunk| remaining = max_bytes - output.bytesize break if remaining <= 0 chunk_text = chunk[:lines].join if chunk_text.bytesize <= remaining output << chunk_text next end output << clip_single_chunk(chunk[:lines], max_bytes: remaining) break end if output.empty? first_chunk_text = chunks.first[:lines].join return first_chunk_text.byteslice(0, max_bytes) end output end |
.clip_diff_context(diff, max_bytes:) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/services/git/git_reader.rb', line 38 def self.clip_diff_context(diff, max_bytes:) return diff if diff.bytesize <= max_bytes chunks = split_by_file(diff) clipped = if chunks.empty? diff.byteslice(0, max_bytes) else clip_chunks(chunks, max_bytes: max_bytes) end append_notice(clipped, max_bytes: max_bytes) end |
.clip_single_chunk(lines, max_bytes:) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/services/git/git_reader.rb', line 123 def self.clip_single_chunk(lines, max_bytes:) output = +'' return output if max_bytes <= 0 header_lines, hunks = partition_chunk_lines(lines) append_lines_with_limit(output, header_lines, max_bytes: max_bytes) return output if hunks.empty? append_hunks_with_limit(output, hunks, max_bytes: max_bytes) output end |
.recent_commits(count: 10) ⇒ Object
33 34 35 36 |
# File 'lib/services/git/git_reader.rb', line 33 def self.recent_commits(count: 10) out, = Open3.capture2('git', 'log', '--oneline', "-#{count}") out end |
.split_by_file(diff) ⇒ Object
Returns [{ path: String, lines: Array<String> }]
94 95 96 |
# File 'lib/services/git/git_reader.rb', line 94 def self.split_by_file(diff) Commiti::DiffParser.split_by_file_lines(diff) end |
.staged_diff ⇒ Object
11 12 13 14 15 16 17 18 19 |
# File 'lib/services/git/git_reader.rb', line 11 def self.staged_diff # Strip context lines using -U0 and filter out binary/lockfile noise diff, status = Open3.capture2('git', 'diff', '--cached', '-U0') raise 'Failed to read staged diff.' unless status.success? raise 'No staged changes. Run `git add` first.' if diff.strip.empty? filtered_diff = filter_diff_noise(diff) clip_diff_context(filtered_diff, max_bytes: MAX_DIFF_BYTES) end |