Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

FileUtils.ln_r #4

Closed
wants to merge 2 commits into from

5 participants

7rans John Mair Urabe, Shyouhei Jamie Winsor Zachary Scott
7rans

This patch adds FileUtils.ln_r (recursive hard link). It is patterned after #cp_r and I have used it in an app of mine, and thus far it has worked fine.

The only thing about it that I am not 100% sure, is it's handling of non-file and non-directory file types. I just assumed any other type other than a directory can be hard linked.

Also I made a note about using --remove-destination vs. --force I'm not sure why one would be used over the other. #ln uses --force while #cp_r uses --remove-destination. I went with the later.

John Mair

"The only thing about it that I am not 100% sure, is it's handling of non-file and non-directory file types. "

'its' not 'it's' ;)

Urabe, Shyouhei
Owner

Hi, can you post it to our redmine? As this is a new feature matz's approval is required. Once that's made it's OK for me to pull it into the mainstream. Thank you.

http://redmine.ruby-lang.org/projects/ruby-19/issues/new
(remember to set the tracker as "feature")

Tim Lucas toolmantim referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
Jamie Winsor

:+1:

Having a convenience function to recursively create hard links based on a source directory is a rare need, but a need, nonetheless. I think FileUtils is a fine place for it when compared to the other choices of where to place it in Ruby core.

Zachary Scott
Collaborator

Closing this as there is already an open ticket on redmine

Zachary Scott zzak closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 23, 2010
  1. 7rans

    add FileUtils#ln_r

    trans authored
  2. 7rans

    change cp to ln

    trans authored
This page is out of date. Refresh to see the latest.
Showing with 74 additions and 0 deletions.
  1. +74 −0 lib/fileutils.rb
74 lib/fileutils.rb
View
@@ -317,6 +317,44 @@ def ln(src, dest, options = {})
OPT_TABLE['link'] = [:force, :noop, :verbose]
#
+ # Options: noop verbose dereference_root remove_destination
+ #
+ # Hard link +src+ to +dest+. If +src+ is a directory, this method links
+ # all its contents recursively. If +dest+ is a directory, links
+ # +src+ to +dest/src+.
+ #
+ # +src+ can be a list of files.
+ #
+ # # Installing ruby library "mylib" under the site_ruby
+ # FileUtils.rm_r site_ruby + '/mylib', :force
+ # FileUtils.ln_r 'lib/', site_ruby + '/mylib'
+ #
+ # # Examples of copying several files to target directory.
+ # FileUtils.ln_r %w(mail.rb field.rb debug/), site_ruby + '/tmail'
+ # FileUtils.ln_r Dir.glob('*.rb'), '/home/aamine/lib/ruby', :noop => true, :verbose => true
+ #
+ # # If you want to copy all contents of a directory instead of the
+ # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
+ # # use following code.
+ # FileUtils.ln_r 'src/.', 'dest' # cp_r('src', 'dest') makes src/dest,
+ # # but this doesn't.
+ #
+ # TODO: Why --remove-destination and not --force?
+ def ln_r(src, dest, options = {})
+ fu_check_options options, OPT_TABLE['ln_r']
+ fu_output_message "ln -r#{options[:remove_destination] ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
+ return if options[:noop]
+ options = options.dup
+ options[:dereference_root] = true unless options.key?(:dereference_root)
+ fu_each_src_dest(src, dest) do |s, d|
+ link_entry s, d, options[:dereference_root], options[:remove_destination]
+ end
+ end
+ module_function :ln_r
+
+ OPT_TABLE['ln_r'] = [:noop, :verbose, :dereference_root, :remove_destination]
+
+ #
# Options: force noop verbose
#
# <b><tt>ln_s(old, new, options = {})</tt></b>
@@ -372,6 +410,26 @@ def ln_sf(src, dest, options = {})
OPT_TABLE['ln_sf'] = [:noop, :verbose]
#
+ # Hard links a file system entry +src+ to +dest+.
+ # If +src+ is a directory, this method links its contents recursively.
+ #
+ # Both of +src+ and +dest+ must be a path name.
+ # +src+ must exist, +dest+ must not exist.
+ #
+ # If +dereference_root+ is true, this method dereference tree root.
+ #
+ # If +remove_destination+ is true, this method removes each destination file before copy.
+ #
+ def link_entry(src, dest, dereference_root = false, remove_destination = false)
+ Entry_.new(src, nil, dereference_root).traverse do |ent|
+ destent = Entry_.new(dest, ent.rel, false)
+ File.unlink destent.path if remove_destination && File.file?(destent.path)
+ ent.link destent.path
+ end
+ end
+ module_function :link_entry
+
+ #
# Options: preserve noop verbose
#
# Copies a file content +src+ to +dest+. If +dest+ is a directory,
@@ -1235,6 +1293,22 @@ def chown(uid, gid)
end
end
+ def link(dest)
+ case
+ when directory?
+ if !File.exist?(dest) and descendant_diretory?(dest, path)
+ raise ArgumentError, "cannot link directory %s to itself %s" % [path, dest]
+ end
+ begin
+ Dir.mkdir dest
+ rescue
+ raise unless File.directory?(dest)
+ end
+ else
+ File.link path(), dest
+ end
+ end
+
def copy(dest)
case
when file?
Something went wrong with that request. Please try again.