Class: Danger::GitUtils

Inherits:
Plugin
  • Object
show all
Defined in:
lib/dangermattic/plugins/common/git_utils.rb

Overview

Represents a utility plugin for working with Git: to check added and modified lines in Git diffs, to determine the type of change (added, removed, or other) in a diff line, and to retrieve lists of added, modified, and deleted files.

    git_utils.change_type(diff_line: "- line removed")
    #=> :removed

    git_utils.change_type(diff_line: " context line")
    #=> :other

Examples:

Check if there is a "TODO" in Ruby files:

git_utils.check_added_diff_lines(
  file_selector: ->(path) { path.end_with?('.rb') },
  line_matcher: ->(line) { line.include?('TODO') },
  message: 'Found a TODO in a Ruby file'
)

Get added lines from a diff patch:

added_lines = git_utils.added_lines(diff_patch: diff_patch)

Get removed lines from a diff patch:

removed_lines = git_utils.removed_lines(diff_patch: diff_patch)

Determining the change type of a diff line:

git_utils.change_type(diff_line: "+ new line added")
#=> :added

Select removed lines from a diff patch:

removed_lines = git_utils.select_lines(diff_patch: diff_patch, change_type: :removed)

See Also:

  • Automattic/dangermattic

Defined Under Namespace

Classes: MatchedData

Instance Method Summary collapse

Instance Method Details

#added_and_modified_filesArray<String>

Get the list of added and modified files in the current Pull Request.

Returns:

  • (Array<String>)

    An array containing the file paths of added and modified files.



127
128
129
# File 'lib/dangermattic/plugins/common/git_utils.rb', line 127

def added_and_modified_files
  danger.git.added_files + danger.git.modified_files
end

#added_lines(diff_patch:) ⇒ String

Returns the lines that were added in the given diff patch.

Parameters:

  • diff_patch (String)

    The diff patch containing the changes.

Returns:

  • (String)

    A concatenated string of added lines.



144
145
146
# File 'lib/dangermattic/plugins/common/git_utils.rb', line 144

def added_lines(diff_patch:)
  select_lines(diff_patch: diff_patch, change_type: :added)
end

#all_changed_filesArray<String>

Get the list of all files added, modified and deleted in the current Pull Request.

Returns:

  • (Array<String>)

    An array containing the file paths of all changed files.



135
136
137
# File 'lib/dangermattic/plugins/common/git_utils.rb', line 135

def all_changed_files
  danger.git.added_files + danger.git.modified_files + danger.git.deleted_files
end

#change_type(diff_line:) ⇒ Symbol

Determine the type of change for a given line in a git diff.

Parameters:

  • diff_line (String)

    The line from a git diff that needs to be classified.

Returns:

  • (Symbol)

    The type of change for the given diff line. Possible values are:

    • :added for added lines
    • :removed for removed lines
    • :other for any other type of lines


114
115
116
117
118
119
120
121
122
# File 'lib/dangermattic/plugins/common/git_utils.rb', line 114

def change_type(diff_line:)
  if diff_line.start_with?('+') && !diff_line.start_with?('+++ ')
    :added
  elsif diff_line.start_with?('-') && !diff_line.start_with?('--- ')
    :removed
  else
    :other
  end
end

#check_added_diff_lines(file_selector:, line_matcher:, message:, report_type: :warning) ⇒ void

This method returns an undefined value.

Check added lines in a PR for a specific pattern and issue a warning or failure message when found.

Examples:

Checking for added lines containing 'FIXME' and failing the build:

check_added_diff_lines(file_selector: ->(path) { File.extname(path) == ('.swift') }, line_matcher: ->(line) { line.include?("FIXME") }, message: "A FIXME was added, failing build.", report_type: :error)

Parameters:

  • file_selector (Proc)

    A block to select the files in the PR. The block should take a file path as input and return true if the file should be checked.

  • line_matcher (Proc)

    A block that will select the diff lines to report. The block should take a line of text as input and return true if the line matches the pattern.

  • message (String)

    The warning or failure message to display when the pattern is found in a line.

  • report_type (Symbol) (defaults to: :warning)

    (optional) Type of report (:error, :warning, :message) whenever a line matches the criteria. Default is :warning.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/dangermattic/plugins/common/git_utils.rb', line 54

def check_added_diff_lines(file_selector:, line_matcher:, message:, report_type: :warning)
  modified_files = added_and_modified_files.select(&file_selector)

  matches = matching_lines_in_diff_files(
    files: modified_files,
    line_matcher: line_matcher,
    change_type: :added
  )

  matches.each do |match|
    match.lines.each do |line|
      final_message = <<~MESSAGE
        #{message}
        File `#{match.file}`:
        ```diff
        #{line.chomp}
        ```
      MESSAGE

      reporter.report(message: final_message, type: report_type)
    end
  end
end

#matching_lines_in_diff_files(files:, line_matcher:, change_type: nil) ⇒ Array<MatchedData>

Matches diff lines in the provided files based on the line matcher and change type

Parameters:

  • files (Array<String>)

    List of file names to check

  • line_matcher (Proc)

    A callable that takes a line and returns true if it matches the desired pattern

  • change_type (Symbol, Array<Symbol>, nil) (defaults to: nil)

    Change type(s) to filter lines (e.g., :added, :removed, :context, [:added, :removed], …), or nil for no filter

Returns:

  • (Array<MatchedData>)

    Array of MatchedData objects representing matched lines in files



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/dangermattic/plugins/common/git_utils.rb', line 87

def matching_lines_in_diff_files(files:, line_matcher:, change_type: nil)
  change_types = Array(change_type).map(&:to_sym)
  matched_data = []

  files.each do |file|
    matched_lines = []

    diff = danger.git.diff_for_file(file)

    diff.patch.each_line do |line|
      matched_lines << line if line_matcher.call(line) && (change_type.nil? || change_types.include?(change_type(diff_line: line)))
    end

    matched_data << MatchedData.new(file, matched_lines) unless matched_lines.empty?
  end

  matched_data
end

#removed_lines(diff_patch:) ⇒ String

Returns the lines that were removed in the given diff patch.

Parameters:

  • diff_patch (String)

    The diff patch containing the changes.

Returns:

  • (String)

    A concatenated string of removed lines.



153
154
155
# File 'lib/dangermattic/plugins/common/git_utils.rb', line 153

def removed_lines(diff_patch:)
  select_lines(diff_patch: diff_patch, change_type: :removed)
end

#select_lines(diff_patch:, change_type:) ⇒ String

Selects lines of a specific change type (added or removed) from the given diff patch.

Parameters:

  • diff_patch (String)

    The diff patch containing the changes.

  • change_type (Symbol)

    The desired change type (:added or :removed).

Returns:

  • (String)

    A concatenated string of selected lines of the specified change type.



163
164
165
166
# File 'lib/dangermattic/plugins/common/git_utils.rb', line 163

def select_lines(diff_patch:, change_type:)
  selected_lines = diff_patch.lines.select { |line| change_type(diff_line: line) == change_type }
  selected_lines.map { |line| line[1..] }.join
end