2

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?

NateW
  • 2,101
  • 3
  • 28
  • 37
SomeNorwegianGuy
  • 1,494
  • 4
  • 17
  • 43
  • The `undefined method` is telling you that it is not defined in that context. Not sure WHY it's saying undefined when the code is right there in the same file. Something to do with the execution context of `Gem::Specification.new`? It's looking for your method inside "Gem::Specification:::Module" so maybe extend that module? – Beartech Apr 26 '15 at 16:43
  • Yeah, I think it could work to extend that module(haven't tried it), but that seems very hacky... – SomeNorwegianGuy Apr 26 '15 at 17:16
  • Ok, so let's look at context. If you are not referring to `|s|` in your `getSubmofduleFiles()` method, why does it have to be in the block? I'm not up on making Gems so I'm just kind of spitballing this. What happens if you call it outside the `do` block? – Beartech Apr 26 '15 at 18:53
  • @Beartech's suggestion actually makes quite a bit of sense, I don't think i have seen a gem which places requires inside the `Gem::Specification.new` block. Personally I would put your submodule require in `'/lib/nameofgem.rb'` – max Apr 26 '15 at 20:03
  • @Beartech You're right, with code that was there, it is unlikely that that would have been necessary. I forgot a "s.files +=", fixed it now – SomeNorwegianGuy Apr 26 '15 at 22:37

1 Answers1

2

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.

YellowApple
  • 901
  • 8
  • 13