I've always used git
to determine which files should go into the gem package:
gem.files = `git ls-files`.split "\n"
Unfortunately, this approach has recently proved to be inappropriate. I need a self-contained, pure-Ruby solution.
My first idea was to simply glob the entire directory, but that alone is likely to include unwanted files. So, after researching the problem, I came up with this:
# example.gemspec
directory = File.dirname File.expand_path __FILE__
dotfiles = %w(.gitignore .rvmrc)
ignore_file = '.gitignore'
file_list = []
Dir.chdir directory do
ignored = File.readlines(ignore_file).map(&:chomp).reject { |glob| glob =~ /\A(#|\s*\z)/ }
file_list.replace Dir['**/**'] + dotfiles
file_list.delete_if do |file|
File.directory?(file) or ignored.any? { |glob| File.fnmatch? glob, file }
end
end
# Later...
gem.files = file_list
That seems a bit complex for a gemspec
. It also does not fully support gitignore
's pattern format. It currently seems to work but I'd rather not run into problems later.
Is there a simpler but robust way to compute the gem's list of files? Most gems apparently use git ls-files
, and the ones that don't either use a solution similar to mine or specify the files manually.
With Rake
The easiest solution depending on rake to list all files from a directory, but exclude everything in the
.gitignore
file:RubyGems
Official rubygems solution, list and exclude manually:
Bundler
Bundler solution, list manually:
Note: rejecting directories is useless as gem will ignore them by default.
Vagrant
Vagrant solution to mimic
git ls-files
and taking care of.gitignore
in pure ruby:Pathspec
Using pathspec gem
Match Path Specifications, such as .gitignore, in Ruby!
See https://github.com/highb/pathspec-ruby
References
Ref: Bundler Vagrant RubyGems Rake easy solution