gemvault 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.containerignore +10 -0
- data/.rubocop.yml +8 -1
- data/CHANGELOG.md +30 -0
- data/CLAUDE.md +5 -4
- data/Dockerfile.test +11 -1
- data/README.md +3 -11
- data/Rakefile +9 -0
- data/issues.rec +540 -17
- data/lib/bundler/plugin/vault_source.rb +48 -73
- data/lib/bundler/plugin/vaulted_gem.rb +66 -0
- data/lib/gemvault/archive_entry.rb +6 -0
- data/lib/gemvault/cli/command.rb +9 -5
- data/lib/gemvault/cli/commands/extract.rb +11 -11
- data/lib/gemvault/cli/commands/new.rb +3 -2
- data/lib/gemvault/cli/commands/remove.rb +15 -5
- data/lib/gemvault/cli/commands/upgrade.rb +37 -13
- data/lib/gemvault/dbvault.rb +12 -9
- data/lib/gemvault/deprecation.rb +26 -24
- data/lib/gemvault/gem_entry.rb +20 -24
- data/lib/gemvault/gem_extraction.rb +19 -23
- data/lib/gemvault/gem_reference/any_version.rb +6 -2
- data/lib/gemvault/gem_reference/parser.rb +44 -0
- data/lib/gemvault/gem_reference/specific_version.rb +9 -25
- data/lib/gemvault/gem_reference.rb +13 -45
- data/lib/gemvault/manifest.rb +44 -42
- data/lib/gemvault/tarball.rb +53 -0
- data/lib/gemvault/tarvault.rb +47 -56
- data/lib/gemvault/vault.rb +17 -13
- data/lib/gemvault/vault_path.rb +33 -0
- data/lib/gemvault/vault_upgrade.rb +31 -24
- data/lib/gemvault/version.rb +1 -1
- data/lib/gemvault.rb +1 -0
- data/lib/rubygems/resolver/vault_set.rb +5 -7
- data/lib/rubygems/source/vault.rb +28 -32
- data/lib/rubygems_plugin.rb +8 -6
- metadata +7 -16
- data/lib/gemvault/tar_archive.rb +0 -66
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c643dd2d86d0a918dbecb5a8f20026746a0e60670eaa5590009fe35e6f9b9b0
|
|
4
|
+
data.tar.gz: fa0f695ae5d5d9ab9686caa479cc89c2c6954fc8c53bfdd02841cf12578622bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d16d9d84c05c143a2372eaee7bd55b162aca32019a4709227f689ce47a4c725bd4d2d8a64b9b788f32d107ec37ae8c61b73178d547e60613a221bd55d48aff53
|
|
7
|
+
data.tar.gz: 21b8fbd66feeea5146546632f5636a194c698c2ab6aa1d51ae0d9544b021dc15f32d4c1171a98e92c67fe62b56cfe2f57dab5138fef2c8dc6a4bb5d194b1952d
|
data/.containerignore
ADDED
data/.rubocop.yml
CHANGED
|
@@ -17,7 +17,7 @@ plugins:
|
|
|
17
17
|
|
|
18
18
|
AllCops:
|
|
19
19
|
NewCops: enable
|
|
20
|
-
TargetRubyVersion: 4.
|
|
20
|
+
TargetRubyVersion: 3.4.8
|
|
21
21
|
Exclude:
|
|
22
22
|
- bin/*
|
|
23
23
|
- vendor/**/*
|
|
@@ -137,6 +137,13 @@ Style/ArgumentsForwarding:
|
|
|
137
137
|
Style/RedundantBegin:
|
|
138
138
|
Enabled: false
|
|
139
139
|
|
|
140
|
+
# Data value objects that carry constants, nested value types, or any class
|
|
141
|
+
# body read best as `class X < Data.define(...)`. The assignment form the cop
|
|
142
|
+
# prefers leaks block-level constants to the enclosing scope and forces a
|
|
143
|
+
# `.freeze` (Style/MutableConstant) on the class. Permitted by David.
|
|
144
|
+
Style/DataInheritance:
|
|
145
|
+
Enabled: false
|
|
146
|
+
|
|
140
147
|
# Compact class names are fine for small files and tests.
|
|
141
148
|
Style/ClassAndModuleChildren:
|
|
142
149
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -19,10 +19,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
19
19
|
preserving every gem and timestamp, writing a `.bak` backup by default, with
|
|
20
20
|
`--dry-run` and `--no-backup` flags. It is a no-op on an already-current vault.
|
|
21
21
|
|
|
22
|
+
- All CLI commands accept `vault://` and `file://` locators wherever they take
|
|
23
|
+
a vault path, e.g. `gemvault list vault:///path/to/myvault.gemv`; resolution
|
|
24
|
+
is shared with the RubyGems source via `Gemvault::VaultPath` (issue #9).
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- `bundle plugin install bundler-source-vault` no longer dies with
|
|
28
|
+
`LoadError: cannot load such file -- bundler/plugin/vault_source`. The shim's
|
|
29
|
+
`plugins.rb` now derives the gem root from its own installed location (local
|
|
30
|
+
plugin root, global plugin root, or plain GEM_HOME), registers any spec dirs
|
|
31
|
+
RubyGems is not searching, and resets RubyGems' spec stub cache when it
|
|
32
|
+
predates the just-installed gems (issue #10).
|
|
33
|
+
- `bundle exec` no longer fails Gemfile parsing with `Could not find 'bundler'
|
|
34
|
+
(>= 2.0)` under `path: vendor` on rubies that ship bundler as a regular gem:
|
|
35
|
+
gemvault no longer declares `bundler` as a runtime dependency (issue #12).
|
|
36
|
+
- Vault gems whose versions carry a non-numeric suffix (e.g. `0.2.1.patch1`)
|
|
37
|
+
install from a vault with `gem install --pre`, matching RubyGems' prerelease
|
|
38
|
+
semantics (issue #6).
|
|
39
|
+
|
|
22
40
|
### Changed
|
|
23
41
|
- `sqlite3` is no longer a runtime dependency. Gemvault runs dependency-free on
|
|
24
42
|
the tarball path (including JRuby); `sqlite3` is loaded lazily only to read a
|
|
25
43
|
legacy SQLite vault, with a clear error if it is not installed.
|
|
44
|
+
- `bundler` is no longer a runtime dependency; the Bundler plugin always runs
|
|
45
|
+
inside an existing Bundler process, and the declared dependency broke gem
|
|
46
|
+
activation in restricted GEM_PATH contexts.
|
|
47
|
+
- CI is unblocked (issue #11): RuboCop's TargetRubyVersion now matches the
|
|
48
|
+
gemspec's `required_ruby_version` floor (3.4.8), the previously-missing
|
|
49
|
+
`spec:integration` rake task exists alongside a non-integration `spec:core`, the
|
|
50
|
+
unit job no longer needs podman, and the integration job installs podman
|
|
51
|
+
when the runner image lacks it.
|
|
52
|
+
- Reading a vault's `manifest.json` is now strict: an entry missing any required
|
|
53
|
+
field (`name`, `version`, `platform`, `created_at`, `sha256`, `encrypted`)
|
|
54
|
+
raises instead of silently loading `nil` fields, so a truncated or hand-edited
|
|
55
|
+
manifest fails fast rather than yielding a subtly broken vault.
|
|
26
56
|
|
|
27
57
|
### Deprecated
|
|
28
58
|
- The SQLite vault format is deprecated and now **read-only**: existing SQLite
|
data/CLAUDE.md
CHANGED
|
@@ -17,6 +17,7 @@ Do NOT modify `.rubocop.yml` or use inline `# rubocop:disable` tags without expl
|
|
|
17
17
|
9. ALWAYS write specs first. The workflow is: identify the domain concept (rule 5), write specs describing its behavior, then implement. No implementation without a failing spec.
|
|
18
18
|
10. Integration specs are the first line of defense for CLI-tool bugs. For any bug reported from using the CLI tool (not the gemvault lib / Ruby API), the FIRST spec you write is an integration spec that reproduces the user's exact invocation — real subprocess, real vault, real exit code. Stub-heavy unit specs are complementary, not sufficient: they prove internal logic produces the expected value assuming surrounding wiring works, but a user's bug report is evidence the wiring didn't work.
|
|
19
19
|
11. If an integration spec is not catching a reported CLI-tool bug, one of two things is true, and the fix starts by diagnosing which: (a) existing integration specs are not specific enough — extend them to cover the exact scenario before touching production code; or (b) the scenario is not spec'd at all, which means the work is not a bug fix but a new feature — write integration specs for the contract first (per rule 1), then implement.
|
|
20
|
+
12. NEVER write to /tmp. Use /workspace/tmp
|
|
20
21
|
|
|
21
22
|
## Additional rules
|
|
22
23
|
|
|
@@ -25,7 +26,7 @@ Do NOT modify `.rubocop.yml` or use inline `# rubocop:disable` tags without expl
|
|
|
25
26
|
|
|
26
27
|
## Project Overview
|
|
27
28
|
|
|
28
|
-
Multi-gem portable archives
|
|
29
|
+
Multi-gem portable archives. A single `.gemv` file is a tarball holding multiple `.gem` files plus a `manifest.json` index; legacy SQLite vaults are read-only.
|
|
29
30
|
|
|
30
31
|
Two gems, one repo:
|
|
31
32
|
|
|
@@ -56,7 +57,7 @@ gem install --source file:///path/to/myvault.gemv foo
|
|
|
56
57
|
## Architecture
|
|
57
58
|
|
|
58
59
|
- `gemvault.gemspec` — main gem spec (name: `gemvault`)
|
|
59
|
-
- `lib/gemvault/vault.rb` —
|
|
60
|
+
- `lib/gemvault/vault.rb` — Vault facade choosing a backend by file format (Tarvault current, legacy Dbvault read-only)
|
|
60
61
|
- `lib/gemvault/cli.rb` — CLI dispatcher (new/add/list/remove/extract)
|
|
61
62
|
- `lib/bundler/plugin/vault_source.rb` — Bundler `Plugin::API::Source` implementation
|
|
62
63
|
- `lib/rubygems_plugin.rb` — RubyGems plugin: monkey-patches for `--source myvault.gemv` support
|
|
@@ -69,7 +70,7 @@ gem install --source file:///path/to/myvault.gemv foo
|
|
|
69
70
|
|
|
70
71
|
## Key Design Decisions
|
|
71
72
|
|
|
72
|
-
-
|
|
73
|
+
- Tar storage — portable, dependency-free, single file, inspectable with `tar`; legacy SQLite vaults readable via lazily-loaded sqlite3
|
|
73
74
|
- Specs extracted from gem blobs at runtime (no separate spec storage)
|
|
74
75
|
- Vault opened/closed per operation in the source plugin (no persistent connection)
|
|
75
76
|
- `fetch_gemspec_files` checks installed state — Bundler computes `full_gem_path` as `dirname(loaded_from)`, so `loaded_from` must point inside the gem directory
|
|
@@ -93,7 +94,7 @@ Integration tests use a manually-written Bundler plugin index to avoid rubygems.
|
|
|
93
94
|
|
|
94
95
|
## Dependencies
|
|
95
96
|
|
|
96
|
-
- `bundler`
|
|
97
|
+
- `bundler` — NOT a dependency; the plugin always runs inside an existing Bundler process, and declaring it breaks gem activation under `bundle exec`'s restricted GEM_PATH
|
|
97
98
|
- `command_kit` (~> 0.6) — runtime (CLI)
|
|
98
99
|
- `sqlite3` (~> 2.0) — NOT a runtime dependency; loaded lazily only to read a legacy SQLite (Dbvault) vault. Declared in the Gemfile for development/test.
|
|
99
100
|
- `minitest`, `rake` — development
|
data/Dockerfile.test
CHANGED
|
@@ -11,5 +11,15 @@ RUN cd /tmp/build \
|
|
|
11
11
|
&& rm -rf /tmp/build
|
|
12
12
|
|
|
13
13
|
# sqlite3 is not a gemvault runtime dependency; install it here so the upgrade
|
|
14
|
-
# integration test can
|
|
14
|
+
# integration test can read the committed legacy SQLite (Dbvault) fixture it
|
|
15
|
+
# migrates.
|
|
15
16
|
RUN gem install --no-document sqlite3
|
|
17
|
+
|
|
18
|
+
# Gem files for integration specs that install the plugin from a local gem
|
|
19
|
+
# index at spec runtime, kept for offline use: command_kit is gemvault's
|
|
20
|
+
# runtime dependency; the bundler gem lets specs simulate distro rubies where
|
|
21
|
+
# bundler is a regular (non-default) gem.
|
|
22
|
+
RUN mkdir -p /opt/gems \
|
|
23
|
+
&& cd /opt/gems \
|
|
24
|
+
&& gem fetch command_kit -v 0.6.0 \
|
|
25
|
+
&& gem fetch bundler -v "$(ruby -rbundler -e 'print Bundler::VERSION')"
|
data/README.md
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# Gemvault
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A file that behaves like a private gem server.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
New vaults are portable tarballs (no runtime dependencies, works on JRuby); the original SQLite format is still read transparently. See [Vault format versioning](#vault-format-versioning).
|
|
5
|
+
You can commit it to your repo, drop it on S3, email it, put it on a USB drive, or whatever you feel like doing. Bundler and RubyGems read from it directly.
|
|
8
6
|
|
|
9
7
|
## Installation
|
|
10
8
|
|
|
@@ -29,7 +27,6 @@ end
|
|
|
29
27
|
bundle install
|
|
30
28
|
```
|
|
31
29
|
|
|
32
|
-
Bundler auto-discovers the `bundler-source-vault` plugin, installs it, and resolves gems from the vault alongside rubygems.org. No extra configuration.
|
|
33
30
|
|
|
34
31
|
### RubyGems CLI
|
|
35
32
|
|
|
@@ -67,12 +64,7 @@ gemvault upgrade myvault.gemv --no-backup # skip the default myvault.gemv.bak c
|
|
|
67
64
|
|
|
68
65
|
## How It Works
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
tar -tf myvault.gemv # tarball (v2) vault
|
|
74
|
-
sqlite3 myvault.gemv "SELECT name, version, platform FROM gems" # SQLite (v1) vault
|
|
75
|
-
```
|
|
67
|
+
The gemv file is a tarball containing your .gem files and a json manifest. It has no dependencies other than the tar utilities that rubygems provides.
|
|
76
68
|
|
|
77
69
|
When Bundler sees `type: :vault` in your Gemfile, it auto-installs the `bundler-source-vault` plugin from rubygems.org. The plugin implements the `Bundler::Plugin::API::Source` interface — it reads gemspecs from the vault, participates in dependency resolution, then extracts and installs gems from the vault's blob storage.
|
|
78
70
|
|
data/Rakefile
CHANGED
|
@@ -10,6 +10,14 @@ require "rspec/core/rake_task"
|
|
|
10
10
|
|
|
11
11
|
RSpec::Core::RakeTask.new(:spec)
|
|
12
12
|
|
|
13
|
+
RSpec::Core::RakeTask.new("spec:core") do |t|
|
|
14
|
+
t.rspec_opts = "--tag ~integration"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
RSpec::Core::RakeTask.new("spec:integration") do |t|
|
|
18
|
+
t.rspec_opts = "--tag integration"
|
|
19
|
+
end
|
|
20
|
+
|
|
13
21
|
require "rubocop/rake_task"
|
|
14
22
|
RuboCop::RakeTask.new
|
|
15
23
|
|
|
@@ -59,6 +67,7 @@ namespace :shim do
|
|
|
59
67
|
end
|
|
60
68
|
|
|
61
69
|
Rake::Task[:spec].enhance ["spec:setup"]
|
|
70
|
+
Rake::Task["spec:integration"].enhance ["spec:setup"]
|
|
62
71
|
Rake::Task[:build].enhance ["shim:build"]
|
|
63
72
|
Rake::Task[:release].enhance ["shim:release"]
|
|
64
73
|
Rake::Task[:clobber].enhance ["spec:teardown"]
|