class Git::Diff
Diff between two commits or between a commit and the working tree
@example Diff between two commits
diff = repo.diff('HEAD~1', 'HEAD') diff.size # => 3 diff.insertions # => 20 diff.deletions # => 5
@example Limit diff to a specific path
diff = repo.diff('HEAD~1', 'HEAD').path('lib/')
@api public
Attributes
The starting commit ref
@return [String, nil] the starting commit ref, or ‘nil` if not set
The ending commit ref
@return [String, nil] the ending commit ref, or ‘nil` if not set
Public Class Methods
Source
# File lib/git/diff.rb, line 38 def initialize(base, from = nil, to = nil) @base = base @from = from&.to_s @to = to&.to_s @path = nil @full_diff_files = nil end
Creates a new Diff
@example
diff = Git::Diff.new(base, 'HEAD~1', 'HEAD')
@param base [Git::Repository] the git repository
@param from [String, nil] the starting commit ref, or ‘nil` to compare
from the index
@param to [String, nil] the ending commit ref, or ‘nil` to compare to
the working tree
@return [void]
Public Instance Methods
Source
# File lib/git/diff.rb, line 118 def [](key) process_full @full_diff_files.assoc(key)[1] end
Returns the diff file info for the given path
@example
diff['lib/git.rb'] # => #<Git::Diff::DiffFile ...>
@param key [String] the file path to look up
@return [Git::Diff::DiffFile] the diff file object for the given path
Source
# File lib/git/diff.rb, line 193 def deletions stats_provider.deletions end
Returns the total number of deleted lines in the diff
@example
diff.deletions # => 10
@return [Integer] the number of deleted lines
Source
# File lib/git/diff.rb, line 144 def each(&) process_full @full_diff_files.map { |file| file[1] }.each(&) end
Iterates over each changed file in the diff
@overload each
@example Get an enumerator diff.each.map(&:path) # => ["lib/git.rb", "README.md"] @return [Enumerator<Git::Diff::DiffFile>] an enumerator over the changed files
@overload each(&block)
@example Iterate with a block
diff.each { |file| puts file.path }
@yield [file] each changed file in the diff
@yieldparam file [Git::Diff::DiffFile] a changed file
@yieldreturn [void]
@return [Array<Git::Diff::DiffFile>] the array of changed files
Source
# File lib/git/diff.rb, line 204 def insertions stats_provider.insertions end
Returns the total number of inserted lines in the diff
@example
diff.insertions # => 32
@return [Integer] the number of inserted lines
Source
# File lib/git/diff.rb, line 182 def lines stats_provider.lines end
Returns the total number of changed lines in the diff
@example
diff.lines # => 42
@return [Integer] the total number of inserted and deleted lines
Source
# File lib/git/diff.rb, line 171 def name_status path_status_provider.to_h end
Returns the path-to-status hash for all changed files in the diff
@example
diff.name_status # => { "lib/git.rb" => "M", "README.md" => "A" }
@return [Hash<String, String>] map of file path to git status letter
Source
# File lib/git/diff.rb, line 104 def patch @base.diff_full(@from, @to, path_limiter: @path) end
Returns the full diff output as a string
@example
diff.patch # => "diff --git a/file.rb b/file.rb\n..."
@return [String] the raw output of ‘git diff`
Source
# File lib/git/diff.rb, line 81 def path(*paths) validate_paths_not_arrays(paths) cleaned_paths = paths.compact @path = if cleaned_paths.empty? nil elsif cleaned_paths.length == 1 cleaned_paths.first else cleaned_paths end self end
Limits the diff to the specified path(s)
When called with no arguments (or only nil arguments), removes any existing path filter, showing all files in the diff. Internally stores a single path as a String and multiple paths as an Array for efficiency.
@example Limit diff to a single path
git.diff('HEAD~3', 'HEAD').path('lib/')
@example Limit diff to multiple paths
git.diff('HEAD~3', 'HEAD').path('src/', 'docs/', 'README.md')
@example Remove path filtering (show all files)
diff.path # or diff.path(nil)
@param paths [String, Pathname] one or more paths to filter the diff;
pass no arguments to remove filtering
@return [self] returns self for method chaining
@raise [ArgumentError] if any path is an Array (use splatted arguments instead)
Source
# File lib/git/diff.rb, line 156 def size stats_provider.total[:files] end
Returns the number of changed files in the diff
@example
diff.size # => 3
@return [Integer] the number of changed files
Source
# File lib/git/diff.rb, line 219 def stats { files: stats_provider.files, total: stats_provider.total } end
Returns a statistics hash for the diff
@example
diff.stats # => { # files: { "lib/git.rb" => { insertions: 5, deletions: 2 } }, # total: { insertions: 5, deletions: 2, lines: 7 } # }
@return [Hash] statistics including per-file and total insert/delete counts
Private Instance Methods
Source
# File lib/git/diff.rb, line 366 def path_status_provider @path_status_provider ||= Git::DiffPathStatus.new(@base, @from, @to, @path) end
Returns a memoized DiffPathStatus provider for this diff
@return [Git::DiffPathStatus] the path status provider
Source
# File lib/git/diff.rb, line 356 def process_full return if @full_diff_files @full_diff_files = process_full_diff end
Triggers full diff processing if not yet done
@return [void]
Source
# File lib/git/diff.rb, line 383 def process_full_diff FullDiffParser.new(@base, patch).parse end
Parses the full diff output into DiffFile objects
@return [Array<Array(String, Git::Diff::DiffFile)>] list of
`[filename, DiffFile]` pairs
Source
# File lib/git/diff.rb, line 374 def stats_provider @stats_provider ||= Git::DiffStats.new(@base, @from, @to, @path) end
Returns a memoized DiffStats provider for this diff
@return [Git::DiffStats] the stats provider
Source
# File lib/git/diff.rb, line 344 def validate_paths_not_arrays(paths) return unless paths.any?(Array) raise ArgumentError, 'path expects individual arguments, not arrays. ' \ "Use path('lib/', 'docs/') not path(['lib/', 'docs/'])" end
Validates that no path argument is an Array
@param paths [Array] the raw paths array passed to {#path}
@return [void]
@raise [ArgumentError] if any element of paths is an Array