mnenv 0.1.2 → 0.1.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.
- checksums.yaml +4 -4
- data/lib/mnenv/commands/snap_command.rb +10 -19
- data/lib/mnenv/gemfile/extractor.rb +2 -0
- data/lib/mnenv/models/snap_channel.rb +23 -0
- data/lib/mnenv/models/snap_version.rb +5 -14
- data/lib/mnenv/repository.rb +1 -1
- data/lib/mnenv/snap/fetcher.rb +95 -24
- data/lib/mnenv/snap/login_failed_error.rb +11 -0
- data/lib/mnenv/snap/missing_credentials_error.rb +11 -0
- data/lib/mnenv/snap/snapcraft_not_available_error.rb +11 -0
- data/lib/mnenv/snap_repository.rb +24 -39
- data/lib/mnenv/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ebbe93f7754277cc8cb84ed21cf9d8c588c8dc9edd2164a51a4e175509e0afc8
|
|
4
|
+
data.tar.gz: d6c02ff55dbf8dbc816102e603c07a0a5e947b0570cfda4b6d08c0736f5e78da
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1a6b0db4fb7021a8b82af5532632c39273afe217984487f61e21b1110738a3f2cc04221de9056d18f77b5656264bbaf7224bea5a417e2455ce26a0e8f00d0695
|
|
7
|
+
data.tar.gz: bd4196df600ebd1fcfcafc5db7baa6dc35dcf5ceafb762a6615e3fde71f3ca4d8de315d00e372b3cf836772c40d6e6c9a784bd27faf5b0aabf325044e8aac2bb
|
|
@@ -28,17 +28,9 @@ module Mnenv
|
|
|
28
28
|
desc 'refresh', 'Fetch and add new Snap versions (incremental)'
|
|
29
29
|
def refresh
|
|
30
30
|
fetcher = Snap::Fetcher.new
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# Build map of existing composite keys
|
|
34
|
-
existing_keys = repo.all.map { |v| "#{v.version}-#{v.revision}-#{v.arch}-#{v.channel}" }
|
|
31
|
+
existing = fetcher.repository.all.map(&:version)
|
|
35
32
|
remote_versions = fetcher.fetch_all
|
|
36
|
-
|
|
37
|
-
# Find truly new versions (composite key doesn't exist)
|
|
38
|
-
new_versions = remote_versions.reject do |v|
|
|
39
|
-
key = "#{v.version}-#{v.revision}-#{v.arch}-#{v.channel}"
|
|
40
|
-
existing_keys.include?(key)
|
|
41
|
-
end
|
|
33
|
+
new_versions = remote_versions.reject { |v| existing.include?(v.version) }
|
|
42
34
|
|
|
43
35
|
if new_versions.empty?
|
|
44
36
|
puts 'No new Snap versions found'
|
|
@@ -55,22 +47,21 @@ module Mnenv
|
|
|
55
47
|
puts "Revamped #{versions.size} Snap versions"
|
|
56
48
|
end
|
|
57
49
|
|
|
58
|
-
desc 'update VERSION', 'Update a specific Snap version
|
|
50
|
+
desc 'update VERSION', 'Update a specific Snap version'
|
|
59
51
|
def update(version)
|
|
60
52
|
fetcher = Snap::Fetcher.new
|
|
61
53
|
versions = fetcher.fetch_all
|
|
62
|
-
|
|
54
|
+
target = versions.find { |v| v.version == version }
|
|
63
55
|
|
|
64
|
-
if
|
|
65
|
-
puts "Snap version #{version} not found
|
|
66
|
-
puts 'Note: Historical versions no longer in Snap API cannot be updated'
|
|
56
|
+
if target.nil?
|
|
57
|
+
puts "Snap version #{version} not found"
|
|
67
58
|
exit 1
|
|
68
59
|
end
|
|
69
60
|
|
|
70
|
-
fetcher.repository.save_all(
|
|
71
|
-
puts "Updated
|
|
72
|
-
|
|
73
|
-
puts " - #{v.arch
|
|
61
|
+
fetcher.repository.save_all([target])
|
|
62
|
+
puts "Updated 1 Snap entry for version #{version}:"
|
|
63
|
+
target.channels.each do |v|
|
|
64
|
+
puts " - channel: #{v.name} arch: #{v.arch} revision: #{v.revision}"
|
|
74
65
|
end
|
|
75
66
|
end
|
|
76
67
|
|
|
@@ -80,6 +80,8 @@ module Mnenv
|
|
|
80
80
|
# Store relative paths (relative to data/gemfile directory)
|
|
81
81
|
version.gemfile_path = "v#{version.version}/Gemfile"
|
|
82
82
|
version.gemfile_lock_path = "v#{version.version}/Gemfile.lock.archived"
|
|
83
|
+
# Set parsed_at to now if not already set
|
|
84
|
+
version.parsed_at = DateTime.now if version.parsed_at.nil?
|
|
83
85
|
|
|
84
86
|
repository.save(version)
|
|
85
87
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mnenv
|
|
4
|
+
class SnapChannel < Lutaml::Model::Serializable
|
|
5
|
+
attribute :revision, :integer
|
|
6
|
+
attribute :arch, :string, default: 'amd64'
|
|
7
|
+
attribute :name, :string, default: 'stable'
|
|
8
|
+
|
|
9
|
+
key_value do
|
|
10
|
+
map 'name', to: :name
|
|
11
|
+
map 'revision', to: :revision
|
|
12
|
+
map 'arch', to: :arch
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_hash
|
|
16
|
+
super.merge(
|
|
17
|
+
'revision' => revision,
|
|
18
|
+
'arch' => arch,
|
|
19
|
+
'name' => name
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -1,29 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'version'
|
|
4
|
+
require_relative 'snap_channel'
|
|
4
5
|
|
|
5
6
|
module Mnenv
|
|
6
7
|
class SnapVersion < ArtifactVersion
|
|
7
|
-
attribute :
|
|
8
|
-
|
|
9
|
-
attribute :channel, :string, default: 'stable'
|
|
8
|
+
attribute :channels, ::Mnenv::SnapChannel,
|
|
9
|
+
collection: true, default: -> { [] }
|
|
10
10
|
|
|
11
11
|
key_value do
|
|
12
|
-
map '
|
|
13
|
-
map 'published_at', to: :published_at
|
|
14
|
-
map 'parsed_at', to: :parsed_at
|
|
15
|
-
map 'revision', to: :revision
|
|
16
|
-
map 'arch', to: :arch
|
|
17
|
-
map 'channel', to: :channel
|
|
12
|
+
map 'channels', to: :channels
|
|
18
13
|
end
|
|
19
14
|
|
|
20
|
-
def display_name = revision ? "#{version}-#{revision}" : "v#{version}"
|
|
21
|
-
|
|
22
15
|
def to_hash
|
|
23
16
|
super.merge(
|
|
24
|
-
'
|
|
25
|
-
'arch' => arch,
|
|
26
|
-
'channel' => channel
|
|
17
|
+
'channels' => channels.map(&:to_hash)
|
|
27
18
|
)
|
|
28
19
|
end
|
|
29
20
|
end
|
data/lib/mnenv/repository.rb
CHANGED
data/lib/mnenv/snap/fetcher.rb
CHANGED
|
@@ -8,6 +8,9 @@ require 'uri'
|
|
|
8
8
|
require 'json'
|
|
9
9
|
require 'fileutils'
|
|
10
10
|
require 'net/http'
|
|
11
|
+
require_relative 'missing_credentials_error'
|
|
12
|
+
require_relative 'snapcraft_not_available_error'
|
|
13
|
+
require_relative 'login_failed_error'
|
|
11
14
|
|
|
12
15
|
module Mnenv
|
|
13
16
|
module Snap
|
|
@@ -24,45 +27,112 @@ module Mnenv
|
|
|
24
27
|
ARCHITECTURES = %w[amd64 arm64].freeze
|
|
25
28
|
|
|
26
29
|
def fetch_all
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
fetch_all_from_snapcraft
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def fetch_all_from_cache
|
|
34
|
+
# Load existing versions from YAML
|
|
35
|
+
version_map = repository.all
|
|
29
36
|
|
|
30
37
|
# Fetch current heads from snap_metadata API
|
|
31
38
|
current_versions = fetch_current_heads
|
|
32
39
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
current_versions.each_key do |k|
|
|
41
|
+
next if repository.exists?(k)
|
|
42
|
+
|
|
43
|
+
# Add new version
|
|
44
|
+
version_map << SnapVersion.new(
|
|
45
|
+
version: k,
|
|
46
|
+
parsed_at: DateTime.now,
|
|
47
|
+
channels: current_versions[k].map do |cv|
|
|
48
|
+
SnapChannel.new(
|
|
49
|
+
name: cv.fetch('channel'),
|
|
50
|
+
revision: cv.fetch('revision'),
|
|
51
|
+
arch: cv.fetch('arch')
|
|
52
|
+
)
|
|
53
|
+
end
|
|
47
54
|
)
|
|
48
55
|
end
|
|
49
56
|
|
|
50
|
-
version_map
|
|
57
|
+
version_map
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def fetch_all_from_snapcraft
|
|
61
|
+
raise MissingCredentialsError unless ENV['SNAPCRAFT_STORE_CREDENTIALS']
|
|
62
|
+
raise SnapcraftNotAvailableError unless snapcraft_available?
|
|
63
|
+
|
|
64
|
+
login_result = system('echo "$SNAPCRAFT_STORE_CREDENTIALS" | snapcraft login --with -')
|
|
65
|
+
|
|
66
|
+
raise LoginFailedError unless login_result
|
|
67
|
+
|
|
68
|
+
# delete the environment variable immediately to prevent
|
|
69
|
+
# duplicate login error
|
|
70
|
+
ENV.delete('SNAPCRAFT_STORE_CREDENTIALS')
|
|
71
|
+
|
|
72
|
+
result = `snapcraft revisions metanorma`
|
|
73
|
+
snap_revisions = parse_snap_revisions(result)
|
|
74
|
+
build_snap_version_map(snap_revisions)
|
|
51
75
|
end
|
|
52
76
|
|
|
53
77
|
private
|
|
54
78
|
|
|
55
|
-
def
|
|
56
|
-
|
|
79
|
+
def snapcraft_available?
|
|
80
|
+
system('command -v snapcraft > /dev/null 2>&1')
|
|
57
81
|
end
|
|
58
82
|
|
|
59
|
-
def
|
|
60
|
-
|
|
83
|
+
def parse_snap_revisions(data)
|
|
84
|
+
lines = data.lines.map(&:strip).reject { |l| l.empty? || l.start_with?('Rev.') }
|
|
85
|
+
revisions = []
|
|
86
|
+
lines.each do |line|
|
|
87
|
+
fields = line.split(/\s{2,}/)
|
|
88
|
+
rev, uploaded, arches, version, channels = fields
|
|
89
|
+
revisions << {
|
|
90
|
+
version: version,
|
|
91
|
+
published_at: uploaded,
|
|
92
|
+
revision: rev,
|
|
93
|
+
arch: arches,
|
|
94
|
+
channels: channels
|
|
95
|
+
}
|
|
96
|
+
end
|
|
97
|
+
revisions
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def build_snap_version_map(snap_revisions)
|
|
101
|
+
versions = []
|
|
102
|
+
latest_version = snap_revisions.first[:version]
|
|
103
|
+
|
|
104
|
+
snap_revisions.each do |sr|
|
|
105
|
+
snap_version = versions.find { |v| v&.version == sr[:version] }
|
|
106
|
+
if snap_version.nil?
|
|
107
|
+
snap_version = SnapVersion.new
|
|
108
|
+
snap_version.version = sr[:version]
|
|
109
|
+
snap_version.published_at = sr[:published_at]
|
|
110
|
+
snap_version.parsed_at = DateTime.now
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
channels = sr[:channels].split(',').map(&:strip)
|
|
114
|
+
channels.each do |channel|
|
|
115
|
+
next unless channel.start_with? 'latest/'
|
|
116
|
+
|
|
117
|
+
channel = channel.sub('latest/', '')
|
|
118
|
+
next if (sr[:version] == latest_version) && !channel.end_with?('*')
|
|
119
|
+
|
|
120
|
+
snap_version.channels << SnapChannel.new(
|
|
121
|
+
name: channel.gsub('*', ''),
|
|
122
|
+
revision: sr[:revision],
|
|
123
|
+
arch: sr[:arch]
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
versions << snap_version
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
versions.reverse
|
|
61
131
|
end
|
|
62
132
|
|
|
63
133
|
# Fetch current heads from snap_metadata API for all channel/arch combinations
|
|
64
134
|
def fetch_current_heads
|
|
65
|
-
versions =
|
|
135
|
+
versions = {}
|
|
66
136
|
|
|
67
137
|
CHANNELS.each do |channel|
|
|
68
138
|
ARCHITECTURES.each do |arch|
|
|
@@ -88,8 +158,9 @@ module Mnenv
|
|
|
88
158
|
|
|
89
159
|
if data['_embedded'] && data['_embedded']['clickindex:package']
|
|
90
160
|
pkg = data['_embedded']['clickindex:package'][0]
|
|
91
|
-
|
|
92
|
-
|
|
161
|
+
|
|
162
|
+
versions[pkg['version']] ||= []
|
|
163
|
+
versions[pkg['version']] << {
|
|
93
164
|
'revision' => pkg['revision'],
|
|
94
165
|
'arch' => arch,
|
|
95
166
|
'channel' => channel
|
|
@@ -8,45 +8,30 @@ module Mnenv
|
|
|
8
8
|
def version_class = SnapVersion
|
|
9
9
|
def source_name = :snap
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
def snap_key(*args)
|
|
39
|
-
case args.size
|
|
40
|
-
when 1
|
|
41
|
-
# Single SnapVersion object
|
|
42
|
-
v = args.first
|
|
43
|
-
"#{v.version}-#{v.revision}-#{v.arch}-#{v.channel}"
|
|
44
|
-
when 4
|
|
45
|
-
# version, revision, arch, channel
|
|
46
|
-
version_number, revision, arch, channel = args
|
|
47
|
-
"#{version_number}-#{revision}-#{arch}-#{channel}"
|
|
48
|
-
else
|
|
49
|
-
raise ArgumentError, 'snap_key requires 1 or 4 arguments'
|
|
11
|
+
protected
|
|
12
|
+
|
|
13
|
+
def load
|
|
14
|
+
data = fetch_versions_data
|
|
15
|
+
|
|
16
|
+
return if data.nil? || data['versions'].nil?
|
|
17
|
+
|
|
18
|
+
data['versions'].each do |version_hash|
|
|
19
|
+
channels = version_hash['channels'].map do |c|
|
|
20
|
+
SnapChannel.new(
|
|
21
|
+
name: c['name'],
|
|
22
|
+
revision: c['revision'],
|
|
23
|
+
arch: c['arch']
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
version = SnapVersion.new.tap do |v|
|
|
28
|
+
v.version = version_hash['version']
|
|
29
|
+
v.published_at = version_hash['published_at']
|
|
30
|
+
v.parsed_at = version_hash['parsed_at']
|
|
31
|
+
v.channels = channels
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
cache_version(version)
|
|
50
35
|
end
|
|
51
36
|
end
|
|
52
37
|
end
|
data/lib/mnenv/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mnenv
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-03-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -206,6 +206,7 @@ files:
|
|
|
206
206
|
- lib/mnenv/models/chocolatey_version.rb
|
|
207
207
|
- lib/mnenv/models/gemfile_version.rb
|
|
208
208
|
- lib/mnenv/models/homebrew_version.rb
|
|
209
|
+
- lib/mnenv/models/snap_channel.rb
|
|
209
210
|
- lib/mnenv/models/snap_version.rb
|
|
210
211
|
- lib/mnenv/models/version.rb
|
|
211
212
|
- lib/mnenv/paths.rb
|
|
@@ -220,6 +221,9 @@ files:
|
|
|
220
221
|
- lib/mnenv/shim_manager.rb
|
|
221
222
|
- lib/mnenv/snap.rb
|
|
222
223
|
- lib/mnenv/snap/fetcher.rb
|
|
224
|
+
- lib/mnenv/snap/login_failed_error.rb
|
|
225
|
+
- lib/mnenv/snap/missing_credentials_error.rb
|
|
226
|
+
- lib/mnenv/snap/snapcraft_not_available_error.rb
|
|
223
227
|
- lib/mnenv/snap_repository.rb
|
|
224
228
|
- lib/mnenv/source_registry.rb
|
|
225
229
|
- lib/mnenv/sources.rb
|