module Backup

Stores the original release files together so a single completed upload can recover them.

Definitions

def self.write(path, files)

Write the release files to a tar archive.

Signature

parameter path String

The destination archive path.

parameter files Array(String)

Original release files, stored under their basenames.

returns Nil

After writing and closing the archive.

Implementation

def self.write(path, files)
	File.open(path, "wb") do |output|
		::Gem::Package::TarWriter.new(output) do |archive|
			files.each do |file|
				archive.add_file(File.basename(file), 0644){|entry| entry.write(File.binread(file))}
			end
		end
	end
end

def self.read(path, names)

Read only the expected regular files; reject missing, duplicate, or unexpected entries before extraction.

Signature

parameter path String

The archive to inspect without extracting filesystem paths.

parameter names Array(String)

Exactly the permitted basenames for the gem, receipt, and two attestation files.

returns Hash(String, String)

Binary file contents keyed by basename.

raises RuntimeError

If entries are missing, duplicated, unexpected, or not regular files.

Implementation

def self.read(path, names)
	files = {}
	
	File.open(path, "rb") do |input|
		::Gem::Package::TarReader.new(input) do |archive|
			archive.each do |entry|
				name = entry.full_name
				raise "Unexpected release backup entry: #{name}" unless entry.file? && names.include?(name) && !files.key?(name)
				files[name] = entry.read
			end
		end
	end
	raise "Release backup is incomplete." unless files.keys.sort == names.sort
	
	return files
end