I'm trying to include files from all git submodules in a gemspec file. The gemspec reads as following
require File.expand_path(File.dirname(__FILE__)) + '/lib/nameofgem.rb'
# Gets all files, from all submodules, and returns them
# as an array
def getSubmoduleFiles()
files = []
# get an array of submodule dirs by executing 'pwd' inside each submodule
`git submodule --quiet foreach pwd`.split("\n").each do |submodule_path|
gemRootDir = File.dirname(File.expand_path(__FILE__))
# for each submodule, change working directory to that submodule
Dir.chdir(submodule_path) do
submodule_files = getSubmoduleFiles()
# issue git ls-files in submodule's directory
submodule_files + `git ls-files`.split("\n")
puts "found:"
puts submodule_files.to_s
puts
# prepend the submodule path to create absolute file paths
submodule_files_fullpaths = submodule_files.map do |filename|
"#{submodule_path}/#{filename}"
end
# remove leading path parts to get paths relative to the gem's root dir
# (this assumes, that the gemspec resides in the gem's root dir)
submodule_files_paths = submodule_files_fullpaths.map do |filename|
filename.gsub "#{gemRootDir}/", ""
end
# add relative paths to gem.files
files += submodule_files_paths
end
end
return files
end
Gem::Specification.new do |s|
s.name = 'name'
s.version = "1.1.1"
s.executables << 'exec'
s.licenses = ['LICENCE']
s.summary = "Does stuff"
s.description = "Longer description of stuff"
s.authors = ["author"]
s.email = 'my@email'
s.files = `git ls-files -- lib/*`.split("\n")
s.homepage = 'https://example.com/'
s.required_ruby_version = '>= 2.0.0'
s.files += getSubmoduleFiles()
end
But in the do block, I get
Invalid gemspec in [nameofgem.gemspec]: undefined method `getSubmoduleFiles' for Gem::Specification:::Module
What am I doing wrong? Why can't a call the function from within the do block?
It seems that gemspec files do some weird stuff with scoping and namespacing (in the entire file, not just within the gemspec block itself), but after banging my head against my desk for 15 minutes and downing yet another beer to dull the existential torment induced by my inability to call a function in a gemspec, I figured out a reasonably clean solution: just stick self.
in front of the function name in both the definition and invocation, like so:
def self.foo
puts 'It works :)'
end
Gem::Specification.new do |s|
# ...
self.foo # should print 'It works :)' instead of erroring out
# ...
end
Why this is necessary, and why nobody else seems to have asked or answered this question anywhere on the World Wide Web, I haven't the faintest idea, but here we go.