sync

in lib/omnibus/file_syncer.rb [90:172]


    def sync(source, destination, options = {})
      unless File.directory?(source)
        raise ArgumentError, "`source' must be a directory, but was a " \
          "`#{File.ftype(source)}'! If you just want to sync a file, use " \
          "the `copy' method instead."
      end

      source_files = all_files_under(source, options)

      
      FileUtils.mkdir_p(destination) unless File.directory?(destination)

      
      source_files.each do |source_file|
        relative_path = relative_path_for(source_file, source)

        
        parent = File.join(destination, File.dirname(relative_path))
        FileUtils.mkdir_p(parent) unless File.directory?(parent)

        case File.ftype(source_file).to_sym
        when :directory
          FileUtils.mkdir_p("#{destination}/#{relative_path}")
        when :link
          target = File.readlink(source_file)

          Dir.chdir(destination) do
            FileUtils.ln_sf(target, "#{destination}/#{relative_path}")
          end
        when :file
          source_stat = File.stat(source_file)
          
          
          if hardlink? source_stat
            if existing = hardlink_sources[[source_stat.dev, source_stat.ino]]
              FileUtils.ln(existing, "#{destination}/#{relative_path}", force: true)
            else
              begin
                FileUtils.cp(source_file, "#{destination}/#{relative_path}")
              rescue Errno::EACCES
                FileUtils.cp_r(source_file, "#{destination}/#{relative_path}", remove_destination: true)
              end
              hardlink_sources.store([source_stat.dev, source_stat.ino], "#{destination}/#{relative_path}")
            end
          else
            
            
            
            
            
            begin
              FileUtils.cp(source_file, "#{destination}/#{relative_path}")
            rescue Errno::EACCES
              FileUtils.cp_r(source_file, "#{destination}/#{relative_path}", remove_destination: true)
            end
          end
        else
          raise "Unknown file type: `File.ftype(source_file)' at `#{source_file}'!"
        end
      end

      
      destination_files = glob("#{destination}/**/*")

      
      
      relative_source_files = source_files.map do |file|
        relative_path_for(file, source)
      end
      relative_destination_files = destination_files.map do |file|
        relative_path_for(file, destination)
      end

      
      
      extra_files = relative_destination_files - relative_source_files
      extra_files.each do |file|
        FileUtils.rm_rf(File.join(destination, file))
      end

      true
    end