mnenv 0.1.0 → 0.1.1
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/Gemfile +3 -0
- data/PROPOSAL.md +197 -0
- data/README.adoc +168 -461
- data/Rakefile +7 -4
- data/bin/Install-Mnenv.ps1 +145 -0
- data/bin/mnenv-installer +72 -0
- data/completions/bash +47 -0
- data/completions/fish +29 -0
- data/completions/powershell.ps1 +94 -0
- data/completions/zsh +43 -0
- data/lib/mnenv/binary_repository.rb +189 -0
- data/lib/mnenv/chocolatey.rb +7 -0
- data/lib/mnenv/cli.rb +110 -10
- data/lib/mnenv/commands/available_command.rb +169 -0
- data/lib/mnenv/commands/chocolatey_command.rb +4 -5
- data/lib/mnenv/commands/gemfile_command.rb +4 -5
- data/lib/mnenv/commands/homebrew_command.rb +4 -5
- data/lib/mnenv/commands/install_command.rb +234 -0
- data/lib/mnenv/commands/snap_command.rb +5 -7
- data/lib/mnenv/commands/uninstall_command.rb +42 -0
- data/lib/mnenv/commands/version_command.rb +213 -0
- data/lib/mnenv/commands.rb +9 -4
- data/lib/mnenv/gemfile/extractor.rb +10 -3
- data/lib/mnenv/gemfile.rb +8 -0
- data/lib/mnenv/gemfile_repository.rb +0 -2
- data/lib/mnenv/homebrew.rb +7 -0
- data/lib/mnenv/installer/base.rb +62 -0
- data/lib/mnenv/installer/factory.rb +17 -0
- data/lib/mnenv/installer.rb +12 -0
- data/lib/mnenv/installers/binary_installer.rb +242 -0
- data/lib/mnenv/installers/gemfile_installer.rb +76 -0
- data/lib/mnenv/json_formatter.rb +3 -13
- data/lib/mnenv/logger.rb +9 -1
- data/lib/mnenv/models/binary_version.rb +78 -0
- data/lib/mnenv/models/chocolatey_version.rb +7 -0
- data/lib/mnenv/models/gemfile_version.rb +19 -5
- data/lib/mnenv/models/homebrew_version.rb +7 -0
- data/lib/mnenv/models/snap_version.rb +8 -0
- data/lib/mnenv/models/version.rb +16 -0
- data/lib/mnenv/models.rb +7 -5
- data/lib/mnenv/paths.rb +69 -0
- data/lib/mnenv/repository.rb +50 -35
- data/lib/mnenv/resolver +72 -0
- data/lib/mnenv/shells/base.rb +32 -0
- data/lib/mnenv/shells/bash.rb +72 -0
- data/lib/mnenv/shells/cmd.rb +108 -0
- data/lib/mnenv/shells/factory.rb +82 -0
- data/lib/mnenv/shells/power_shell.rb +110 -0
- data/lib/mnenv/shim_manager.rb +121 -0
- data/lib/mnenv/snap.rb +7 -0
- data/lib/mnenv/snap_repository.rb +2 -19
- data/lib/mnenv/source_registry.rb +69 -0
- data/lib/mnenv/version.rb +1 -1
- data/lib/mnenv/versions_manager.rb +92 -0
- data/lib/mnenv.rb +3 -0
- data/mnenv.gemspec +4 -1
- data/scripts/cross-source-switching-test.sh +214 -0
- data/scripts/integration-test.sh +89 -0
- data/scripts/version-switching-test.sh +151 -0
- metadata +82 -247
- data/data/chocolatey/versions.yaml +0 -812
- data/data/gemfile/v1.1.6/Gemfile +0 -4
- data/data/gemfile/v1.1.6/Gemfile.lock.archived +0 -232
- data/data/gemfile/v1.1.7/Gemfile +0 -4
- data/data/gemfile/v1.1.7/Gemfile.lock.archived +0 -235
- data/data/gemfile/v1.1.8/Gemfile +0 -4
- data/data/gemfile/v1.1.8/Gemfile.lock.archived +0 -238
- data/data/gemfile/v1.10.0/Gemfile +0 -5
- data/data/gemfile/v1.10.0/Gemfile.lock.archived +0 -930
- data/data/gemfile/v1.10.1/Gemfile +0 -5
- data/data/gemfile/v1.10.1/Gemfile.lock.archived +0 -929
- data/data/gemfile/v1.10.10/Gemfile +0 -5
- data/data/gemfile/v1.10.10/Gemfile.lock.archived +0 -973
- data/data/gemfile/v1.10.11/Gemfile +0 -5
- data/data/gemfile/v1.10.11/Gemfile.lock.archived +0 -975
- data/data/gemfile/v1.10.2/Gemfile +0 -5
- data/data/gemfile/v1.10.2/Gemfile.lock.archived +0 -939
- data/data/gemfile/v1.10.3/Gemfile +0 -5
- data/data/gemfile/v1.10.3/Gemfile.lock.archived +0 -946
- data/data/gemfile/v1.10.5/Gemfile +0 -5
- data/data/gemfile/v1.10.5/Gemfile.lock.archived +0 -958
- data/data/gemfile/v1.10.6/Gemfile +0 -5
- data/data/gemfile/v1.10.6/Gemfile.lock.archived +0 -969
- data/data/gemfile/v1.10.7/Gemfile +0 -5
- data/data/gemfile/v1.10.7/Gemfile.lock.archived +0 -969
- data/data/gemfile/v1.10.8/Gemfile +0 -5
- data/data/gemfile/v1.10.8/Gemfile.lock.archived +0 -968
- data/data/gemfile/v1.10.9/Gemfile +0 -5
- data/data/gemfile/v1.10.9/Gemfile.lock.archived +0 -972
- data/data/gemfile/v1.11.0/Gemfile +0 -5
- data/data/gemfile/v1.11.0/Gemfile.lock.archived +0 -971
- data/data/gemfile/v1.11.1/Gemfile +0 -5
- data/data/gemfile/v1.11.1/Gemfile.lock.archived +0 -975
- data/data/gemfile/v1.11.4/Gemfile +0 -5
- data/data/gemfile/v1.11.4/Gemfile.lock.archived +0 -1046
- data/data/gemfile/v1.11.5/Gemfile +0 -5
- data/data/gemfile/v1.11.5/Gemfile.lock.archived +0 -1047
- data/data/gemfile/v1.12.10/Gemfile +0 -3
- data/data/gemfile/v1.12.10/Gemfile.lock.archived +0 -1073
- data/data/gemfile/v1.12.3/Gemfile +0 -3
- data/data/gemfile/v1.12.3/Gemfile.lock.archived +0 -1050
- data/data/gemfile/v1.12.4/Gemfile +0 -3
- data/data/gemfile/v1.12.4/Gemfile.lock.archived +0 -1056
- data/data/gemfile/v1.12.5/Gemfile +0 -3
- data/data/gemfile/v1.12.5/Gemfile.lock.archived +0 -1054
- data/data/gemfile/v1.12.6/Gemfile +0 -3
- data/data/gemfile/v1.12.6/Gemfile.lock.archived +0 -1056
- data/data/gemfile/v1.12.8/Gemfile +0 -3
- data/data/gemfile/v1.12.8/Gemfile.lock.archived +0 -1063
- data/data/gemfile/v1.13.0/Gemfile +0 -3
- data/data/gemfile/v1.13.0/Gemfile.lock.archived +0 -1074
- data/data/gemfile/v1.13.2/Gemfile +0 -3
- data/data/gemfile/v1.13.2/Gemfile.lock.archived +0 -899
- data/data/gemfile/v1.13.3/Gemfile +0 -3
- data/data/gemfile/v1.13.3/Gemfile.lock.archived +0 -938
- data/data/gemfile/v1.13.4/Gemfile +0 -3
- data/data/gemfile/v1.13.4/Gemfile.lock.archived +0 -938
- data/data/gemfile/v1.13.5/Gemfile +0 -3
- data/data/gemfile/v1.13.5/Gemfile.lock.archived +0 -944
- data/data/gemfile/v1.13.7/Gemfile +0 -3
- data/data/gemfile/v1.13.7/Gemfile.lock.archived +0 -944
- data/data/gemfile/v1.13.8/Gemfile +0 -3
- data/data/gemfile/v1.13.8/Gemfile.lock.archived +0 -944
- data/data/gemfile/v1.13.9/Gemfile +0 -3
- data/data/gemfile/v1.13.9/Gemfile.lock.archived +0 -956
- data/data/gemfile/v1.14.3/Gemfile +0 -3
- data/data/gemfile/v1.14.3/Gemfile.lock.archived +0 -950
- data/data/gemfile/v1.2.12/Gemfile +0 -3
- data/data/gemfile/v1.2.12/Gemfile.lock.archived +0 -283
- data/data/gemfile/v1.2.2/Gemfile +0 -4
- data/data/gemfile/v1.2.2/Gemfile.lock.archived +0 -224
- data/data/gemfile/v1.2.3/Gemfile +0 -4
- data/data/gemfile/v1.2.3/Gemfile.lock.archived +0 -231
- data/data/gemfile/v1.2.6/Gemfile +0 -4
- data/data/gemfile/v1.2.6/Gemfile.lock.archived +0 -239
- data/data/gemfile/v1.2.8/Gemfile +0 -4
- data/data/gemfile/v1.2.8/Gemfile.lock.archived +0 -233
- data/data/gemfile/v1.2.9/Gemfile +0 -4
- data/data/gemfile/v1.2.9/Gemfile.lock.archived +0 -245
- data/data/gemfile/v1.3.1/Gemfile +0 -3
- data/data/gemfile/v1.3.1/Gemfile.lock.archived +0 -296
- data/data/gemfile/v1.3.2/Gemfile +0 -3
- data/data/gemfile/v1.3.2/Gemfile.lock.archived +0 -296
- data/data/gemfile/v1.3.4/Gemfile +0 -3
- data/data/gemfile/v1.3.4/Gemfile.lock.archived +0 -284
- data/data/gemfile/v1.3.5/Gemfile +0 -3
- data/data/gemfile/v1.3.5/Gemfile.lock.archived +0 -284
- data/data/gemfile/v1.3.6/Gemfile +0 -3
- data/data/gemfile/v1.3.6/Gemfile.lock.archived +0 -286
- data/data/gemfile/v1.3.9/Gemfile +0 -3
- data/data/gemfile/v1.3.9/Gemfile.lock.archived +0 -334
- data/data/gemfile/v1.4.0/Gemfile +0 -3
- data/data/gemfile/v1.4.0/Gemfile.lock.archived +0 -330
- data/data/gemfile/v1.4.10/Gemfile +0 -4
- data/data/gemfile/v1.4.10/Gemfile.lock.archived +0 -461
- data/data/gemfile/v1.4.11/Gemfile +0 -4
- data/data/gemfile/v1.4.11/Gemfile.lock.archived +0 -452
- data/data/gemfile/v1.4.12/Gemfile +0 -4
- data/data/gemfile/v1.4.12/Gemfile.lock.archived +0 -452
- data/data/gemfile/v1.4.13/Gemfile +0 -4
- data/data/gemfile/v1.4.13/Gemfile.lock.archived +0 -455
- data/data/gemfile/v1.4.14/Gemfile +0 -4
- data/data/gemfile/v1.4.14/Gemfile.lock.archived +0 -456
- data/data/gemfile/v1.4.18/Gemfile +0 -3
- data/data/gemfile/v1.4.18/Gemfile.lock.archived +0 -486
- data/data/gemfile/v1.4.3/Gemfile +0 -3
- data/data/gemfile/v1.4.3/Gemfile.lock.archived +0 -339
- data/data/gemfile/v1.4.4/Gemfile +0 -3
- data/data/gemfile/v1.4.4/Gemfile.lock.archived +0 -339
- data/data/gemfile/v1.4.5/Gemfile +0 -3
- data/data/gemfile/v1.4.5/Gemfile.lock.archived +0 -348
- data/data/gemfile/v1.4.6/Gemfile +0 -3
- data/data/gemfile/v1.4.6/Gemfile.lock.archived +0 -357
- data/data/gemfile/v1.4.7/Gemfile +0 -3
- data/data/gemfile/v1.4.7/Gemfile.lock.archived +0 -391
- data/data/gemfile/v1.4.8/Gemfile +0 -3
- data/data/gemfile/v1.4.8/Gemfile.lock.archived +0 -445
- data/data/gemfile/v1.4.9/Gemfile +0 -3
- data/data/gemfile/v1.4.9/Gemfile.lock.archived +0 -448
- data/data/gemfile/v1.5.0/Gemfile +0 -3
- data/data/gemfile/v1.5.0/Gemfile.lock.archived +0 -478
- data/data/gemfile/v1.5.10/Gemfile +0 -3
- data/data/gemfile/v1.5.10/Gemfile.lock.archived +0 -668
- data/data/gemfile/v1.5.11/Gemfile +0 -3
- data/data/gemfile/v1.5.11/Gemfile.lock.archived +0 -668
- data/data/gemfile/v1.5.15/Gemfile +0 -3
- data/data/gemfile/v1.5.15/Gemfile.lock.archived +0 -686
- data/data/gemfile/v1.5.16/Gemfile +0 -3
- data/data/gemfile/v1.5.16/Gemfile.lock.archived +0 -684
- data/data/gemfile/v1.5.17/Gemfile +0 -3
- data/data/gemfile/v1.5.17/Gemfile.lock.archived +0 -684
- data/data/gemfile/v1.5.18/Gemfile +0 -5
- data/data/gemfile/v1.5.18/Gemfile.lock.archived +0 -691
- data/data/gemfile/v1.5.19/Gemfile +0 -5
- data/data/gemfile/v1.5.19/Gemfile.lock.archived +0 -703
- data/data/gemfile/v1.5.20/Gemfile +0 -5
- data/data/gemfile/v1.5.20/Gemfile.lock.archived +0 -703
- data/data/gemfile/v1.5.21/Gemfile +0 -5
- data/data/gemfile/v1.5.21/Gemfile.lock.archived +0 -707
- data/data/gemfile/v1.5.22/Gemfile +0 -5
- data/data/gemfile/v1.5.22/Gemfile.lock.archived +0 -707
- data/data/gemfile/v1.5.23/Gemfile +0 -5
- data/data/gemfile/v1.5.23/Gemfile.lock.archived +0 -711
- data/data/gemfile/v1.5.24/Gemfile +0 -5
- data/data/gemfile/v1.5.24/Gemfile.lock.archived +0 -711
- data/data/gemfile/v1.5.3/Gemfile +0 -3
- data/data/gemfile/v1.5.3/Gemfile.lock.archived +0 -651
- data/data/gemfile/v1.5.4/Gemfile +0 -3
- data/data/gemfile/v1.5.4/Gemfile.lock.archived +0 -657
- data/data/gemfile/v1.5.5/Gemfile +0 -3
- data/data/gemfile/v1.5.5/Gemfile.lock.archived +0 -657
- data/data/gemfile/v1.5.6/Gemfile +0 -3
- data/data/gemfile/v1.5.6/Gemfile.lock.archived +0 -657
- data/data/gemfile/v1.5.7/Gemfile +0 -3
- data/data/gemfile/v1.5.7/Gemfile.lock.archived +0 -657
- data/data/gemfile/v1.5.8/Gemfile +0 -3
- data/data/gemfile/v1.5.8/Gemfile.lock.archived +0 -655
- data/data/gemfile/v1.5.9/Gemfile +0 -3
- data/data/gemfile/v1.5.9/Gemfile.lock.archived +0 -656
- data/data/gemfile/v1.6.1/Gemfile +0 -5
- data/data/gemfile/v1.6.1/Gemfile.lock.archived +0 -721
- data/data/gemfile/v1.6.10/Gemfile +0 -5
- data/data/gemfile/v1.6.10/Gemfile.lock.archived +0 -744
- data/data/gemfile/v1.6.11/Gemfile +0 -5
- data/data/gemfile/v1.6.11/Gemfile.lock.archived +0 -744
- data/data/gemfile/v1.6.12/Gemfile +0 -5
- data/data/gemfile/v1.6.12/Gemfile.lock.archived +0 -745
- data/data/gemfile/v1.6.13/Gemfile +0 -5
- data/data/gemfile/v1.6.13/Gemfile.lock.archived +0 -745
- data/data/gemfile/v1.6.14/Gemfile +0 -5
- data/data/gemfile/v1.6.14/Gemfile.lock.archived +0 -754
- data/data/gemfile/v1.6.15/Gemfile +0 -5
- data/data/gemfile/v1.6.15/Gemfile.lock.archived +0 -757
- data/data/gemfile/v1.6.2/Gemfile +0 -5
- data/data/gemfile/v1.6.2/Gemfile.lock.archived +0 -718
- data/data/gemfile/v1.6.3/Gemfile +0 -5
- data/data/gemfile/v1.6.3/Gemfile.lock.archived +0 -728
- data/data/gemfile/v1.6.4/Gemfile +0 -5
- data/data/gemfile/v1.6.4/Gemfile.lock.archived +0 -730
- data/data/gemfile/v1.6.5/Gemfile +0 -5
- data/data/gemfile/v1.6.5/Gemfile.lock.archived +0 -733
- data/data/gemfile/v1.6.6/Gemfile +0 -5
- data/data/gemfile/v1.6.6/Gemfile.lock.archived +0 -733
- data/data/gemfile/v1.6.7/Gemfile +0 -5
- data/data/gemfile/v1.6.7/Gemfile.lock.archived +0 -733
- data/data/gemfile/v1.6.9/Gemfile +0 -5
- data/data/gemfile/v1.6.9/Gemfile.lock.archived +0 -744
- data/data/gemfile/v1.7.0/Gemfile +0 -5
- data/data/gemfile/v1.7.0/Gemfile.lock.archived +0 -750
- data/data/gemfile/v1.7.1/Gemfile +0 -5
- data/data/gemfile/v1.7.1/Gemfile.lock.archived +0 -750
- data/data/gemfile/v1.7.2/Gemfile +0 -5
- data/data/gemfile/v1.7.2/Gemfile.lock.archived +0 -747
- data/data/gemfile/v1.7.3/Gemfile +0 -5
- data/data/gemfile/v1.7.3/Gemfile.lock.archived +0 -755
- data/data/gemfile/v1.7.4/Gemfile +0 -5
- data/data/gemfile/v1.7.4/Gemfile.lock.archived +0 -756
- data/data/gemfile/v1.7.5/Gemfile +0 -5
- data/data/gemfile/v1.7.5/Gemfile.lock.archived +0 -759
- data/data/gemfile/v1.7.6/Gemfile +0 -5
- data/data/gemfile/v1.7.6/Gemfile.lock.archived +0 -768
- data/data/gemfile/v1.8.10/Gemfile +0 -5
- data/data/gemfile/v1.8.10/Gemfile.lock.archived +0 -792
- data/data/gemfile/v1.8.11/Gemfile +0 -5
- data/data/gemfile/v1.8.11/Gemfile.lock.archived +0 -862
- data/data/gemfile/v1.8.3/Gemfile +0 -5
- data/data/gemfile/v1.8.3/Gemfile.lock.archived +0 -773
- data/data/gemfile/v1.8.4/Gemfile +0 -5
- data/data/gemfile/v1.8.4/Gemfile.lock.archived +0 -768
- data/data/gemfile/v1.8.5/Gemfile +0 -5
- data/data/gemfile/v1.8.5/Gemfile.lock.archived +0 -768
- data/data/gemfile/v1.8.6/Gemfile +0 -5
- data/data/gemfile/v1.8.6/Gemfile.lock.archived +0 -777
- data/data/gemfile/v1.8.7/Gemfile +0 -5
- data/data/gemfile/v1.8.7/Gemfile.lock.archived +0 -777
- data/data/gemfile/v1.8.8/Gemfile +0 -5
- data/data/gemfile/v1.8.8/Gemfile.lock.archived +0 -778
- data/data/gemfile/v1.8.9/Gemfile +0 -5
- data/data/gemfile/v1.8.9/Gemfile.lock.archived +0 -775
- data/data/gemfile/v1.9.0/Gemfile +0 -5
- data/data/gemfile/v1.9.0/Gemfile.lock.archived +0 -871
- data/data/gemfile/v1.9.1/Gemfile +0 -5
- data/data/gemfile/v1.9.1/Gemfile.lock.archived +0 -906
- data/data/gemfile/v1.9.2/Gemfile +0 -5
- data/data/gemfile/v1.9.2/Gemfile.lock.archived +0 -898
- data/data/gemfile/v1.9.3/Gemfile +0 -5
- data/data/gemfile/v1.9.3/Gemfile.lock.archived +0 -898
- data/data/gemfile/v1.9.4/Gemfile +0 -5
- data/data/gemfile/v1.9.4/Gemfile.lock.archived +0 -901
- data/data/gemfile/v1.9.5/Gemfile +0 -5
- data/data/gemfile/v1.9.5/Gemfile.lock.archived +0 -903
- data/data/gemfile/v1.9.6/Gemfile +0 -5
- data/data/gemfile/v1.9.6/Gemfile.lock.archived +0 -900
- data/data/gemfile/v1.9.7/Gemfile +0 -5
- data/data/gemfile/v1.9.7/Gemfile.lock.archived +0 -922
- data/data/gemfile/v1.9.8/Gemfile +0 -5
- data/data/gemfile/v1.9.8/Gemfile.lock.archived +0 -933
- data/data/gemfile/versions.yaml +0 -751
- data/data/homebrew/versions.yaml +0 -567
- data/data/snap/github_tags.json +0 -42
- data/data/snap/versions.yaml +0 -589
- data/snapcraft-list-copied-from-site.md +0 -101
|
@@ -4,12 +4,14 @@ require 'thor'
|
|
|
4
4
|
require 'json'
|
|
5
5
|
|
|
6
6
|
module Mnenv
|
|
7
|
+
autoload :SnapRepository, 'mnenv/snap_repository'
|
|
8
|
+
autoload :JsonFormatter, 'mnenv/json_formatter'
|
|
9
|
+
autoload :Snap, 'mnenv/snap'
|
|
10
|
+
|
|
7
11
|
class SnapCommand < Thor
|
|
8
12
|
desc 'list', 'List all Snap versions'
|
|
9
13
|
method_option :format, type: :string, aliases: '-f', default: 'text'
|
|
10
14
|
def list
|
|
11
|
-
require_relative '../snap_repository'
|
|
12
|
-
require_relative '../json_formatter'
|
|
13
15
|
repo = SnapRepository.new
|
|
14
16
|
versions = repo.all
|
|
15
17
|
|
|
@@ -25,8 +27,6 @@ module Mnenv
|
|
|
25
27
|
|
|
26
28
|
desc 'refresh', 'Fetch and add new Snap versions (incremental)'
|
|
27
29
|
def refresh
|
|
28
|
-
require_relative '../snap/fetcher'
|
|
29
|
-
require_relative '../snap_repository'
|
|
30
30
|
fetcher = Snap::Fetcher.new
|
|
31
31
|
repo = fetcher.repository
|
|
32
32
|
|
|
@@ -50,7 +50,6 @@ module Mnenv
|
|
|
50
50
|
|
|
51
51
|
desc 'revamp', 'Re-fetch all Snap versions'
|
|
52
52
|
def revamp
|
|
53
|
-
require_relative '../snap/fetcher'
|
|
54
53
|
fetcher = Snap::Fetcher.new
|
|
55
54
|
versions = fetcher.fetch_and_save
|
|
56
55
|
puts "Revamped #{versions.size} Snap versions"
|
|
@@ -58,14 +57,13 @@ module Mnenv
|
|
|
58
57
|
|
|
59
58
|
desc 'update VERSION', 'Update a specific Snap version (all arch/channel combinations)'
|
|
60
59
|
def update(version)
|
|
61
|
-
require_relative '../snap/fetcher'
|
|
62
60
|
fetcher = Snap::Fetcher.new
|
|
63
61
|
versions = fetcher.fetch_all
|
|
64
62
|
targets = versions.select { |v| v.version == version }
|
|
65
63
|
|
|
66
64
|
if targets.empty?
|
|
67
65
|
puts "Snap version #{version} not found in current channel-map"
|
|
68
|
-
puts
|
|
66
|
+
puts 'Note: Historical versions no longer in Snap API cannot be updated'
|
|
69
67
|
exit 1
|
|
70
68
|
end
|
|
71
69
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'tty/prompt'
|
|
4
|
+
require_relative '../installer'
|
|
5
|
+
|
|
6
|
+
module Mnenv
|
|
7
|
+
class UninstallCommand < Thor
|
|
8
|
+
namespace :uninstall
|
|
9
|
+
|
|
10
|
+
class_option :force, type: :boolean, aliases: '-f', default: false,
|
|
11
|
+
desc: 'Force uninstallation without confirmation'
|
|
12
|
+
|
|
13
|
+
desc 'VERSION', 'Uninstall a specific Metanorma version'
|
|
14
|
+
method_option :force, type: :boolean, aliases: '-f', default: false
|
|
15
|
+
def uninstall(version)
|
|
16
|
+
version_dir = File.expand_path("~/.mnenv/versions/#{version}")
|
|
17
|
+
|
|
18
|
+
unless Dir.exist?(version_dir)
|
|
19
|
+
puts "Version #{version} is not installed."
|
|
20
|
+
return
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
unless options[:force]
|
|
24
|
+
prompt = TTY::Prompt.new
|
|
25
|
+
unless prompt.yes?("Uninstall Metanorma #{version}? This cannot be undone.")
|
|
26
|
+
puts 'Uninstallation cancelled.'
|
|
27
|
+
return
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
FileUtils.rm_rf(version_dir)
|
|
32
|
+
|
|
33
|
+
# Regenerate shims
|
|
34
|
+
ShimManager.new.regenerate_all
|
|
35
|
+
|
|
36
|
+
puts "Uninstalled Metanorma #{version}"
|
|
37
|
+
rescue StandardError => e
|
|
38
|
+
warn "Error: #{e.message}"
|
|
39
|
+
exit 1
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'tty/prompt'
|
|
4
|
+
require 'json'
|
|
5
|
+
require_relative '../installer'
|
|
6
|
+
require_relative '../binary_repository'
|
|
7
|
+
|
|
8
|
+
module Mnenv
|
|
9
|
+
class VersionCommand < Thor
|
|
10
|
+
namespace :version
|
|
11
|
+
|
|
12
|
+
class_option :source, type: :string, enum: %w[gemfile binary],
|
|
13
|
+
desc: 'Source type (gemfile or binary)'
|
|
14
|
+
class_option :interactive, type: :boolean, aliases: '-i', default: false,
|
|
15
|
+
desc: 'Interactive mode for version selection'
|
|
16
|
+
|
|
17
|
+
desc 'use VERSION', 'Set Metanorma version for current shell session'
|
|
18
|
+
method_option :source, type: :string, enum: %w[gemfile binary]
|
|
19
|
+
method_option :interactive, type: :boolean, aliases: '-i', default: false
|
|
20
|
+
def use(version = nil)
|
|
21
|
+
version, source = resolve_version_and_source(version, options[:source], options[:interactive])
|
|
22
|
+
|
|
23
|
+
puts "export METANORMA_VERSION=#{version}"
|
|
24
|
+
puts "export METANORMA_SOURCE=#{source}" if source
|
|
25
|
+
puts "# Run this in your shell, or use: eval \"$(mnenv use #{version}#{" --source #{source}" if source})\""
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc 'global VERSION', 'Set default Metanorma version globally'
|
|
29
|
+
method_option :source, type: :string, enum: %w[gemfile binary]
|
|
30
|
+
method_option :interactive, type: :boolean, aliases: '-i', default: false
|
|
31
|
+
def global(version = nil)
|
|
32
|
+
version, source = resolve_version_and_source(version, options[:source], options[:interactive])
|
|
33
|
+
verify_installed!(version, source)
|
|
34
|
+
|
|
35
|
+
File.write(Paths::VERSION_FILE, version)
|
|
36
|
+
File.write(Paths::SOURCE_FILE, source) if source
|
|
37
|
+
puts "Global Metanorma version set to #{version}#{source ? " (source: #{source})" : ''}"
|
|
38
|
+
rescue StandardError => e
|
|
39
|
+
warn "Error: #{e.message}"
|
|
40
|
+
exit 1
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
desc 'local VERSION', 'Set Metanorma version for current directory'
|
|
44
|
+
method_option :source, type: :string, enum: %w[gemfile binary]
|
|
45
|
+
method_option :interactive, type: :boolean, aliases: '-i', default: false
|
|
46
|
+
def local(version = nil)
|
|
47
|
+
version, source = resolve_version_and_source(version, options[:source], options[:interactive])
|
|
48
|
+
verify_installed!(version, source)
|
|
49
|
+
|
|
50
|
+
File.write('.metanorma-version', version)
|
|
51
|
+
File.write('.metanorma-source', source) if source
|
|
52
|
+
puts "Local Metanorma version set to #{version}#{source ? " (source: #{source})" : ''}"
|
|
53
|
+
puts "Created .metanorma-version#{source ? ' and .metanorma-source' : ''}"
|
|
54
|
+
rescue StandardError => e
|
|
55
|
+
warn "Error: #{e.message}"
|
|
56
|
+
exit 1
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
desc 'versions', 'List all installed Metanorma versions'
|
|
60
|
+
method_option :format, type: :string, aliases: '-f', default: 'text',
|
|
61
|
+
desc: 'Output format (text or json)'
|
|
62
|
+
def versions
|
|
63
|
+
installed = list_installed_versions
|
|
64
|
+
|
|
65
|
+
if installed.empty?
|
|
66
|
+
puts 'No versions installed.'
|
|
67
|
+
puts "\nRun: mnenv install --list"
|
|
68
|
+
return
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
current_version, current_source = resolve_current
|
|
72
|
+
|
|
73
|
+
case options[:format]
|
|
74
|
+
when 'json'
|
|
75
|
+
output = {
|
|
76
|
+
'current_version' => current_version,
|
|
77
|
+
'current_source' => current_source,
|
|
78
|
+
'installed' => installed.map do |version, sources|
|
|
79
|
+
sources.map do |source|
|
|
80
|
+
{
|
|
81
|
+
'version' => version,
|
|
82
|
+
'source' => source,
|
|
83
|
+
'current' => version == current_version && source == current_source
|
|
84
|
+
}
|
|
85
|
+
end
|
|
86
|
+
end.flatten
|
|
87
|
+
}
|
|
88
|
+
puts JSON.pretty_generate(output)
|
|
89
|
+
else
|
|
90
|
+
puts 'Installed Metanorma versions:'
|
|
91
|
+
|
|
92
|
+
installed.sort.reverse.each do |version, sources|
|
|
93
|
+
sources.sort.each do |source|
|
|
94
|
+
is_current = version == current_version && source == current_source
|
|
95
|
+
marker = is_current ? '* ' : ' '
|
|
96
|
+
puts " #{marker}#{version} (source: #{source})"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
puts "\nCurrent version: #{current_version || 'none'}"
|
|
101
|
+
puts "Current source: #{current_source || 'none'}"
|
|
102
|
+
puts "\nTo see available versions, run: mnenv install --list"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
# List installed versions with their sources
|
|
109
|
+
# Uses Paths::INSTALLED_DIR with new naming convention: <version>-<source>
|
|
110
|
+
def list_installed_versions
|
|
111
|
+
return {} unless Dir.exist?(Paths::INSTALLED_DIR)
|
|
112
|
+
|
|
113
|
+
versions = Hash.new { |h, k| h[k] = [] }
|
|
114
|
+
|
|
115
|
+
Dir.glob(File.join(Paths::INSTALLED_DIR, '*')).each do |dir|
|
|
116
|
+
next unless File.directory?(dir)
|
|
117
|
+
|
|
118
|
+
dir_name = File.basename(dir)
|
|
119
|
+
version, source = Paths.parse_version_dir(dir_name)
|
|
120
|
+
|
|
121
|
+
# Only include valid version-source directories
|
|
122
|
+
next unless version && source
|
|
123
|
+
|
|
124
|
+
versions[version] << source
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
versions
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def resolve_version_and_source(version, source, interactive)
|
|
131
|
+
version, source = select_version_interactive if interactive || version.nil?
|
|
132
|
+
source ||= default_source
|
|
133
|
+
[version, source]
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def select_version_interactive
|
|
137
|
+
prompt = TTY::Prompt.new
|
|
138
|
+
installed = list_installed_versions
|
|
139
|
+
|
|
140
|
+
raise 'No versions installed. Run: mnenv install --list' if installed.empty?
|
|
141
|
+
|
|
142
|
+
choices = installed.flat_map do |version, sources|
|
|
143
|
+
sources.map do |source|
|
|
144
|
+
{ name: "#{version} (#{source})", value: [version, source] }
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
version, source = prompt.select('Select a version:', choices)
|
|
149
|
+
|
|
150
|
+
[version, source]
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def verify_installed!(version, source)
|
|
154
|
+
version_dir = Paths.version_install_dir(version, source)
|
|
155
|
+
return if Dir.exist?(version_dir)
|
|
156
|
+
|
|
157
|
+
raise "Version #{version} (source: #{source}) is not installed. Run: mnenv install #{version} --source #{source}"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def installed_versions
|
|
161
|
+
list_installed_versions.keys.sort
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def default_source
|
|
165
|
+
if File.exist?(Paths::SOURCE_FILE)
|
|
166
|
+
File.read(Paths::SOURCE_FILE).strip
|
|
167
|
+
else
|
|
168
|
+
'gemfile'
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def resolve_version
|
|
173
|
+
return ENV['METANORMA_VERSION'] if ENV['METANORMA_VERSION']
|
|
174
|
+
|
|
175
|
+
dir = Dir.pwd
|
|
176
|
+
loop do
|
|
177
|
+
return File.read(File.join(dir, '.metanorma-version')).strip if File.exist?(File.join(dir,
|
|
178
|
+
'.metanorma-version'))
|
|
179
|
+
|
|
180
|
+
parent = File.dirname(dir)
|
|
181
|
+
break if parent == dir # Reached root
|
|
182
|
+
|
|
183
|
+
dir = parent
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
return File.read(Paths::VERSION_FILE).strip if File.exist?(Paths::VERSION_FILE)
|
|
187
|
+
|
|
188
|
+
nil
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def resolve_source
|
|
192
|
+
return ENV['METANORMA_SOURCE'] if ENV['METANORMA_SOURCE']
|
|
193
|
+
|
|
194
|
+
dir = Dir.pwd
|
|
195
|
+
loop do
|
|
196
|
+
return File.read(File.join(dir, '.metanorma-source')).strip if File.exist?(File.join(dir, '.metanorma-source'))
|
|
197
|
+
|
|
198
|
+
parent = File.dirname(dir)
|
|
199
|
+
break if parent == dir # Reached root
|
|
200
|
+
|
|
201
|
+
dir = parent
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
return File.read(Paths::SOURCE_FILE).strip if File.exist?(Paths::SOURCE_FILE)
|
|
205
|
+
|
|
206
|
+
'gemfile'
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def resolve_current
|
|
210
|
+
[resolve_version, resolve_source]
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
data/lib/mnenv/commands.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
module Mnenv
|
|
4
|
+
autoload :GemfileCommand, 'mnenv/commands/gemfile_command'
|
|
5
|
+
autoload :SnapCommand, 'mnenv/commands/snap_command'
|
|
6
|
+
autoload :HomebrewCommand, 'mnenv/commands/homebrew_command'
|
|
7
|
+
autoload :ChocolateyCommand, 'mnenv/commands/chocolatey_command'
|
|
8
|
+
autoload :InstallCommand, 'mnenv/commands/install_command'
|
|
9
|
+
autoload :VersionCommand, 'mnenv/commands/version_command'
|
|
10
|
+
autoload :UninstallCommand, 'mnenv/commands/uninstall_command'
|
|
11
|
+
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'English'
|
|
3
4
|
require_relative '../logger'
|
|
4
5
|
require_relative '../gemfile_repository'
|
|
5
6
|
require_relative './fetcher'
|
|
@@ -36,7 +37,7 @@ module Mnenv
|
|
|
36
37
|
|
|
37
38
|
def extract_incremental
|
|
38
39
|
remote_versions = fetcher.fetch_all
|
|
39
|
-
existing_versions = repository.all.select
|
|
40
|
+
existing_versions = repository.all.select(&:exists_locally?).map(&:version)
|
|
40
41
|
|
|
41
42
|
missing = remote_versions.reject { |v| existing_versions.include?(v.version) }
|
|
42
43
|
|
|
@@ -74,12 +75,18 @@ module Mnenv
|
|
|
74
75
|
|
|
75
76
|
cleanup_docker_image(version.version)
|
|
76
77
|
|
|
78
|
+
# Update version metadata after successful extraction
|
|
79
|
+
version.gemfile_exists = true
|
|
80
|
+
# Store relative paths (relative to data/gemfile directory)
|
|
81
|
+
version.gemfile_path = "v#{version.version}/Gemfile"
|
|
82
|
+
version.gemfile_lock_path = "v#{version.version}/Gemfile.lock.archived"
|
|
83
|
+
|
|
77
84
|
repository.save(version)
|
|
78
85
|
end
|
|
79
86
|
|
|
80
87
|
def pull_docker_image(version_number)
|
|
81
88
|
system('docker', 'pull', "#{Fetcher::DOCKER_IMAGE}:#{version_number}", out: File::NULL)
|
|
82
|
-
raise 'Failed to pull Docker image' unless
|
|
89
|
+
raise 'Failed to pull Docker image' unless $CHILD_STATUS.success?
|
|
83
90
|
end
|
|
84
91
|
|
|
85
92
|
def extract_gemfiles(version)
|
|
@@ -89,7 +96,7 @@ module Mnenv
|
|
|
89
96
|
cmd = "docker run --rm --entrypoint sh #{Fetcher::DOCKER_IMAGE}:#{version.version} -c '#{script}'"
|
|
90
97
|
output = `#{cmd}`
|
|
91
98
|
|
|
92
|
-
raise "Extraction failed for #{version.version}" unless
|
|
99
|
+
raise "Extraction failed for #{version.version}" unless $CHILD_STATUS.success?
|
|
93
100
|
|
|
94
101
|
gemfile, gemfile_lock = parse_gemfile_output(output)
|
|
95
102
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mnenv
|
|
4
|
+
class Installer
|
|
5
|
+
class InstallationError < StandardError; end
|
|
6
|
+
class DevelopmentToolsMissing < InstallationError; end
|
|
7
|
+
|
|
8
|
+
attr_reader :version, :source
|
|
9
|
+
|
|
10
|
+
def initialize(version, source: nil, target_dir: nil)
|
|
11
|
+
@version = version
|
|
12
|
+
@source = source || default_source
|
|
13
|
+
@target_dir = target_dir || default_target_dir
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def install
|
|
17
|
+
verify_prerequisites!
|
|
18
|
+
create_install_directory
|
|
19
|
+
perform_installation
|
|
20
|
+
regenerate_shims
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def installed?
|
|
24
|
+
Dir.exist?(version_dir)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def default_target_dir
|
|
30
|
+
@default_target_dir ||= Paths.version_install_dir(version, source)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def version_dir
|
|
34
|
+
@target_dir
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def verify_prerequisites!
|
|
38
|
+
raise NotImplementedError, "#{self.class} must implement verify_prerequisites!"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def perform_installation
|
|
42
|
+
raise NotImplementedError, "#{self.class} must implement perform_installation!"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def create_install_directory
|
|
46
|
+
FileUtils.mkdir_p(version_dir)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def regenerate_shims
|
|
50
|
+
ShimManager.new.regenerate_all
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def default_source
|
|
54
|
+
# Try to read from ~/.mnenv/source, else default to gemfile
|
|
55
|
+
if File.exist?(Paths::SOURCE_FILE)
|
|
56
|
+
File.read(Paths::SOURCE_FILE).strip
|
|
57
|
+
else
|
|
58
|
+
'gemfile' # Default: faster for devs
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mnenv
|
|
4
|
+
class InstallerFactory
|
|
5
|
+
def self.create(version, source:)
|
|
6
|
+
case source.to_s
|
|
7
|
+
when 'gemfile'
|
|
8
|
+
Installers::GemfileInstaller.new(version, source: source)
|
|
9
|
+
when 'binary'
|
|
10
|
+
Installers::BinaryInstaller.new(version, source: source)
|
|
11
|
+
else
|
|
12
|
+
raise Installer::InstallationError,
|
|
13
|
+
"Unknown source: #{source}. Use: gemfile or binary"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mnenv
|
|
4
|
+
autoload :Installer, 'mnenv/installer/base'
|
|
5
|
+
autoload :InstallerFactory, 'mnenv/installer/factory'
|
|
6
|
+
autoload :ShimManager, 'mnenv/shim_manager'
|
|
7
|
+
|
|
8
|
+
module Installers
|
|
9
|
+
autoload :GemfileInstaller, 'mnenv/installers/gemfile_installer'
|
|
10
|
+
autoload :BinaryInstaller, 'mnenv/installers/binary_installer'
|
|
11
|
+
end
|
|
12
|
+
end
|