Class: Gitlab::Git::Diff

Inherits:
Object
  • Object
show all
Includes:
EncodingHelper
Defined in:
lib/gitlab_git/diff.rb

Defined Under Namespace

Classes: TimeoutError

Constant Summary collapse

DIFF_SIZE_LIMIT =

The maximum size of a diff to display.

102400
DIFF_COLLAPSE_LIMIT =

The maximum size before a diff is collapsed.

10240

Constants included from EncodingHelper

EncodingHelper::ENCODING_CONFIDENCE_THRESHOLD

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from EncodingHelper

#encode!, #encode_utf8

Constructor Details

#initialize(raw_diff, collapse: false) ⇒ Diff

Returns a new instance of Diff.



176
177
178
179
180
181
182
183
184
185
186
187
# 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

Instance Attribute Details

#a_modeObject

Diff properties



9
10
11
# File 'lib/gitlab_git/diff.rb', line 9

def a_mode
  @a_mode
end

#b_modeObject

Diff properties



9
10
11
# File 'lib/gitlab_git/diff.rb', line 9

def b_mode
  @b_mode
end

#deleted_fileObject

Stats properties



12
13
14
# File 'lib/gitlab_git/diff.rb', line 12

def deleted_file
  @deleted_file
end

#diffObject

Diff properties



9
10
11
# File 'lib/gitlab_git/diff.rb', line 9

def diff
  @diff
end

#new_fileObject

Stats properties



12
13
14
# File 'lib/gitlab_git/diff.rb', line 12

def new_file
  @new_file
end

#new_pathObject

Diff properties



9
10
11
# File 'lib/gitlab_git/diff.rb', line 9

def new_path
  @new_path
end

#old_pathObject

Diff properties



9
10
11
# File 'lib/gitlab_git/diff.rb', line 9

def old_path
  @old_path
end

#renamed_fileObject

Stats properties



12
13
14
# File 'lib/gitlab_git/diff.rb', line 12

def renamed_file
  @renamed_file
end

#too_largeObject

Returns the value of attribute too_large.



14
15
16
# File 'lib/gitlab_git/diff.rb', line 14

def too_large
  @too_large
end

Class Method Details

.between(repo, head, base, options = {}, *paths) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 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 = {}) ⇒ Object

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.


140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# 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

Instance Method Details

#collapsed?Boolean

Returns:

  • (Boolean)


231
232
233
234
# File 'lib/gitlab_git/diff.rb', line 231

def collapsed?
  return @collapsed if defined?(@collapsed)
  false
end

#collapsible?Boolean

Returns:

  • (Boolean)


221
222
223
# File 'lib/gitlab_git/diff.rb', line 221

def collapsible?
  @diff.bytesize >= DIFF_COLLAPSE_LIMIT
end

#line_countObject



209
210
211
# File 'lib/gitlab_git/diff.rb', line 209

def line_count
  @line_count ||= Util.count_lines(@diff)
end

#prune_collapsed_diff!Object



236
237
238
239
240
# File 'lib/gitlab_git/diff.rb', line 236

def prune_collapsed_diff!
  @diff = ''
  @line_count = 0
  @collapsed = true
end

#prune_large_diff!Object



225
226
227
228
229
# File 'lib/gitlab_git/diff.rb', line 225

def prune_large_diff!
  @diff = ''
  @line_count = 0
  @too_large = true
end

#serialize_keysObject



189
190
191
# 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?Boolean

Returns:

  • (Boolean)


205
206
207
# File 'lib/gitlab_git/diff.rb', line 205

def submodule?
  a_mode == '160000' || b_mode == '160000'
end

#to_hashObject



193
194
195
196
197
198
199
200
201
202
203
# 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?Boolean

Returns:

  • (Boolean)


213
214
215
216
217
218
219
# 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