Hi!

The methods in "fileutils" seem to be modeled after UNIX commands like
rm/mkdir/cd/... and sometimes with options added to the name (e.g.
"mkdir_p"). I guess this also means that the methods should work like
the corresponding UNIX commands.

But I think "rm_rf" behaves strange. The corresponding UNIX command
"rm -rf" has as a post condition that the files/directories given as
argument should be *nonexisting* after the command. Otherwise the exit
code will signal that the command failed. More specifically the
man-page says the following about the -f option (on OS-X):

     -f          Attempt to remove the files without prompting for confirma-
                 tion, regardless of the file's permissions.  If the file does
                 not exist, do not display a diagnostic message or modify the
                 exit status to reflect an error.  The -f option overrides any
                 previous -i options.

It does *not* say that the command totally ignores any errors. To
illustrate this, suppose I run the following commands:

    $ mkdir -p test-dir1/dir2
    $ touch test-dir1/dir2/file1
    $ sudo chown nobody:nobody test-dir1/dir2

    $ rm -rf test-dir1 ; echo $status
    rm: cannot remove `test-dir1/dir2/file1': Permission denied
    1

The exit is nonzero since the command failed to remove the directory
tree. I suppose this means that FileUtils.rm_rf should give an
exception in the same situation. But it doesn't.

Should this be considered a bug in FileUtils, or is there some reason
why FileUtils differ in behavior?

Below I give a Ruby unit-test that illustrates the current "misfeature".

/Johan Holmberg

#--------------------------------
# NOTE: script uses "sudo" and "rm -rf". I don't like putting such "strong"
# commands in test scripts, but used with caution it should not be dangerous.
# And this unit test is just for illustrating the "bug".

require "test/unit"
require "fileutils"

class TC_rm_rf < Test::Unit::TestCase

    def test_failing_rm_rf
        # setup tree that we will not be able to remove
        ok = true
        ok &&= system "sudo rm -rf test-dir1"
        ok &&= system "mkdir -p test-dir1/dir2"
        ok &&= system "touch test-dir1/dir2/file1"
        ok &&= system "sudo chown nobody:nobody test-dir1/dir2"
        assert(ok)

        begin
            FileUtils.rm_rf("test-dir1")
            got_exception = false
        rescue => e
            got_exception = true
        end

        if got_exception
            assert( File.exist?("test-dir1"),
                    "Exception so we should have failed to remove 'test-dir1'" )
        else
            assert( ! File.exist?("test-dir1"),
                    "'test-dir1' still exists, but we got no exception" )
        end
    end
end

#--------------------------------

Running the script above give the following error:

  1) Failure:
test_failing_rm_rf(TC_rm_rf) [TC_rm_rf.rb:28]:
'test-dir1' still exists, but we got no exception.
<false> is not true.

1 tests, 2 assertions, 1 failures, 0 errors

#--------------------------------