本日のお裾分け

日々の開発で得た知識をシェアします。Java/Scala/Ruby/javascript

fileutils@7.0以前がyankedになり、bundle installがコケる件

4月からRailsエンジニアになったのですが、RubyGemsの文化って本当に早いですね…。
入社した時はRails5.1.0.beta1だったのが、もうRails5.1.1だったり。
ソースを読む機会が多くて勉強にはなりますが、プロダクト的にはこれを追い続けるのはツラいな〜と思ったり。

今日はRubyGemsから消えてしまったfileutilsの話をします。

TL; DR

ActiveSupportが標準ライブラリのfileutilsを読み込んでいるので、
標準ライブラリのFileUtilsに存在する関数だけを使う場合は、GemFileから消してしまってよい。
fileutilsで拡張していた標準ライブラリになかった関数を使っていた場合は、Gemをローカルインストールするなりの対応が必要。

経緯

数日前にDockerコンテナを消してしまい、作り直そうとしたところ、、、

$ bundle install
Fetching gem metadata from https://rubygems.org/............
Fetching version metadata from https://rubygems.org/...
Fetching dependency metadata from https://rubygems.org/..
Resolving dependencies.....
Your bundle is locked to fileutils (0.7), but that version could not be found in any of the sources listed in your Gemfile. If you haven't changed sources, that means the
author of fileutils (0.7) has removed it. You'll need to update your bundle to a different version of fileutils (0.7) that hasn't been removed in order to install.

こんなエラーが。 Gemfile.lockfileutils@0.7を使ってるけどRubyGemsにないとのこと。 RubyGems/fileutilsを見てみると、、、確かにない。

Gemfile.lockがない場合、こんなメッセージになります。

$ bundle install
~~~(略)~~~
Gem::InstallError: fileutils requires Ruby version >= 2.5.0dev.
An error occurred while installing fileutils (0.7.2), and Bundler cannot continue.
Make sure that `gem install fileutils -v '0.7.2'` succeeds before bundling.

fileutilsRuby@2.5.0dev以上でしか使えないと。

開発中のバージョンでしか使えないってどーゆーこと?と思い、調べてみると、こんな記事が。

Does FileUtils require an unavailable Ruby version?/stackoverflow

the gemification of the stdlib has only just now begun and is targeted at Ruby 2.5/3.0, so naturally that’s what those Gems require.

Unless you are on Ruby 2.5, just use the stdlib version.

Ruby@2.5/3.0を目処に標準ライブラリのGem化をしてますよと。
2.5を使っていない限りfileutilsGemを使わずに標準ライブラリを使いなさいと。

なるほどと思い、Gemfileからgem 'fileutils'を消してみる。

と、動く。

標準ライブラリってrequireしないと動かないんじゃ?と思ったが動く。
不安になってpryデバッグしてみると、確かに標準ライブラリのFileUtilsを使っている。

[1] pry(#<ImageUtils>)> step

From: /Users/shinse/.rbenv/versions/2.1.4/lib/ruby/2.1.0/fileutils.rb @ line 203 FileUtils.mkdir_p:

    198:   #     * /usr/local/lib/ruby
    199:   #
    200:   # You can pass several directories at a time in a list.
    201:   #
    202:   def mkdir_p(list, options = {})
 => 203:     fu_check_options options, OPT_TABLE['mkdir_p']
    204:     list = fu_list(list)
    205:     fu_output_message "mkdir -p #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" if options[:verbose]
    206:     return *list if options[:noop]
    207:
    208:     list.map {|path| remove_tailing_slash(path)}.each do |path|

じゃー多分どっかでrequire 'fileutils'してるんだろうと思い、
bundle install --path ./tmp/gemで一通りGemをローカルインストールしてみると、、、

あった。

active_support/core_ext/file/atomic.rb

ActiveSupportのコア拡張ハンパない。

今回のケースだと、無事標準ライブラリの関数しか使っていなかったので、ローカルインストールせずにすみそうです。

以上。