@@ -298,6 +298,39 @@ def ln(src, dest, force: nil, noop: nil, verbose: nil)
298298 alias link ln
299299 module_function :link
300300
301+ #
302+ # :call-seq:
303+ # FileUtils.cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false)
304+ #
305+ # Hard link +src+ to +dest+. If +src+ is a directory, this method links
306+ # all its contents recursively. If +dest+ is a directory, links
307+ # +src+ to +dest/src+.
308+ #
309+ # +src+ can be a list of files.
310+ #
311+ # # Installing ruby library "mylib" under the site_ruby
312+ # FileUtils.rm_r site_ruby + '/mylib', :force => true
313+ # FileUtils.cp_lr 'lib/', site_ruby + '/mylib'
314+ #
315+ # # Examples of copying several files to target directory.
316+ # FileUtils.cp_lr %w(mail.rb field.rb debug/), site_ruby + '/tmail'
317+ # FileUtils.cp_lr Dir.glob('*.rb'), '/home/aamine/lib/ruby', :noop => true, :verbose => true
318+ #
319+ # # If you want to copy all contents of a directory instead of the
320+ # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
321+ # # use following code.
322+ # FileUtils.cp_lr 'src/.', 'dest' # cp_r('src', 'dest') makes src/dest, but this doesn't.
323+ #
324+ def cp_lr ( src , dest , noop : nil , verbose : nil ,
325+ dereference_root : true , remove_destination : false )
326+ fu_output_message "cp -lr#{ remove_destination ? ' --remove-destination' : '' } #{ [ src , dest ] . flatten . join ' ' } " if verbose
327+ return if noop
328+ fu_each_src_dest ( src , dest ) do |s , d |
329+ link_entry s , d , dereference_root , remove_destination
330+ end
331+ end
332+ module_function :cp_lr
333+
301334 #
302335 # :call-seq:
303336 # FileUtils.ln_s(target, link, force: nil, noop: nil, verbose: nil)
@@ -344,6 +377,26 @@ def ln_sf(src, dest, noop: nil, verbose: nil)
344377 end
345378 module_function :ln_sf
346379
380+ #
381+ # Hard links a file system entry +src+ to +dest+.
382+ # If +src+ is a directory, this method links its contents recursively.
383+ #
384+ # Both of +src+ and +dest+ must be a path name.
385+ # +src+ must exist, +dest+ must not exist.
386+ #
387+ # If +dereference_root+ is true, this method dereference tree root.
388+ #
389+ # If +remove_destination+ is true, this method removes each destination file before copy.
390+ #
391+ def link_entry ( src , dest , dereference_root = false , remove_destination = false )
392+ Entry_ . new ( src , nil , dereference_root ) . traverse do |ent |
393+ destent = Entry_ . new ( dest , ent . rel , false )
394+ File . unlink destent . path if remove_destination && File . file? ( destent . path )
395+ ent . link destent . path
396+ end
397+ end
398+ module_function :link_entry
399+
347400 #
348401 # Copies a file content +src+ to +dest+. If +dest+ is a directory,
349402 # copies +src+ to +dest/src+.
@@ -1278,6 +1331,22 @@ def chown(uid, gid)
12781331 end
12791332 end
12801333
1334+ def link ( dest )
1335+ case
1336+ when directory?
1337+ if !File . exist? ( dest ) and descendant_directory? ( dest , path )
1338+ raise ArgumentError , "cannot link directory %s to itself %s" % [ path , dest ]
1339+ end
1340+ begin
1341+ Dir . mkdir dest
1342+ rescue
1343+ raise unless File . directory? ( dest )
1344+ end
1345+ else
1346+ File . link path ( ) , dest
1347+ end
1348+ end
1349+
12811350 def copy ( dest )
12821351 lstat
12831352 case
0 commit comments