Module: Git::Parsers::Diff Private

Defined in:
lib/git/parsers/diff.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.

Note:

Combined/merge diffs (e.g., from git diff --cc or git show <merge>) are not supported. These have a different format with multiple +/- columns per parent.

Parser for git diff output in various formats

Handles parsing of --numstat, --shortstat, --dirstat, --raw, and --patch output. This parser is used by stash show, diff, show, and log commands.

Design Note: Namespace Organization

This parser creates and returns DiffResult and DiffFile*Info 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 git diff 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.

Defined Under Namespace

Modules: Numstat, Patch, Raw

Constant Summary collapse

STATUS_MAP =

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.

Status letter to symbol mapping for --raw output

{
  'A' => :added,
  'M' => :modified,
  'D' => :deleted,
  'R' => :renamed,
  'C' => :copied,
  'T' => :type_changed
}.freeze
NULL_SHA =

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.

Null SHA for non-existent files

'0' * 7
NULL_MODE =

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.

Null mode for non-existent files

'000000'
RENAME_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.

Rename format patterns from git numstat -M output: old_name.rb => new_name.rb {old_dir => new_dir}/file.rb dir/{old_name.rb => new_name.rb}

/\A(.+) => (.+)\z/
BRACE_RENAME_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.

/\A(.*)\{(.+) => (.+)\}(.*)\z/

Class Method Summary collapse

Class Method Details

.build_result(files:, shortstat:, dirstat:) ⇒ Git::DiffResult

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 DiffResult from parsed components

Parameters:

  • files (Array)

    array of file info objects

  • shortstat (Hash)

    parsed shortstat data

  • dirstat (Git::DirstatInfo, nil)

    parsed dirstat data

Returns:



71
72
73
74
75
76
77
78
79
# File 'lib/git/parsers/diff.rb', line 71

def build_result(files:, shortstat:, dirstat:)
  Git::DiffResult.new(
    files_changed: shortstat[:files_changed],
    total_insertions: shortstat[:insertions],
    total_deletions: shortstat[:deletions],
    files: files,
    dirstat: dirstat
  )
end

.empty_resultGit::DiffResult

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 an empty DiffResult

Returns:



85
86
87
88
89
90
# File 'lib/git/parsers/diff.rb', line 85

def empty_result
  Git::DiffResult.new(
    files_changed: 0, total_insertions: 0, total_deletions: 0,
    files: [], dirstat: nil
  )
end

.parse_dirstat(lines) ⇒ Git::DirstatInfo

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 dirstat lines into DirstatInfo

Examples:

parse_dirstat(["  50.0% lib/", "  50.0% spec/"])
# => #<Git::DirstatInfo entries: [...]>

Parameters:

  • lines (Array<String>)

    dirstat output lines

Returns:



120
121
122
123
124
125
126
127
# File 'lib/git/parsers/diff.rb', line 120

def parse_dirstat(lines)
  entries = lines.filter_map do |line|
    next unless (match = line.match(/^\s*([\d.]+)%\s+(.+)$/))

    Git::DirstatEntry.new(percentage: match[1].to_f, directory: match[2])
  end
  Git::DirstatInfo.new(entries: entries)
end

.parse_shortstat(line) ⇒ Hash

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 shortstat line into components

Examples:

parse_shortstat(" 3 files changed, 10 insertions(+), 5 deletions(-)")
# => { files_changed: 3, insertions: 10, deletions: 5 }

Parameters:

  • line (String, nil)

    the shortstat line

Returns:

  • (Hash)

    { files_changed:, insertions:, deletions: }



101
102
103
104
105
106
107
108
109
# File 'lib/git/parsers/diff.rb', line 101

def parse_shortstat(line)
  return { files_changed: 0, insertions: 0, deletions: 0 } if line.nil?

  {
    files_changed: line.match(/(\d+)\s+files?\s+changed/)&.[](1).to_i,
    insertions: line.match(/(\d+)\s+insertions?\(\+\)/)&.[](1).to_i,
    deletions: line.match(/(\d+)\s+deletions?\(-\)/)&.[](1).to_i
  }
end

.parse_stat_value(value) ⇒ Integer

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 stat value (handles '-' for binary files)

Parameters:

  • value (String)

    the stat value string

Returns:

  • (Integer)

    the numeric value (0 for binary files)



134
135
136
# File 'lib/git/parsers/diff.rb', line 134

def parse_stat_value(value)
  value == '-' ? 0 : value.to_i
end

.unescape_path(path) ⇒ 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.

Unescape quoted path from git output

Parameters:

  • path (String)

    potentially quoted path

Returns:

  • (String)

    unescaped path



143
144
145
146
147
# File 'lib/git/parsers/diff.rb', line 143

def unescape_path(path)
  return path unless path&.start_with?('"') && path.end_with?('"')

  Git::EscapedPath.new(path[1..-2]).unescape
end