9

私はいつもgitどのファイルをgemパッケージに入れるべきかを決定するために使用しました:

gem.files = `git ls-files`.split "\n"

残念ながら、このアプローチは最近不適切であることが判明しました。自己完結型の純粋なRubyソリューションが必要です。

私の最初のアイデアは、単にディレクトリ全体をグロブすることでしたが、それだけで不要なファイルが含まれる可能性があります。それで、問題を調査した後、私はこれを思いつきました:

# 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

これは、にとって少し複雑に思えgemspecます。また、gitignoreのパターン形式を完全にはサポートしていません。現在は機能しているようですが、後で問題が発生することはありません。

gemのファイルリストを計算するためのより簡単で堅牢な方法はありますか?ほとんどのgemは明らかにを使用git ls-filesしており、私のようなソリューションを使用していないものや、ファイルを手動で指定していないものもあります。

4

2 に答える 2

9

やあ、

純粋なRubyを使用してプロジェクトのすべてのファイルを一覧表示できます。

gem.files = Dir['**/*'].keep_if { |file| File.file?(file) }

または、手動で行うこともできます。このソリューションは、RubyonRailsのgemで使用されます。

gem.files = Dir['lib/**/*'] + %w(.yardopts Gemfile LICENSE README.md Rakefile my_gem.gemspec)
于 2013-05-12T10:16:20.903 に答える
2

熊手付き

ディレクトリからすべてのファイルを一覧表示するが、ファイル内のすべてを除外するrakeに依存する最も簡単な解決策.gitignore

require 'rake/file_list'
Rake::FileList['**/*'].exclude(*File.read('.gitignore').split)

RubyGems

公式のrubygemsソリューション、手動でリストして除外します。

require 'rake'
spec.files = FileList['lib/*.rb',
                      'bin/*',
                      '[A-Z]*',
                      'test/*'].to_a

# or without Rake...
spec.files = Dir['lib/*.rb'] + Dir['bin/*']
spec.files += Dir['[A-Z]*'] + Dir['test/**/*']
spec.files.reject! { |fn| fn.include? "CVS" }

バンドラー

Bundlerソリューション、手動で一覧表示:

s.files = Dir.glob("{lib,exe}/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }

注:gemはデフォルトでディレクトリを無視するため、ディレクトリを拒否しても意味がありません。

Vagrant

純粋なルビーを模倣git ls-filesして世話をするためのVagrantソリューション:.gitignore

  # The following block of code determines the files that should be included
  # in the gem. It does this by reading all the files in the directory where
  # this gemspec is, and parsing out the ignored files from the gitignore.
  # Note that the entire gitignore(5) syntax is not supported, specifically
  # the "!" syntax, but it should mostly work correctly.
  root_path      = File.dirname(__FILE__)
  all_files      = Dir.chdir(root_path) { Dir.glob("**/{*,.*}") }
  all_files.reject! { |file| [".", ".."].include?(File.basename(file)) }
  all_files.reject! { |file| file.start_with?("website/") }
  all_files.reject! { |file| file.start_with?("test/") }
  gitignore_path = File.join(root_path, ".gitignore")
  gitignore      = File.readlines(gitignore_path)
  gitignore.map!    { |line| line.chomp.strip }
  gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }

  unignored_files = all_files.reject do |file|
    # Ignore any directories, the gemspec only cares about files
    next true if File.directory?(file)

    # Ignore any paths that match anything in the gitignore. We do
    # two tests here:
    #
    #   - First, test to see if the entire path matches the gitignore.
    #   - Second, match if the basename does, this makes it so that things
    #     like '.DS_Store' will match sub-directories too (same behavior
    #     as git).
    #
    gitignore.any? do |ignore|
      File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
        File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
    end
  end

Pathspec

pathspecgemを使用するMatch Path Specifications, such as .gitignore, in Ruby!

https://github.com/highb/pathspec-rubyを参照してください

参考文献

参照: Bundler VagrantRubyGemsRakeの 簡単 ソリューション

于 2019-08-03T19:25:35.827 に答える