Module: Ocran::GemSpecQueryable

Defined in:
lib/ocran/gem_spec_queryable.rb

Constant Summary collapse

GEM_SCRIPT_RE =
/\.rbw?$/
GEM_EXTRA_RE =
%r{(
  # Auxiliary files in the root of the gem
  ^(\.\/)?(History|Install|Manifest|README|CHANGES|Licen[sc]e|Contributors|ChangeLog|BSD|GPL).*$ |
  # Installation files in the root of the gem
  ^(\.\/)?(Rakefile|setup.rb|extconf.rb)$ |
  # Documentation/test directories in the root of the gem
  ^(\.\/)?(doc|ext|examples|test|tests|benchmarks|spec)\/ |
  # Directories anywhere
  (^|\/)(\.autotest|\.svn|\.cvs|\.git)(\/|$) |
  # Unlikely extensions
  \.(rdoc|c|cpp|c\+\+|cxx|h|hxx|hpp|obj|o|a)$
)}xi
GEM_NON_FILE_RE =
/(#{GEM_EXTRA_RE}|#{GEM_SCRIPT_RE})/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.detect_gems_from(features, verbose: false) ⇒ Object

Fall back to gem detection



87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ocran/gem_spec_queryable.rb', line 87

def detect_gems_from(features, verbose: false)
  features.inject([]) do |gems, feature|
    if gems.any? { |spec| feature.subpath?(spec.gem_dir) }
      # Skip if found in known Gem dir
    elsif (spec = GemSpecQueryable.find_spec(feature))
      gems << spec
    else
      puts "Failed to load gemspec for #{feature}" if verbose
    end

    gems
  end
end

.find_gem_path(path) ⇒ Object

find_gem_path method searches for the path of the gem containing the specified path. The ‘path’ argument is a file or directory path. It checks each gem’s installation path in Gem.path to see if the specified path is a subpath. Returns the gem’s path if found, or nil if not found.



31
32
33
34
35
# File 'lib/ocran/gem_spec_queryable.rb', line 31

def find_gem_path(path)
  return unless defined?(Gem)

  Gem.path.find { |gem_path| Pathname(path).subpath?(gem_path) }
end

.find_spec(path) ⇒ Object

find_spec method searches and returns a Gem::Specification object based on the specified path. Internally, it uses find_spec_file to obtain the path to the gemspec file, and if that file exists, it calls Gem::Specification.load to load the gem’s specifications. Returns the loaded Gem::Specification object, or nil if the gemspec file does not exist.



64
65
66
67
68
69
# File 'lib/ocran/gem_spec_queryable.rb', line 64

def find_spec(path)
  return unless defined?(Gem)

  spec_file = find_spec_file(path)
  spec_file && Gem::Specification.load(spec_file)
end

.find_spec_file(path) ⇒ Object

find_spec_file method searches for the path of the gemspec file of the gem containing the specified path. The ‘path’ argument is a file or directory path. It searches within the “gems” directory in each directory listed in Gem.path to check if the specified path is a subpath. If the gemspec file exists, it returns its path; otherwise, it returns nil.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/ocran/gem_spec_queryable.rb', line 43

def find_spec_file(path)
  return unless defined?(Gem)

  feature = Pathname(path)
  Gem.path.each do |gem_path|
    gems_dir = File.join(gem_path, "gems")
    next unless feature.subpath?(gems_dir)

    full_name = feature.relative_path_from(gems_dir).each_filename.first
    spec_path = File.join(gem_path, "specifications", "#{full_name}.gemspec")
    return spec_path if File.exist?(spec_path)
  end
  nil
end

.gem_inclusion_set(spec_name, gem_options) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/ocran/gem_spec_queryable.rb', line 101

def gem_inclusion_set(spec_name, gem_options)
  include = [:loaded, :files]
  gem_options.each do |negate, option, list|
    next unless list.nil? || list.include?(spec_name)

    case option
    when :minimal
      include = [:loaded]
    when :guess
      include = [:loaded, :files]
    when :all
      include = [:scripts, :files]
    when :full
      include = [:scripts, :files, :extras]
    when :spec
      include = [:spec]
    when :scripts, :files, :extras
      if negate
        include.delete(option)
      else
        include.push(option)
      end
    else
      raise "Invalid Gem content detection option: #{option}"
    end
  end
  include.uniq!
  include
end

.scanning_gemfile(gemfile_path) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/ocran/gem_spec_queryable.rb', line 71

def scanning_gemfile(gemfile_path)
  # Ensure the necessary libraries are loaded to scan the Gemfile.
  # This is particularly useful in custom-built Ruby environments or
  # where certain libraries might be excluded.
  %w[rubygems bundler].each do |lib|
    require lib
  rescue LoadError
    raise "Couldn't scan Gemfile, unable to load #{lib}"
  end

  ENV["BUNDLE_GEMFILE"] = gemfile_path.to_s
  # Bundler.load.specs includes the spec for Bundler itself
  Bundler.load.specs.to_a
end

Instance Method Details

#extra_filesObject



141
142
143
# File 'lib/ocran/gem_spec_queryable.rb', line 141

def extra_files
  gem_root_files.select { |path| path.relative_path_from(gem_root).to_posix =~ GEM_EXTRA_RE }
end

#find_gem_files(file_sets, features_from_gems) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/ocran/gem_spec_queryable.rb', line 151

def find_gem_files(file_sets, features_from_gems)
  actual_files = file_sets.flat_map do |set|
    case set
    when :spec
      files.map { |file| Pathname(file) }
    when :loaded
      features_from_gems.select { |feature| feature.subpath?(gem_dir) }
    when :files
      resource_files
    when :extras
      extra_files
    when :scripts
      script_files
    else
      raise "Invalid file set: #{set}. Please specify a valid file set (:spec, :loaded, :files, :extras, :scripts)."
    end
  end
  actual_files.uniq
  actual_files
end

#gem_rootObject



132
# File 'lib/ocran/gem_spec_queryable.rb', line 132

def gem_root = Pathname(gem_dir)

#gem_root_filesObject

Find the selected files



135
# File 'lib/ocran/gem_spec_queryable.rb', line 135

def gem_root_files = gem_root.find.select(&:file?)

#resource_filesObject



145
146
147
148
149
# File 'lib/ocran/gem_spec_queryable.rb', line 145

def resource_files
  files = gem_root_files.select { |path| path.relative_path_from(gem_root).to_posix !~ GEM_NON_FILE_RE }
  files << Pathname(gem_build_complete_path) if File.exist?(gem_build_complete_path)
  files
end

#script_filesObject



137
138
139
# File 'lib/ocran/gem_spec_queryable.rb', line 137

def script_files
  gem_root_files.select { |path| path.extname =~ GEM_SCRIPT_RE }
end