launch 1.0 → 2.0.0
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/CHANGELOG.md +12 -0
- data/LICENSE +19 -0
- data/README.md +65 -0
- data/ext/extconf.rb +17 -0
- data/ext/launch.c +272 -0
- data/lib/launch.bundle +0 -0
- data/lib/launch.rb +7 -80
- data/lib/launch/errors.rb +22 -0
- data/lib/launch/job.rb +170 -0
- data/lib/launch/test_helper.rb +11 -0
- data/lib/launch/version.rb +3 -0
- data/lib/launch/webrick.rb +21 -27
- data/test/launch/job_test.rb +9 -0
- data/test/launch/service_test.rb +23 -0
- data/test/launch_test.rb +11 -0
- metadata +55 -135
- data.tar.gz.sig +0 -1
- data/.autotest +0 -8
- data/.gemtest +0 -0
- data/History.txt +0 -5
- data/Manifest.txt +0 -11
- data/README.txt +0 -72
- data/Rakefile +0 -37
- data/ext/launch/extconf.rb +0 -6
- data/ext/launch/launch.c +0 -355
- data/sample/echo.rb +0 -107
- data/test/test_launch.rb +0 -55
- metadata.gz.sig +0 -2
@@ -0,0 +1,22 @@
|
|
1
|
+
module Launch
|
2
|
+
class Error < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class JobError < Error
|
6
|
+
attr_reader :job
|
7
|
+
|
8
|
+
def initialize(job, message = nil)
|
9
|
+
@job = job
|
10
|
+
super(message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class InvalidJob < JobError
|
15
|
+
end
|
16
|
+
|
17
|
+
class JobAlreadyExists < JobError
|
18
|
+
end
|
19
|
+
|
20
|
+
class UnknownJob < JobError
|
21
|
+
end
|
22
|
+
end
|
data/lib/launch/job.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
module Launch
|
2
|
+
require "launch/errors"
|
3
|
+
|
4
|
+
class Job
|
5
|
+
class << self
|
6
|
+
def checkin
|
7
|
+
from_launch Launch.message(Messages::CHECKIN)
|
8
|
+
rescue Errno::EPERM
|
9
|
+
raise JobError.new(nil, "must checkin from process spawned by lauchd for job with sockets")
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(label)
|
13
|
+
from_launch Launch.message(Messages::GETJOB => label)
|
14
|
+
rescue Errno::ESRCH
|
15
|
+
raise UnknownJob.new(nil, "no job exists with the label `#{label}'")
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def from_launch(launch)
|
20
|
+
job = allocate
|
21
|
+
job.launch_attributes = launch
|
22
|
+
job
|
23
|
+
end
|
24
|
+
|
25
|
+
@@launch_attributes = Hash.new { |h, k| h[k] = { :lazy_value => lambda { nil } } }
|
26
|
+
def launch_attr(name, launch_key, options = {}, &block)
|
27
|
+
@@launch_attributes[launch_key][:name] = name
|
28
|
+
@@launch_attributes[launch_key][:lazy_value] = block if block
|
29
|
+
|
30
|
+
class_eval <<-EVAL, __FILE__, __LINE__ + 1 unless options[:write_only]
|
31
|
+
def #{name}
|
32
|
+
unless @launch_attributes.key?("#{launch_key}")
|
33
|
+
@launch_attributes["#{launch_key}"] = @@launch_attributes["#{launch_key}"][:lazy_value].call
|
34
|
+
end
|
35
|
+
|
36
|
+
@launch_attributes["#{launch_key}"]
|
37
|
+
end
|
38
|
+
EVAL
|
39
|
+
class_eval <<-EVAL, __FILE__, __LINE__ + 1 unless options[:read_only]
|
40
|
+
def #{name}=(value)
|
41
|
+
@launch_attributes["#{launch_key}"] = value
|
42
|
+
end
|
43
|
+
EVAL
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
launch_attr :abandon_process_group, ABANDONPROCESSGROUP
|
48
|
+
launch_attr :debug, DEBUG
|
49
|
+
launch_attr :disabled, DISABLED
|
50
|
+
launch_attr :enable_globbing, ENABLEGLOBBING
|
51
|
+
launch_attr :enable_transactions, ENABLETRANSACTIONS
|
52
|
+
launch_attr :environment_variables, ENVIRONMENTVARIABLES do
|
53
|
+
{}
|
54
|
+
end
|
55
|
+
launch_attr :exit_timeout, EXITTIMEOUT
|
56
|
+
launch_attr :group_name, GROUPNAME
|
57
|
+
launch_attr :hard_resource_limits, HARDRESOURCELIMITS
|
58
|
+
launch_attr :hopefully_exits_first, HOPEFULLYEXITSFIRST
|
59
|
+
launch_attr :hopefully_exits_last, HOPEFULLYEXITSLAST
|
60
|
+
launch_attr :ignore_process_group_at_shutdown, IGNOREPROCESSGROUPATSHUTDOWN
|
61
|
+
launch_attr :inetd_compatibility, INETDCOMPATIBILITY
|
62
|
+
launch_attr :init_groups, INITGROUPS
|
63
|
+
launch_attr :keep_alive, KEEPALIVE do
|
64
|
+
{}
|
65
|
+
end
|
66
|
+
launch_attr :label, LABEL
|
67
|
+
launch_attr :last_exit_status, LASTEXITSTATUS, :read_only => true
|
68
|
+
launch_attr :launch_only_once, LAUNCHONLYONCE
|
69
|
+
launch_attr :limit_load_from_hosts, LIMITLOADFROMHOSTS do
|
70
|
+
[]
|
71
|
+
end
|
72
|
+
launch_attr :limit_load_to_hosts, LIMITLOADTOHOSTS do
|
73
|
+
[]
|
74
|
+
end
|
75
|
+
launch_attr :limit_load_to_session_type, LIMITLOADTOSESSIONTYPE do
|
76
|
+
[]
|
77
|
+
end
|
78
|
+
launch_attr :nice, NICE
|
79
|
+
launch_attr :on_demand, ONDEMAND
|
80
|
+
launch_attr :pid, PID, :read_only => true
|
81
|
+
launch_attr :policies, POLICIES
|
82
|
+
launch_attr :program, PROGRAM
|
83
|
+
launch_attr :program_arguments, PROGRAMARGUMENTS do
|
84
|
+
[]
|
85
|
+
end
|
86
|
+
launch_attr :queue_directories, QUEUEDIRECTORIES
|
87
|
+
launch_attr :root_directory, ROOTDIRECTORY
|
88
|
+
launch_attr :run_at_load, RUNATLOAD
|
89
|
+
launch_attr :sockets, SOCKETS do
|
90
|
+
Hash.new { |h, k| h[k] = [] }
|
91
|
+
end
|
92
|
+
launch_attr :soft_resource_limits, SOFTRESOURCELIMITS
|
93
|
+
launch_attr :standard_error_path, STANDARDERRORPATH
|
94
|
+
launch_attr :standard_in_path, STANDARDINPATH
|
95
|
+
launch_attr :standard_out_path, STANDARDOUTPATH
|
96
|
+
launch_attr :start_calendar_interval, STARTCALENDARINTERVAL
|
97
|
+
launch_attr :start_interval, STARTINTERVAL
|
98
|
+
launch_attr :start_on_mount, STARTONMOUNT
|
99
|
+
launch_attr :throttle_interval, THROTTLEINTERVAL
|
100
|
+
launch_attr :timeout, TIMEOUT
|
101
|
+
launch_attr :umask, UMASK
|
102
|
+
launch_attr :user_name, USERNAME
|
103
|
+
launch_attr :wait_for_debugger, WAITFORDEBUGGER
|
104
|
+
launch_attr :watch_paths, WATCHPATHS
|
105
|
+
launch_attr :working_directory, WORKINGDIRECTORY
|
106
|
+
|
107
|
+
def attributes=(attributes)
|
108
|
+
attributes.each do |key, value|
|
109
|
+
send(:"#{key}=", value)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def initialize(attributes = {})
|
114
|
+
@launch_attributes = {}
|
115
|
+
|
116
|
+
self.attributes = attributes
|
117
|
+
|
118
|
+
yield self if block_given?
|
119
|
+
end
|
120
|
+
|
121
|
+
def inspect
|
122
|
+
"#<#{self.class} #{attributes_inspect}>"
|
123
|
+
end
|
124
|
+
|
125
|
+
def launch_attributes
|
126
|
+
@launch_attributes
|
127
|
+
end
|
128
|
+
|
129
|
+
def launch_attributes=(attributes)
|
130
|
+
@launch_attributes = attributes
|
131
|
+
end
|
132
|
+
|
133
|
+
def remove
|
134
|
+
message(Messages::REMOVEJOB => label)
|
135
|
+
end
|
136
|
+
|
137
|
+
def start
|
138
|
+
message(Messages::STARTJOB => label)
|
139
|
+
end
|
140
|
+
|
141
|
+
def stop
|
142
|
+
message(Messages::STOPJOB => label)
|
143
|
+
end
|
144
|
+
|
145
|
+
def submit
|
146
|
+
message(Messages::SUBMITJOB => launch_attributes)
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
def attributes_inspect
|
151
|
+
@@launch_attributes.select do |launch_key, attribute|
|
152
|
+
@launch_attributes.key?(launch_key)
|
153
|
+
end.map do |launch_key, attribute|
|
154
|
+
"#{attribute[:name]}: #{@launch_attributes[launch_key].inspect}"
|
155
|
+
end.join(", ")
|
156
|
+
end
|
157
|
+
|
158
|
+
def message(msg)
|
159
|
+
Launch.message(msg)
|
160
|
+
rescue Errno::ESRCH
|
161
|
+
raise UnknownJob.new(self, "no job exists with the label `#{label}'")
|
162
|
+
rescue Errno::EINVAL
|
163
|
+
raise InvalidJob.new(self, "job is invalid")
|
164
|
+
rescue Errno::EEXIST
|
165
|
+
raise JobAlreadyExists.new(self, "job with label `#{label}' already exists")
|
166
|
+
rescue SystemCallError => e
|
167
|
+
raise JobError.new(self, e.message)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/lib/launch/webrick.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "rubygems"
|
2
|
+
require "webrick"
|
3
|
+
require "launch"
|
3
4
|
|
4
5
|
##
|
5
6
|
# Launch::WEBrickHTTPServer adds launchd support to WEBrick.
|
@@ -46,33 +47,26 @@ require 'webrick'
|
|
46
47
|
# </dict>
|
47
48
|
# </dict>
|
48
49
|
# </plist>
|
50
|
+
module Launch
|
51
|
+
class WEBrickHTTPServer < WEBrick::HTTPServer
|
52
|
+
##
|
53
|
+
# Initializes an HTTP server with +options+ and set the server's listeners
|
54
|
+
# using Launch. A TERM handler to shut down the server is automatically
|
55
|
+
# set.
|
56
|
+
#
|
57
|
+
# +:LaunchdSockets+ may be set to change the socket key from the default of
|
58
|
+
# <tt>'WEBrickSockets'</tt>
|
59
|
+
def initialize(options = {})
|
60
|
+
options[:DoNotListen] = true
|
61
|
+
sockets_key = options.delete(:LaunchdSockets) || 'WEBrickSockets'
|
49
62
|
|
50
|
-
|
51
|
-
|
52
|
-
include Launch
|
63
|
+
super
|
53
64
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
# set.
|
58
|
-
#
|
59
|
-
# +:LaunchdSockets+ may be set to change the socket key from the default of
|
60
|
-
# <tt>'WEBrickSockets'</tt>
|
65
|
+
@job = Launch::Job.checkin
|
66
|
+
sockets = @job.sockets[sockets_key]
|
67
|
+
listeners.replace(socket)
|
61
68
|
|
62
|
-
|
63
|
-
|
64
|
-
sockets_key = options.delete(:LaunchdSockets) || 'WEBrickSockets'
|
65
|
-
|
66
|
-
super
|
67
|
-
|
68
|
-
launch_checkin
|
69
|
-
|
70
|
-
servers = launch_sockets sockets_key, TCPServer
|
71
|
-
|
72
|
-
listeners.replace servers
|
73
|
-
|
74
|
-
trap 'TERM' do shutdown end
|
69
|
+
trap("TERM") { shutdown }
|
70
|
+
end
|
75
71
|
end
|
76
|
-
|
77
72
|
end
|
78
|
-
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "launch/test_helper"
|
2
|
+
|
3
|
+
describe "launch_service" do
|
4
|
+
before do
|
5
|
+
@job = Launch::Job.new
|
6
|
+
@job.label = "org.launch.test"
|
7
|
+
@job.environment_variables = ENV.to_hash
|
8
|
+
@job.program_arguments << Gem.ruby
|
9
|
+
@job.program_arguments << "-e"
|
10
|
+
@job.program_arguments << <<-PROGRAM
|
11
|
+
requrie "rubygems"
|
12
|
+
require "launch"
|
13
|
+
|
14
|
+
|
15
|
+
PROGRAM
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "when submitting job" do
|
19
|
+
it "should return true" do
|
20
|
+
lambda { Launch::Job.checkin }.must_raise(Launch::JobError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/test/launch_test.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "launch/test_helper"
|
2
|
+
|
3
|
+
describe Launch do
|
4
|
+
describe "when listing jobs" do
|
5
|
+
it "should return an array of Launch::Jobs" do
|
6
|
+
jobs = Launch.jobs
|
7
|
+
jobs.must_be_instance_of Array
|
8
|
+
jobs.first.must_be_instance_of Launch::Job if jobs.first
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
metadata
CHANGED
@@ -1,153 +1,73 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: launch
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
version: "1.0"
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Eric Hodel
|
9
|
+
- Samuel Kadolph
|
13
10
|
autorequire:
|
14
11
|
bindir: bin
|
15
|
-
cert_chain:
|
16
|
-
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
ZXQwHhcNMDcxMjIxMDIwNDE0WhcNMDgxMjIwMDIwNDE0WjBBMRAwDgYDVQQDDAdk
|
21
|
-
cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
|
22
|
-
FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
|
23
|
-
LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
|
24
|
-
U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm
|
25
|
-
Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
|
26
|
-
mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
|
27
|
-
g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
|
28
|
-
sCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
|
29
|
-
BBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAHagT4lfX
|
30
|
-
kP/hDaiwGct7XPuVGbrOsKRVD59FF5kETBxEc9UQ1clKWngf8JoVuEoKD774dW19
|
31
|
-
bU0GOVWO+J6FMmT/Cp7nuFJ79egMf/gy4gfUfQMuvfcr6DvZUPIs9P/TlK59iMYF
|
32
|
-
DIOQ3DxdF3rMzztNUCizN4taVscEsjCcgW6WkUJnGdqlu3OHWpQxZBJkBTjPCoc6
|
33
|
-
UW6on70SFPmAy/5Cq0OJNGEWBfgD9q7rrs/X8GGwUWqXb85RXnUVi/P8Up75E0ag
|
34
|
-
14jEc90kN+C7oI/AGCBN0j6JnEtYIEJZibjjDJTSMWlUKKkj30kq7hlUC2CepJ4v
|
35
|
-
x52qPcexcYZR7w==
|
36
|
-
-----END CERTIFICATE-----
|
12
|
+
cert_chain: []
|
13
|
+
date: 2011-08-07 00:00:00.000000000Z
|
14
|
+
dependencies: []
|
15
|
+
description: ! 'launch is a wrapper for liblaunch which lets you load, unload, reload,
|
16
|
+
submit, remove, start, stop and list jobs for
|
37
17
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
prerelease: false
|
44
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
45
|
-
none: false
|
46
|
-
requirements:
|
47
|
-
- - ">="
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
hash: 11
|
50
|
-
segments:
|
51
|
-
- 2
|
52
|
-
- 0
|
53
|
-
- 2
|
54
|
-
version: 2.0.2
|
55
|
-
type: :development
|
56
|
-
version_requirements: *id001
|
57
|
-
- !ruby/object:Gem::Dependency
|
58
|
-
name: rake-compiler
|
59
|
-
prerelease: false
|
60
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
|
-
requirements:
|
63
|
-
- - ~>
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
hash: 5
|
66
|
-
segments:
|
67
|
-
- 0
|
68
|
-
- 7
|
69
|
-
version: "0.7"
|
70
|
-
type: :development
|
71
|
-
version_requirements: *id002
|
72
|
-
- !ruby/object:Gem::Dependency
|
73
|
-
name: hoe
|
74
|
-
prerelease: false
|
75
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
76
|
-
none: false
|
77
|
-
requirements:
|
78
|
-
- - ">="
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
hash: 43
|
81
|
-
segments:
|
82
|
-
- 2
|
83
|
-
- 9
|
84
|
-
- 0
|
85
|
-
version: 2.9.0
|
86
|
-
type: :development
|
87
|
-
version_requirements: *id003
|
88
|
-
description: |-
|
89
|
-
Launch allows agents and daemons launched by launchd to retrieve their list of
|
90
|
-
sockets. Launchd is an open source framework for launching and managing
|
91
|
-
daemons, programs and scripts provided by Apple.
|
92
|
-
email:
|
18
|
+
launchd as well as checkin from a process spawned by launchd and retrieve the sockets
|
19
|
+
for the job that spawned the process.
|
20
|
+
|
21
|
+
'
|
22
|
+
email:
|
93
23
|
- drbrain@segment7.net
|
24
|
+
- samuel@kadolph.com
|
94
25
|
executables: []
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
-
|
100
|
-
-
|
101
|
-
-
|
102
|
-
|
103
|
-
- .
|
104
|
-
-
|
105
|
-
- Manifest.txt
|
106
|
-
- README.txt
|
107
|
-
- Rakefile
|
108
|
-
- ext/launch/extconf.rb
|
109
|
-
- ext/launch/launch.c
|
110
|
-
- lib/launch.rb
|
26
|
+
extensions:
|
27
|
+
- ext/extconf.rb
|
28
|
+
extra_rdoc_files: []
|
29
|
+
files:
|
30
|
+
- ext/extconf.rb
|
31
|
+
- ext/launch.c
|
32
|
+
- lib/launch/errors.rb
|
33
|
+
- lib/launch/job.rb
|
34
|
+
- lib/launch/test_helper.rb
|
35
|
+
- lib/launch/version.rb
|
111
36
|
- lib/launch/webrick.rb
|
112
|
-
-
|
113
|
-
-
|
114
|
-
- .
|
115
|
-
|
116
|
-
|
37
|
+
- lib/launch.bundle
|
38
|
+
- lib/launch.rb
|
39
|
+
- CHANGELOG.md
|
40
|
+
- LICENSE
|
41
|
+
- README.md
|
42
|
+
- test/launch/job_test.rb
|
43
|
+
- test/launch/service_test.rb
|
44
|
+
- test/launch_test.rb
|
45
|
+
homepage: https://github.com/samuelkadolph/ruby-launch
|
117
46
|
licenses: []
|
118
|
-
|
119
47
|
post_install_message:
|
120
|
-
rdoc_options:
|
121
|
-
|
122
|
-
- README.txt
|
123
|
-
require_paths:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
124
50
|
- lib
|
125
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
52
|
none: false
|
127
|
-
requirements:
|
128
|
-
- -
|
129
|
-
- !ruby/object:Gem::Version
|
130
|
-
|
131
|
-
|
132
|
-
- 1
|
133
|
-
- 9
|
134
|
-
- 2
|
135
|
-
version: 1.9.2
|
136
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.8.7
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
58
|
none: false
|
138
|
-
requirements:
|
139
|
-
- -
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
|
142
|
-
segments:
|
143
|
-
- 0
|
144
|
-
version: "0"
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
145
63
|
requirements: []
|
146
|
-
|
147
|
-
|
148
|
-
rubygems_version: 1.5.3
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 1.8.6
|
149
66
|
signing_key:
|
150
67
|
specification_version: 3
|
151
|
-
summary:
|
152
|
-
|
153
|
-
|
68
|
+
summary: Wrapper for liblaunch which allows you to manage jobs and checkin from processes
|
69
|
+
spawned by launchd.
|
70
|
+
test_files:
|
71
|
+
- test/launch/job_test.rb
|
72
|
+
- test/launch/service_test.rb
|
73
|
+
- test/launch_test.rb
|