mnenv 0.1.0 → 0.1.2
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 +111 -0
- data/lib/mnenv/commands/version_command.rb +167 -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 +46 -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/platform_detector.rb +109 -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/sources.rb +46 -0
- data/lib/mnenv/version.rb +1 -1
- data/lib/mnenv/version_resolver.rb +108 -0
- data/lib/mnenv/versions_manager.rb +92 -0
- data/lib/mnenv.rb +6 -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 +85 -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
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open-uri'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'net/http'
|
|
6
|
+
require 'rubygems/package'
|
|
7
|
+
require 'zlib'
|
|
8
|
+
require 'tempfile'
|
|
9
|
+
require_relative '../installer/base'
|
|
10
|
+
require_relative '../binary_repository'
|
|
11
|
+
|
|
12
|
+
module Mnenv
|
|
13
|
+
module Installers
|
|
14
|
+
class BinaryInstaller < Installer
|
|
15
|
+
PACKED_MN_REPO = 'metanorma/packed-mn'
|
|
16
|
+
RELEASES_URL = "https://api.github.com/repos/#{PACKED_MN_REPO}/releases".freeze
|
|
17
|
+
|
|
18
|
+
def verify_prerequisites!
|
|
19
|
+
verify_version_available!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def perform_installation
|
|
23
|
+
download_binary
|
|
24
|
+
make_executable
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def make_executable
|
|
28
|
+
# Linux/macOS: make the binary executable
|
|
29
|
+
binary_path = File.join(version_dir, 'metanorma')
|
|
30
|
+
FileUtils.chmod(0o755, binary_path) if File.exist?(binary_path)
|
|
31
|
+
|
|
32
|
+
# Windows: .exe files don't need chmod
|
|
33
|
+
exe_path = File.join(version_dir, 'metanorma.exe')
|
|
34
|
+
nil unless File.exist?(exe_path)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def verify_version_available!
|
|
40
|
+
repo = BinaryRepository.new
|
|
41
|
+
binary_version = repo.find(version)
|
|
42
|
+
|
|
43
|
+
return if binary_version
|
|
44
|
+
|
|
45
|
+
available = repo.all.map(&:version).first(5).join(', ')
|
|
46
|
+
raise InstallationError, "Binary version #{version} not found.\n" \
|
|
47
|
+
"Available: #{available}...\n" \
|
|
48
|
+
"Or use: mnenv install #{version} --source=gemfile"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def download_binary
|
|
52
|
+
url, format = binary_url_and_format
|
|
53
|
+
warn "Downloading #{url}..."
|
|
54
|
+
|
|
55
|
+
tempfile = download_to_tempfile(url)
|
|
56
|
+
|
|
57
|
+
case format
|
|
58
|
+
when 'tgz'
|
|
59
|
+
extract_tgz(tempfile)
|
|
60
|
+
when 'zip'
|
|
61
|
+
extract_zip(tempfile)
|
|
62
|
+
when 'exe'
|
|
63
|
+
# Windows .exe - just copy directly
|
|
64
|
+
FileUtils.cp(tempfile.path, File.join(version_dir, 'metanorma.exe'))
|
|
65
|
+
else
|
|
66
|
+
raise InstallationError, "Unknown binary format: #{format}"
|
|
67
|
+
end
|
|
68
|
+
rescue OpenURI::HTTPError => e
|
|
69
|
+
raise InstallationError, "Failed to download binary: #{e.message}"
|
|
70
|
+
ensure
|
|
71
|
+
tempfile&.close&.unlink
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def binary_url_and_format
|
|
75
|
+
repo = BinaryRepository.new
|
|
76
|
+
binary_version = repo.find(version)
|
|
77
|
+
|
|
78
|
+
raise InstallationError, "Binary version #{version} not found in repository" unless binary_version
|
|
79
|
+
|
|
80
|
+
platform, arch, variant = detect_platform_arch_variant
|
|
81
|
+
|
|
82
|
+
# Try to find a matching platform in the version data
|
|
83
|
+
# Priority: exe for Windows, tgz for Unix, then zip as fallback
|
|
84
|
+
formats = platform == 'windows' ? %w[exe zip] : %w[tgz]
|
|
85
|
+
|
|
86
|
+
formats.each do |fmt|
|
|
87
|
+
platform_data = binary_version.find_platform(
|
|
88
|
+
name: platform,
|
|
89
|
+
arch: arch,
|
|
90
|
+
variant: variant,
|
|
91
|
+
format: fmt
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return [platform_data['url'], fmt] if platform_data && platform_data['url']
|
|
95
|
+
|
|
96
|
+
# Try without variant (for non-musl systems)
|
|
97
|
+
platform_data = binary_version.find_platform(
|
|
98
|
+
name: platform,
|
|
99
|
+
arch: arch,
|
|
100
|
+
variant: nil,
|
|
101
|
+
format: fmt
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return [platform_data['url'], fmt] if platform_data && platform_data['url']
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Fallback: construct URL manually (for backward compatibility)
|
|
108
|
+
warn 'Warning: Platform data not found in cache, constructing URL manually'
|
|
109
|
+
fallback_url_and_format(platform, arch, variant)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def fallback_url_and_format(platform, arch, variant)
|
|
113
|
+
tag_name = "v#{version}"
|
|
114
|
+
|
|
115
|
+
if platform == 'windows'
|
|
116
|
+
url_exe = "https://github.com/#{PACKED_MN_REPO}/releases/download/#{tag_name}/metanorma-#{platform}-#{arch}.exe"
|
|
117
|
+
return [url_exe, 'exe'] if url_exists?(url_exe)
|
|
118
|
+
|
|
119
|
+
url_zip = "https://github.com/#{PACKED_MN_REPO}/releases/download/#{tag_name}/metanorma-#{platform}-#{arch}.zip"
|
|
120
|
+
return [url_zip, 'zip'] if url_exists?(url_zip)
|
|
121
|
+
|
|
122
|
+
raise InstallationError, "No Windows binary found for version #{version}"
|
|
123
|
+
else
|
|
124
|
+
# Try with variant (e.g., musl)
|
|
125
|
+
if variant
|
|
126
|
+
url_variant = "https://github.com/#{PACKED_MN_REPO}/releases/download/#{tag_name}/metanorma-#{platform}-#{variant}-#{arch}.tgz"
|
|
127
|
+
return [url_variant, 'tgz'] if url_exists?(url_variant)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
url_with_arch = "https://github.com/#{PACKED_MN_REPO}/releases/download/#{tag_name}/metanorma-#{platform}-#{arch}.tgz"
|
|
131
|
+
return [url_with_arch, 'tgz'] if url_exists?(url_with_arch)
|
|
132
|
+
|
|
133
|
+
raise InstallationError, "No binary found for #{platform}/#{arch} version #{version}"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def download_to_tempfile(url)
|
|
138
|
+
tempfile = Tempfile.new(['mnenv-binary', '.tmp'])
|
|
139
|
+
URI.open(url, 'rb') do |io|
|
|
140
|
+
IO.copy_stream(io, tempfile)
|
|
141
|
+
end
|
|
142
|
+
tempfile.rewind
|
|
143
|
+
tempfile
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def extract_tgz(tempfile)
|
|
147
|
+
found = false
|
|
148
|
+
Gem::Package::TarReader.new(Zlib::GzipReader.open(tempfile.path)) do |tar|
|
|
149
|
+
tar.each do |entry|
|
|
150
|
+
next unless entry.file?
|
|
151
|
+
|
|
152
|
+
# Look for the metanorma binary
|
|
153
|
+
# The archive may contain:
|
|
154
|
+
# - metanorma (expected)
|
|
155
|
+
# - metanorma-linux-x86_64 (actual packed-mn naming)
|
|
156
|
+
# - metanorma-darwin-arm64
|
|
157
|
+
# etc.
|
|
158
|
+
filename = File.basename(entry.full_name)
|
|
159
|
+
next unless filename.start_with?('metanorma') && !filename.include?('.')
|
|
160
|
+
|
|
161
|
+
if filename == 'metanorma'
|
|
162
|
+
else
|
|
163
|
+
# Rename metanorma-linux-x86_64 to just metanorma
|
|
164
|
+
end
|
|
165
|
+
target_name = 'metanorma'
|
|
166
|
+
|
|
167
|
+
File.open(File.join(version_dir, target_name), 'wb') do |f|
|
|
168
|
+
f.write(entry.read)
|
|
169
|
+
end
|
|
170
|
+
found = true
|
|
171
|
+
break
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
raise InstallationError, 'Could not find metanorma binary in archive' unless found
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def extract_zip(tempfile)
|
|
179
|
+
require 'zip'
|
|
180
|
+
|
|
181
|
+
Zip::File.open(tempfile.path) do |zip_file|
|
|
182
|
+
entry = zip_file.find { |e| File.basename(e.name) == 'metanorma.exe' }
|
|
183
|
+
raise InstallationError, 'Could not find metanorma.exe in zip archive' unless entry
|
|
184
|
+
|
|
185
|
+
File.open(File.join(version_dir, 'metanorma.exe'), 'wb') do |f|
|
|
186
|
+
f.write(entry.get_input_stream.read)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def url_exists?(url)
|
|
192
|
+
uri = URI(url)
|
|
193
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
|
194
|
+
response = http.head(uri.path)
|
|
195
|
+
response.is_a?(Net::HTTPSuccess)
|
|
196
|
+
end
|
|
197
|
+
rescue StandardError
|
|
198
|
+
false
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def detect_platform_arch_variant
|
|
202
|
+
platform = case RbConfig::CONFIG['host_os']
|
|
203
|
+
when /linux/ then 'linux'
|
|
204
|
+
when /darwin/ then 'darwin'
|
|
205
|
+
when /mswin|mingw|cygwin/ then 'windows'
|
|
206
|
+
else raise InstallationError, 'Unsupported platform for binary installations'
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Detect architecture
|
|
210
|
+
arch = case RbConfig::CONFIG['host_cpu']
|
|
211
|
+
when /arm64|aarch64/ then 'arm64'
|
|
212
|
+
when /x86_64|x64/ then 'x86_64'
|
|
213
|
+
else 'x86_64' # Default to x86_64
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Detect variant (e.g., musl for Alpine Linux)
|
|
217
|
+
variant = detect_variant if platform == 'linux'
|
|
218
|
+
|
|
219
|
+
[platform, arch, variant]
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def detect_variant
|
|
223
|
+
# Check for musl libc (Alpine Linux)
|
|
224
|
+
if File.exist?('/etc/alpine-release')
|
|
225
|
+
'musl'
|
|
226
|
+
elsif File.symlink?('/lib/libc.musl-x86_64.so.1')
|
|
227
|
+
'musl'
|
|
228
|
+
end
|
|
229
|
+
rescue StandardError
|
|
230
|
+
nil
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def fetch_releases
|
|
234
|
+
URI(RELEASES_URL).open do |io|
|
|
235
|
+
JSON.parse(io.read)
|
|
236
|
+
end
|
|
237
|
+
rescue OpenURI::HTTPError => e
|
|
238
|
+
raise InstallationError, "Failed to fetch releases: #{e.message}"
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../installer/base'
|
|
4
|
+
|
|
5
|
+
module Mnenv
|
|
6
|
+
module Installers
|
|
7
|
+
class GemfileInstaller < Installer
|
|
8
|
+
def verify_prerequisites!
|
|
9
|
+
verify_version_exists!
|
|
10
|
+
verify_development_tools!
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def perform_installation
|
|
14
|
+
copy_gemfiles
|
|
15
|
+
bundle_install
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def verify_version_exists!
|
|
21
|
+
repo = GemfileRepository.new
|
|
22
|
+
return if repo.exists?(version)
|
|
23
|
+
|
|
24
|
+
available = repo.all.map(&:display_name).join(', ')
|
|
25
|
+
raise InstallationError, "Version #{version} not found in Gemfile repository. " \
|
|
26
|
+
"Available: #{available}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def verify_development_tools!
|
|
30
|
+
required_tools = %w[ruby bundle]
|
|
31
|
+
|
|
32
|
+
# Use 'where' on Windows, 'which' on Unix
|
|
33
|
+
which_cmd = Gem.win_platform? ? 'where' : 'which'
|
|
34
|
+
|
|
35
|
+
missing_tools = required_tools.reject do |tool|
|
|
36
|
+
system(which_cmd, tool, out: File::NULL, err: File::NULL)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
return if missing_tools.empty?
|
|
40
|
+
|
|
41
|
+
raise DevelopmentToolsMissing,
|
|
42
|
+
"Development tools required for Gemfile installation.\n" \
|
|
43
|
+
"Missing: #{missing_tools.join(', ')}\n" \
|
|
44
|
+
"Install with: apt-get install ruby bundler build-essential # Debian/Ubuntu\n" \
|
|
45
|
+
" brew install ruby bundler # macOS\n" \
|
|
46
|
+
"Or use: mnenv install #{version} --source=binary"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def copy_gemfiles
|
|
50
|
+
repo = GemfileRepository.new
|
|
51
|
+
version_obj = repo.find(version)
|
|
52
|
+
|
|
53
|
+
raise InstallationError, "Version #{version} not found" unless version_obj
|
|
54
|
+
|
|
55
|
+
gemfile_source = version_obj.gemfile_path_calc
|
|
56
|
+
gemfile_lock_source = version_obj.gemfile_lock_path_calc
|
|
57
|
+
|
|
58
|
+
raise InstallationError, "Gemfile not found for #{version}" unless File.exist?(gemfile_source)
|
|
59
|
+
raise InstallationError, "Gemfile.lock not found for #{version}" unless File.exist?(gemfile_lock_source)
|
|
60
|
+
|
|
61
|
+
FileUtils.cp(gemfile_source, File.join(version_dir, 'Gemfile'))
|
|
62
|
+
FileUtils.cp(gemfile_lock_source, File.join(version_dir, 'Gemfile.lock'))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def bundle_install
|
|
66
|
+
Dir.chdir(version_dir) do
|
|
67
|
+
# Use system with bundler for proper isolation
|
|
68
|
+
# Don't suppress output to help debug issues
|
|
69
|
+
unless system('bundle', 'install', '--path', '.bundle', '--binstubs', 'bin')
|
|
70
|
+
raise InstallationError, "Bundle install failed for #{version}"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/mnenv/json_formatter.rb
CHANGED
|
@@ -5,12 +5,9 @@ require 'json'
|
|
|
5
5
|
module Mnenv
|
|
6
6
|
class JsonFormatter
|
|
7
7
|
def self.format_version(version)
|
|
8
|
-
|
|
9
|
-
'version' => version.version,
|
|
10
|
-
'published_at' => format_timestamp(version.published_at),
|
|
11
|
-
'parsed_at' => format_timestamp(version.parsed_at),
|
|
8
|
+
version.to_hash.merge(
|
|
12
9
|
'display_name' => version.display_name
|
|
13
|
-
|
|
10
|
+
).merge(version_specific_fields(version))
|
|
14
11
|
end
|
|
15
12
|
|
|
16
13
|
def self.format_versions(versions)
|
|
@@ -22,18 +19,11 @@ module Mnenv
|
|
|
22
19
|
end
|
|
23
20
|
|
|
24
21
|
class << self
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
# Additional fields specific to JSON output format
|
|
27
23
|
def version_specific_fields(version)
|
|
28
24
|
case version
|
|
29
25
|
when GemfileVersion
|
|
30
26
|
{ 'gemfile_exists' => version.exists_locally? }
|
|
31
|
-
when SnapVersion
|
|
32
|
-
{ 'revision' => version.revision, 'channel' => version.channel }
|
|
33
|
-
when HomebrewVersion
|
|
34
|
-
{ 'tag_name' => version.tag_name, 'commit_sha' => version.commit_sha }
|
|
35
|
-
when ChocolateyVersion
|
|
36
|
-
{ 'package_name' => version.package_name, 'is_pre_release' => version.is_pre_release }
|
|
37
27
|
else
|
|
38
28
|
{}
|
|
39
29
|
end
|
data/lib/mnenv/logger.rb
CHANGED
|
@@ -10,6 +10,7 @@ module Mnenv
|
|
|
10
10
|
success: '✅',
|
|
11
11
|
warning: '⚠️',
|
|
12
12
|
error: '❌',
|
|
13
|
+
debug: '🔍',
|
|
13
14
|
pulling: '📥',
|
|
14
15
|
extracting: '📦',
|
|
15
16
|
skipping: '⏭️',
|
|
@@ -33,6 +34,13 @@ module Mnenv
|
|
|
33
34
|
warn Paint["#{EMOJIS[:error]} ERROR: #{message}", :red, :bold]
|
|
34
35
|
end
|
|
35
36
|
|
|
37
|
+
# Only outputs when verbose mode is enabled
|
|
38
|
+
def debug(message)
|
|
39
|
+
return unless Cli.verbose?
|
|
40
|
+
|
|
41
|
+
puts Paint["#{EMOJIS[:debug]} [DEBUG] #{message}", :magenta]
|
|
42
|
+
end
|
|
43
|
+
|
|
36
44
|
def pulling(version)
|
|
37
45
|
puts Paint["#{EMOJIS[:pulling]} Pulling metanorma/metanorma:#{version}...", :blue]
|
|
38
46
|
end
|
|
@@ -48,7 +56,7 @@ module Mnenv
|
|
|
48
56
|
end
|
|
49
57
|
|
|
50
58
|
def header(message)
|
|
51
|
-
puts "\n
|
|
59
|
+
puts "\n#{Paint["=== #{message} ===", :bold, :white]}\n"
|
|
52
60
|
end
|
|
53
61
|
|
|
54
62
|
def section(message)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'version'
|
|
4
|
+
|
|
5
|
+
module Mnenv
|
|
6
|
+
class BinaryVersion < ArtifactVersion
|
|
7
|
+
attribute :metadata, :hash, default: {}
|
|
8
|
+
|
|
9
|
+
key_value do
|
|
10
|
+
map 'version', to: :version
|
|
11
|
+
map 'published_at', to: :published_at
|
|
12
|
+
map 'parsed_at', to: :parsed_at
|
|
13
|
+
map 'metadata', to: :metadata
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Binary versions use plain version display (no 'v' prefix)
|
|
17
|
+
def display_name = version
|
|
18
|
+
|
|
19
|
+
# Get the release tag name (with 'v' prefix)
|
|
20
|
+
def tag_name = "v#{version}"
|
|
21
|
+
|
|
22
|
+
# Get the GitHub release URL
|
|
23
|
+
def html_url
|
|
24
|
+
metadata&.dig('html_url')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Get list of available assets for this release
|
|
28
|
+
def assets
|
|
29
|
+
metadata&.dig('assets') || []
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Get platforms info (with URLs, format, etc.)
|
|
33
|
+
def platforms
|
|
34
|
+
metadata&.dig('platforms') || []
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Check if binary is available for a specific platform
|
|
38
|
+
def binary_for_platform?(platform)
|
|
39
|
+
assets.any? { |a| a == "metanorma-#{platform}" }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Find the best matching platform entry for current system
|
|
43
|
+
# Returns the platform hash with url, format, etc.
|
|
44
|
+
def find_platform(name:, arch:, variant: nil, format: nil)
|
|
45
|
+
candidates = platforms.select { |p| p['name'] == name && p['arch'] == arch }
|
|
46
|
+
|
|
47
|
+
# Filter by variant
|
|
48
|
+
# - If variant is specified, match platforms with that variant
|
|
49
|
+
# - If variant is nil, match platforms WITHOUT a variant (glibc, not musl)
|
|
50
|
+
candidates = if variant
|
|
51
|
+
candidates.select { |p| p['variant'] == variant }
|
|
52
|
+
else
|
|
53
|
+
candidates.select { |p| p['variant'].nil? }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Filter by format if specified
|
|
57
|
+
candidates = candidates.select { |p| p['format'] == format } if format
|
|
58
|
+
|
|
59
|
+
candidates.first
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Get download URL for a specific platform/arch combination
|
|
63
|
+
def download_url(name:, arch:, variant: nil, format: nil)
|
|
64
|
+
platform = find_platform(name: name, arch: arch, variant: variant, format: format)
|
|
65
|
+
platform&.dig('url')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Get available platform names
|
|
69
|
+
def available_platforms
|
|
70
|
+
platforms.map { |p| p['name'] }.uniq
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Get available architectures for a platform
|
|
74
|
+
def available_arches_for(platform_name)
|
|
75
|
+
platforms.select { |p| p['name'] == platform_name }.map { |p| p['arch'] }.uniq
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'version'
|
|
4
|
+
require_relative '../versions_manager'
|
|
4
5
|
|
|
5
6
|
module Mnenv
|
|
6
7
|
class GemfileVersion < ArtifactVersion
|
|
@@ -8,6 +9,15 @@ module Mnenv
|
|
|
8
9
|
attribute :gemfile_path, :string
|
|
9
10
|
attribute :gemfile_lock_path, :string
|
|
10
11
|
|
|
12
|
+
# Class-level versions manager for dependency injection in tests
|
|
13
|
+
class << self
|
|
14
|
+
def versions_manager
|
|
15
|
+
@versions_manager ||= VersionsManager.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
attr_writer :versions_manager
|
|
19
|
+
end
|
|
20
|
+
|
|
11
21
|
key_value do
|
|
12
22
|
map 'version', to: :version
|
|
13
23
|
map 'published_at', to: :published_at
|
|
@@ -17,7 +27,9 @@ module Mnenv
|
|
|
17
27
|
map 'gemfile_lock_path', to: :gemfile_lock_path
|
|
18
28
|
end
|
|
19
29
|
|
|
20
|
-
def data_dir
|
|
30
|
+
def data_dir
|
|
31
|
+
@data_dir ||= File.join(self.class.versions_manager.data_path, 'gemfile')
|
|
32
|
+
end
|
|
21
33
|
|
|
22
34
|
def directory_path = File.join(data_dir, "v#{version}")
|
|
23
35
|
|
|
@@ -31,10 +43,12 @@ module Mnenv
|
|
|
31
43
|
File.file?(gemfile_lock_path_calc)
|
|
32
44
|
end
|
|
33
45
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
def to_hash
|
|
47
|
+
super.merge(
|
|
48
|
+
'gemfile_exists' => gemfile_exists,
|
|
49
|
+
'gemfile_path' => gemfile_path,
|
|
50
|
+
'gemfile_lock_path' => gemfile_lock_path
|
|
51
|
+
)
|
|
38
52
|
end
|
|
39
53
|
end
|
|
40
54
|
end
|
data/lib/mnenv/models/version.rb
CHANGED
|
@@ -16,6 +16,22 @@ module Mnenv
|
|
|
16
16
|
|
|
17
17
|
def display_name = "v#{version}"
|
|
18
18
|
|
|
19
|
+
# Serialize version to hash for persistence
|
|
20
|
+
# Subclasses should override and merge with super
|
|
21
|
+
def to_hash
|
|
22
|
+
{
|
|
23
|
+
'version' => version,
|
|
24
|
+
'published_at' => format_timestamp(published_at),
|
|
25
|
+
'parsed_at' => format_timestamp(parsed_at)
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def format_timestamp(time)
|
|
32
|
+
time&.strftime('%Y-%m-%dT%H:%M:%SZ')
|
|
33
|
+
end
|
|
34
|
+
|
|
19
35
|
protected
|
|
20
36
|
|
|
21
37
|
def version_parts = version.split('.').map(&:to_i)
|
data/lib/mnenv/models.rb
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
require 'lutaml/model'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
module Mnenv
|
|
6
|
+
autoload :ArtifactVersion, 'mnenv/models/version'
|
|
7
|
+
autoload :GemfileVersion, 'mnenv/models/gemfile_version'
|
|
8
|
+
autoload :SnapVersion, 'mnenv/models/snap_version'
|
|
9
|
+
autoload :HomebrewVersion, 'mnenv/models/homebrew_version'
|
|
10
|
+
autoload :ChocolateyVersion, 'mnenv/models/chocolatey_version'
|
|
11
|
+
end
|
data/lib/mnenv/paths.rb
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mnenv
|
|
4
|
+
# Centralized directory paths for mnenv
|
|
5
|
+
# This ensures consistency across all components
|
|
6
|
+
module Paths
|
|
7
|
+
# Base directory for all mnenv data
|
|
8
|
+
MNENV_DIR = File.expand_path('~/.mnenv').freeze
|
|
9
|
+
|
|
10
|
+
# Directory for the git clone of metanorma/versions (READ-ONLY data)
|
|
11
|
+
# Contains: data/gemfile/versions.yaml, data/gemfile/v1.14.4/Gemfile, etc.
|
|
12
|
+
VERSIONS_DATA_DIR = File.join(MNENV_DIR, 'versions').freeze
|
|
13
|
+
|
|
14
|
+
# Directory for installed Metanorma versions
|
|
15
|
+
# Contains: 1.14.3-gemfile/, 1.14.3-binary/, 1.14.4-gemfile/, etc.
|
|
16
|
+
INSTALLED_DIR = File.join(MNENV_DIR, 'installed').freeze
|
|
17
|
+
|
|
18
|
+
# Directory for shim scripts
|
|
19
|
+
SHIMS_DIR = File.join(MNENV_DIR, 'shims').freeze
|
|
20
|
+
|
|
21
|
+
# Directory for mnenv library files (resolver, etc.)
|
|
22
|
+
LIB_DIR = File.join(MNENV_DIR, 'lib', 'mnenv').freeze
|
|
23
|
+
|
|
24
|
+
# Global version file
|
|
25
|
+
VERSION_FILE = File.join(MNENV_DIR, 'version').freeze
|
|
26
|
+
|
|
27
|
+
# Global source file
|
|
28
|
+
SOURCE_FILE = File.join(MNENV_DIR, 'source').freeze
|
|
29
|
+
|
|
30
|
+
class << self
|
|
31
|
+
# Ensure all required directories exist
|
|
32
|
+
def ensure_directories
|
|
33
|
+
FileUtils.mkdir_p(MNENV_DIR)
|
|
34
|
+
FileUtils.mkdir_p(INSTALLED_DIR)
|
|
35
|
+
FileUtils.mkdir_p(SHIMS_DIR)
|
|
36
|
+
FileUtils.mkdir_p(LIB_DIR)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Get the installation directory for a specific version and source
|
|
40
|
+
# @param version [String] The version number (e.g., "1.14.4")
|
|
41
|
+
# @param source [String] The source type (e.g., "gemfile", "binary")
|
|
42
|
+
# @return [String] The full path to the installation directory
|
|
43
|
+
def version_install_dir(version, source = nil)
|
|
44
|
+
if source
|
|
45
|
+
File.join(INSTALLED_DIR, "#{version}-#{source}")
|
|
46
|
+
else
|
|
47
|
+
# Backward compatibility: if no source specified, use version only
|
|
48
|
+
File.join(INSTALLED_DIR, version)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Get the path to the data directory within the versions repo
|
|
53
|
+
def versions_data_path
|
|
54
|
+
File.join(VERSIONS_DATA_DIR, 'data')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Parse a directory name into version and source components
|
|
58
|
+
# @param dir_name [String] Directory name like "1.14.4-gemfile" or "1.14.4"
|
|
59
|
+
# @return [Array<String, String>] Tuple of [version, source] where source may be nil
|
|
60
|
+
def parse_version_dir(dir_name)
|
|
61
|
+
if dir_name =~ /^(.+)-(gemfile|binary)$/
|
|
62
|
+
[Regexp.last_match(1), Regexp.last_match(2)]
|
|
63
|
+
else
|
|
64
|
+
[dir_name, nil]
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|