rubygems-requirements-system 0.0.2 → 0.0.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/README.md +138 -3
- data/doc/text/news.md +12 -0
- data/lib/rubygems-requirements-system/installer.rb +17 -76
- data/lib/rubygems-requirements-system/os-release.rb +1 -1
- data/lib/rubygems-requirements-system/package.rb +21 -0
- data/lib/rubygems-requirements-system/platform/base.rb +19 -3
- data/lib/rubygems-requirements-system/platform/debian.rb +67 -4
- data/lib/rubygems-requirements-system/platform/fedora.rb +76 -4
- data/lib/rubygems-requirements-system/platform/red-hat-enterprise-linux.rb +5 -5
- data/lib/rubygems-requirements-system/platform/ubuntu.rb +2 -2
- data/lib/rubygems-requirements-system/requirement.rb +36 -0
- data/lib/rubygems-requirements-system/requirements-parser.rb +112 -0
- data/lib/rubygems-requirements-system/system-repository.rb +48 -0
- data/lib/rubygems-requirements-system/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82e9618b8faccc8a97c5bed8acff02ae39a405e94bb02d9353ad5dc264dda420
|
4
|
+
data.tar.gz: f20b793d2dc732c13d2f6c581f103697de2f489afca060eef6e386576f814e3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9d9abee1cf5832aa8b0d883218addaa3c59cfed9128f3abd836787a2b8e018eb68b04794ded74231691effd09d06dce8809eb01eceae33e8158bce1f7c84558
|
7
|
+
data.tar.gz: e420c6d08d4f28c7407622f1417dfbd5b90bf7444146812a0ed6795fd6c829bcd1945a8a24ce22d0660a242cf247861328bda7a983442346d1608c76fbc22cea
|
data/README.md
CHANGED
@@ -173,7 +173,7 @@ Gem::Specification.new do |spec|
|
|
173
173
|
#
|
174
174
|
# On Ubuntu 24.04:
|
175
175
|
# https://packages.groonga.org/%{distribution}/groonga-apt-source-latest-%{code_name}.deb ->
|
176
|
-
# https://packages.groonga.org/ubuntu/groonga-apt-source-latest-
|
176
|
+
# https://packages.groonga.org/ubuntu/groonga-apt-source-latest-noble.deb
|
177
177
|
spec.requirements << "system: groonga: debian: https://packages.groonga.org/%{distribution}/groonga-apt-source-latest-%{code_name}.deb"
|
178
178
|
# Install libgroonga-dev from the registered repository.
|
179
179
|
spec.requirements << "system: groonga: debian: libgroonga-dev"
|
@@ -207,10 +207,145 @@ Gem::Specification.new do |spec|
|
|
207
207
|
end
|
208
208
|
```
|
209
209
|
|
210
|
+
### Install repositories
|
211
|
+
|
212
|
+
You can install APT/Yum repositories by specifying metadata.
|
213
|
+
|
214
|
+
You need to specify multiple metadata for one repository. So you need
|
215
|
+
to use multiple `spec.requirements` for one repository. Here is the
|
216
|
+
syntax for one repository:
|
217
|
+
|
218
|
+
```ruby
|
219
|
+
spec.requirements << "system: #{package}: #{platform}: repository: #{key1}: #{value1}"
|
220
|
+
spec.requirements << "system: #{package}: #{platform}: repository: #{key2}: #{value2}"
|
221
|
+
# ...
|
222
|
+
```
|
223
|
+
|
224
|
+
You must specify at least `id` as `key`. For example:
|
225
|
+
|
226
|
+
```
|
227
|
+
spec.requirements << "system: libpq: debian: repository: id: pgdg"
|
228
|
+
```
|
229
|
+
|
230
|
+
You can start another repository metadata by starting `id` metadata
|
231
|
+
for another repository:
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
spec.requirements << "system: #{package}: #{platform}: repository: id: repository1
|
235
|
+
spec.requirements << "system: #{package}: #{platform}: repository: #{key1_1}: #{value1_1}"
|
236
|
+
spec.requirements << "system: #{package}: #{platform}: repository: #{key1_2}: #{value1_2}"
|
237
|
+
# ...
|
238
|
+
spec.requirements << "system: #{package}: #{platform}: repository: id: repository2
|
239
|
+
spec.requirements << "system: #{package}: #{platform}: repository: #{key2_1}: #{value2_1}"
|
240
|
+
spec.requirements << "system: #{package}: #{platform}: repository: #{key2_2}: #{value2_2}"
|
241
|
+
# ...
|
242
|
+
```
|
243
|
+
|
244
|
+
Here are metadata for a APT repository:
|
245
|
+
|
246
|
+
* `compoennts`: Optional. The default is `main`.
|
247
|
+
* `signed-by`: Optional. The URL of armored keyring that is used for
|
248
|
+
signing this repository.
|
249
|
+
* `suites`: Optional. The default is `%{code_name}`.
|
250
|
+
* `types`: Optional. The default is `deb`.
|
251
|
+
* `uris`: Required. The URLs that provide this repository.
|
252
|
+
|
253
|
+
See also: https://wiki.debian.org/SourcesList
|
254
|
+
|
255
|
+
Here are metadata for a Yum repository:
|
256
|
+
|
257
|
+
* `baseurl`: Required. The base URL that provides this repository.
|
258
|
+
* `gpgkey`: Optional. The URL of GPG key that is used for signing this
|
259
|
+
repository.
|
260
|
+
* `name`: Optional. The name of this repository.
|
261
|
+
|
262
|
+
See also: TODO: Is there any URL that describes the specification of
|
263
|
+
`.repo` file?
|
264
|
+
|
265
|
+
You can use placeholder for metadata values with `%{KEY}` format.
|
266
|
+
|
267
|
+
Here are available placeholders:
|
268
|
+
|
269
|
+
`debian` family platforms:
|
270
|
+
|
271
|
+
* `distribution`: The `ID` value in `/etc/os-release`. It's `debian`,
|
272
|
+
`ubuntu` and so on.
|
273
|
+
* `code_name`: The `VERSION_CODENAME` value in `/etc/os-release`. It's
|
274
|
+
`bookworm`, `noble` and so on.
|
275
|
+
* `version`: The `VERSION_ID` value in `/etc/os-release`. It's `12`,
|
276
|
+
`24.04` and so on.
|
277
|
+
|
278
|
+
`fedora` family platforms:
|
279
|
+
|
280
|
+
* `distribution`: The `ID` value in `/etc/os-release`. It's `fedora`,
|
281
|
+
`rhel`, `almalinux` and so on.
|
282
|
+
* `major_version`: The major part of `VERSION_ID` value in
|
283
|
+
`/etc/os-release`. It's `41`, `9` and so on.
|
284
|
+
* `version`: The `VERSION_ID` value in `/etc/os-release`. It's `41`,
|
285
|
+
`9.5` and so on.
|
286
|
+
|
287
|
+
Here is an example that uses this feature for adding a new repository:
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
Gem::Specification.new do |spec|
|
291
|
+
# ...
|
292
|
+
|
293
|
+
# Install PostgreSQL's APT repository on Debian family platforms.
|
294
|
+
#
|
295
|
+
# %{code_name} is placeholders.
|
296
|
+
#
|
297
|
+
# On Debian GNU/Linux bookworm:
|
298
|
+
# %{code_name}-pgdg ->
|
299
|
+
# bookworm-pgdg
|
300
|
+
#
|
301
|
+
# On Ubuntu 24.04:
|
302
|
+
# %{code_name}-pgdg ->
|
303
|
+
# noble-pgdg
|
304
|
+
spec.requirements << "system: libpq: debian: repository: id: pgdg"
|
305
|
+
spec.requirements << "system: libpq: debian: repository: uris: https://apt.postgresql.org/pub/repos/apt"
|
306
|
+
spec.requirements << "system: libpq: debian: repository: signed-by: https://www.postgresql.org/media/keys/ACCC4CF8.asc"
|
307
|
+
spec.requirements << "system: libpq: debian: repository: suites: %{code_name}-pgdg"
|
308
|
+
spec.requirements << "system: libpq: debian: repository: components: main"
|
309
|
+
# Install libpq-dev from the registered repository.
|
310
|
+
spec.requirements << "system: libpq: debian: libpq-dev"
|
311
|
+
|
312
|
+
# Install PostgreSQL's Yum repository on RHEL family platforms:
|
313
|
+
spec.requirements << "system: libpq: rhel: repository: id: pgdg17"
|
314
|
+
spec.requirements << "system: libpq: rhel: repository: name: PostgreSQL 17 $releasever - $basearch"
|
315
|
+
spec.requirements << "system: libpq: rhel: repository: baseurl: https://download.postgresql.org/pub/repos/yum/17/redhat/rhel-$releasever-$basearch"
|
316
|
+
spec.requirements << "system: libpq: rhel: repository: gpgkey: https://download.postgresql.org/pub/repos/yum/keys/PGDG-RPM-GPG-KEY-RHEL"
|
317
|
+
# You can disable built-in "postgresql" module by "module: disable:
|
318
|
+
# postgresql".
|
319
|
+
spec.requirements << "system: libpq: rhel: module: disable: postgresql"
|
320
|
+
# Install postgresql17-devel from the registered repository. But
|
321
|
+
# users can't find "libpq.pc" provided by postgresql17-devel without
|
322
|
+
# PKG_CONFIG_PATH=/usr/pgsql-17/lib/pkgconfig ...
|
323
|
+
spec.requirements << "system: libpq: rhel: postgresql17-devel"
|
324
|
+
|
325
|
+
# ...
|
326
|
+
end
|
327
|
+
```
|
328
|
+
|
329
|
+
## Configurations
|
330
|
+
|
331
|
+
### Opt-out
|
332
|
+
|
333
|
+
If you don't like that gems may install system packages automatically,
|
334
|
+
you can disable this feature by the followings:
|
335
|
+
|
336
|
+
1. Set `RUBYGEMS_REQUIREMENTS_SYSTEM=false`
|
337
|
+
2. Add the following configuration to `~/.gemrc`:
|
338
|
+
|
339
|
+
```yaml
|
340
|
+
requirements_system:
|
341
|
+
enabled: true
|
342
|
+
```
|
343
|
+
|
210
344
|
## Requirements
|
211
345
|
|
212
|
-
RubyGems 3.
|
213
|
-
plugin immediately since 3.
|
346
|
+
RubyGems 3.4.14 or later is required. RubyGems can load installed
|
347
|
+
plugin immediately since 3.4.14. Ruby 3.2.3 or later ships RubyGems
|
348
|
+
3.4.14 or later.
|
214
349
|
|
215
350
|
If `gem install glib2` installs rubygems-requirements-system gem as a
|
216
351
|
dependency, old RubyGems doesn't use a RubyGems plugin in
|
data/doc/text/news.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 0.0.3 - 2025-01-13
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* Added support for opt-out.
|
8
|
+
|
9
|
+
* debian: Added support for adding APT repository by raw metadata.
|
10
|
+
|
11
|
+
* fedora: Added support for adding Yum repository by raw metadata.
|
12
|
+
|
13
|
+
* fedora: Added support for enabling/disabling module.
|
14
|
+
|
3
15
|
## 0.0.2 - 2025-01-08
|
4
16
|
|
5
17
|
### Improvements
|
@@ -20,40 +20,9 @@ require "pkg-config"
|
|
20
20
|
require_relative "version"
|
21
21
|
|
22
22
|
require_relative "platform"
|
23
|
+
require_relative "requirements-parser"
|
23
24
|
|
24
25
|
module RubyGemsRequirementsSystem
|
25
|
-
Package = Struct.new(:id, :operator, :version) do
|
26
|
-
def valid?
|
27
|
-
return false if id.empty?
|
28
|
-
return false if operator and version.nil?
|
29
|
-
true
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
Requirement = Struct.new(:packages, :system_packages) do
|
34
|
-
def satisfied?
|
35
|
-
packages.any? do |package|
|
36
|
-
installed?(package)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
def installed?(package)
|
42
|
-
package_config = PKGConfig.package_config(package.id)
|
43
|
-
begin
|
44
|
-
package_config.cflags
|
45
|
-
rescue PackageConfig::NotFoundError
|
46
|
-
return false
|
47
|
-
end
|
48
|
-
|
49
|
-
return true if package.version.nil?
|
50
|
-
|
51
|
-
current_version = Gem::Version.new(package_config.version)
|
52
|
-
required_version = Gem::Version.new(package.version)
|
53
|
-
current_version.__send__(package.operator, required_version)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
26
|
class Installer
|
58
27
|
include Gem::UserInteraction
|
59
28
|
|
@@ -63,7 +32,10 @@ module RubyGemsRequirementsSystem
|
|
63
32
|
end
|
64
33
|
|
65
34
|
def install
|
66
|
-
|
35
|
+
return true unless enabled?
|
36
|
+
|
37
|
+
parser = RequirementsParser.new(@gemspec.requirements, @platform)
|
38
|
+
requirements = parser.parse
|
67
39
|
requirements.all? do |requirement|
|
68
40
|
next true if requirement.satisfied?
|
69
41
|
@platform.install(requirement)
|
@@ -71,52 +43,21 @@ module RubyGemsRequirementsSystem
|
|
71
43
|
end
|
72
44
|
|
73
45
|
private
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
components = gemspec_requirement.split(/: +/, 4)
|
79
|
-
next unless components.size == 4
|
80
|
-
|
81
|
-
id, raw_packages, platform, system_package = components
|
82
|
-
next unless id == "system"
|
83
|
-
|
84
|
-
packages = parse_packages(raw_packages)
|
85
|
-
next if packages.empty?
|
86
|
-
|
87
|
-
all_packages_set[packages] = true
|
88
|
-
|
89
|
-
next unless @platform.target?(platform)
|
90
|
-
requirements[packages] ||= []
|
91
|
-
requirements[packages] << system_package
|
92
|
-
end
|
93
|
-
(all_packages_set.keys - requirements.keys).each do |not_used_packages|
|
94
|
-
system_packages = @platform.default_system_packages(not_used_packages)
|
95
|
-
next if system_packages.nil?
|
96
|
-
requirements[not_used_packages] = system_packages
|
97
|
-
end
|
98
|
-
requirements.collect do |packages, system_packages|
|
99
|
-
Requirement.new(packages, system_packages)
|
46
|
+
def enabled?
|
47
|
+
case ENV["RUBYGEMS_REQUIREMENTS_SYSTEM"]
|
48
|
+
when "0", "no", "NO", "false", "FALSE"
|
49
|
+
return false
|
100
50
|
end
|
101
|
-
end
|
102
51
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
#
|
108
|
-
|
109
|
-
# Gem::Specification#requirements is a free form
|
110
|
-
# configuration. So there are configuration values that use
|
111
|
-
# "system: ..." but not for this plugin. We can report a
|
112
|
-
# warning instead.
|
113
|
-
packages.each do |package|
|
114
|
-
unless package.valid?
|
115
|
-
# TODO: Report a warning
|
116
|
-
return []
|
117
|
-
end
|
52
|
+
requirements_system = Gem.configuration["requirements_system"] || {}
|
53
|
+
case requirements_system["enabled"]
|
54
|
+
when false
|
55
|
+
return false
|
56
|
+
when "false" # "true"/"false" isn't converted to boolean with old RubyGems
|
57
|
+
return false
|
118
58
|
end
|
119
|
-
|
59
|
+
|
60
|
+
true
|
120
61
|
end
|
121
62
|
end
|
122
63
|
end
|
@@ -14,4 +14,25 @@
|
|
14
14
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
15
|
|
16
16
|
module RubyGemsRequirementsSystem
|
17
|
+
Package = Struct.new(:id, :operator, :required_version) do
|
18
|
+
class << self
|
19
|
+
def parse(input)
|
20
|
+
new(*input.split(/\s*(==|>=|>|<=|<)\s*/, 3))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid?
|
25
|
+
return false if id.empty?
|
26
|
+
return false if operator and required_version.nil?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def satisfied?(target_version)
|
31
|
+
return true if required_version.nil?
|
32
|
+
|
33
|
+
target = Gem::Version.new(target_version)
|
34
|
+
required = Gem::Version.new(required_version)
|
35
|
+
target.__send__(operator, required)
|
36
|
+
end
|
37
|
+
end
|
17
38
|
end
|
@@ -15,6 +15,7 @@
|
|
15
15
|
|
16
16
|
require "fileutils"
|
17
17
|
require "open-uri"
|
18
|
+
require "rubygems/user_interaction"
|
18
19
|
require "tempfile"
|
19
20
|
|
20
21
|
require_relative "../executable-finder"
|
@@ -33,6 +34,14 @@ module RubyGemsRequirementsSystem
|
|
33
34
|
nil
|
34
35
|
end
|
35
36
|
|
37
|
+
def valid_system_package?(package)
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
def valid_system_repository?(repository)
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
36
45
|
def install(requirement)
|
37
46
|
synchronize do
|
38
47
|
requirement.system_packages.any? do |package|
|
@@ -108,12 +117,19 @@ module RubyGemsRequirementsSystem
|
|
108
117
|
end
|
109
118
|
|
110
119
|
def run_command_line(package, action, command_line)
|
120
|
+
if package.is_a?(SystemRepository)
|
121
|
+
package_label = "repository(#{package.id})"
|
122
|
+
else
|
123
|
+
package_label = package
|
124
|
+
end
|
125
|
+
prefix = "requirements: system: #{package_label}: #{action}"
|
126
|
+
say("#{prefix}: Start")
|
111
127
|
failed_to_get_super_user_priviledge = false
|
112
128
|
if have_priviledge?
|
113
129
|
succeeded = system(*command_line)
|
114
130
|
else
|
115
131
|
if sudo
|
116
|
-
prompt = "[sudo] password for %u to #{action} <#{
|
132
|
+
prompt = "[sudo] password for %u to #{action} <#{package_label}>: "
|
117
133
|
command_line = [sudo, "-p", prompt, *command_line]
|
118
134
|
succeeded = system(*command_line)
|
119
135
|
else
|
@@ -126,13 +142,13 @@ module RubyGemsRequirementsSystem
|
|
126
142
|
else
|
127
143
|
result_message = succeeded ? "succeeded" : "failed"
|
128
144
|
end
|
129
|
-
say("#{
|
145
|
+
say("#{prefix}: #{result_message}")
|
130
146
|
|
131
147
|
unless succeeded
|
132
148
|
escaped_command_line = command_line.collect do |part|
|
133
149
|
Shellwords.escape(part)
|
134
150
|
end
|
135
|
-
alert_warning("
|
151
|
+
alert_warning("#{prefix}: Failed.")
|
136
152
|
alert_warning("Run the following command " +
|
137
153
|
"to #{action} required system package: " +
|
138
154
|
escaped_command_line.join(" "))
|
@@ -42,6 +42,14 @@ module RubyGemsRequirementsSystem
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
def valid_system_repository?(repository)
|
46
|
+
uris = repository["uris"]
|
47
|
+
return false if uris.nil?
|
48
|
+
return false if uris.empty?
|
49
|
+
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
45
53
|
private
|
46
54
|
def prepare_command_lines(package)
|
47
55
|
[
|
@@ -50,8 +58,62 @@ module RubyGemsRequirementsSystem
|
|
50
58
|
end
|
51
59
|
|
52
60
|
def install_command_line(package)
|
61
|
+
if package.is_a?(SystemRepository)
|
62
|
+
install_command_line_repository(package)
|
63
|
+
else
|
64
|
+
install_command_line_package(package)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def install_command_line_repository(repository)
|
69
|
+
temporary_file_base_name = [
|
70
|
+
"rubygems-requirements-system-debian-#{repository.id}",
|
71
|
+
".sources",
|
72
|
+
]
|
73
|
+
sources = create_temporary_file(temporary_file_base_name)
|
74
|
+
signed_by_url = resolve_value_template(repository["signed-by"])
|
75
|
+
if signed_by_url
|
76
|
+
signed_by = URI.open(signed_by_url) do |response|
|
77
|
+
response.read
|
78
|
+
end
|
79
|
+
else
|
80
|
+
signed_by = nil
|
81
|
+
end
|
82
|
+
suites = repository["suites"] || "%{code_name}"
|
83
|
+
components = repository["components"] || "main"
|
84
|
+
{
|
85
|
+
"Types" => repository["types"] || "deb",
|
86
|
+
"URIs" => resolve_value_template(repository["uris"]),
|
87
|
+
"Suites" => resolve_value_template(suites),
|
88
|
+
"Components" => resolve_value_template(components),
|
89
|
+
"Signed-By" => signed_by,
|
90
|
+
}.each do |key, value|
|
91
|
+
next if value.nil?
|
92
|
+
if value.include?("\n")
|
93
|
+
sources.puts("#{key}:")
|
94
|
+
value.each_line(chomp: true) do |line|
|
95
|
+
if line.empty?
|
96
|
+
sources.puts(" .")
|
97
|
+
else
|
98
|
+
sources.puts(" #{line}")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
else
|
102
|
+
sources.puts("#{key}: #{value}")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
sources.close
|
106
|
+
FileUtils.chmod("go+r", sources.path)
|
107
|
+
[
|
108
|
+
"cp",
|
109
|
+
sources.path,
|
110
|
+
"/etc/apt/sources.list.d/#{repository.id}.sources",
|
111
|
+
]
|
112
|
+
end
|
113
|
+
|
114
|
+
def install_command_line_package(package)
|
53
115
|
if package.start_with?("https://")
|
54
|
-
package_url =
|
116
|
+
package_url = resolve_value_template(package)
|
55
117
|
temporary_file_base_name = [
|
56
118
|
"rubygems-requirements-system-debian",
|
57
119
|
File.extname(package),
|
@@ -61,7 +123,6 @@ module RubyGemsRequirementsSystem
|
|
61
123
|
IO.copy_stream(response, local_package)
|
62
124
|
end
|
63
125
|
local_package.close
|
64
|
-
@temporary_files << local_package
|
65
126
|
FileUtils.chmod("go+r", local_package.path)
|
66
127
|
package = local_package.path
|
67
128
|
end
|
@@ -80,9 +141,11 @@ module RubyGemsRequirementsSystem
|
|
80
141
|
true
|
81
142
|
end
|
82
143
|
|
83
|
-
def
|
144
|
+
def resolve_value_template(template)
|
145
|
+
return nil if template.nil?
|
146
|
+
|
84
147
|
os_release = OSRelease.new
|
85
|
-
|
148
|
+
template % {
|
86
149
|
distribution: os_release.id,
|
87
150
|
code_name: os_release.version_codename,
|
88
151
|
version: os_release.version_id,
|
@@ -31,25 +31,97 @@ module RubyGemsRequirementsSystem
|
|
31
31
|
platform == "fedora"
|
32
32
|
end
|
33
33
|
|
34
|
+
def valid_system_package?(package)
|
35
|
+
return true unless package.start_with?("module:")
|
36
|
+
|
37
|
+
action, target = parse_module_system_package(package)
|
38
|
+
case action
|
39
|
+
when "enable", "disable"
|
40
|
+
else
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
return false if target.nil?
|
44
|
+
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def valid_system_repository?(repository)
|
49
|
+
baseurl = repository["baseurl"]
|
50
|
+
return false if baseurl.nil?
|
51
|
+
return false if baseurl.empty?
|
52
|
+
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
34
56
|
def default_system_packages(packages)
|
35
57
|
packages.collect {|package| "pkgconfig(#{package.id})"}
|
36
58
|
end
|
37
59
|
|
38
60
|
private
|
61
|
+
def parse_module_system_package(package)
|
62
|
+
# "module: disable: postgresql" ->
|
63
|
+
# ["module", "disable", "postgresql"]
|
64
|
+
_, action, target = package.split(/:\s*/, 3)
|
65
|
+
[action, target]
|
66
|
+
end
|
67
|
+
|
39
68
|
def install_command_line(package)
|
69
|
+
if package.is_a?(SystemRepository)
|
70
|
+
install_command_line_repository(package)
|
71
|
+
elsif package.start_with?("module:")
|
72
|
+
install_command_line_module(package)
|
73
|
+
else
|
74
|
+
install_command_line_package(package)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def install_command_line_repository(repository)
|
79
|
+
temporary_file_base_name = [
|
80
|
+
"rubygems-requirements-system-fedora-#{repository.id}",
|
81
|
+
".repo",
|
82
|
+
]
|
83
|
+
repo = create_temporary_file(temporary_file_base_name)
|
84
|
+
repo.puts("[#{repository.id}]")
|
85
|
+
{
|
86
|
+
"name" => resolve_value_template(repository["name"]),
|
87
|
+
"baseurl" => resolve_value_template(repository["baseurl"]),
|
88
|
+
"enabled" => "1",
|
89
|
+
"gpgcheck" => repository["gpgkey"] ? "1" : "0",
|
90
|
+
"gpgkey" => resolve_value_template(repository["gpgkey"]),
|
91
|
+
}.each do |key, value|
|
92
|
+
next if value.nil?
|
93
|
+
repo.puts("#{key}=#{value}")
|
94
|
+
end
|
95
|
+
repo.close
|
96
|
+
FileUtils.chmod("go+r", repo.path)
|
97
|
+
[
|
98
|
+
"cp",
|
99
|
+
repo.path,
|
100
|
+
"/etc/yum.repos.d/#{repository.id}.repo",
|
101
|
+
]
|
102
|
+
end
|
103
|
+
|
104
|
+
def install_command_line_module(package)
|
105
|
+
action, target = parse_module_system_package(package)
|
106
|
+
["dnf", "-y", "module", action, target]
|
107
|
+
end
|
108
|
+
|
109
|
+
def install_command_line_package(package)
|
40
110
|
if package.start_with?("https://")
|
41
|
-
package =
|
111
|
+
package = resolve_value_template(package)
|
42
112
|
end
|
43
|
-
["dnf", "
|
113
|
+
["dnf", "-y", "install", package]
|
44
114
|
end
|
45
115
|
|
46
116
|
def need_super_user_priviledge?
|
47
117
|
true
|
48
118
|
end
|
49
119
|
|
50
|
-
def
|
120
|
+
def resolve_value_template(template)
|
121
|
+
return nil if template.nil?
|
122
|
+
|
51
123
|
os_release = OSRelease.new
|
52
|
-
|
124
|
+
template % {
|
53
125
|
distribution: os_release.id,
|
54
126
|
major_version: major_version.to_s,
|
55
127
|
version: os_release.version_id,
|
@@ -39,16 +39,16 @@ module RubyGemsRequirementsSystem
|
|
39
39
|
end
|
40
40
|
|
41
41
|
private
|
42
|
-
def
|
42
|
+
def install_command_line_package(package)
|
43
43
|
if package.start_with?("https://")
|
44
|
-
package =
|
44
|
+
package = resolve_value_template(package)
|
45
45
|
end
|
46
46
|
if major_version >= 9
|
47
|
-
["dnf", "install", "--enablerepo=crb",
|
47
|
+
["dnf", "-y", "install", "--enablerepo=crb", package]
|
48
48
|
elsif major_version >= 8
|
49
|
-
["dnf", "install", "--enablerepo=powertools",
|
49
|
+
["dnf", "-y", "install", "--enablerepo=powertools", package]
|
50
50
|
else
|
51
|
-
["yum", "
|
51
|
+
["yum", "-y", "install", package]
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -39,7 +39,7 @@ module RubyGemsRequirementsSystem
|
|
39
39
|
|
40
40
|
private
|
41
41
|
def prepare_command_lines(package)
|
42
|
-
if package.start_with?("ppa:")
|
42
|
+
if package.is_a?(String) and package.start_with?("ppa:")
|
43
43
|
[
|
44
44
|
["apt-get", "update"],
|
45
45
|
install_command_line("software-properties-common"),
|
@@ -49,7 +49,7 @@ module RubyGemsRequirementsSystem
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
52
|
+
def install_command_line_package(package)
|
53
53
|
if package.start_with?("ppa:")
|
54
54
|
[
|
55
55
|
"add-apt-repository",
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright (C) 2025 Ruby-GNOME Project Team
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
module RubyGemsRequirementsSystem
|
17
|
+
Requirement = Struct.new(:packages, :system_packages) do
|
18
|
+
def satisfied?
|
19
|
+
packages.any? do |package|
|
20
|
+
installed?(package)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def installed?(package)
|
26
|
+
package_config = PKGConfig.package_config(package.id)
|
27
|
+
begin
|
28
|
+
package_config.cflags
|
29
|
+
rescue PackageConfig::NotFoundError
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
|
33
|
+
package.satisfied?(package_config.version)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# Copyright (C) 2025 Ruby-GNOME Project Team
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require_relative "package"
|
17
|
+
require_relative "requirement"
|
18
|
+
require_relative "system-repository"
|
19
|
+
|
20
|
+
module RubyGemsRequirementsSystem
|
21
|
+
class RequirementsParser
|
22
|
+
def initialize(gemspec_requirements, platform)
|
23
|
+
@gemspec_requirements = gemspec_requirements
|
24
|
+
@platform = platform
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse
|
28
|
+
all_packages_set = {}
|
29
|
+
requirements = {}
|
30
|
+
@gemspec_requirements.each do |gemspec_requirement|
|
31
|
+
components = gemspec_requirement.split(/:\s*/, 4)
|
32
|
+
next unless components.size == 4
|
33
|
+
|
34
|
+
id, raw_packages, platform, system_package = components
|
35
|
+
next unless id == "system"
|
36
|
+
|
37
|
+
packages = parse_packages(raw_packages)
|
38
|
+
next if packages.empty?
|
39
|
+
|
40
|
+
all_packages_set[packages] = true
|
41
|
+
|
42
|
+
next unless @platform.target?(platform)
|
43
|
+
requirements[packages] ||= []
|
44
|
+
requirements[packages] << system_package
|
45
|
+
end
|
46
|
+
(all_packages_set.keys - requirements.keys).each do |not_used_packages|
|
47
|
+
system_packages = @platform.default_system_packages(not_used_packages)
|
48
|
+
next if system_packages.nil?
|
49
|
+
requirements[not_used_packages] = system_packages
|
50
|
+
end
|
51
|
+
requirements.collect do |packages, system_packages|
|
52
|
+
system_packages = detect_system_repositories(system_packages)
|
53
|
+
Requirement.new(packages, system_packages)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def parse_packages(raw_packages)
|
59
|
+
packages = raw_packages.split(/\s*\|\s*/).collect do |raw_package|
|
60
|
+
Package.parse(raw_package)
|
61
|
+
end
|
62
|
+
# Ignore this requirement if any invalid package is included.
|
63
|
+
# We must not report an error for this because
|
64
|
+
# Gem::Specification#requirements is a free form
|
65
|
+
# configuration. So there are configuration values that use
|
66
|
+
# "system: ..." but not for this plugin. We can report a
|
67
|
+
# warning instead.
|
68
|
+
packages.each do |package|
|
69
|
+
unless package.valid?
|
70
|
+
# TODO: Report a warning
|
71
|
+
return []
|
72
|
+
end
|
73
|
+
end
|
74
|
+
packages
|
75
|
+
end
|
76
|
+
|
77
|
+
def detect_system_repositories(original_system_packages)
|
78
|
+
system_packages = []
|
79
|
+
repository_properties = {}
|
80
|
+
|
81
|
+
flush_repository = lambda do
|
82
|
+
return if repository_properties.empty?
|
83
|
+
properties = repository_properties
|
84
|
+
repository_properties = {}
|
85
|
+
|
86
|
+
id = properties.delete("id")
|
87
|
+
return if id.nil?
|
88
|
+
repository = SystemRepository.new(id, properties)
|
89
|
+
return unless @platform.valid_system_repository?(repository)
|
90
|
+
system_packages << repository
|
91
|
+
end
|
92
|
+
|
93
|
+
original_system_packages.each do |system_package|
|
94
|
+
unless system_package.start_with?("repository:")
|
95
|
+
flush_repository.call
|
96
|
+
next unless @platform.valid_system_package?(system_package)
|
97
|
+
system_packages << system_package
|
98
|
+
next
|
99
|
+
end
|
100
|
+
_, key, value = system_package.strip.split(/:\s*/, 3)
|
101
|
+
next if value.empty?
|
102
|
+
if key == "id" and repository_properties.key?("id")
|
103
|
+
flush_repository.call
|
104
|
+
end
|
105
|
+
repository_properties[key] = value
|
106
|
+
end
|
107
|
+
flush_repository.call
|
108
|
+
|
109
|
+
system_packages
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Copyright (C) 2025 Ruby-GNOME Project Team
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
module RubyGemsRequirementsSystem
|
17
|
+
class SystemRepository
|
18
|
+
attr_reader :id
|
19
|
+
attr_reader :properties
|
20
|
+
protected :properties
|
21
|
+
def initialize(id, properties)
|
22
|
+
@id = id
|
23
|
+
@properties = properties
|
24
|
+
end
|
25
|
+
|
26
|
+
def ==(other)
|
27
|
+
other.is_a?(self.class) and
|
28
|
+
@id == other.id and
|
29
|
+
@properties == other.properties
|
30
|
+
end
|
31
|
+
|
32
|
+
def eql?(other)
|
33
|
+
self == other
|
34
|
+
end
|
35
|
+
|
36
|
+
def hash
|
37
|
+
[@id, @properties].hash
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
@properties[key]
|
42
|
+
end
|
43
|
+
|
44
|
+
def each(&block)
|
45
|
+
@properties.each(&block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubygems-requirements-system
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sutou Kouhei
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-01-
|
10
|
+
date: 2025-01-13 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: pkg-config
|
@@ -65,6 +65,9 @@ files:
|
|
65
65
|
- lib/rubygems-requirements-system/platform/suse.rb
|
66
66
|
- lib/rubygems-requirements-system/platform/ubuntu.rb
|
67
67
|
- lib/rubygems-requirements-system/platform/unknown.rb
|
68
|
+
- lib/rubygems-requirements-system/requirement.rb
|
69
|
+
- lib/rubygems-requirements-system/requirements-parser.rb
|
70
|
+
- lib/rubygems-requirements-system/system-repository.rb
|
68
71
|
- lib/rubygems-requirements-system/version.rb
|
69
72
|
- lib/rubygems_plugin.rb
|
70
73
|
homepage: https://github.com/ruby-gnome/rubygems-requirements-system
|