class Gitlab::Git::Diff
Constants
- DIFF_COLLAPSE_LIMIT
The maximum size before a diff is collapsed.
- DIFF_SIZE_LIMIT
The maximum size of a diff to display.
Attributes
a_mode[RW]
Diff
properties
b_mode[RW]
Diff
properties
deleted_file[RW]
Stats properties
diff[RW]
Diff
properties
new_file[RW]
Stats properties
new_path[RW]
Diff
properties
old_path[RW]
Diff
properties
renamed_file[RW]
Stats properties
too_large[RW]
Public Class Methods
between(repo, head, base, options = {}, *paths)
click to toggle source
# File lib/gitlab_git/diff.rb, line 23 def between(repo, head, base, options = {}, *paths) straight = options.delete(:straight) || false common_commit = if straight base else # Only show what is new in the source branch # compared to the target branch, not the other way # around. The linex below with merge_base is # equivalent to diff with three dots (git diff # branch1...branch2) From the git documentation: # "git diff A...B" is equivalent to "git diff # $(git-merge-base A B) B" repo.merge_base_commit(head, base) end options ||= {} actual_options = filter_diff_options(options) repo.diff(common_commit, head, actual_options, *paths) end
filter_diff_options(options, default_options = {})
click to toggle source
Return a copy of the options
hash containing only keys that can be passed to Rugged. Allowed options are:
:max_size :: An integer specifying the maximum byte size of a file before a it will be treated as binary. The default value is 512MB. :context_lines :: The number of unchanged lines that define the boundary of a hunk (and to display before and after the actual changes). The default is 3. :interhunk_lines :: The maximum number of unchanged lines between hunk boundaries before the hunks will be merged into a one. The default is 0. :old_prefix :: The virtual "directory" to prefix to old filenames in hunk headers. The default is "a". :new_prefix :: The virtual "directory" to prefix to new filenames in hunk headers. The default is "b". :reverse :: If true, the sides of the diff will be reversed. :force_text :: If true, all files will be treated as text, disabling binary attributes & detection. :ignore_whitespace :: If true, all whitespace will be ignored. :ignore_whitespace_change :: If true, changes in amount of whitespace will be ignored. :ignore_whitespace_eol :: If true, whitespace at end of line will be ignored. :ignore_submodules :: if true, submodules will be excluded from the diff completely. :patience :: If true, the "patience diff" algorithm will be used (currenlty unimplemented). :include_ignored :: If true, ignored files will be included in the diff. :include_untracked :: If true, untracked files will be included in the diff. :include_unmodified :: If true, unmodified files will be included in the diff. :recurse_untracked_dirs :: Even if +:include_untracked+ is true, untracked directories will only be marked with a single entry in the diff. If this flag is set to true, all files under ignored directories will be included in the diff, too. :disable_pathspec_match :: If true, the given +*paths+ will be applied as exact matches, instead of as fnmatch patterns. :deltas_are_icase :: If true, filename comparisons will be made with case-insensitivity. :include_untracked_content :: if true, untracked content will be contained in the the diff patch text. :skip_binary_check :: If true, diff deltas will be generated without spending time on binary detection. This is useful to improve performance in cases where the actual file content difference is not needed. :include_typechange :: If true, type changes for files will not be interpreted as deletion of the "old file" and addition of the "new file", but will generate typechange records. :include_typechange_trees :: Even if +:include_typechange+ is true, blob -> tree changes will still usually be handled as a deletion of the blob. If this flag is set to true, blob -> tree changes will be marked as typechanges. :ignore_filemode :: If true, file mode changes will be ignored. :recurse_ignored_dirs :: Even if +:include_ignored+ is true, ignored directories will only be marked with a single entry in the diff. If this flag is set to true, all files under ignored directories will be included in the diff, too.
# File lib/gitlab_git/diff.rb, line 140 def filter_diff_options(options, default_options = {}) allowed_options = [:max_size, :context_lines, :interhunk_lines, :old_prefix, :new_prefix, :reverse, :force_text, :ignore_whitespace, :ignore_whitespace_change, :ignore_whitespace_eol, :ignore_submodules, :patience, :include_ignored, :include_untracked, :include_unmodified, :recurse_untracked_dirs, :disable_pathspec_match, :deltas_are_icase, :include_untracked_content, :skip_binary_check, :include_typechange, :include_typechange_trees, :ignore_filemode, :recurse_ignored_dirs, :paths, :max_files, :max_lines, :all_diffs, :no_collapse] if default_options actual_defaults = default_options.dup actual_defaults.keep_if do |key| allowed_options.include?(key) end else actual_defaults = {} end if options filtered_opts = options.dup filtered_opts.keep_if do |key| allowed_options.include?(key) end filtered_opts = actual_defaults.merge(filtered_opts) else filtered_opts = actual_defaults end filtered_opts end
new(raw_diff, collapse: false)
click to toggle source
# File lib/gitlab_git/diff.rb, line 176 def initialize(raw_diff, collapse: false) case raw_diff when Hash init_from_hash(raw_diff, collapse: collapse) when Rugged::Patch, Rugged::Diff::Delta init_from_rugged(raw_diff, collapse: collapse) when nil raise "Nil as raw diff passed" else raise "Invalid raw diff type: #{raw_diff.class}" end end
Public Instance Methods
collapsed?()
click to toggle source
# File lib/gitlab_git/diff.rb, line 231 def collapsed? return @collapsed if defined?(@collapsed) false end
collapsible?()
click to toggle source
# File lib/gitlab_git/diff.rb, line 221 def collapsible? @diff.bytesize >= DIFF_COLLAPSE_LIMIT end
line_count()
click to toggle source
# File lib/gitlab_git/diff.rb, line 209 def line_count @line_count ||= Util.count_lines(@diff) end
prune_collapsed_diff!()
click to toggle source
# File lib/gitlab_git/diff.rb, line 236 def prune_collapsed_diff! @diff = '' @line_count = 0 @collapsed = true end
prune_large_diff!()
click to toggle source
# File lib/gitlab_git/diff.rb, line 225 def prune_large_diff! @diff = '' @line_count = 0 @too_large = true end
serialize_keys()
click to toggle source
# File lib/gitlab_git/diff.rb, line 189 def serialize_keys @serialize_keys ||= %i(diff new_path old_path a_mode b_mode new_file renamed_file deleted_file too_large) end
submodule?()
click to toggle source
# File lib/gitlab_git/diff.rb, line 205 def submodule? a_mode == '160000' || b_mode == '160000' end
to_hash()
click to toggle source
# File lib/gitlab_git/diff.rb, line 193 def to_hash hash = {} keys = serialize_keys keys.each do |key| hash[key] = send(key) end hash end
too_large?()
click to toggle source
# File lib/gitlab_git/diff.rb, line 213 def too_large? if @too_large.nil? @too_large = @diff.bytesize >= DIFF_SIZE_LIMIT else @too_large end end
Private Instance Methods
init_from_hash(hash, collapse: false)
click to toggle source
# File lib/gitlab_git/diff.rb, line 269 def init_from_hash(hash, collapse: false) raw_diff = hash.symbolize_keys serialize_keys.each do |key| send(:"#{key}=", raw_diff[key.to_sym]) end prune_large_diff! if too_large? prune_collapsed_diff! if collapse && collapsible? end
init_from_rugged(rugged, collapse: false)
click to toggle source
# File lib/gitlab_git/diff.rb, line 244 def init_from_rugged(rugged, collapse: false) if rugged.is_a?(Rugged::Patch) init_from_rugged_patch(rugged, collapse: collapse) d = rugged.delta else d = rugged end @new_path = encode!(d.new_file[:path]) @old_path = encode!(d.old_file[:path]) @a_mode = d.old_file[:mode].to_s(8) @b_mode = d.new_file[:mode].to_s(8) @new_file = d.added? @renamed_file = d.renamed? @deleted_file = d.deleted? end
init_from_rugged_patch(patch, collapse: false)
click to toggle source
# File lib/gitlab_git/diff.rb, line 261 def init_from_rugged_patch(patch, collapse: false) # Don't bother initializing diffs that are too large. If a diff is # binary we're not going to display anything so we skip the size check. return if !patch.delta.binary? && prune_large_patch(patch, collapse) @diff = encode!(strip_diff_headers(patch.to_s)) end
prune_large_patch(patch, collapse)
click to toggle source
If the patch surpasses any of the diff limits it calls the appropiate prune method and returns true. Otherwise returns false.
# File lib/gitlab_git/diff.rb, line 282 def prune_large_patch(patch, collapse) size = 0 patch.each_hunk do |hunk| hunk.each_line do |line| size += line.content.bytesize if size >= DIFF_SIZE_LIMIT prune_large_diff! return true end end end if collapse && size >= DIFF_COLLAPSE_LIMIT prune_collapsed_diff! return true end false end
strip_diff_headers(diff_text)
click to toggle source
Strip out the information at the beginning of the patch's text to match Grit's output
# File lib/gitlab_git/diff.rb, line 306 def strip_diff_headers(diff_text) # Delete everything up to the first line that starts with '---' or # 'Binary' diff_text.sub!(/\A.*?^(---|Binary)/m, '\1') if diff_text.start_with?('---', 'Binary') diff_text else # If the diff_text did not contain a line starting with '---' or # 'Binary', return the empty string. No idea why; we are just # preserving behavior from before the refactor. '' end end