Method: Pathname#copy_as

Defined in:
lib/pleasant_path/pathname.rb

#copy_as(destination) ⇒ Pathname #copy_as(destination) {|source, destination| ... } ⇒ Pathname

Copies the file or directory indicated by the Pathname to destination, replacing any existing file or directory.

If a block is given and a file or directory does exist at the destination, the block is called with the source and destination Pathnames, and the return value of the block is used as the new destination. If the block returns the source Pathname or nil, the copy is aborted.

Creates any necessary parent directories of the destination. Returns the destination as a Pathname (or the source Pathname in the case that the copy is aborted).

WARNING: Due to system API limitations, the copy is performed in two steps, non-atomically. First, any file or directory existing at the destination is deleted. Next, the source is copied to the destination. The second step can fail independently of the first, e.g. due to insufficient disk space, leaving the file or directory previously at the destination deleted without replacement.

Examples:

Without a block

FileUtils.touch("file")

Pathname.new("file").copy_as("dir/file")
  # == Pathname.new("dir/file")

File.exist?("file")      # == true
File.exist?("dir/file")  # == true

Error on older source

File.write("file", "A")
sleep 1
File.write("file.new", "B")

Pathname.new("file.new").copy_as("file") do |source, destination|
  if source.mtime < destination.mtime
    raise "cannot replace newer file #{destination} with #{source}"
  end
  destination
end                    # == Pathname.new("file")

File.read("file.new")  # == "B"
File.read("file")      # == "B"

Abort on conflict

File.write("file1", "A")
File.write("file2", "B")

Pathname.new("file1").copy_as("file2") do |source, destination|
  puts "#{source} not copied to #{destination} due to conflict"
  nil
end                 # == Pathname.new("file1")

File.read("file1")  # == "A"
File.read("file2")  # == "B"

New destination on conflict

File.write("file1", "A")
File.write("file2", "B")

Pathname.new("file1").copy_as("file2") do |source, destination|
  destination.available_name
end                   # == Pathname.new("file2_1")

File.read("file1")    # == "A"
File.read("file2")    # == "B"
File.read("file2_1")  # == "A"

Overloads:



708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
# File 'lib/pleasant_path/pathname.rb', line 708

def copy_as(destination)
  destination = destination.to_pathname

  if block_given? && destination.exist? && self.exist? && !File.identical?(self, destination)
    destination = yield self, destination
    destination = nil if destination == self
  end

  if destination
    destination.delete! unless File.identical?(self, destination)
    self.copy(destination.make_dirname)
  end

  destination || self
end