From a7fe15306b5b8f611d43d88df640ffa057625479 Mon Sep 17 00:00:00 2001
From: 7rans <transfire@gmail.com>
Date: Wed, 22 Dec 2010 16:34:59 -0500
Subject: [PATCH 1/2] add FileUtils#ln_r

---
 lib/fileutils.rb |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/lib/fileutils.rb b/lib/fileutils.rb
index 73e2bfe..806daf7 100644
--- a/lib/fileutils.rb
+++ b/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 "cp -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?
-- 
1.7.10


From da7698bc55c0feae9fceb5da555e75f812ce33d0 Mon Sep 17 00:00:00 2001
From: 7rans <transfire@gmail.com>
Date: Wed, 22 Dec 2010 16:46:23 -0500
Subject: [PATCH 2/2] change cp to ln

---
 lib/fileutils.rb |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/fileutils.rb b/lib/fileutils.rb
index 806daf7..feeb846 100644
--- a/lib/fileutils.rb
+++ b/lib/fileutils.rb
@@ -342,7 +342,7 @@ def ln(src, dest, options = {})
   # TODO: Why --remove-destination and not --force?
   def ln_r(src, dest, options = {})
     fu_check_options options, OPT_TABLE['ln_r']
-    fu_output_message "cp -r#{options[:remove_destination] ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
+    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)
-- 
1.7.10

