Project

General

Profile

Bug #13889

FileUtils.rmdir が Errno::ENOTEMPTY を無視している

Added by tkubo_ncs (Takehiro KUBO) 10 months ago. Updated 6 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.1.6p336 (2015-04-13 revision 50298)
[ruby-dev:50236]

Description

2.1 や最新のリファレンスには FileUtils.rmdir で削除対象のディレクトリが空ではない場合は Errno::ENOTEMPTY が発生すると書かれていますが、
FileUtils.rmdir を空でないディレクトリに対して呼んでもエラーにはならず、削除もされません。

irb(main):002:0> FileUtils.mkdir("dir")
=> ["dir"]
irb(main):003:0> FileUtils.touch("dir/file")
=> ["dir/file"]
irb(main):004:0> FileUtils.rmdir("dir")
=> ["dir"]                                   #<= エラーは出ない
irb(main):005:0> File.exist?("dir")          #<= 残っている
=> true
irb(main):006:0> File.exist?("dir/file")
=> true

fileutils.rb のソースで ENOTEMPTY が rescue されているようです。(trunk でも)

def rmdir(list, options = {})
  fu_check_options options, OPT_TABLE['rmdir']
  list = fu_list(list)
  parents = options[:parents]
  fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if options[:verbose]
  return if options[:noop]
  list.each do |dir|
    begin
      Dir.rmdir(dir = remove_tailing_slash(dir))
      if parents
        until (parent = File.dirname(dir)) == '.' or parent == dir
          dir = parent
          Dir.rmdir(dir)
        end
      end
    rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT    <= ここです
    end
  end
end
module_function :rmdir

実際無視するのが正しいならリファレンスの方を修正していただければと思います。

Associated revisions

Revision 2635984c
Added by nobu (Nobuyoshi Nakada) 10 months ago

fileutils.rb: error at rmdir

  • lib/fileutils.rb (rmdir): should not ignore errors first, except for parent directories. [Bug #13889]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59934 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 59934
Added by nobu (Nobuyoshi Nakada) 10 months ago

fileutils.rb: error at rmdir

  • lib/fileutils.rb (rmdir): should not ignore errors first, except for parent directories. [Bug #13889]

Revision 59934
Added by nobu (Nobuyoshi Nakada) 10 months ago

fileutils.rb: error at rmdir

  • lib/fileutils.rb (rmdir): should not ignore errors first, except for parent directories. [Bug #13889]

History

#1 [ruby-dev:50238] Updated by sho-h (Sho Hashimoto) 10 months ago

1.9から故意に無視するようになったようでしたので日本語リファレンスの方を修正しました。そのうちWebの方も反映されるかと思います。

#2 [ruby-dev:50239] Updated by sho-h (Sho Hashimoto) 10 months ago

追記漏れに気付いたので追記しました。

Errno::ENOTEMPTYについてはoptions[:verbose]がtrueの時だけ何か出力するくらいはしてもいいかもしれません。

#3 [ruby-dev:50240] Updated by tkubo_ncs (Takehiro KUBO) 10 months ago

1.9から故意に無視するようになった

ちなみにこちらは何か理由があったのでしょうか?

Errno::ENOTEMPTYについてはoptions[:verbose]がtrueの時だけ何か出力するくらいはしてもいいかもしれません。

はい、そのような挙動ならエラーに削除エラーに気づけて良いかと思います。

#4 Updated by nobu (Nobuyoshi Nakada) 10 months ago

  • Status changed from Open to Closed

Applied in changeset trunk|r59934.


fileutils.rb: error at rmdir

  • lib/fileutils.rb (rmdir): should not ignore errors first, except for parent directories. [Bug #13889]

#5 [ruby-dev:50249] Updated by nagachika (Tomoyuki Chikanaga) 10 months ago

  • Status changed from Closed to Open

r59934 の変更で parent で親ディレクトリに遡っている時以外は Errno::ENOTEMPTY を無視しないように変更したようです(従ってドキュメントの ENOTEMPTY の記述の削除は戻したほうがいいかも?)。しかし存在しない名前を FileUtils.rmdir に指定した時にエラーにならなかったのが Errno::ENOENT が発生するなるようになってしまっているようです。

% ./ruby -r fileutils -e 'FileUtils.rmdir "notexist"'
% ./ruby -r ./lib/fileutils -e 'FileUtils.rmdir "notexist" rescue p $!'
#<Errno::ENOENT: No such file or directory @ dir_s_rmdir - notexist>

#6 [ruby-dev:50337] Updated by nagachika (Tomoyuki Chikanaga) 8 months ago

  • Backport changed from 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN to 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: DONTNEED
  • Status changed from Open to Closed

「しかし存在しない名前を FileUtils.rmdir に指定した時にエラーにならなかったのが Errno::ENOENT が発生するなるようになってしまっている」 については、fileutils はコマンドラインツールの挙動に倣うもので、rmdir(1) が存在しないパスを指定された時にはエラーになるので、r59934 後の挙動のほうが正しいということで閉じてしまいます。

一応挙動が変わるので、Backport 欄は 2.4 は DONTNEED にしておきます。

#7 [ruby-dev:50416] Updated by vo.x (Vit Ondruch) 6 months ago

The decision to not backport this is questionable IMO.

For example, the test suite of spring-watcher-listen passes testing against Ruby 2.4, but unintentionally leaves files/directories behind, because the FileUtils.rmdir secretly swallows the errors.

Testing against Ruby 2.5, the test suite fails of course and at the end, the code must be fixed anyway 1.

So why not backport this? Why are you keep hiding something which is obviously error?

Also available in: Atom PDF