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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 100a593cb7221bf6cc5842ad00c67335809a351905251a6088c3698b41fa9b95
4
- data.tar.gz: 6645dea254fbdd76dbd2fc1de7f8471f27185d205d5a23e038665d060f253cfa
3
+ metadata.gz: 3c643dd2d86d0a918dbecb5a8f20026746a0e60670eaa5590009fe35e6f9b9b0
4
+ data.tar.gz: fa0f695ae5d5d9ab9686caa479cc89c2c6954fc8c53bfdd02841cf12578622bd
5
5
  SHA512:
6
- metadata.gz: a973851f5b6b7b9eaa48fcf21a25660bc3770d36c992ff758e4b9ace061a64e5b2cdd6a0270ee335ca3d2a6cf1b80f842b69e6768a98fd85741ec91141786a60
7
- data.tar.gz: 16b6a27438852230e49569493d526efdcf6b07f499137cdcb73a18b29ef06bd89ddf2def281649109bbf1cfbacce1e7e3d4bfdddae44984855fa378e1b79c51f
6
+ metadata.gz: d16d9d84c05c143a2372eaee7bd55b162aca32019a4709227f689ce47a4c725bd4d2d8a64b9b788f32d107ec37ae8c61b73178d547e60613a221bd55d48aff53
7
+ data.tar.gz: 21b8fbd66feeea5146546632f5636a194c698c2ab6aa1d51ae0d9544b021dc15f32d4c1171a98e92c67fe62b56cfe2f57dab5138fef2c8dc6a4bb5d194b1952d
data/.containerignore ADDED
@@ -0,0 +1,10 @@
1
+ .bundle
2
+ .git
3
+ gemv
4
+ pkg
5
+ tmp
6
+ vendor
7
+ *.gem
8
+ *.gemv
9
+ references
10
+ references/
data/.rubocop.yml CHANGED
@@ -17,7 +17,7 @@ plugins:
17
17
 
18
18
  AllCops:
19
19
  NewCops: enable
20
- TargetRubyVersion: 4.0
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 backed by SQLite. A single `.gemv` file contains multiple `.gem` files.
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` — Core vault class (SQLite CRUD for gem blobs + specs)
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
- - SQLite storage — random access, ACID, single file, inspectable with `sqlite3` CLI
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` (>= 2.0) runtime
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 build a legacy SQLite (Dbvault) fixture to migrate.
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 gem server in a file. No HTTP. No infrastructure.
3
+ A file that behaves like a private gem server.
4
4
 
5
- A `.gemv` file is a self-contained archive that contains Ruby gems. Commit it to your repo, drop it on S3, email it, put it on a USB drive Bundler and RubyGems read from it directly. Private gems without running a server.
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
- A `.gemv` file is a self-contained archive of gem metadata and raw `.gem` blobs. A current-format (tarball) vault has a `manifest.json` first entry followed by the `.gem` files, inspectable with standard tools:
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"]