Include files from git submodules when building a ruby gem

Today I ran into the following situation. I wanted to build a gem with bundler which has some vendor assets included as git submodules. My directory structure was something like that

.git/
app/*
lib/*
vendor/assets/javascripts/es5-shim (submodule)
vendor/assets/javascripts/pathjs (submodule)

When doing

rake build

the files from the submodules where not included in the gem, because the gemspec specifies the files as follows.

gem.files = `git ls-files`.split($\)

Unfortunately, git ls-files does not list files from submodules and that’s why, these files are not included in the gem.

I solved this by utilizing git submodules’s foreach statement in combination with some ruby string manipulation.

The resulting gemspec looks like this.


# -*- encoding: utf-8 -*-
require File.expand_path('../lib/example/version', __FILE__)
Gem::Specification.new do |gem|
gem.authors = ["John Doe"]
gem.email = ["john_doe@example.org"]
gem.description = %q{Write a gem description}
gem.summary = %q{Write a gem summary}
gem.homepage = ""
gem.files = `git ls-files`.split($\)
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
gem.name = "example"
gem.require_paths = ["lib"]
gem.version = Example::VERSION
# get an array of submodule dirs by executing 'pwd' inside each submodule
`git submodule –quiet foreach pwd`.split($\).each do |submodule_path|
# for each submodule, change working directory to that submodule
Dir.chdir(submodule_path) do
# issue git ls-files in submodule's directory
submodule_files = `git ls-files`.split($\)
# 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 "#{File.dirname(__FILE__)}/", ""
end
# add relative paths to gem.files
gem.files += submodule_files_paths
end
end
end

view raw

example.gemspec

hosted with ❤ by GitHub

Matt Connolly suggested a shorter version of the gemspec. Have a look at his comment.

Include files from git submodules when building a ruby gem

2 thoughts on “Include files from git submodules when building a ruby gem

  1. mattconnolly says:

    You can do it with less code like this:


    Gem::Specification.new do |s|
    # normal spec stuff above
    s.files = `git ls-files`.split("\n")
    # get an array of submodule dirs by executing 'pwd' inside each submodule
    gem_dir = File.expand_path(File.dirname(__FILE__)) + "/"
    `git submodule –quiet foreach pwd`.split($\).each do |submodule_path|
    Dir.chdir(submodule_path) do
    submodule_relative_path = submodule_path.sub gem_dir, ""
    # issue git ls-files in submodule's directory and
    # prepend the submodule path to create absolute file paths
    `git ls-files`.split($\).each do |filename|
    s.files << "#{submodule_relative_path}/#{filename}"
    end
    end
    end
    end

    Thanks for the great idea!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s