class NSWTopo::Archive
def self.open(out_path: nil, in_path: nil, &block)
def self.open(out_path: nil, in_path: nil, &block) buffer, reader = StringIO.new, in_path ? Zlib::GzipReader : StringIO reader.open(*in_path) do |input| begin version = Version[input.comment] raise "map file too old: created with nswtopo %s, minimum %s required" % [version, MIN_VERSION] unless version >= MIN_VERSION raise "nswtopo too old: map file created with nswtopo %s, this version %s" % [version, VERSION] unless version <= VERSION rescue Version::Error raise "unrecognised map file: %s" % in_path end if in_path && false != Config["versioning"] Gem::Package::TarReader.new(input) do |tar| archive = new(tar).tap(&block) archive.each do |entry| buffer.write entry.header buffer.write entry.read buffer.write ?\0 while buffer.pos % 512 > 0 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, Config["zlib-level"] || Zlib::BEST_SPEED do |gzip| gzip.comment = VERSION.creator_string 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 rescue SystemCallError raise "couldn't save #{out_path}" end log_success "map saved" end if out_path && buffer.size.nonzero? rescue Zlib::GzipFile::Error raise Invalid end
def changed?
def changed? @entries.any? end
def delete(filename)
def delete(filename) find do |entry| entry.full_name == filename end&.tap do @entries[filename] = nil end end
def each(&block)
def each(&block) @tar.rewind @tar.each do |entry| yield entry unless @entries.key? entry.full_name end @entries.each do |filename, entry| yield entry.tap(&:rewind) if entry end end
def initialize(tar)
def initialize(tar) @tar, @entries = tar, Hash[] end
def mtime(filename)
def mtime(filename) find do |entry| entry.full_name == filename end&.then do |entry| Time.at entry.header.mtime end end
def read(filename)
def read(filename) find do |entry| entry.full_name == filename end&.read end
def uptodate?(depender, *dependees)
def uptodate?(depender, *dependees) return unless mtime(depender) dependees.all? do |dependee| mtimes = [depender, dependee].map(&method(:mtime)) mtimes.all? && mtimes.inject(&:>=) end end
def write(filename, content)
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