Class: Gemvault::Vault

Inherits:
Object
  • Object
show all
Extended by:
Forwardable, VaultSession
Defined in:
lib/gemvault/vault.rb

Overview

The public vault interface. Delegates storage to a backend chosen by file format: a Dbvault (SQLite) for existing SQLite files, a Tarvault (tarball) otherwise. New vaults are Tarvaults. Only the selected backend is loaded, so the tar path never requires sqlite3.

Defined Under Namespace

Classes: DuplicateGemError, Error, InvalidGemError, NotFoundError, ReadOnlyError, UnsupportedVersionError

Constant Summary collapse

SQLITE_MAGIC =
"SQLite format 3#{0.chr}".freeze
TAR_MAGIC =
"ustar".freeze
TAR_MAGIC_OFFSET =
257
CURRENT_FORMAT =
2
MIN_READABLE_FORMAT =
1

Class Method Summary collapse

Instance Method Summary collapse

Methods included from VaultSession

open

Constructor Details

#initialize(path, create: false) ⇒ Vault

Returns a new instance of Vault.



86
87
88
89
# File 'lib/gemvault/vault.rb', line 86

def initialize(path, create: false)
  absolute_path = Pathname(path).expand_path
  @backend = self.class.backend_for(absolute_path, create:)
end

Class Method Details

.assert_readable!(version:, path:) ⇒ Object



33
34
35
36
37
38
# File 'lib/gemvault/vault.rb', line 33

def self.assert_readable!(version:, path:)
  return if version.between?(MIN_READABLE_FORMAT, CURRENT_FORMAT)

  raise UnsupportedVersionError,
        "Vault #{path} is format #{version}; this gemvault reads up to #{CURRENT_FORMAT}. Upgrade gemvault."
end

.backend_for(path, create:) ⇒ Object

Raises:



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/gemvault/vault.rb', line 40

def self.backend_for(path, create:)
  return build_tarvault(path, create: true) if create
  raise NotFoundError, "Vault not found: #{path}" unless path.exist?

  case container_kind(path)
  when :sqlite then build_dbvault(path)
  when :tar then build_tarvault(path, create: false)
  else
    raise Error, "Unrecognized vault format: #{path} (not a Dbvault or Tarvault; it may require a newer gemvault)"
  end
end

.build_dbvault(path) ⇒ Object



70
71
72
73
74
75
76
77
78
79
# File 'lib/gemvault/vault.rb', line 70

def self.build_dbvault(path)
  begin
    require_relative "dbvault"
    Dbvault.new(path)
  rescue LoadError => e
    raise Error,
          "#{path} is a legacy SQLite vault; it needs the sqlite3 gem (#{e.message}). " \
          "Install sqlite3, or upgrade the vault with a gemvault that includes it."
  end
end

.build_tarvault(path, create:) ⇒ Object



81
82
83
84
# File 'lib/gemvault/vault.rb', line 81

def self.build_tarvault(path, create:)
  require_relative "tarvault"
  Tarvault.new(path, create:)
end

.container_kind(path) ⇒ Object



52
53
54
55
56
57
# File 'lib/gemvault/vault.rb', line 52

def self.container_kind(path)
  return :sqlite if sqlite?(path)
  return :tar if tar?(path)

  :unknown
end

.sqlite?(path) ⇒ Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/gemvault/vault.rb', line 59

def self.sqlite?(path)
  path.exist? && path.binread(SQLITE_MAGIC.bytesize) == SQLITE_MAGIC
end

.tar?(path) ⇒ Boolean

Returns:

  • (Boolean)


63
64
65
66
67
68
# File 'lib/gemvault/vault.rb', line 63

def self.tar?(path)
  return false unless path.exist?

  header = path.binread(TAR_MAGIC_OFFSET + TAR_MAGIC.bytesize)
  header.to_s[TAR_MAGIC_OFFSET, TAR_MAGIC.bytesize] == TAR_MAGIC
end