Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

FileUtils.ln_r #4

Closed
wants to merge 2 commits into from

5 participants

@trans

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.

@banister

"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' ;)

@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")

@toolmantim toolmantim referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@reset

:+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.

@zzak
Collaborator

Closing this as there is already an open ticket on redmine

@zzak zzak closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 22, 2010
  1. @trans

    add FileUtils#ln_r

    trans authored
  2. @trans

    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
View
74 lib/fileutils.rb
@@ -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.