Class: NSWTopo::Archive

Inherits:
Object
  • Object
show all
Extended by:
Safely
Defined in:
lib/nswtopo/archive.rb

Constant Summary

Constants included from Log

Log::FAILURE, Log::NEUTRAL, Log::SUCCESS, Log::UPDATE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Safely

safely

Methods included from Log

#log_abort, #log_neutral, #log_success, #log_update, #log_warn

Constructor Details

#initialize(path, tar_in) ⇒ Archive

Returns a new instance of Archive.



5
6
7
# File 'lib/nswtopo/archive.rb', line 5

def initialize(path, tar_in)
  @tar_in, @basename, @entries = tar_in, path.basename(".tgz").basename(".tar.gz").to_s, Hash[]
end

Instance Attribute Details

#basenameObject (readonly)

Returns the value of attribute basename.



8
9
10
# File 'lib/nswtopo/archive.rb', line 8

def basename
  @basename
end

Class Method Details

.open(out_path, in_path = nil, &block) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/nswtopo/archive.rb', line 55

def self.open(out_path, in_path = nil, &block)
  buffer, reader = StringIO.new, in_path ? Zlib::GzipReader : StringIO

  reader.open(*in_path) do |input|
    if in_path
      version = input.comment.to_s[/^nswtopo (.+)$/, 1]
      raise "unrecognised map file: %s" % in_path unless version
      comparison = version.split(?.).map(&:to_i) <=> MIN_VERSION.split(?.).map(&:to_i)
      raise "map file too old: version %s, minimum %s required" % [version, MIN_VERSION] unless comparison >= 0
    end
    Gem::Package::TarReader.new(input) do |tar_in|
      archive = new(out_path, tar_in).tap(&block)
      Gem::Package::TarWriter.new(buffer) do |tar_out|
        archive.each &tar_out.method(:add_entry)
      end if archive.changed?
    end
  end

  Dir.mktmppath do |temp_dir|
    log_update "nswtopo: saving map..."
    temp_path = temp_dir / "temp.tgz"
    Zlib::GzipWriter.open temp_path, Zlib::BEST_COMPRESSION do |gzip|
      gzip.comment = "nswtopo %s" % VERSION
      gzip.write buffer.string
    rescue Interrupt
      log_update "nswtopo: interrupted, please wait..."
      raise
    end
    safely "saving map file, please wait..." do
      FileUtils.cp temp_path, out_path
    end
    log_success "map saved"
  end unless buffer.size.zero?

rescue Zlib::GzipFile::Error
  raise "unrecognised map file: %s" % in_path
end

Instance Method Details

#changed?Boolean

Returns:

  • (Boolean)


48
49
50
51
52
53
# File 'lib/nswtopo/archive.rb', line 48

def changed?
  return true if @entries.values.any?
  @entries.keys.any? do |filename|
    @tar_in.seek(filename, &:itself)
  end
end

#delete(filename) ⇒ Object



10
11
12
# File 'lib/nswtopo/archive.rb', line 10

def delete(filename)
  @entries[filename] = nil
end

#each(&block) ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/nswtopo/archive.rb', line 39

def each(&block)
  @tar_in.each do |entry|
    yield entry unless @entries.key? entry.full_name
  end
  @entries.each do |filename, entry|
    yield entry if entry
  end
end

#mtime(filename) ⇒ Object



20
21
22
23
# File 'lib/nswtopo/archive.rb', line 20

def mtime(filename)
  header = @entries.key?(filename) ? @entries[filename]&.header : @tar_in.seek(filename, &:header)
  Time.at header.mtime if header
end

#read(filename) ⇒ Object



25
26
27
28
29
# File 'lib/nswtopo/archive.rb', line 25

def read(filename)
  @entries.key?(filename) ? @entries[filename]&.read : @tar_in.seek(filename, &:read)
ensure
  @entries[filename]&.rewind
end

#uptodate?(depender, *dependees) ⇒ Boolean

Returns:

  • (Boolean)


31
32
33
34
35
36
37
# File 'lib/nswtopo/archive.rb', line 31

def uptodate?(depender, *dependees)
  return unless mtime(depender)
  dependees.all? do |dependee|
    mtimes = [depender, dependee].map(&method(:mtime))
    mtimes.all? && mtimes.inject(&:>=)
  end
end

#write(filename, content) ⇒ Object



14
15
16
17
18
# File 'lib/nswtopo/archive.rb', line 14

def write(filename, content)
  io = StringIO.new content
  header = Gem::Package::TarHeader.new name: filename, size: io.size, prefix: "", mode: 0o0644, mtime: Time.now
  @entries[filename] = Gem::Package::TarReader::Entry.new header, io
end