[前][次][番号順一覧][スレッド一覧]

ruby-changes:50591

From: mame <ko1@a...>
Date: Tue, 13 Mar 2018 17:18:08 +0900 (JST)
Subject: [ruby-changes:50591] mame:r62739 (trunk): Add FileUtils#cp_lr

mame	2018-03-13 17:18:03 +0900 (Tue, 13 Mar 2018)

  New Revision: 62739

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62739

  Log:
    Add FileUtils#cp_lr
    
    * lib/fileutils.rb: Add FileUtils#cp_lr.  This method creates hard links
      of each file from directory to another directory recursively.
      This patch is based on Thomas Sawyers and Zachary Scott.
      [Feature #4189] [ruby-core:33820]

  Modified files:
    trunk/NEWS
    trunk/lib/fileutils.rb
    trunk/test/fileutils/test_fileutils.rb
Index: lib/fileutils.rb
===================================================================
--- lib/fileutils.rb	(revision 62738)
+++ lib/fileutils.rb	(revision 62739)
@@ -297,6 +297,39 @@ module FileUtils https://github.com/ruby/ruby/blob/trunk/lib/fileutils.rb#L297
 
   #
   # :call-seq:
+  #   FileUtils.cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false)
+  #
+  # 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 => true
+  #   FileUtils.cp_lr 'lib/', site_ruby + '/mylib'
+  #
+  #   # Examples of copying several files to target directory.
+  #   FileUtils.cp_lr %w(mail.rb field.rb debug/), site_ruby + '/tmail'
+  #   FileUtils.cp_lr 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.cp_lr 'src/.', 'dest'  # cp_r('src', 'dest') makes src/dest, but this doesn't.
+  #
+  def cp_lr(src, dest, noop: nil, verbose: nil,
+            dereference_root: true, remove_destination: false)
+    fu_output_message "cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
+    return if noop
+    fu_each_src_dest(src, dest) do |s, d|
+      link_entry s, d, dereference_root, remove_destination
+    end
+  end
+  module_function :cp_lr
+
+  #
+  # :call-seq:
   #   FileUtils.ln_s(target, link, force: nil, noop: nil, verbose: nil)
   #   FileUtils.ln_s(target,  dir, force: nil, noop: nil, verbose: nil)
   #   FileUtils.ln_s(targets, dir, force: nil, noop: nil, verbose: nil)
@@ -342,6 +375,26 @@ module FileUtils https://github.com/ruby/ruby/blob/trunk/lib/fileutils.rb#L375
   module_function :ln_sf
 
   #
+  # 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
+
+  #
   # Copies a file content +src+ to +dest+.  If +dest+ is a directory,
   # copies +src+ to +dest/src+.
   #
@@ -1252,6 +1305,22 @@ module FileUtils https://github.com/ruby/ruby/blob/trunk/lib/fileutils.rb#L1305
       end
     end
 
+    def link(dest)
+      case
+      when directory?
+        if !File.exist?(dest) and descendant_directory?(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)
       lstat
       case
Index: NEWS
===================================================================
--- NEWS	(revision 62738)
+++ NEWS	(revision 62739)
@@ -102,6 +102,12 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L102
 
   * erb command's -S option is deprecated, which will be removed in the next version.
 
+* FileUtils
+
+  * New method:
+
+    * FileUtils#cp_lr [Feature #4189]
+
 * Matrix
 
   * New method:
Index: test/fileutils/test_fileutils.rb
===================================================================
--- test/fileutils/test_fileutils.rb	(revision 62738)
+++ test/fileutils/test_fileutils.rb	(revision 62739)
@@ -449,6 +449,45 @@ class TestFileUtils < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/test/fileutils/test_fileutils.rb#L449
     cp_r 'tmp/src', 'tmp/dest/', remove_destination: true
   end if have_symlink?
 
+  def test_cp_lr
+    check_singleton :cp_lr
+
+    cp_lr 'data', 'tmp'
+    TARGETS.each do |fname|
+      assert_same_file fname, "tmp/#{fname}"
+    end
+
+    # a/* -> b/*
+    mkdir 'tmp/cpr_src'
+    mkdir 'tmp/cpr_dest'
+    File.open('tmp/cpr_src/a', 'w') {|f| f.puts 'a' }
+    File.open('tmp/cpr_src/b', 'w') {|f| f.puts 'b' }
+    File.open('tmp/cpr_src/c', 'w') {|f| f.puts 'c' }
+    mkdir 'tmp/cpr_src/d'
+    cp_lr 'tmp/cpr_src/.', 'tmp/cpr_dest'
+    assert_same_file 'tmp/cpr_src/a', 'tmp/cpr_dest/a'
+    assert_same_file 'tmp/cpr_src/b', 'tmp/cpr_dest/b'
+    assert_same_file 'tmp/cpr_src/c', 'tmp/cpr_dest/c'
+    assert_directory 'tmp/cpr_dest/d'
+    my_rm_rf 'tmp/cpr_src'
+    my_rm_rf 'tmp/cpr_dest'
+
+    bug3588 = '[ruby-core:31360]'
+    mkdir 'tmp2'
+    assert_nothing_raised(ArgumentError, bug3588) do
+      cp_lr 'tmp', 'tmp2'
+    end
+    assert_directory 'tmp2/tmp'
+    assert_raise(ArgumentError, bug3588) do
+      cp_lr 'tmp2', 'tmp2/new_tmp2'
+    end
+
+    bug12892 = '[ruby-core:77885] [Bug #12892]'
+    assert_raise(Errno::ENOENT, bug12892) do
+      cp_lr 'non/existent', 'tmp'
+    end
+  end if have_hardlink?
+
   def test_mv
     check_singleton :mv
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]