gemvault 0.2.0 → 0.2.3

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.
data/issues.rec CHANGED
@@ -57,9 +57,9 @@ Description: Installing bundler-source-vault 0.1.2
57
57
  + from /Users/davidgillis/.rbenv/versions/4.0.1/lib/ruby/site_ruby/4.0.0/rubygems.rb:304:in 'Gem.activate_and_load_bin_path'
58
58
  + from /Users/davidgillis/.rbenv/versions/4.0.1/bin/bundle:25:in '<main>'
59
59
  + /Users/davidgillis/.rbenv/versions/4.0.1/lib/ruby/gems/4.0.0/gems/bundler-4.0.8/lib/bundler/source_list.rb:59:in 'Bundler::SourceList#add_plugin_source': undefined method 'new' for nil (NoMethodError)
60
- +
60
+ +
61
61
  + add_source_to_list Plugin.source(source).new(options), @plugin_sources
62
- +
62
+ +
63
63
  + RESOLUTION: replicated by spec/integration/bundle_install_spec.rb ("path-installed
64
64
  + bundler plugin's source directory has been renamed"): Bundler's plugin index pins
65
65
  + the absolute path, and `gemvault doctor` clears it and reinstalls. Installing the
@@ -86,7 +86,7 @@ Description: Steps to replicate:
86
86
  + ```
87
87
  +
88
88
  + Where vendored.gemv is the name of the old file, and there is still an entry in Gemfile.lock
89
- +
89
+ +
90
90
  + RESOLUTION: fixed on the tarvault branch; replicated by
91
91
  + spec/integration/bundle_install_spec.rb ("when the .gemv file is renamed and the
92
92
  + Gemfile updated to match"), passing.
@@ -101,7 +101,7 @@ Description: This vault is in vendor/vendored_gems.gmv, relative to the Gemfile
101
101
  + ```
102
102
  + Installing acme 1.0.1 from vault vendored_gems.gemv
103
103
  + ```
104
- +
104
+ +
105
105
  + RESOLUTION: fixed on the tarvault branch; replicated by
106
106
  + spec/integration/bundle_install_spec.rb ("logs the relative path as written"),
107
107
  + passing.
@@ -122,7 +122,7 @@ Description: Anytime I run bundle install, I always see:
122
122
  + ```
123
123
  +
124
124
  + This is unacceptable. these should only need to be installed once
125
- +
125
+ +
126
126
  + ANALYSIS: upstream Bundler behavior. Bundler::Plugin.gemfile_install runs on
127
127
  + every `bundle install`/`bundle update` (bundler cli/install.rb:41), re-resolves
128
128
  + the inferred plugin definition remotely, and Source::Rubygems#install checks
@@ -143,7 +143,7 @@ Description: Consider the following:
143
143
  + ```
144
144
  +
145
145
  + Notice an absolute path was passed to --source, yet it tried to resolve locally
146
- +
146
+ +
147
147
  + RESOLUTION: fixed on the tarvault branch; replicated by
148
148
  + spec/integration/gem_install_spec.rb ("accepts a vault:// URI with an absolute
149
149
  + path" and the file:// variant), passing. URI stripping now lives in
@@ -158,7 +158,7 @@ Description: When adding a gem like 'ronin-db-0.2.1.patch1.gem', gemvault succes
158
158
  + gemvault add myvault.gemv ronin-db-0.2.1.patch1.gem # success
159
159
  + gem install --debug --verbose --clear-sources --source file://myvault.gemv ronin-db # failure
160
160
  + ```
161
- +
161
+ +
162
162
  + RESOLUTION: RubyGems semantics, not a vault bug. A version containing letters
163
163
  + (0.2.1.patch1) is a prerelease everywhere in RubyGems, and `gem install`
164
164
  + excludes prereleases unless --pre is passed; with --pre the install from a
@@ -171,7 +171,7 @@ Id: 7
171
171
  Updated: Sun, 19 Jul 2026 03:27:39 +0000
172
172
  Name: Gemvault pollutes project dir with plugin files in .bundle
173
173
  Description: Why is it not using the plugin that is already installed globally?
174
- +
174
+ +
175
175
  + ANALYSIS: two parts. (1) Global `bundle plugin install bundler-source-vault`
176
176
  + crashed outright (issue #10's bug also hit the global root); that is fixed and
177
177
  + covered by spec/integration/plugin_install_spec.rb ("when run outside any
@@ -192,7 +192,7 @@ Description: Consider the following:
192
192
  + ```
193
193
  +
194
194
  + Notice an absolute path was passed to --source, yet it tried to resolve locally
195
- +
195
+ +
196
196
  + RESOLUTION: duplicate of #5; see its resolution.
197
197
  Status: closed
198
198
 
@@ -200,7 +200,7 @@ Id: 9
200
200
  Updated: Sun, 19 Jul 2026 03:27:39 +0000
201
201
  Name: Gemvault commands should also be able to accept a uri
202
202
  Description: e.g. gemvault list vault:///Users/davidgillis/repos/vault/rubylib/myvault.gemv
203
- +
203
+ +
204
204
  + RESOLUTION: implemented. Gemvault::VaultPath resolves vault:// and file://
205
205
  + locators (absolute and two-slash relative forms) and every CLI command that
206
206
  + opens a vault goes through it, as does the RubyGems source. Covered by
@@ -617,7 +617,7 @@ Description:
617
617
  + https://github.com/ruby/rubygems/search?q=cannot+load+such+file+--+bundler%2Fplugin%2Fvault_source&type=Issues
618
618
  +
619
619
  + If there aren't any reports for this error yet, please fill in the new issue form located at https://github.com/ruby/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md. Make sure to copy and paste the full output of this command under the "What happened instead?" section.
620
- +
620
+ +
621
621
  + RESOLUTION: two root causes, both fixed. (1) `bundle plugin install` switches
622
622
  + GEM_HOME to the plugin root mid-process, and RubyGems' spec stub cache is
623
623
  + populated during resolution, before gemvault is installed there; the shim's
@@ -637,14 +637,14 @@ Id: 11
637
637
  Updated: Sun, 19 Jul 2026 03:56:57 +0000
638
638
  Name: CI tests aren't running
639
639
  Description: CI tests should be running on all platforms
640
- +
640
+ +
641
641
  + ANALYSIS: .github/workflows/ci.yml exists (unit tests, specs, rubocop on
642
642
  + push/PR to master). Two likely reasons it cannot go green: (1) `rake rubocop`
643
643
  + exits nonzero on the pre-existing Gemspec/RequiredRubyVersion offenses
644
644
  + (required_ruby_version ">= 3.4.8" vs TargetRubyVersion 4.0 in .rubocop.yml) --
645
645
  + pick one and align; (2) `rake spec` builds/uses a podman image, so the runner
646
646
  + needs podman available. Not replicable as a podman rspec spec (CI infra).
647
- +
647
+ +
648
648
  + RESOLUTION: three blockers fixed. (1) TargetRubyVersion aligned to 3.4.8, the
649
649
  + gemspec floor, clearing the Gemspec/RequiredRubyVersion offenses; whole
650
650
  + tracked tree is rubocop-clean. (2) The integration job invoked
@@ -663,14 +663,14 @@ Updated: Sun, 19 Jul 2026 03:27:39 +0000
663
663
  Name: bundle exec fails after successful bundle install with path vendor
664
664
  Description: Reported 2026-07-19 (reversal-store): bundle install succeeds, then
665
665
  + any `bundle exec` fails while parsing the Gemfile:
666
- +
666
+ +
667
667
  + ```
668
668
  + [!] There was an error parsing `Gemfile`: Could not find 'bundler' (>= 2.0)
669
669
  + among 101 total gem(s)
670
670
  + Checked in 'GEM_PATH=/workspace/vendor/ruby/4.0.0' at:
671
671
  + /workspace/.bundle/plugin/specifications/gemvault-0.1.5.gemspec
672
672
  + ```
673
- +
673
+ +
674
674
  + RESOLUTION: gemvault declared bundler as a runtime dependency. Under
675
675
  + `bundle exec` with path vendor, GEM_PATH is restricted to the app bundle, and
676
676
  + on rubies where bundler is a regular (non-default) gem its spec is invisible,
@@ -681,3 +681,339 @@ Description: Reported 2026-07-19 (reversal-store): bundle install succeeds, then
681
681
  + reinstalling bundler as a regular gem and deleting its default-gem spec stub;
682
682
  + also covers the system-installed (`gem install gemvault`) flow. Both passing.
683
683
  Status: closed
684
+
685
+ Id: 13
686
+ Updated: Sun, 26 Jul 2026 20:33:33 -0400
687
+ Name: bundle install fails, nothing seems to fix it
688
+ Description: bundle install does not complete successfully (ruby 4.0.1 &jruby 10.1.0.0). Tried doing all of these:
689
+ + 1. gemvault doctor (below, completes successfully, but another bundle install fails)
690
+ + 2. rm -rf .bundle/plugin && bundle install
691
+ + 3. rm -f Gemfile.lock && bundle install
692
+ + 4. 2 & 3 combined before bundle install
693
+ +
694
+ + ```
695
+ + jruby -S gemvault doctor
696
+ + Uninstalled plugin bundler-source-vault
697
+ + Fetching gem metadata from https://rubygems.org/.......
698
+ + Resolving dependencies...
699
+ + Installing bundler-source-vault 0.2.0
700
+ + Installed plugin bundler-source-vault
701
+ + Bundle complete! 15 Gemfile dependencies, 50 gems now installed.
702
+ + Bundled gems are installed into `./vendor`
703
+ + ❯ bundle install
704
+ + Fetching gem metadata from https://rubygems.org/.......
705
+ + Resolving dependencies...
706
+ + Installing bundler-source-vault 0.2.0
707
+ +
708
+ + [!] There was an error parsing `Gemfile`: cannot load such file -- bundler/plugin/vault_source. Bundler cannot continue.
709
+ +
710
+ + # from /Users/davidgillis/repos/reversal-store/Gemfile:19
711
+ + # -------------------------------------------
712
+ + #
713
+ + > source "vendor/vendored.gemv", type: :vault do
714
+ + # gem 'jarpack', "~> 0.2.1"
715
+ + # -------------------------------------------
716
+ + ```
717
+ +
718
+ + RESOLUTION: the plugin root never held gemvault, and the shim's require had no
719
+ + way to reach the copy that did exist. Bundler's Source::Rubygems#install
720
+ + short-circuits on `installed?(spec) && !force`, so a plugin dependency already
721
+ + present on the ambient GEM_PATH is never downloaded into the plugin root --
722
+ + which is every machine where `gem install gemvault` has run. That stays hidden
723
+ + until the app bundle is populated: from the second `bundle install` onward
724
+ + Bundler restricts GEM_PATH to the bundle, the ambient gemvault falls out of
725
+ + scope, and nothing is left to resolve. Hence the reported permanence: step 2-4
726
+ + all rebuild the same incomplete plugin root. shim/plugins.rb now locates
727
+ + gemvault's lib across every root that can hold it, including the ones Bundler
728
+ + masked (Bundler.original_env GEM_HOME/GEM_PATH), and puts it on $LOAD_PATH
729
+ + instead of relying on gem activation. Using $LOAD_PATH also fixes a second
730
+ + failure found while reproducing this -- `Could not find 'command_kit' (~> 0.6)`
731
+ + when gemvault does land in the plugin root -- because activation demands the
732
+ + full runtime dependency set while vault_source.rb reaches the rest of gemvault
733
+ + through require_relative alone.
734
+ +
735
+ + The integration suite could not have caught this. Dockerfile.test installed
736
+ + gemvault AND bundler-source-vault system-wide, so `require
737
+ + "bundler/plugin/vault_source"` resolved from the ambient GEM_HOME no matter
738
+ + what the plugin root contained, and the ruby base image's
739
+ + BUNDLE_APP_CONFIG=/usr/local/bundle moved Bundler::Plugin.root out of the
740
+ + project so no spec ever exercised a project-local .bundle/plugin. The shim is
741
+ + no longer installed system-wide (specs resolve it from the local gem index),
742
+ + BUNDLE_APP_CONFIG is unset in the container, and gemvault stays installed
743
+ + system-wide on purpose because that is the trigger. Removing the mask turned 13
744
+ + previously green specs red; all now pass against the tree's shim rather than an
745
+ + ambient copy. Replicated by spec/integration/plugin_root_deps_spec.rb (repeated
746
+ + bundle install, and bundle exec under a restricted GEM_PATH).
747
+ Status: closed
748
+
749
+ Id: 14
750
+ Updated: Wed, 29 Jul 2026 16:41:11 -0400
751
+ Name: gemvault doctor fails when bundler/inline is used
752
+ Description: Loudly fails with 2 errors, one of which is "can't find gemfile"
753
+ Status: open
754
+
755
+ Id: 15
756
+ Updated: Wed, 29 Jul 2026 17:39:23 -0400
757
+ Name: gemvault new fails on path/to/gemvault.gemv
758
+ Description: I did it in /tmp, maybe that's why?
759
+ +
760
+ + RESOLUTION: /tmp was a red herring -- the trigger is the missing parent
761
+ + directory. `gemvault new path/to/gemvault.gemv` reached Tempfile.create with a
762
+ + nonexistent dirname and died with a raw Errno::ENOENT and a 25-line Ruby
763
+ + backtrace; with path/to already present the same command always worked.
764
+ +
765
+ + A vault is one file, so `gemvault new vendor/vendored.gemv` in a tree that has
766
+ + no vendor yet reads as an ordinary request rather than a mistake: the missing
767
+ + directories are now created, and the shallowest one created is reported
768
+ + ("Created directory vendor") so nothing appears out of nowhere. What cannot be
769
+ + papered over is raised as VaultDestination::Error and printed as one line with
770
+ + exit 1 -- a parent that is a file, or one that cannot be created (EACCES).
771
+ + SystemCallError from the vault write itself is caught the same way, so no path
772
+ + through `gemvault new` ends in a backtrace.
773
+ +
774
+ + Gemvault::VaultDestination owns the .gemv suffix defaulting, the occupied-path
775
+ + check and the parent creation; the command stays thin. Replicated first by
776
+ + spec/integration/cli/commands/new_spec.rb (real subprocess, real vault, real
777
+ + exit code -- 5 of its 9 examples failed against the old code, including one
778
+ + asserting the absence of Errno::ENOENT), with unit cover in
779
+ + spec/gemvault/vault_destination_spec.rb and spec/gemvault/cli/commands/new_spec.rb.
780
+ Status: closed
781
+
782
+ Id: 16
783
+ Updated: Wed, 29 Jul 2026 18:25:48 -0400
784
+ Name: Add jruby-ci workflow
785
+ Description: It should be already set up on the jruby-support branch. It just needs to be picked from it. DO NOT use the other code in that - it is very outdated
786
+ Status: open
787
+
788
+ Id: 17
789
+ Updated: Thu, 30 Jul 2026 00:07:42 +0000
790
+ Name: Integration CI job reddens on transient podman/crun failures
791
+ Description: Both `integration` jobs failed on master (run 30496142063) and on PR #17 with:
792
+ +
793
+ + ```
794
+ + error running container: from /usr/bin/crun creating container for
795
+ + [/bin/sh -c dnf -y install ...]: unknown version specified
796
+ + ```
797
+ +
798
+ + Nothing had changed between the last green run and the first red one: same runner
799
+ + image 20260720.247.2, same pre-installed podman, same fedora:44 blob and config
800
+ + digests, same SOURCE_DIGEST build arg, and the only commit in between touched
801
+ + issues.rec text. Rerunning the identical commit went green.
802
+ +
803
+ + `rake spec:build` had no retry, so one momentary container-runtime failure reddens
804
+ + the whole run -- and because the matrix cancels the sibling leg, a flake reads as a
805
+ + real break in the suite CLAUDE.md calls the first line of defense for CLI bugs.
806
+ +
807
+ + RESOLUTION: the image lifecycle moved out of the Rakefile into ContainerImage
808
+ + (spec/support/container_image.rb), which retries a failed build ATTEMPTS (3) times
809
+ + and announces each retry. Nothing in the exit status separates a transient runtime
810
+ + failure from a real Dockerfile error, so every failure is retried; a genuinely broken
811
+ + Dockerfile still fails, just after 3 tries, and fails fast because it never reaches
812
+ + the network. Commands run through an injected Shell so the retry behaviour is
813
+ + specified without podman (spec/container_image_spec.rb, spec/shell_spec.rb), and the
814
+ + loop was also confirmed against real podman with a Dockerfile that exits nonzero.
815
+ +
816
+ + RESOLUTION: the `jruby` job is picked into .github/workflows/ci.yml; none of the
817
+ + branch's Sequel/jdbc-sqlite3 code came with it. Master needs none of it -- the
818
+ + tarball format uses only rubygems' own tar tooling, so gemvault already runs on
819
+ + JRuby. Three of the branch job's details did not survive the pick: JAVA_OPTS
820
+ + --enable-native-access existed to silence a jdbc-sqlite3 warning under Java 25
821
+ + (no JDBC driver here, and the job pins Java 21), BUNDLE_FROZEN existed for a
822
+ + committed MRI-resolved lock (Gemfile.lock is gitignored on master), and the
823
+ + branch's matrix/podman edits to the MRI jobs are the outdated part.
824
+ +
825
+ + Two things the branch job would have hit on master, both found by running it:
826
+ + (1) `bundle install` died on the sqlite3 C extension, which cannot build on the
827
+ + JVM. sqlite3 is a dev-only dependency for the legacy Dbvault read path, so the
828
+ + Gemfile now scopes it `platform: %i[ruby windows]`; nothing under test/ touches
829
+ + sqlite3, which is why the job runs `rake test` only and leaves the sqlite3-backed
830
+ + specs to the MRI jobs. (2) `bundle install` then exhausted JRuby's default 500MB
831
+ + heap during resolution -- inherent to the Gemfile, not to sqlite3 -- so the job
832
+ + sets JRUBY_OPTS=-J-Xmx2048m, the remedy JRuby's own error message prescribes.
833
+ +
834
+ + Verified locally against JRuby 10.1.0.0 on Java 25 (installed for this; the box
835
+ + had none, and no install-jruby script existed -- one is now at
836
+ + ~/.local/bin/install-jruby): bundle install clean with sqlite3 absent, rake test
837
+ + 113 tests / 231 assertions / 0 failures. MRI unaffected: sqlite3 still resolves,
838
+ + rake test 113/0, spec:core 130 examples/0 failures, rubocop 111 files clean.
839
+ Status: closed
840
+
841
+ Id: 18
842
+ Updated: Thu, 30 Jul 2026 01:06:09 +0000
843
+ Name: Integration CI broken by runner image podman 5 / crun 1.14 mismatch
844
+ Description: Every `integration` job fails at the Dockerfile's dnf layer with:
845
+ +
846
+ + ```
847
+ + error running container: from /usr/bin/crun creating container for
848
+ + [/bin/sh -c dnf -y install ...]: unknown version specified
849
+ + ```
850
+ +
851
+ + This looked like issue #17's flake and is not. Correlating the runner image
852
+ + against the outcome settles it:
853
+ +
854
+ + | runner image | podman | outcome |
855
+ + |---------------------|--------|-------------|
856
+ + | 20260720.247 (old) | 4.9.3 | pass |
857
+ + | 20260726.254 (new) | 5.8.4 | crun error |
858
+ +
859
+ + Every genuine failure is on 20260726.254; every job on 20260720.247 either passed
860
+ + or was cancelled by fail-fast (which is what made two of them look like failures).
861
+ + GitHub rolls the image out gradually, so jobs land on either one -- hence reruns
862
+ + sometimes helping and sometimes not, and hence integration CI going permanently
863
+ + red as the rollout completes.
864
+ +
865
+ + The new image bumped podman 4.9.3 -> 5.8.4 and left Ubuntu 24.04's crun 1.14 in
866
+ + place. podman 5 writes an OCI config declaring ociVersion 1.2.0; crun 1.14
867
+ + rejects any version not prefixed "1.0" with exactly "unknown version
868
+ + specified". A dev box running podman 5.8.4 with crun 1.28 builds and runs the
869
+ + same image fine, which is the control.
870
+ +
871
+ + Nothing about this is intermittent, so #17's retry cannot help: three attempts
872
+ + on the same runner fail three times.
873
+ +
874
+ + RESOLUTION: the integration job installs a pinned crun 1.28 (newer than any
875
+ + noble package) and names it in GEMVAULT_PODMAN_RUNTIME; Podman.command inserts
876
+ + `--runtime` ahead of the subcommand when that variable is set, so both
877
+ + ContainerImage's build and ContainerHelper's container runs go through it. Unset
878
+ + -- every dev machine, and any runner whose podman and crun agree -- podman
879
+ + chooses as before. The job also prints podman, crun and the chosen runtime, so
880
+ + the next mismatch names itself instead of being mistaken for a flake, and
881
+ + fail-fast is off because one leg cancelling the other hid which had broken.
882
+ +
883
+ + Verified locally both ways: with the variable set to a downloaded crun 1.28,
884
+ + spec:build plus 135 integration examples pass; with it unset, the same. A
885
+ + config-file override (`[engine.runtimes]`) was tried first and did not take --
886
+ + podman kept /usr/bin/crun -- which is why this uses the explicit flag.
887
+ Status: closed
888
+
889
+ Id: 19
890
+ Updated: Fri, 31 Jul 2026 09:18:45 -0400
891
+ Name: Deps in Dockerfile.test are not dynamically inferred
892
+ Description: Bundler version, command kit version, and all other deps that are being installed need to be inferred from this project via bundler info, and should be passed in as ENV variables. Hardcoding is not acceptable
893
+ Status: open
894
+
895
+ Id: 20
896
+ Updated: Fri, 31 Jul 2026 13:42:28 -0400
897
+ Name: Received the following error during bundle install:
898
+ Description: [dev@rstore]/workspace% bundle install
899
+ + Bundler 4.0.14 is running, but your lockfile was generated with 4.0.17. Installing Bundler 4.0.17 and restarting using that version.
900
+ + Source locally installed gems is ignoring #<Bundler::StubSpecification name=io-event version=1.19.4 platform=ruby> because it is missing extensions
901
+ + Fetching gem metadata from https://rubygems.org/.
902
+ + Source rubygems repository https://rubygems.org/ is ignoring #<Bundler::StubSpecification name=io-event version=1.19.4 platform=ruby> because it is missing extensions
903
+ + Installing bundler 4.0.17
904
+ + Ignoring io-event-1.19.4 because its extensions are not built. Try: gem pristine io-event --version 1.19.4
905
+ + Fetching gem metadata from https://rubygems.org/.......
906
+ + Source rubygems repository https://rubygems.org/, cached gems or installed locally is ignoring #<Bundler::StubSpecification name=io-event version=1.19.4 platform=ruby> because it is missing extensions
907
+ + Resolving dependencies...
908
+ + Fetching json 2.21.2
909
+ + Installing json 2.21.2 with native extensions
910
+ + Fetching gemvault 0.2.2
911
+ + Installing gemvault 0.2.2
912
+ + Fetching bundler-source-vault 0.2.2
913
+ + Installing bundler-source-vault 0.2.2
914
+ + The following plugin paths don't exist: /Users/davidgillis/.rbenv/versions/4.0.1/lib/ruby/gems/4.0.0/gems/bundler-source-vault-0.2.1/..
915
+ +
916
+ + This can happen if the plugin was installed with a different version of Ruby that has since been uninstalled.
917
+ +
918
+ + If you would like to reinstall the plugin, run:
919
+ +
920
+ + bundler plugin uninstall bundler-source-vault && bundler plugin install bundler-source-vault
921
+ +
922
+ + Continuing without installing plugin bundler-source-vault.
923
+ + /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/source_list.rb:59:in 'Bundler::SourceList#add_plugin_source': undefined method 'new' for nil (NoMethodError)
924
+ +
925
+ + add_source_to_list Plugin.source(source).new(options), @plugin_sources
926
+ + ^^^^
927
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:135:in 'Bundler::Dsl#source'
928
+ + from /workspace/Gemfile:20:in 'block in Bundler::Dsl#eval_gemfile'
929
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:49:in 'BasicObject#instance_eval'
930
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:49:in 'block in Bundler::Dsl#eval_gemfile'
931
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:330:in 'Bundler::Dsl#with_gemfile'
932
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:47:in 'Bundler::Dsl#eval_gemfile'
933
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:13:in 'Bundler::Dsl.evaluate'
934
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/definition.rb:40:in 'Bundler::Definition.build'
935
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler.rb:235:in 'Bundler.definition'
936
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/env.rb:36:in 'Bundler::Env.report'
937
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/friendly_errors.rb:71:in 'Bundler::FriendlyErrors.request_issue_report_for'
938
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/friendly_errors.rb:50:in 'Bundler::FriendlyErrors.log_error'
939
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/friendly_errors.rb:124:in 'Bundler.with_friendly_errors'
940
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/exe/bundle:20:in '<top (required)>'
941
+ + from /usr/local/share/ruby/site_ruby/rubygems.rb:305:in 'Kernel#load'
942
+ + from /usr/local/share/ruby/site_ruby/rubygems.rb:305:in 'Gem.activate_and_load_bin_path'
943
+ + from /usr/local/bin/bundle:25:in '<main>'
944
+ + /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/source_list.rb:59:in 'Bundler::SourceList#add_plugin_source': undefined method 'new' for nil (NoMethodError)
945
+ +
946
+ + add_source_to_list Plugin.source(source).new(options), @plugin_sources
947
+ + ^^^^
948
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:135:in 'Bundler::Dsl#source'
949
+ + from /workspace/Gemfile:20:in 'block in Bundler::Dsl#eval_gemfile'
950
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:49:in 'BasicObject#instance_eval'
951
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:49:in 'block in Bundler::Dsl#eval_gemfile'
952
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:330:in 'Bundler::Dsl#with_gemfile'
953
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:47:in 'Bundler::Dsl#eval_gemfile'
954
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/dsl.rb:13:in 'Bundler::Dsl.evaluate'
955
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/definition.rb:40:in 'Bundler::Definition.build'
956
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler.rb:235:in 'Bundler.definition'
957
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/cli/install.rb:45:in 'Bundler::CLI::Install#run'
958
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/cli.rb:296:in 'block in Bundler::CLI#install'
959
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/settings.rb:145:in 'Bundler::Settings#temporary'
960
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/cli.rb:295:in 'Bundler::CLI#install'
961
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/vendor/thor/lib/thor/command.rb:28:in 'Bundler::Thor::Command#run'
962
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in 'Bundler::Thor::Invocation#invoke_command'
963
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/vendor/thor/lib/thor.rb:538:in 'Bundler::Thor.dispatch'
964
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/cli.rb:35:in 'Bundler::CLI.dispatch'
965
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/vendor/thor/lib/thor/base.rb:584:in 'Bundler::Thor::Base::ClassMethods#start'
966
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/cli.rb:29:in 'Bundler::CLI.start'
967
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/exe/bundle:28:in 'block in <top (required)>'
968
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/lib/bundler/friendly_errors.rb:118:in 'Bundler.with_friendly_errors'
969
+ + from /workspace/vendor/ruby/4.0.0/gems/bundler-4.0.17/exe/bundle:20:in '<top (required)>'
970
+ + from /usr/local/share/ruby/site_ruby/rubygems.rb:305:in 'Kernel#load'
971
+ + from /usr/local/share/ruby/site_ruby/rubygems.rb:305:in 'Gem.activate_and_load_bin_path'
972
+ + from /usr/local/bin/bundle:25:in '<main>'
973
+ +
974
+ + Though I will add that gemvault doctor followed by bundle install fixed the issue
975
+ Status: open
976
+
977
+ Id: 21
978
+ Updated: Fri, 31 Jul 2026 13:54:09 -0400
979
+ Name: bundle info fails when gem is in vault
980
+ Description: bundle info jarpack
981
+ + Source locally installed gems is ignoring #<Bundler::StubSpecification name=json version=2.21.2 platform=ruby> because it is missing extensions
982
+ + Could not find gem 'jarpack'.
983
+ + Did you mean 'jarpack'?
984
+ +
985
+ +
986
+ + bundle info jarpack
987
+ Status: open
988
+
989
+ Id: 22
990
+ Updated: Mon, 10 Aug 2026 10:03:35 -0400
991
+ Name: Add github actions disclaimer/instructions
992
+ Description: bundler-cache: true on the ruby/setup-ruby action will not work correctly:
993
+ +
994
+ + - uses: ruby/setup-ruby@v1
995
+ + with:
996
+ + ruby-version: ${{ matrix.ruby }}
997
+ + # bundler-cache runs `bundle lock`, which cannot parse the vault source until
998
+ + # `bundle install` has fetched its plugin; install and cache manually instead.
999
+ + bundler-cache: false
1000
+ + - name: Cache gems
1001
+ + uses: actions/cache@v6
1002
+ + with:
1003
+ + path: |
1004
+ + vendor/bundle
1005
+ + .bundle/plugin
1006
+ + key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ hashFiles('Gemfile', '*.gemspec', 'vendor/vendored.gemv') }}
1007
+ + restore-keys: |
1008
+ + ${{ runner.os }}-gems-${{ matrix.ruby }}-
1009
+ +
1010
+ + - name: Install gems
1011
+ + run: | # confine gems to vendor/bundle so the cache never shadows vendor/vendored.gemv
1012
+ + bundle config set --local path vendor/bundle
1013
+ + bundle install --jobs 4 --retry 3
1014
+ Updated: Mon, 10 Aug 2026 10:14:51 -0400
1015
+ Name: Gemvault spams warnings on bundle install
1016
+ Description: /workspace/.bundle/plugin/gems/bundler-source-vault-0.2.2/gemvault_load_path.rb:31: warning: already initialized constant BundlerSourceVault::GemvaultLoadPath::GEM
1017
+ + /workspace/.bundle/plugin/gems/bundler-source-vault-0.2.2/gemvault_load_path.rb:32: warning: already initialized constant BundlerSourceVault::GemvaultLoadPath::SHIM
1018
+ + /workspace/.bundle/plugin/gems/bundler-source-vault-0.2.2/gemvault_load_path.rb:33: warning: already initialized constant BundlerSourceVault::GemvaultLoadPath::VAULT_SOURCE
1019
+ Status: open
@@ -1,5 +1,6 @@
1
- require "pathname"
2
1
  require_relative "../command"
2
+ require_relative "../destination"
3
+ require_relative "../../vault_destination"
3
4
 
4
5
  module Gemvault
5
6
  class CLI
@@ -13,16 +14,23 @@ module Gemvault
13
14
  desc: "Vault name (auto-appends .gemv)"
14
15
 
15
16
  def run(name)
16
- path = Pathname(name.end_with?(".gemv") ? name : "#{name}.gemv")
17
-
18
- if path.exist?
19
- print_error("#{path} already exists")
17
+ begin
18
+ destination = build_destination(name)
19
+ destination.refuse_existing
20
+ destination.create_parents
21
+ Vault.create(destination.path)
22
+ puts "Created #{destination.path}"
23
+ rescue VaultDestination::Error, Vault::Error, SystemCallError => e
24
+ print_error(e.message)
20
25
  exit(1)
21
26
  end
27
+ end
28
+
29
+ private
22
30
 
23
- vault = Vault.new(path, create: true)
24
- vault.close
25
- puts "Created #{path}"
31
+ def build_destination(name)
32
+ vault_destination = VaultDestination.new(name)
33
+ Destination.new(vault_destination, stdout:)
26
34
  end
27
35
  end
28
36
  end
@@ -0,0 +1,29 @@
1
+ require "forwardable"
2
+
3
+ module Gemvault
4
+ class CLI
5
+ ##
6
+ # A VaultDestination as the CLI presents it: the same operations, with the
7
+ # directories they grow narrated on +stdout+ so nothing appears on disk
8
+ # unannounced. What the destination refuses still surfaces as
9
+ # <tt>VaultDestination::Error</tt> for the command to report.
10
+ class Destination
11
+ extend Forwardable
12
+
13
+ def_delegators :@destination, :path, :refuse_existing
14
+
15
+ def initialize(destination, stdout:)
16
+ @destination = destination
17
+ @stdout = stdout
18
+ end
19
+
20
+ # Creates the destination's missing parent directories, reporting the
21
+ # shallowest one created so the user learns where the tree grew.
22
+ def create_parents
23
+ missing = @destination.missing_directory
24
+ @destination.create_parents
25
+ @stdout.puts "Created directory #{missing}" if missing
26
+ end
27
+ end
28
+ end
29
+ end
@@ -30,6 +30,11 @@ module Gemvault
30
30
  :spec_from_blob, :with_gem_file, :size, :close, :closed?,
31
31
  :path, :format_version
32
32
 
33
+ # Creates an empty vault file at +path+, leaving it closed.
34
+ def self.create(path)
35
+ new(path, create: true).close
36
+ end
37
+
33
38
  def self.assert_readable!(version:, path:)
34
39
  return if version.between?(MIN_READABLE_FORMAT, CURRENT_FORMAT)
35
40
 
@@ -0,0 +1,70 @@
1
+ require "pathname"
2
+
3
+ module Gemvault
4
+ ##
5
+ # Where a new vault is about to be written: the <tt>.gemv</tt> path itself,
6
+ # and the directories that have to exist before anything can be written to it.
7
+ #
8
+ # A vault is one file, so <tt>gemvault new vendor/vendored.gemv</tt> in a tree
9
+ # that has no <tt>vendor</tt> yet reads as an ordinary request rather than a
10
+ # mistake, and the missing directories are created. What cannot be papered
11
+ # over -- something already occupying the path, a parent that is a file, a
12
+ # parent that cannot be created -- is raised as Error, so the CLI reports one
13
+ # line instead of a Ruby backtrace.
14
+ class VaultDestination
15
+ SUFFIX = ".gemv".freeze
16
+
17
+ ##
18
+ # Raised when the path cannot hold a new vault.
19
+ class Error < StandardError; end
20
+
21
+ # The vault's path, with SUFFIX appended if the name lacked it.
22
+ attr_reader :path
23
+
24
+ def initialize(name)
25
+ locator = suffixed(name.to_s)
26
+ @path = Pathname(locator)
27
+ end
28
+
29
+ # Raises Error when something already occupies the vault's path.
30
+ def refuse_existing
31
+ raise Error, "#{@path} already exists" if @path.exist?
32
+ end
33
+
34
+ # :call-seq:
35
+ # missing_directory -> Pathname or nil
36
+ #
37
+ # The shallowest directory create_parents would have to make -- creating it
38
+ # brings every deeper one with it -- or +nil+ when the parent already
39
+ # exists.
40
+ def missing_directory
41
+ @path.dirname.ascend.reject(&:exist?).last
42
+ end
43
+
44
+ # Creates the vault's missing parent directories.
45
+ def create_parents
46
+ parent = @path.dirname
47
+ return if parent.directory?
48
+
49
+ raise Error, "#{parent} is not a directory" if parent.exist?
50
+
51
+ make(parent)
52
+ end
53
+
54
+ private
55
+
56
+ def suffixed(locator)
57
+ return locator if locator.end_with?(SUFFIX)
58
+
59
+ "#{locator}#{SUFFIX}"
60
+ end
61
+
62
+ def make(parent)
63
+ begin
64
+ parent.mkpath
65
+ rescue SystemCallError => e
66
+ raise Error, "cannot create directory #{parent}: #{e.message}"
67
+ end
68
+ end
69
+ end
70
+ end
@@ -1,3 +1,3 @@
1
1
  module Gemvault
2
- VERSION = "0.2.0".freeze
2
+ VERSION = "0.2.3".freeze
3
3
  end