gel 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/exe/gel +13 -0
- data/lib/gel.rb +22 -0
- data/lib/gel/catalog.rb +153 -0
- data/lib/gel/catalog/common.rb +82 -0
- data/lib/gel/catalog/compact_index.rb +152 -0
- data/lib/gel/catalog/dependency_index.rb +125 -0
- data/lib/gel/catalog/legacy_index.rb +157 -0
- data/lib/gel/catalog/marshal_hacks.rb +16 -0
- data/lib/gel/command.rb +86 -0
- data/lib/gel/command/config.rb +11 -0
- data/lib/gel/command/env.rb +7 -0
- data/lib/gel/command/exec.rb +66 -0
- data/lib/gel/command/help.rb +7 -0
- data/lib/gel/command/install.rb +7 -0
- data/lib/gel/command/install_gem.rb +16 -0
- data/lib/gel/command/lock.rb +34 -0
- data/lib/gel/command/ruby.rb +10 -0
- data/lib/gel/command/shell_setup.rb +25 -0
- data/lib/gel/command/stub.rb +12 -0
- data/lib/gel/command/update.rb +11 -0
- data/lib/gel/compatibility.rb +4 -0
- data/lib/gel/compatibility/bundler.rb +54 -0
- data/lib/gel/compatibility/bundler/cli.rb +6 -0
- data/lib/gel/compatibility/bundler/friendly_errors.rb +3 -0
- data/lib/gel/compatibility/bundler/setup.rb +4 -0
- data/lib/gel/compatibility/rubygems.rb +192 -0
- data/lib/gel/compatibility/rubygems/command.rb +4 -0
- data/lib/gel/compatibility/rubygems/dependency_installer.rb +0 -0
- data/lib/gel/compatibility/rubygems/gem_runner.rb +6 -0
- data/lib/gel/config.rb +80 -0
- data/lib/gel/db.rb +294 -0
- data/lib/gel/direct_gem.rb +29 -0
- data/lib/gel/environment.rb +592 -0
- data/lib/gel/error.rb +104 -0
- data/lib/gel/gemfile_parser.rb +144 -0
- data/lib/gel/gemspec_parser.rb +95 -0
- data/lib/gel/git_catalog.rb +38 -0
- data/lib/gel/git_depot.rb +119 -0
- data/lib/gel/httpool.rb +148 -0
- data/lib/gel/installer.rb +251 -0
- data/lib/gel/lock_loader.rb +164 -0
- data/lib/gel/lock_parser.rb +64 -0
- data/lib/gel/locked_store.rb +126 -0
- data/lib/gel/multi_store.rb +96 -0
- data/lib/gel/package.rb +156 -0
- data/lib/gel/package/inspector.rb +23 -0
- data/lib/gel/package/installer.rb +267 -0
- data/lib/gel/path_catalog.rb +44 -0
- data/lib/gel/pinboard.rb +140 -0
- data/lib/gel/pub_grub/preference_strategy.rb +82 -0
- data/lib/gel/pub_grub/source.rb +153 -0
- data/lib/gel/runtime.rb +27 -0
- data/lib/gel/store.rb +205 -0
- data/lib/gel/store_catalog.rb +31 -0
- data/lib/gel/store_gem.rb +80 -0
- data/lib/gel/stub_set.rb +51 -0
- data/lib/gel/support/gem_platform.rb +225 -0
- data/lib/gel/support/gem_requirement.rb +264 -0
- data/lib/gel/support/gem_version.rb +398 -0
- data/lib/gel/support/tar.rb +13 -0
- data/lib/gel/support/tar/tar_header.rb +229 -0
- data/lib/gel/support/tar/tar_reader.rb +123 -0
- data/lib/gel/support/tar/tar_reader/entry.rb +154 -0
- data/lib/gel/support/tar/tar_writer.rb +339 -0
- data/lib/gel/tail_file.rb +205 -0
- data/lib/gel/version.rb +5 -0
- data/lib/gel/work_pool.rb +143 -0
- data/man/man1/gel-exec.1 +16 -0
- data/man/man1/gel-install.1 +16 -0
- data/man/man1/gel.1 +30 -0
- metadata +131 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "strscan"
|
4
|
+
|
5
|
+
class Gel::LockParser
|
6
|
+
def parse(content)
|
7
|
+
sections = []
|
8
|
+
|
9
|
+
scanner = StringScanner.new(content)
|
10
|
+
while section = scanner.scan(/^(\w.+)\n/)
|
11
|
+
section.chomp!
|
12
|
+
case section
|
13
|
+
when "GIT", "PATH", "GEM"
|
14
|
+
content = {}
|
15
|
+
while scanner.skip(/^ \b/)
|
16
|
+
label = scanner.scan(/[^:]+:/).chop
|
17
|
+
if scanner.skip(/ /)
|
18
|
+
value = scanner.scan(/.*/)
|
19
|
+
scanner.skip(/\n/)
|
20
|
+
(content[label] ||= []) << value
|
21
|
+
else
|
22
|
+
scanner.skip(/\n/)
|
23
|
+
value = []
|
24
|
+
while scanner.skip(/^ \b/)
|
25
|
+
entry = scanner.scan(/.*/)
|
26
|
+
scanner.skip(/\n/)
|
27
|
+
children = []
|
28
|
+
while scanner.skip(/^ \b/)
|
29
|
+
child = scanner.scan(/.*/)
|
30
|
+
children << child
|
31
|
+
scanner.skip(/\n/)
|
32
|
+
end
|
33
|
+
if children.empty?
|
34
|
+
value << [entry]
|
35
|
+
else
|
36
|
+
value << [entry, children]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
content[label] = value
|
40
|
+
end
|
41
|
+
end
|
42
|
+
when "PLATFORMS", "DEPENDENCIES"
|
43
|
+
content = []
|
44
|
+
while scanner.skip(/^ \b/)
|
45
|
+
entry = scanner.scan(/.*/)
|
46
|
+
content << entry
|
47
|
+
scanner.skip(/\n/)
|
48
|
+
end
|
49
|
+
when "BUNDLED WITH"
|
50
|
+
content = []
|
51
|
+
while scanner.skip(/^ \b/)
|
52
|
+
entry = scanner.scan(/.*/)
|
53
|
+
content << entry
|
54
|
+
scanner.skip(/\n/)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
scanner.skip(/\n+/)
|
58
|
+
|
59
|
+
sections << [section, content]
|
60
|
+
end
|
61
|
+
|
62
|
+
sections
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gel::LockedStore
|
4
|
+
attr_reader :inner
|
5
|
+
|
6
|
+
def initialize(inner)
|
7
|
+
@inner = inner
|
8
|
+
@locked_versions = nil
|
9
|
+
|
10
|
+
@lib_cache = Hash.new { |h, k| h[k] = [] }
|
11
|
+
@full_cache = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def paths
|
15
|
+
@inner.paths
|
16
|
+
end
|
17
|
+
|
18
|
+
def root
|
19
|
+
@inner.root
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
content = @locked_versions.map { |name, version| "#{name}=#{version.is_a?(String) ? version : version.root}" }
|
24
|
+
content = ["(none)"] if content.empty?
|
25
|
+
content.sort!
|
26
|
+
|
27
|
+
"#<#{self.class} inner=#{@inner.inspect} locks=#{content.join(",")}>"
|
28
|
+
end
|
29
|
+
|
30
|
+
def prepare(locks)
|
31
|
+
return if @full_cache
|
32
|
+
|
33
|
+
inner_versions = {}
|
34
|
+
locks.each do |name, version|
|
35
|
+
if version.is_a?(Gel::StoreGem)
|
36
|
+
version.libs do |file, subdir|
|
37
|
+
@lib_cache[file] << [version, subdir]
|
38
|
+
end
|
39
|
+
else
|
40
|
+
inner_versions[name] = version
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
g = @inner.gems(inner_versions)
|
45
|
+
@inner.libs_for_gems(inner_versions) do |name, version, subs|
|
46
|
+
subs.each do |subdir, files|
|
47
|
+
v = [g[name], subdir]
|
48
|
+
files.each do |file|
|
49
|
+
@lib_cache[file] << v
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def lock(locks)
|
56
|
+
@locked_versions = locks.dup
|
57
|
+
prepare(locks)
|
58
|
+
@full_cache = true
|
59
|
+
end
|
60
|
+
|
61
|
+
def locked?(gem)
|
62
|
+
!@locked_versions || @locked_versions[gem.name] == gem.version
|
63
|
+
end
|
64
|
+
|
65
|
+
def locked_gems
|
66
|
+
@locked_versions ? @locked_versions.values.grep(Gel::StoreGem) : []
|
67
|
+
end
|
68
|
+
|
69
|
+
def gem(name, version)
|
70
|
+
if !@locked_versions || @locked_versions[name] == version
|
71
|
+
@inner.gem(name, version)
|
72
|
+
else
|
73
|
+
locked_gems.find { |g| g.name == name && g.version == version }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def gems(name_version_pairs)
|
78
|
+
r = @inner.gems(name_version_pairs)
|
79
|
+
locked_gems.each do |g|
|
80
|
+
r[g.name] = g
|
81
|
+
end
|
82
|
+
r
|
83
|
+
end
|
84
|
+
|
85
|
+
def gems_for_lib(file)
|
86
|
+
if c = @lib_cache.fetch(file, nil)
|
87
|
+
c.each { |gem, subdir| yield gem, subdir }
|
88
|
+
return
|
89
|
+
end
|
90
|
+
|
91
|
+
hits = []
|
92
|
+
unless @full_cache
|
93
|
+
@inner.gems_for_lib(file) do |gem, subdir|
|
94
|
+
if locked?(gem)
|
95
|
+
hits << [gem, subdir]
|
96
|
+
yield gem, subdir
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
locked_gems.each do |gem|
|
102
|
+
if File.exist?(gem.path(file) + ".rb")
|
103
|
+
hits << [gem, nil]
|
104
|
+
yield gem, nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
@lib_cache[file] = hits
|
109
|
+
end
|
110
|
+
|
111
|
+
def each(gem_name = nil)
|
112
|
+
return enum_for(__callee__, gem_name) unless block_given?
|
113
|
+
|
114
|
+
list = locked_gems
|
115
|
+
|
116
|
+
@inner.each(gem_name) do |gem|
|
117
|
+
next unless locked?(gem)
|
118
|
+
yield gem
|
119
|
+
list.delete gem
|
120
|
+
end
|
121
|
+
|
122
|
+
list.each do |gem|
|
123
|
+
yield gem if !gem_name || gem.name == gem_name
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rbconfig"
|
4
|
+
require_relative "stub_set"
|
5
|
+
|
6
|
+
class Gel::MultiStore
|
7
|
+
VERSION = "#{RbConfig::CONFIG["ruby_version"]}"
|
8
|
+
|
9
|
+
attr_reader :root
|
10
|
+
attr_reader :monitor
|
11
|
+
|
12
|
+
def initialize(root, stores)
|
13
|
+
@root = File.realpath(File.expand_path(root)) if root
|
14
|
+
@stores = stores
|
15
|
+
|
16
|
+
@monitor = Monitor.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def stub_set
|
20
|
+
@stub_set ||= Gel::StubSet.new(@root)
|
21
|
+
end
|
22
|
+
|
23
|
+
def paths
|
24
|
+
@stores.values.flat_map(&:paths).uniq
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](architecture, version = false)
|
28
|
+
@stores[self.class.subkey(architecture, version)]
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.subkey(architecture, version)
|
32
|
+
architecture ||= "ruby"
|
33
|
+
if version && architecture == "ruby"
|
34
|
+
VERSION
|
35
|
+
elsif version
|
36
|
+
"#{architecture}-#{VERSION}"
|
37
|
+
else
|
38
|
+
"#{architecture}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def prepare(versions)
|
43
|
+
@stores.each do |_, store|
|
44
|
+
store.prepare(versions)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def gems_for_lib(file)
|
49
|
+
@stores.each do |_, store|
|
50
|
+
store.gems_for_lib(file) do |gem, subdir|
|
51
|
+
yield gem, subdir
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def each(gem_name = nil, &block)
|
57
|
+
return enum_for(__callee__, gem_name) unless block_given?
|
58
|
+
|
59
|
+
@stores.each do |_, store|
|
60
|
+
store.each(gem_name, &block)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def gem(name, version)
|
65
|
+
@stores.each do |_, store|
|
66
|
+
g = store.gem(name, version)
|
67
|
+
return g if g
|
68
|
+
end
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def gems(name_version_pairs)
|
73
|
+
result = {}
|
74
|
+
|
75
|
+
@stores.each do |_, store|
|
76
|
+
result.update(store.gems(name_version_pairs)) do |l, r|
|
77
|
+
l
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
result
|
82
|
+
end
|
83
|
+
|
84
|
+
def gem?(name, version, platform = nil)
|
85
|
+
@stores.any? do |key, store|
|
86
|
+
next if platform && !key.start_with?(platform)
|
87
|
+
store.gem?(name, version)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def libs_for_gems(versions, &block)
|
92
|
+
@stores.each do |_, store|
|
93
|
+
store.libs_for_gems(versions, &block)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/gel/package.rb
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zlib"
|
4
|
+
require "yaml"
|
5
|
+
|
6
|
+
require_relative "support/tar"
|
7
|
+
|
8
|
+
module Gel
|
9
|
+
class Package
|
10
|
+
class Specification
|
11
|
+
def initialize(inner)
|
12
|
+
@inner = inner
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
@inner.name
|
17
|
+
end
|
18
|
+
|
19
|
+
def version
|
20
|
+
@inner.version
|
21
|
+
end
|
22
|
+
|
23
|
+
def architecture
|
24
|
+
@inner.architecture
|
25
|
+
end
|
26
|
+
|
27
|
+
def bindir
|
28
|
+
@inner.bindir
|
29
|
+
end
|
30
|
+
|
31
|
+
def executables
|
32
|
+
@inner.executables
|
33
|
+
end
|
34
|
+
|
35
|
+
def require_paths
|
36
|
+
@inner.require_paths
|
37
|
+
end
|
38
|
+
|
39
|
+
def extensions
|
40
|
+
@inner.extensions
|
41
|
+
end
|
42
|
+
|
43
|
+
def runtime_dependencies
|
44
|
+
h = {}
|
45
|
+
@inner.dependencies.each do |dep|
|
46
|
+
next unless dep.type == :runtime || dep.type.nil?
|
47
|
+
req = dep.requirement || dep.version_requirements
|
48
|
+
h[dep.name] = req.requirements.map { |pair| pair.map(&:to_s) }
|
49
|
+
end
|
50
|
+
h
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class YAMLLoader < ::YAML::ClassLoader::Restricted
|
55
|
+
#--
|
56
|
+
# Based on YAML.safe_load
|
57
|
+
def self.load(yaml, filename)
|
58
|
+
result = if Psych::VERSION < "3.1" # Ruby 2.5 & below
|
59
|
+
::YAML.parse(yaml, filename)
|
60
|
+
else
|
61
|
+
::YAML.parse(yaml, filename: filename)
|
62
|
+
end
|
63
|
+
return unless result
|
64
|
+
|
65
|
+
class_loader = self.new
|
66
|
+
scanner = ::YAML::ScalarScanner.new class_loader
|
67
|
+
|
68
|
+
visitor = ::YAML::Visitors::ToRuby.new scanner, class_loader
|
69
|
+
visitor.accept result
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize
|
73
|
+
super(%w(Symbol Time), [])
|
74
|
+
end
|
75
|
+
|
76
|
+
def find(klass)
|
77
|
+
case klass
|
78
|
+
when "Gem::Specification"
|
79
|
+
Gem_Specification
|
80
|
+
when "Gem::Version"
|
81
|
+
Gem_Version
|
82
|
+
when "Gem::Version::Requirement", "Gem::Requirement"
|
83
|
+
Gem_Requirement
|
84
|
+
when "Gem::Platform"
|
85
|
+
Gem_Platform
|
86
|
+
when "Gem::Dependency"
|
87
|
+
Gem_Dependency
|
88
|
+
else
|
89
|
+
super
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Gem_Specification
|
94
|
+
attr_accessor :architecture, :bindir, :executables, :name, :require_paths, :specification_version, :version, :dependencies, :extensions
|
95
|
+
end
|
96
|
+
class Gem_Dependency
|
97
|
+
attr_accessor :name, :requirement, :type, :version_requirements
|
98
|
+
end
|
99
|
+
class Gem_Platform; end
|
100
|
+
Gem_Version = Gel::Support::GemVersion
|
101
|
+
class Gem_Requirement
|
102
|
+
attr_accessor :requirements
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.with_file(reader, filename, checksums)
|
107
|
+
reader.seek(filename) do |stream|
|
108
|
+
if checksums
|
109
|
+
data = stream.read
|
110
|
+
stream.rewind
|
111
|
+
|
112
|
+
checksums.each do |type, map|
|
113
|
+
next unless %w(SHA1 SHA512).include?(type)
|
114
|
+
calculated = Digest(type).hexdigest(data)
|
115
|
+
raise "#{type} checksum mismatch on #{filename}" unless calculated == map[filename]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
yield stream
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.extract(filename, receiver)
|
124
|
+
File.open(filename) do |io|
|
125
|
+
Gel::Support::Tar::TarReader.new(io) do |package_reader|
|
126
|
+
sums = with_file(package_reader, "checksums.yaml.gz", nil) do |sum_stream|
|
127
|
+
yaml = Zlib::GzipReader.new(sum_stream).read
|
128
|
+
|
129
|
+
if Psych::VERSION < "3.1" # Ruby 2.5 & below
|
130
|
+
::YAML.safe_load(yaml, [], [], false, "#{filename}:checksums.yaml.gz")
|
131
|
+
else
|
132
|
+
::YAML.safe_load(yaml, filename: "#{filename}:checksums.yaml.gz")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
spec = with_file(package_reader, "metadata.gz", sums) do |meta_stream|
|
137
|
+
yaml = Zlib::GzipReader.new(meta_stream).read
|
138
|
+
loaded = YAMLLoader.load(yaml, "#{filename}:metadata.gz")
|
139
|
+
Specification.new(loaded)
|
140
|
+
end or raise "no metadata.gz"
|
141
|
+
|
142
|
+
return receiver.gem(spec) do |target|
|
143
|
+
with_file(package_reader, "data.tar.gz", sums) do |data_stream|
|
144
|
+
Gel::Support::Tar::TarReader.new(Zlib::GzipReader.new(data_stream)) do |data_reader|
|
145
|
+
data_reader.each do |entry|
|
146
|
+
target.file(entry.full_name, entry, entry.header.mode)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
true
|
150
|
+
end or raise "no data.tar.gz"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gel
|
4
|
+
class Package
|
5
|
+
class Inspector
|
6
|
+
def initialize(&block)
|
7
|
+
@block = block
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :spec
|
11
|
+
|
12
|
+
def gem(spec)
|
13
|
+
@spec = spec
|
14
|
+
|
15
|
+
yield self if @block
|
16
|
+
end
|
17
|
+
|
18
|
+
def file(filename, io, _mode)
|
19
|
+
@block.call filename, io
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|