Class: Gemvault::Vault
Overview
The public vault interface. Delegates storage to a backend chosen by file
format: a Dbvault (SQLite) for existing SQLite files, a read-only
LegacyTarvault for a tarball still indexed by manifest.json, and a Tarvault
for every other tarball. 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 =
3
- MIN_READABLE_FORMAT =
1
Class Method Summary
collapse
Instance Method Summary
collapse
open
Constructor Details
#initialize(path, create: false) ⇒ Vault
Returns a new instance of Vault.
116
117
118
119
|
# File 'lib/gemvault/vault.rb', line 116
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
.backend_for(path, create:) ⇒ Object
46
47
48
49
50
51
52
53
54
55
56
|
# File 'lib/gemvault/vault.rb', line 46
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
76
77
78
79
80
81
82
83
84
85
|
# File 'lib/gemvault/vault.rb', line 76
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
87
88
89
90
91
92
93
|
# File 'lib/gemvault/vault.rb', line 87
def self.build_tarvault(path, create:)
require_relative "tarvault"
return Tarvault.new(path, create:) if create || !legacy_tarvault?(path)
require_relative "legacy_tarvault"
LegacyTarvault.new(path)
end
|
.container_kind(path) ⇒ Object
58
59
60
61
62
63
|
# File 'lib/gemvault/vault.rb', line 58
def self.container_kind(path)
return :sqlite if sqlite?(path)
return :tar if tar?(path)
:unknown
end
|
.create(path) ⇒ Object
Creates an empty vault file at path, leaving it closed.
35
36
37
|
# File 'lib/gemvault/vault.rb', line 35
def self.create(path)
new(path, create: true).close
end
|
.legacy_tarvault?(path) ⇒ Boolean
A tarball indexed the way vaults were through format 2. Asked by name
rather than by version, because the version is recorded in the very
index this gemvault no longer reads.
An archive too damaged to enumerate answers no rather than raising here.
This runs ahead of every backend, so a wreck raised from it would escape
the rescue Tarvault opens with and reach the user as a tar library's
backtrace; declining instead leaves that path to report it as the
Vault::Error it has always been.
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/gemvault/vault.rb', line 104
def self.legacy_tarvault?(path)
require_relative "manifest_text"
require_relative "tarball"
begin
names = Tarball.new(path).names
!names.include?(ManifestText::FILENAME) && names.include?(ManifestText::LEGACY_FILENAME)
rescue Gem::Package::Error, ArgumentError, Errno::EINVAL
false
end
end
|
.sqlite?(path) ⇒ Boolean
65
66
67
|
# File 'lib/gemvault/vault.rb', line 65
def self.sqlite?(path)
path.exist? && path.binread(SQLITE_MAGIC.bytesize) == SQLITE_MAGIC
end
|