Project

General

Profile

Bug #2731

FileUtils.copy prints error message in $DEBUG mode when destination doesn't exist

Added by murphy (Kornelius Kalnbach) over 9 years ago. Updated over 8 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 1.9.2dev (2010-02-04 trunk 26573) [i386-darwin10.2.0]
Backport:
[ruby-core:28141]

Description

=begin
Trying to copy a file with Ruby:

$ touch source
$ ls destination
ls: destination: No such file or directory
$ ruby -rfileutils -d -e 'FileUtils.copy "source", "destination"'
Exception `Errno::ENOENT' at /usr/local/lib/ruby/1.9.1/fileutils.rb:1429 - No such file or directory - destination
$ ls destination
destination

While the copy succeeds, it prints this confusing message. I don't expect libraries to issue exceptions when performing standard operations. This affects the FileUtils methods install, mv, cp_r, and cp; but the problem is in Entry_#fu_same? (around lib/fileutils.rb:1426):

def fu_same?(a, b) #:nodoc:
if fu_have_st_ino?
st1 = File.stat(a)
st2 = File.stat(b)
st1.dev == st2.dev and st1.ino == st2.ino
else
File.expand_path(a) == File.expand_path(b)
end
rescue Errno::ENOENT
return false
end

So, File.stat(b) is checked even if b doesn't exist. The resulting error message is even explicitely captured and hidden by the rescue. For the methods in question, it is a common case that the destination file doesn't exist.

Here's a version that doesn't rely on exceptions:

def fu_same?(a, b) #:nodoc:
return false if !File.exist?(a) || !File.exist?(b)
if fu_have_st_ino?
st1 = File.stat(a)
st2 = File.stat(b)
st1.dev == st2.dev and st1.ino == st2.ino
else
File.expand_path(a) == File.expand_path(b)
end
end

The problem exists across Ruby versions from 1.8.6 to 1.9.2dev.
=end

History

#1

Updated by mame (Yusuke Endoh) over 9 years ago

  • Status changed from Open to Rejected

=begin
Hi,

2010/2/10 Kornelius Kalnbach redmine@ruby-lang.org:

Trying to copy a file with Ruby:

$ touch source
$ ls destination
ls: destination: No such file or directory
$ ruby -rfileutils -d -e 'FileUtils.copy "source", "destination"'
Exception `Errno::ENOENT' at /usr/local/lib/ruby/1.9.1/fileutils.rb:1429 - No such file or directory - destination
$ ls destination
destination

While the copy succeeds, it prints this confusing message.

You say, library must not use an exception for internal implementation?
The convension is uneasy and too uncomfortable for library authors.

In old convension, an exception might be for exceptional condition.
But currently, it has many use cases not only to represent exceptional
condition but also to represent normal condition (e.g., StopIteration),
to control execution (e.g., DSL), etc.

So this is not a bug and I close the ticket.
Rather, we should reconsider the purpose and behavior of $DEBUG.
Currently, it is worthless in effect.

--
Yusuke ENDOH mame@tsg.ne.jp
=end

#2

Updated by murphy (Kornelius Kalnbach) over 9 years ago

=begin
On 11.04.10 16:08, Yusuke Endoh wrote:

You say, library must not use an exception for internal implementation?
The convension is uneasy and too uncomfortable for library authors.

In old convension, an exception might be for exceptional condition.
But currently, it has many use cases not only to represent exceptional
condition but also to represent normal condition (e.g., StopIteration),
to control execution (e.g., DSL), etc.
You're right. I agree that it's not a bug, more like an inconvenient
behavior. The patch might still be an improvement.

The only workaround I know is:

debug, $DEBUG = $DEBUG, false
FileUtils.copy source, destination
$DEBUG = debug

I don't like such constructs because they look ugly (aka "noise").

So this is not a bug and I close the ticket.
Rather, we should reconsider the purpose and behavior of $DEBUG.
Currently, it is worthless in effect.
Spontaneous idea: Setting $DEBUG to an Exception class or an array of
such classes to specify which exception you want to debug. Improving
Rubys debugging capabilities can't hurt.

[murphy]

=end

Also available in: Atom PDF