class Backup::Jar

Public Class Methods

all(file_item, root_path) click to toggle source
# File lib/backup/jar.rb, line 185
def all(file_item, root_path)
  hashes = file_item.dir("#{root_path}/meta/jars").map do |backup|
    backup[/[0-9a-z]{32}$/]
  end.compact.sort

  result = {}

  hashes.each do |hash|
    jar_local_path = Jar.hash_to_path(file_item, root_path, hash)
    result[jar_local_path] = hash unless jar_local_path.empty?
  end

  result
end
fetch_index_for(file_item, root_path, hash, timestamp) click to toggle source
# File lib/backup/jar.rb, line 212
def fetch_index_for(file_item, root_path, hash, timestamp)
  index = file_item.read_file "#{root_path}/meta/#{hash}/#{timestamp}.yml"
  YAML::load(index) unless index.nil?
end
hash_to_path(file_item, root_path, hash) click to toggle source
# File lib/backup/jar.rb, line 179
def hash_to_path(file_item, root_path, hash)
  file_item.read_file("#{root_path}/meta/jars/#{hash}")
rescue Errno::ENOENT
  ""
end
jar_versions(file_item, root_path, jar, hash = false) click to toggle source
# File lib/backup/jar.rb, line 200
def jar_versions(file_item, root_path, jar, hash = false)
  jar = jar.chop if jar =~ /\/$/
  jar = Digest::MD5.hexdigest(jar) unless hash

  meta_jar_path = "#{root_path}/meta/#{jar}"

  file_item.dir(meta_jar_path, "*.yml").map do |file|
    match = file.match(/^\/?([0-9]{12}).yml$/)
    match[1] if match
  end.compact.sort
end
new(file_item, root_path, local_path, key = nil) click to toggle source
# File lib/backup/jar.rb, line 3
def initialize(file_item, root_path, local_path, key = nil)
  @root_path = root_path
  @local_path = local_path
  @timestamp = Backup::Timestamp.create
  @file_item = file_item
  @key = key
end

Public Instance Methods

hash_local_files() click to toggle source
# File lib/backup/jar.rb, line 148
def hash_local_files
  files = {}

  if File.directory? @local_path
    matches = []
    
    Dir.glob(File.join(@local_path, "/**/*"), File::FNM_DOTMATCH) do |file|
      if File.file?(file) or File.directory?(file)
        puts_fail "Permission denied: #{file}" unless File.readable?(file)

        matches << file if file[/\/\.\.$/].nil? and file[/\/\.$/].nil?
      end
    end

    #matches = matches.select do |match|
    #  match[/\/\.\.$/].nil? and match[/\/\.$/].nil?
    #end

    matches << @local_path

    matches.each do |match|
      files.merge!(@file_item.stat match)
    end
  else
    files = @file_item.stat @local_path
  end

  files
end
jar_hash() click to toggle source
# File lib/backup/jar.rb, line 11
def jar_hash
  Digest::MD5.hexdigest(@local_path)
end
save(increment = false, compression = nil, purge = false) click to toggle source
# File lib/backup/jar.rb, line 15
def save increment = false, compression = nil, purge = false
  @meta_index = {}
  @local_files = hash_local_files

  if increment
    last_timestamp = Jar.jar_versions(@file_item, @root_path, jar_hash, true).last

    if last_timestamp.nil?
      puts_fail "First you must create a full backup for #{@local_path.dark_green}"
    end

    @last_index = Jar.fetch_index_for(@file_item, @root_path, jar_hash, last_timestamp)

    @local_files.keys.each do |file|
      current = @local_files[file].dup
      current.delete(:timestamp)

      unless @last_index[file].nil?
        backup = @last_index[file].dup
        backup.delete(:timestamp)

        if (current == backup) or
           (!current[:checksum].nil? and current[:checksum] == backup[:checksum])

          @meta_index[file] = @local_files[file]
          @meta_index[file][:timestamp] = @last_index[file][:timestamp]
        end
      end
    end
  end

  unless @key.nil?
    @meta_index.merge!({
      :checksum => Base64.encode64(@key.encrypt(@timestamp))
    })
  end

  unless compression.nil?
    @meta_index.merge!({
      :compression => compression.type.to_s
    })
  end

  @file_item.create_directory_once meta_jars_path, meta_jar_path, jar_data_path
  @file_item.create_file_once(
    "#{meta_jars_path}/#{jar_hash}",
    @file_item.semantic_path(@local_path)
  )

  if @file_item.is_a? Backup::FileItem::Cloud
    pbar = ProgressBar.new(
      "Uploading",
      @local_files.keys.count
    )
  else
    pbar = ProgressBar.new(
      "Copying",
      @local_files.keys.count
    )
  end

  pbar.bar_mark = '*'

  begin
    files_to_push = @local_files.keys
    threads = []
    
    32.times do
      threads << Thread.new do

        while file = files_to_push.pop
          if @meta_index[file].nil?
            unless File.directory? file
              data = StringIO.new File.open(file, 'rb').read
              checksum = Digest::MD5.hexdigest(data.read)

              data.seek 0
              data = compression.compress(data.read, 3) unless compression.nil?

              data = @key.encrypt_to_stream(data) if @key

              @file_item.create_file_once(
                "#{jar_data_path}/#{@file_item.file_hash file}",
                data
              )

              pbar.inc
            end

            @meta_index[file] = @local_files[file]
            @meta_index[file][:checksum] = checksum
            @meta_index[file][:timestamp] = @timestamp
          end
        end
      end
    end

    threads.each &:join

  rescue Exception => e
    @meta_index.merge!({
      :jar_path => meta_jar_path,
      :timestamp => @timestamp
    })
    File.open("/var/tmp/encbs.swap", "w") do |f|
      f.print @meta_index.to_yaml
    end

    puts
    puts_fail "Index file has been saved that to allow upload into cloud in next run."
  else
    @file_item.create_file_once(
      "#{meta_jar_path}/#{@timestamp}.yml",
      @meta_index.to_yaml
    )

    pbar.finish

    if purge
      puts "Removing previous backups..."
      previous_versions = Jar.jar_versions @file_item, @root_path, jar_hash, true
      previous_versions.delete @timestamp

      previous_versions.each do |version|
        @file_item.delete_file "#{meta_jar_path}/#{version}.yml"
        @file_item.delete_dir "#{@root_path}/#{jar_hash}/#{version}"
      end
    end
  end

  @timestamp
end

Private Instance Methods

jar_data_path() click to toggle source
# File lib/backup/jar.rb, line 228
def jar_data_path
  "#{@root_path}/#{jar_hash}/#{@timestamp}"
end
meta_jar_path() click to toggle source
# File lib/backup/jar.rb, line 224
def meta_jar_path
  "#{@root_path}/meta/#{jar_hash}"
end
meta_jars_path() click to toggle source
# File lib/backup/jar.rb, line 220
def meta_jars_path
  "#{@root_path}/meta/jars"
end