rubygems-requirements-system 0.0.2 → 0.0.4

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.
@@ -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} <#{package}>: "
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("#{action.capitalize} '#{package}' system package: #{result_message}")
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("'#{package}' system package is required.")
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 = resolve_package_url_template(package)
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 resolve_package_url_template(package_url_template)
144
+ def resolve_value_template(template)
145
+ return nil if template.nil?
146
+
84
147
  os_release = OSRelease.new
85
- package_url_template % {
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 = resolve_package_url_template(package)
111
+ package = resolve_value_template(package)
42
112
  end
43
- ["dnf", "install", "-y", package]
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 resolve_package_url_template(package_url_template)
120
+ def resolve_value_template(template)
121
+ return nil if template.nil?
122
+
51
123
  os_release = OSRelease.new
52
- package_url_template % {
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 install_command_line(package)
42
+ def install_command_line_package(package)
43
43
  if package.start_with?("https://")
44
- package = resolve_package_url_template(package)
44
+ package = resolve_value_template(package)
45
45
  end
46
46
  if major_version >= 9
47
- ["dnf", "install", "--enablerepo=crb", "-y", package]
47
+ ["dnf", "-y", "install", "--enablerepo=crb", package]
48
48
  elsif major_version >= 8
49
- ["dnf", "install", "--enablerepo=powertools", "-y", package]
49
+ ["dnf", "-y", "install", "--enablerepo=powertools", package]
50
50
  else
51
- ["yum", "install", "-y", package]
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 install_command_line(package)
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
@@ -14,5 +14,5 @@
14
14
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
16
  module RubyGemsRequirementsSystem
17
- VERSION = "0.0.2"
17
+ VERSION = "0.0.4"
18
18
  end
@@ -15,7 +15,7 @@
15
15
 
16
16
  require_relative "rubygems-requirements-system/installer"
17
17
 
18
- Gem.pre_install do |installer|
19
- installer = RubyGemsRequirementsSystem::Installer.new(installer.spec)
18
+ Gem.pre_install do |gem_installer|
19
+ installer = RubyGemsRequirementsSystem::Installer.new(gem_installer.spec)
20
20
  installer.install
21
21
  end
data/plugins.rb ADDED
@@ -0,0 +1,17 @@
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
+ # Do nothing. We can use this as a Bundler plugin by this file. If we
17
+ # use this as a Bundler plugin, Bundler install this before other gems.
metadata CHANGED
@@ -1,28 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubygems-requirements-system
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sutou Kouhei
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-08 00:00:00.000000000 Z
11
- dependencies:
12
- - !ruby/object:Gem::Dependency
13
- name: pkg-config
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - ">="
17
- - !ruby/object:Gem::Version
18
- version: '0'
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - ">="
24
- - !ruby/object:Gem::Version
25
- version: '0'
10
+ date: 2025-03-05 00:00:00.000000000 Z
11
+ dependencies: []
26
12
  description: |-
27
13
  Users need to install system packages to install an extension library
28
14
  that depends on system packages. It bothers users because users need to
@@ -46,6 +32,7 @@ files:
46
32
  - lib/rubygems-requirements-system/installer.rb
47
33
  - lib/rubygems-requirements-system/os-release.rb
48
34
  - lib/rubygems-requirements-system/package.rb
35
+ - lib/rubygems-requirements-system/pkg-config.rb
49
36
  - lib/rubygems-requirements-system/platform.rb
50
37
  - lib/rubygems-requirements-system/platform/alpine-linux.rb
51
38
  - lib/rubygems-requirements-system/platform/alt-linux.rb
@@ -65,8 +52,12 @@ files:
65
52
  - lib/rubygems-requirements-system/platform/suse.rb
66
53
  - lib/rubygems-requirements-system/platform/ubuntu.rb
67
54
  - lib/rubygems-requirements-system/platform/unknown.rb
55
+ - lib/rubygems-requirements-system/requirement.rb
56
+ - lib/rubygems-requirements-system/requirements-parser.rb
57
+ - lib/rubygems-requirements-system/system-repository.rb
68
58
  - lib/rubygems-requirements-system/version.rb
69
59
  - lib/rubygems_plugin.rb
60
+ - plugins.rb
70
61
  homepage: https://github.com/ruby-gnome/rubygems-requirements-system
71
62
  licenses:
72
63
  - LGPL-3.0-or-later