1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
# frozen_string_literal: true
module RuboCop # :nodoc:
module Cop # :nodoc:
module Packaging # :nodoc:
# This cop flags the usage of `git ls-files` in gemspec
# and suggests to use a plain Ruby alternative, like `Dir`,
# `Dir.glob`, or `Rake::FileList` instead.
#
# @example
#
# # bad
# Gem::Specification.new do |spec|
# spec.files = `git ls-files`.split("\n")
# spec.test_files = `git ls-files -- spec`.split("\n")
# end
#
# # good
# Gem::Specification.new do |spec|
# spec.files = Dir["lib/**/*", "LICENSE", "README.md"]
# spec.test_files = Dir["spec/**/*"]
# end
#
# # bad
# Gem::Specification.new do |spec|
# spec.files = Dir.chdir(File.expand_path(__dir__)) do
# `git ls-files -z`.split("\\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
# end
# end
#
# # good
# require "rake/file_list"
#
# Gem::Specification.new do |spec|
# spec.files = Rake::FileList["**/*"].exclude(*File.read(".gitignore").split)
# end
#
# # bad
# Gem::Specification.new do |spec|
# spec.files = `git ls-files -- lib/`.split("\n")
# spec.test_files = `git ls-files -- test/{functional,unit}/*`.split("\n")
# spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
# end
#
# # good
# Gem::Specification.new do |spec|
# spec.files = Dir.glob("lib/**/*")
# spec.test_files = Dir.glob("test/{functional,test}/*")
# spec.executables = Dir.glob("bin/*").map{ |f| File.basename(f) }
# end
#
class GemspecGit < Base
# This is the message that will be displayed when RuboCop finds an
# offense of using `git ls-files`.
MSG = "Avoid using git to produce lists of files. " \
"Downstreams often need to build your package in an environment " \
"that does not have git (on purpose). " \
"Use some pure Ruby alternative, like `Dir` or `Dir.glob`."
def_node_search :xstr, <<~PATTERN
(block
(send
(const
(const {cbase nil?} :Gem) :Specification) :new)
(args
(arg _)) `$(xstr (str #starts_with_git?)))
PATTERN
# Extended from the Cop class.
# More about the `#investigate` method can be found here:
# https://github.com/rubocop-hq/rubocop/blob/59543c8e2b66bff249de131fa9105f3eb11e9edb/lib/rubocop/cop/cop.rb#L13-L25
#
# Processing of the AST happens here.
def on_new_investigation
return if processed_source.blank?
xstr(processed_source.ast).each do |node|
add_offense(
node.loc.expression,
message: MSG
)
end
end
# This method is called from inside `#def_node_search`.
# It is used to find strings which start with "git".
def starts_with_git?(str)
str.start_with?("git")
end
end
end
end
end
|