vagrant-parallels 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.
- data/.gitignore +1 -0
- data/.travis.yml +1 -1
- data/Gemfile +3 -2
- data/Rakefile +9 -11
- data/debug.log +27547 -117
- data/lib/vagrant-parallels/action/match_mac_address.rb +10 -3
- data/lib/vagrant-parallels/driver/prl_ctl.rb +16 -1
- data/lib/vagrant-parallels/version.rb +1 -1
- data/locales/en.yml +4 -1
- data/tasks/bundler.rake +3 -0
- data/tasks/test.rake +12 -0
- data/test/support/isolated_environment.rb +46 -0
- data/test/support/tempdir.rb +43 -0
- data/test/unit/base.rb +27 -0
- data/test/unit/driver/prl_ctl_test.rb +138 -0
- data/test/unit/support/shared/parallels_context.rb +30 -0
- data/vagrant-parallels.gemspec +1 -3
- metadata +13 -40
- data/.ruby-gemset +0 -1
- data/spec/vagrant-parallels/setup_spec.rb +0 -7
@@ -9,9 +9,16 @@ module VagrantPlugins
|
|
9
9
|
def call(env)
|
10
10
|
raise Vagrant::Errors::VMBaseMacNotSpecified if !env[:machine].config.vm.base_mac
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
env[:machine].
|
12
|
+
env[:ui].info I18n.t("vagrant_parallels.actions.vm.match_mac.matching")
|
13
|
+
|
14
|
+
base_mac = env[:machine].config.vm.base_mac
|
15
|
+
# Generate new base mac if the specified address is already in use
|
16
|
+
if env[:machine].provider.driver.mac_in_use?(base_mac)
|
17
|
+
env[:ui].info I18n.t("vagrant_parallels.actions.vm.match_mac.generate")
|
18
|
+
env[:machine].provider.driver.set_mac_address('auto')
|
19
|
+
else
|
20
|
+
env[:machine].provider.driver.set_mac_address(base_mac)
|
21
|
+
end
|
15
22
|
|
16
23
|
@app.call(env)
|
17
24
|
end
|
@@ -40,6 +40,7 @@ module VagrantPlugins
|
|
40
40
|
|
41
41
|
def compact(uuid=nil)
|
42
42
|
uuid ||= @uuid
|
43
|
+
# TODO: VM can have more than one hdd!
|
43
44
|
path_to_hdd = read_settings(uuid).fetch("Hardware", {}).fetch("hdd0", {}).fetch("image", nil)
|
44
45
|
raw('prl_disk_tool', 'compact', '--hdd', path_to_hdd) do |type, data|
|
45
46
|
lines = data.split("\r")
|
@@ -80,7 +81,9 @@ module VagrantPlugins
|
|
80
81
|
end
|
81
82
|
|
82
83
|
def clear_shared_folders
|
83
|
-
read_settings.fetch("Host Shared Folders", {}).keys
|
84
|
+
shf = read_settings.fetch("Host Shared Folders", {}).keys
|
85
|
+
shf.delete("enabled")
|
86
|
+
shf.each do |folder|
|
84
87
|
execute("set", @uuid, "--shf-host-del", folder)
|
85
88
|
end
|
86
89
|
end
|
@@ -214,6 +217,18 @@ module VagrantPlugins
|
|
214
217
|
end
|
215
218
|
end
|
216
219
|
|
220
|
+
|
221
|
+
def mac_in_use?(mac)
|
222
|
+
all_macs_in_use = []
|
223
|
+
read_all_info.each do |vm|
|
224
|
+
all_macs_in_use << vm.fetch('Hardware', {}).fetch('net0',{}).fetch('mac', '')
|
225
|
+
end
|
226
|
+
|
227
|
+
valid_mac = mac.upcase.tr('^A-F0-9', '')
|
228
|
+
|
229
|
+
all_macs_in_use.include?(valid_mac)
|
230
|
+
end
|
231
|
+
|
217
232
|
# Returns a hash of all UUIDs assigned to VMs and templates currently
|
218
233
|
# known by Parallels. Keys are 'name' values
|
219
234
|
#
|
data/locales/en.yml
CHANGED
@@ -890,7 +890,10 @@ en:
|
|
890
890
|
The VM import failed! Try running `prlctl import` on the box file
|
891
891
|
manually for more verbose error output.
|
892
892
|
match_mac:
|
893
|
-
|
893
|
+
generate: |-
|
894
|
+
The specified base MAC is already in use. Generating a new unique MAC
|
895
|
+
address for Shared network...
|
896
|
+
matching: Matching MAC address for Shared network...
|
894
897
|
no_base_mac: |-
|
895
898
|
No base MAC address was specified. This is required for the NAT networking
|
896
899
|
to work properly (and hence port forwarding, SSH, etc.). Specifying this
|
data/tasks/bundler.rake
ADDED
data/tasks/test.rake
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
namespace :test do
|
5
|
+
RSpec::Core::RakeTask.new(:unit) do |t|
|
6
|
+
t.pattern = "test/unit/**/*_test.rb"
|
7
|
+
end
|
8
|
+
|
9
|
+
RSpec::Core::RakeTask.new(:acceptance) do |t|
|
10
|
+
t.pattern = "test/acceptance/**/*_test.rb"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "pathname"
|
3
|
+
|
4
|
+
require "log4r"
|
5
|
+
|
6
|
+
require "support/tempdir"
|
7
|
+
|
8
|
+
# This class manages an isolated environment for Vagrant to
|
9
|
+
# run in. It creates a temporary directory to act as the
|
10
|
+
# working directory as well as sets a custom home directory.
|
11
|
+
#
|
12
|
+
# This class also provides various helpers to create Vagrantfiles,
|
13
|
+
# boxes, etc.
|
14
|
+
class IsolatedEnvironment
|
15
|
+
attr_reader :homedir
|
16
|
+
attr_reader :workdir
|
17
|
+
|
18
|
+
# Initializes an isolated environment. You can pass in some
|
19
|
+
# options here to configure runing custom applications in place
|
20
|
+
# of others as well as specifying environmental variables.
|
21
|
+
#
|
22
|
+
# @param [Hash] apps A mapping of application name (such as "vagrant")
|
23
|
+
# to an alternate full path to the binary to run.
|
24
|
+
# @param [Hash] env Additional environmental variables to inject
|
25
|
+
# into the execution environments.
|
26
|
+
def initialize
|
27
|
+
@logger = Log4r::Logger.new("test::isolated_environment")
|
28
|
+
|
29
|
+
# Create a temporary directory for our work
|
30
|
+
@tempdir = Tempdir.new("vagrant")
|
31
|
+
@logger.info("Initialize isolated environment: #{@tempdir.path}")
|
32
|
+
|
33
|
+
# Setup the home and working directories
|
34
|
+
@homedir = Pathname.new(File.join(@tempdir.path, "home"))
|
35
|
+
@workdir = Pathname.new(File.join(@tempdir.path, "work"))
|
36
|
+
|
37
|
+
@homedir.mkdir
|
38
|
+
@workdir.mkdir
|
39
|
+
end
|
40
|
+
|
41
|
+
# This closes the environment by cleaning it up.
|
42
|
+
def close
|
43
|
+
@logger.info("Removing isolated environment: #{@tempdir.path}")
|
44
|
+
FileUtils.rm_rf(@tempdir.path)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
# This class provides an easy way of creating a temporary
|
5
|
+
# directory and having it removed when the application exits.
|
6
|
+
class Tempdir
|
7
|
+
attr_reader :path
|
8
|
+
|
9
|
+
def initialize(basename="vagrant")
|
10
|
+
@path = nil
|
11
|
+
|
12
|
+
# Loop and attempt to create a temporary directory until
|
13
|
+
# it succeeds.
|
14
|
+
while @path.nil?
|
15
|
+
file = Tempfile.new(basename)
|
16
|
+
@path = file.path
|
17
|
+
file.unlink
|
18
|
+
|
19
|
+
begin
|
20
|
+
Dir.mkdir(@path)
|
21
|
+
rescue
|
22
|
+
@path = nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Setup a finalizer to delete the directory. This is the same way
|
27
|
+
# that Tempfile and friends do this...
|
28
|
+
@cleanup_proc = lambda do
|
29
|
+
FileUtils.rm_rf(@path) if File.directory?(@path)
|
30
|
+
end
|
31
|
+
|
32
|
+
ObjectSpace.define_finalizer(self, @cleanup_proc)
|
33
|
+
end
|
34
|
+
|
35
|
+
# This deletes the temporary directory.
|
36
|
+
def unlink
|
37
|
+
# Delete the directory
|
38
|
+
@cleanup_proc.call
|
39
|
+
|
40
|
+
# Undefine the finalizer since we're all cleaned up
|
41
|
+
ObjectSpace.undefine_finalizer(self)
|
42
|
+
end
|
43
|
+
end
|
data/test/unit/base.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rspec/autorun"
|
3
|
+
|
4
|
+
# Require Vagrant itself so we can reference the proper
|
5
|
+
# classes to test.
|
6
|
+
require "vagrant"
|
7
|
+
require 'vagrant-parallels'
|
8
|
+
|
9
|
+
# Add the test directory to the load path
|
10
|
+
$:.unshift File.expand_path("../../", __FILE__)
|
11
|
+
|
12
|
+
# Load in helpers
|
13
|
+
require "support/tempdir"
|
14
|
+
require "unit/support/shared/parallels_context"
|
15
|
+
|
16
|
+
# Do not buffer output
|
17
|
+
$stdout.sync = true
|
18
|
+
$stderr.sync = true
|
19
|
+
|
20
|
+
# Configure RSpec
|
21
|
+
RSpec.configure do |c|
|
22
|
+
c.expect_with :rspec, :stdlib
|
23
|
+
end
|
24
|
+
|
25
|
+
# Configure VAGRANT_CWD so that the tests never find an actual
|
26
|
+
# Vagrantfile anywhere, or at least this minimizes those chances.
|
27
|
+
ENV["VAGRANT_CWD"] = Tempdir.new.path
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require_relative "../base"
|
2
|
+
|
3
|
+
describe VagrantPlugins::Parallels::Driver::PrlCtl do
|
4
|
+
include_context "parallels"
|
5
|
+
|
6
|
+
subject { VagrantPlugins::Parallels::Driver::PrlCtl.new(uuid) }
|
7
|
+
|
8
|
+
describe "compact" do
|
9
|
+
it "compacts the VM disk images" do
|
10
|
+
pending "Should have possibility to compact more than one hdd"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "create_host_only_network" do
|
15
|
+
it "creates host-only NIC"
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "export" do
|
19
|
+
tpl_name = "new_template_name"
|
20
|
+
tpl_uuid = "12345-hfgs-3456-hste"
|
21
|
+
|
22
|
+
it "exports VM to template" do
|
23
|
+
subject.stub(:read_settings).with(tpl_name).
|
24
|
+
and_return({"ID" => tpl_uuid})
|
25
|
+
|
26
|
+
subprocess.should_receive(:execute).
|
27
|
+
with("prlctl", "clone", uuid, "--name", an_instance_of(String), "--template", "--dst",
|
28
|
+
an_instance_of(String), an_instance_of(Hash)).
|
29
|
+
and_return(subprocess_result(stdout: "The VM has been successfully cloned"))
|
30
|
+
subject.export("/path/to/template", tpl_name).should == tpl_uuid
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "clear_shared_folders" do
|
35
|
+
shf_hash = {"enabled" => true, "shf_name_1" => {}, "shf_name_2" => {}}
|
36
|
+
it "deletes every shared folder assigned to the VM" do
|
37
|
+
subject.stub(:read_settings).and_return({"Host Shared Folders" => shf_hash})
|
38
|
+
|
39
|
+
subprocess.should_receive(:execute).exactly(2).times.
|
40
|
+
with("prlctl", "set", uuid, "--shf-host-del", an_instance_of(String), an_instance_of(Hash)).
|
41
|
+
and_return(subprocess_result(stdout: "Shared folder deleted"))
|
42
|
+
subject.clear_shared_folders
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "halt" do
|
47
|
+
it "stops the VM" do
|
48
|
+
subprocess.should_receive(:execute).
|
49
|
+
with("prlctl", "stop", uuid, an_instance_of(Hash)).
|
50
|
+
and_return(subprocess_result(stdout: "VM has been halted gracefully"))
|
51
|
+
subject.halt
|
52
|
+
end
|
53
|
+
|
54
|
+
it "stops the VM force" do
|
55
|
+
subprocess.should_receive(:execute).
|
56
|
+
with("prlctl", "stop", uuid, "--kill", an_instance_of(Hash)).
|
57
|
+
and_return(subprocess_result(stdout: "VM has been halted forcibly"))
|
58
|
+
subject.halt(force=true)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "mac_in_use?" do
|
63
|
+
vm_1 = {
|
64
|
+
'Hardware' => {
|
65
|
+
'net0' => {'mac' => '001C42BB5901'},
|
66
|
+
'net1' => {'mac' => '001C42BB5902'},
|
67
|
+
}
|
68
|
+
}
|
69
|
+
vm_2 = {
|
70
|
+
'Hardware' => {
|
71
|
+
'net0' => {'mac' => '001C42BB5903'},
|
72
|
+
'net1' => {'mac' => '001C42BB5904'},
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
it "checks the MAC address is already in use" do
|
77
|
+
subject.stub(:read_all_info).and_return([vm_1, vm_2])
|
78
|
+
|
79
|
+
subject.mac_in_use?('00:1c:42:bb:59:01').should be_true
|
80
|
+
subject.mac_in_use?('00:1c:42:bb:59:02').should be_false
|
81
|
+
subject.mac_in_use?('00:1c:42:bb:59:03').should be_true
|
82
|
+
subject.mac_in_use?('00:1c:42:bb:59:04').should be_false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "set_mac_address" do
|
87
|
+
it "sets base MAC address to the Shared network adapter" do
|
88
|
+
subprocess.should_receive(:execute).exactly(2).times.
|
89
|
+
with("prlctl", "set", uuid, '--device-set', 'net0', '--type', 'shared', '--mac',
|
90
|
+
an_instance_of(String), an_instance_of(Hash)).
|
91
|
+
and_return(subprocess_result(stdout: "Settings applied"))
|
92
|
+
|
93
|
+
subject.set_mac_address('001C42DD5902')
|
94
|
+
subject.set_mac_address('auto')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "start" do
|
99
|
+
it "starts the VM" do
|
100
|
+
subprocess.should_receive(:execute).
|
101
|
+
with("prlctl", "start", uuid, an_instance_of(Hash)).
|
102
|
+
and_return(subprocess_result(stdout: "VM started"))
|
103
|
+
subject.start
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "suspend" do
|
108
|
+
it "suspends the VM" do
|
109
|
+
subprocess.should_receive(:execute).
|
110
|
+
with("prlctl", "suspend", uuid, an_instance_of(Hash)).
|
111
|
+
and_return(subprocess_result(stdout: "VM suspended"))
|
112
|
+
subject.suspend
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "unregister" do
|
117
|
+
it "suspends the VM" do
|
118
|
+
subprocess.should_receive(:execute).
|
119
|
+
with("prlctl", "unregister", an_instance_of(String), an_instance_of(Hash)).
|
120
|
+
and_return(subprocess_result(stdout: "Specified VM unregistered"))
|
121
|
+
subject.unregister("template_or_vm_uuid")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "version" do
|
126
|
+
it "parses the version from output" do
|
127
|
+
subject.version.should match(/(#{parallels_version}[\d\.]+)/)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "rises ParallelsInstallIncomplete exception when output is invalid" do
|
131
|
+
subprocess.should_receive(:execute).
|
132
|
+
with("prlctl", "--version", an_instance_of(Hash)).
|
133
|
+
and_return(subprocess_result(stdout: "Some incorrect value has been returned!"))
|
134
|
+
expect { subject.version }.
|
135
|
+
to raise_error(VagrantPlugins::Parallels::Errors::ParallelsInstallIncomplete)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
shared_context "parallels" do
|
2
|
+
let(:parallels_context) { true }
|
3
|
+
let(:uuid) { "9876-dcba-8765-hgfe" }
|
4
|
+
let(:parallels_version) { "9" }
|
5
|
+
let(:subprocess) { double("Vagrant::Util::Subprocess") }
|
6
|
+
|
7
|
+
# this is a helper that returns a duck type suitable from a system command
|
8
|
+
# execution; allows setting exit_code, stdout, and stderr in stubs.
|
9
|
+
def subprocess_result(options={})
|
10
|
+
defaults = {exit_code: 0, stdout: "", stderr: ""}
|
11
|
+
double("subprocess_result", defaults.merge(options))
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
# we don't want unit tests to ever run commands on the system; so we wire
|
16
|
+
# in a double to ensure any unexpected messages raise exceptions
|
17
|
+
stub_const("Vagrant::Util::Subprocess", subprocess)
|
18
|
+
|
19
|
+
# drivers will blow up on instantiation if they cannot determine the
|
20
|
+
# Parallels Desktop version, so wire this stub in automatically
|
21
|
+
subprocess.stub(:execute).
|
22
|
+
with("prlctl", "--version", an_instance_of(Hash)).
|
23
|
+
and_return(subprocess_result(stdout: "prlctl version #{parallels_version}.23456.987654"))
|
24
|
+
|
25
|
+
# drivers also call vm_exists? during init;
|
26
|
+
subprocess.stub(:execute).
|
27
|
+
with("prlctl", "list", kind_of(String), "--info", "--json", kind_of(Hash)).
|
28
|
+
and_return(subprocess_result(exit_code: 0))
|
29
|
+
end
|
30
|
+
end
|
data/vagrant-parallels.gemspec
CHANGED
@@ -18,9 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.add_development_dependency "bundler", "~> 1.3"
|
20
20
|
spec.add_development_dependency "rake"
|
21
|
-
spec.add_development_dependency "rspec
|
22
|
-
spec.add_development_dependency "rspec-expectations", "~> 2.12.1"
|
23
|
-
spec.add_development_dependency "rspec-mocks", "~> 2.12.1"
|
21
|
+
spec.add_development_dependency "rspec", "~> 2.14.0"
|
24
22
|
|
25
23
|
# The following block of code determines the files that should be included
|
26
24
|
# in the gem. It does this by reading all the files in the directory where
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-parallels
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -44,13 +44,13 @@ dependencies:
|
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name: rspec
|
47
|
+
name: rspec
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 2.
|
53
|
+
version: 2.14.0
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,39 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 2.
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: rspec-expectations
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ~>
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: 2.12.1
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: 2.12.1
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: rspec-mocks
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ~>
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: 2.12.1
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ~>
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: 2.12.1
|
61
|
+
version: 2.14.0
|
94
62
|
description: Enables Vagrant to manage Parallels machines.
|
95
63
|
email:
|
96
64
|
- yshahin@gmail.com
|
@@ -148,10 +116,15 @@ files:
|
|
148
116
|
- locales/en.yml
|
149
117
|
- Rakefile
|
150
118
|
- README.md
|
151
|
-
-
|
119
|
+
- tasks/bundler.rake
|
120
|
+
- tasks/test.rake
|
121
|
+
- test/support/isolated_environment.rb
|
122
|
+
- test/support/tempdir.rb
|
123
|
+
- test/unit/base.rb
|
124
|
+
- test/unit/driver/prl_ctl_test.rb
|
125
|
+
- test/unit/support/shared/parallels_context.rb
|
152
126
|
- vagrant-parallels.gemspec
|
153
127
|
- .gitignore
|
154
|
-
- .ruby-gemset
|
155
128
|
- .travis.yml
|
156
129
|
homepage: http://github.com/yshahin/vagrant-parallels
|
157
130
|
licenses:
|
@@ -168,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
168
141
|
version: '0'
|
169
142
|
segments:
|
170
143
|
- 0
|
171
|
-
hash:
|
144
|
+
hash: 1018017984449213160
|
172
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
146
|
none: false
|
174
147
|
requirements:
|