mattock 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NWNjNzNlOTczNWY3ZmIzZjc2MWFkMDJkZTI1NzJhODg1Y2JjZDYzMA==
5
- data.tar.gz: !binary |-
6
- MDEyYmRjYTk1MzcwNjQ0NGE5MzlhM2JkMzk2Y2FkMmQwYWIyMWJmNg==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MmQ2ZDc1M2I4MzBjZjM2ZTE1YzliZDc3MWE5NjQ5YzVlODFhZGMwZWFkZDBl
10
- MTA5NzFmYWRlNWU3ZDdkYmI3M2ZhNTg5MGM1N2YwMDAwNmFiZWUyZDgyYTJi
11
- MmU1ODhhM2NkZGJkN2M0OTEwYTA5ODg2YTExODhjNjliOGNmM2Y=
12
- data.tar.gz: !binary |-
13
- YmQ5OGQ1MGIzOGYxNmRhZGEzNDBjZjEzMjY0NTRmMGQ0NjMwM2M0MDEyMTgx
14
- M2E4NTgyZTVmMmQ3NWY2MzAzYzQ2NmU2NzYwNWQzYTA0ZmM4NDlmNDE0OTM0
15
- M2E3MjUxZTMxY2RhOGY5ZDVmNjM1YjYwOTI1OTE2MGY0OGY4OTY=
2
+ SHA1:
3
+ metadata.gz: 4c1151f03e2d5b1b2beae2dbe83fc913acc5781d
4
+ data.tar.gz: 76e9f884109d43f50acfdf12683f8f8922492410
5
+ SHA512:
6
+ metadata.gz: 64dd7f1524c69be09ec730ef8d12493d0f0db779a08bac00b1acbf1e17eb9d5c69040cae92e5897faf25b4fb5845d850c3d6207ca11c51ceb145adf1dd5b218f
7
+ data.tar.gz: 7bdd7d4d2c1010ea3fefad1fd0cf0641398207ff339dbc943bd0d2edadc6655baea1ed80f55ff1c074b40ee19f269acd958af36fd49f89d19d51fd59e34296c5
data/lib/mattock.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  require 'mattock/tasklib'
2
- require 'mattock/command-line'
3
2
  require 'mattock/remote-command-task'
3
+ require 'mattock/command-tasklib'
4
4
  require 'mattock/template-host'
@@ -1,12 +1,19 @@
1
1
  require 'mattock/task'
2
- require 'mattock/command-line'
2
+ begin
3
+ require 'caliph'
4
+ rescue LoadError => le
5
+ if le.message =~ /caliph/
6
+ puts "Mattock's CommandTask (and subclasses) requires a gem called 'caliph' now. Add it to your Gemfile"
7
+ end
8
+ raise
9
+ end
3
10
 
4
11
  module Mattock
5
12
  module CommandTaskMixin
6
- include CommandLineDSL
13
+ include Caliph::CommandLineDSL
7
14
 
8
15
  def self.included(sub)
9
- sub.extend CommandLineDSL
16
+ sub.extend Caliph::CommandLineDSL
10
17
  sub.runtime_setting(:verify_command, nil)
11
18
  sub.runtime_setting(:command)
12
19
  end
@@ -39,12 +46,20 @@ module Mattock
39
46
  command
40
47
  end
41
48
 
49
+ def self.shell
50
+ @shell ||= Caliph.new
51
+ end
52
+
53
+ def shell
54
+ CommandTaskMixin.shell
55
+ end
56
+
42
57
  def action(args)
43
- decorated(command).must_succeed!
58
+ shell.run(decorated(command)).must_succeed!
44
59
  end
45
60
 
46
61
  def check_verification_command
47
- !decorated(verify_command).succeeds?
62
+ !shell.run(decorated(verify_command)).succeeds?
48
63
  end
49
64
 
50
65
  def needed?
@@ -0,0 +1,7 @@
1
+ require 'mattock/tasklib'
2
+
3
+ module Mattock
4
+ class CommandTaskLib < TaskLib
5
+ include Caliph::CommandLineDSL
6
+ end
7
+ end
@@ -107,7 +107,7 @@ module Mattock
107
107
 
108
108
  attr_writer(name)
109
109
  define_method(metadata.reader_method) do
110
- value = metadata.value_on(self)
110
+ metadata.value_on(self)
111
111
  end
112
112
 
113
113
  if existing = default_values.find{|field| field.name == name} and existing.default_value != default_value
@@ -193,6 +193,29 @@ module Mattock
193
193
  }])
194
194
  end
195
195
 
196
+ def from_hash(obj, hash) #XXX It'd be really nice if this could report unused fields
197
+ if Configurable > superclass
198
+ superclass.from_hash(obj, hash)
199
+ end
200
+ default_values.each do |field|
201
+ catch :next do
202
+ key = field.reader_method.to_s
203
+ value = hash.fetch(key.to_s) do
204
+ key = key.to_sym
205
+ hash.fetch(key) do
206
+ throw :next
207
+ end
208
+ end
209
+
210
+ existing_value = obj.__send__(field.reader_method)
211
+ if Configurable === existing_value and value.is_a? Hash
212
+ existing_value.from_hash(value)
213
+ else
214
+ obj.__send__(field.writer_method, value)
215
+ end
216
+ end
217
+ end
218
+ end
196
219
 
197
220
  def included(mod)
198
221
  mod.extend ClassMethods
@@ -27,6 +27,10 @@ module Mattock
27
27
  self.class.to_hash(self)
28
28
  end
29
29
 
30
+ def from_hash(hash)
31
+ self.class.from_hash(self, hash)
32
+ end
33
+
30
34
  def unset_defaults_guard
31
35
  raise "Tried to check required settings before running setup_defaults"
32
36
  end
@@ -20,21 +20,19 @@ module Mattock
20
20
  fail "Need remote server for #{self.class.name}" unless remote_server.address
21
21
 
22
22
  raise "Empty remote command" if command_on_remote.nil?
23
- Mattock::WrappingChain.new do |cmd|
24
- cmd.add Mattock::CommandLine.new("ssh") do |cmd|
25
- cmd.options << "-i #{id_file}" if id_file
26
- cmd.options << "-l #{remote_server.user}" unless remote_server.user.nil?
27
- cmd.options << remote_server.address
28
- cmd.options << "-p #{remote_server.port}" #ok
29
- cmd.options << "-n"
30
- cmd.options << "-#{'v'*verbose}" if verbose > 0
31
- unless ssh_options.empty?
32
- ssh_options.each do |opt|
33
- cmd.options << "-o #{opt}"
34
- end
23
+ cmd("ssh") do |cmd|
24
+ cmd.options << "-i #{id_file}" if id_file
25
+ cmd.options << "-l #{remote_server.user}" unless remote_server.user.nil?
26
+ cmd.options << remote_server.address
27
+ cmd.options << "-p #{remote_server.port}" #ok
28
+ cmd.options << "-n"
29
+ cmd.options << "-#{'v'*verbose}" if verbose > 0
30
+ unless ssh_options.empty?
31
+ ssh_options.each do |opt|
32
+ cmd.options << "-o #{opt}"
35
33
  end
36
34
  end
37
- cmd.add Mattock::ShellEscaped.new(command_on_remote)
35
+ cmd - escaped_command(command_on_remote)
38
36
  end
39
37
  end
40
38
  end
data/spec/command-task.rb CHANGED
@@ -1,28 +1,26 @@
1
1
  require 'mattock/remote-command-task'
2
2
  require 'mattock/bundle-command-task'
3
+
3
4
  require 'mattock/testing/rake-example-group'
4
- require 'mattock/testing/mock-command-line'
5
+ require 'caliph/testing/mock-command-line'
5
6
 
6
7
  describe Mattock::RemoteCommandTask do
7
8
  include Mattock::RakeExampleGroup
8
- include Mattock::CommandLineExampleGroup
9
+ include Caliph::CommandLineExampleGroup
9
10
 
10
11
  let! :remote_task do
11
12
  namespace :test do
12
13
  Mattock::Rake::RemoteCommandTask.define_task do |t|
13
14
  t.remote_server.address = "nowhere.com"
14
- t.command = Mattock::PrereqChain.new do |prereq|
15
- prereq.add Mattock::CommandLine.new("cd", "a_dir")
16
- prereq.add Mattock::PipelineChain.new do |pipe|
17
- pipe.add Mattock::CommandLine.new("ls")
18
- pipe.add Mattock::CommandLine.new("grep") do |cmd|
19
- cmd.options << "*.rb"
20
- cmd.redirect_stderr("/dev/null")
21
- cmd.redirect_stdout("/tmp/rubyfiles.txt")
22
- end
23
- end
15
+ t.command = t.cmd do |cmd|
16
+ cmd.from("cd", "a_dir")
17
+ cmd &= "ls"
18
+ cmd |= "grep"
19
+ cmd.options << "*.rb"
20
+ cmd.redirect_stderr("/dev/null")
21
+ cmd.redirect_stdout("/tmp/rubyfiles.txt")
24
22
  end
25
- t.verify_command = Mattock::CommandLine.new("should_do")
23
+ t.verify_command = t.cmd("should_do")
26
24
  end
27
25
  end
28
26
  end
@@ -43,7 +41,7 @@ end
43
41
 
44
42
  describe Mattock::BundleCommandTask do
45
43
  include Mattock::RakeExampleGroup
46
- include Mattock::CommandLineExampleGroup
44
+ include Caliph::CommandLineExampleGroup
47
45
 
48
46
  let! :bundle_task do
49
47
  Mattock::BundleCommandTask.define_task(:bundle_test) do |t|
data/spec/configurable.rb CHANGED
@@ -35,6 +35,13 @@ describe Mattock::Configurable do
35
35
  hash[:two][:a].should == "a"
36
36
  end
37
37
 
38
+ it "#from_hash" do
39
+ subject.from_hash({:one => 111, "two" => { :a => "aaa" }})
40
+
41
+ subject.one.should == 111
42
+ subject.two.a.should == "aaa"
43
+ end
44
+
38
45
  it "should complain about unset required fields" do
39
46
  expect do
40
47
  subject.check_required
@@ -115,7 +122,7 @@ describe Mattock::Configurable do
115
122
  it "should complain about missing fields" do
116
123
  expect do
117
124
  subject.check_required
118
- end.to raise_error /Required field/
125
+ end.to raise_error(/Required field/)
119
126
  end
120
127
 
121
128
  it "should inspect cleanly" do
@@ -134,7 +141,7 @@ describe Mattock::Configurable do
134
141
  it "should complain about missing fields" do
135
142
  expect do
136
143
  subject.check_required
137
- end.to raise_error /Required field/
144
+ end.to raise_error(/Required field/)
138
145
  end
139
146
  end
140
147
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mattock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Judson Lester
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-24 00:00:00.000000000 Z
11
+ date: 2014-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: corundum
@@ -56,20 +56,41 @@ dependencies:
56
56
  name: tilt
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ! '>'
59
+ - - '>'
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ! '>'
66
+ - - '>'
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: ! " If Rake won't do it by itself, you oughtta Mattock.\n\n If you
70
- survived the pun, you might enjoy this gem.\n\n Features:\n\n * Extensions to
71
- Tasklibs to support powerful deerpaths.\n * A commandline library that supports
72
- mocking for tests.\n * A module to support common templating patterns\n\n"
69
+ - !ruby/object:Gem::Dependency
70
+ name: caliph
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 0.3.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 0.3.1
83
+ description: |2+
84
+ If Rake won't do it by itself, you oughtta Mattock.
85
+
86
+ If you survived the pun, you might enjoy this gem.
87
+
88
+ Features:
89
+
90
+ * Extensions to Tasklibs to support powerful deerpaths.
91
+ * A commandline library that supports mocking for tests.
92
+ * A module to support common templating patterns
93
+
73
94
  email:
74
95
  - nyarly@gmail.com
75
96
  executables: []
@@ -84,12 +105,9 @@ files:
84
105
  - yard_templates/default/module/html/task_definition.erb
85
106
  - yard_templates/default/layout/html/setup.rb
86
107
  - yard_templates/default/layout/html/tasklib_list.erb
87
- - lib/mattock/command-line.rb
88
- - lib/mattock/command-line/command-run-result.rb
89
108
  - lib/mattock/command-task.rb
109
+ - lib/mattock/command-tasklib.rb
90
110
  - lib/mattock/testing/rake-example-group.rb
91
- - lib/mattock/testing/mock-command-line.rb
92
- - lib/mattock/testing/record-commands.rb
93
111
  - lib/mattock/template-host.rb
94
112
  - lib/mattock/yard_extensions.rb
95
113
  - lib/mattock/remote-command-task.rb
@@ -109,7 +127,6 @@ files:
109
127
  - lib/mattock.rb
110
128
  - doc/README
111
129
  - doc/Specifications
112
- - spec/command-line.rb
113
130
  - spec/command-task.rb
114
131
  - spec/tasklib.rb
115
132
  - spec/configurable.rb
@@ -128,17 +145,17 @@ rdoc_options:
128
145
  - --main
129
146
  - doc/README
130
147
  - --title
131
- - mattock-0.7.1 RDoc
148
+ - mattock-0.8.0 RDoc
132
149
  require_paths:
133
150
  - lib/
134
151
  required_ruby_version: !ruby/object:Gem::Requirement
135
152
  requirements:
136
- - - ! '>='
153
+ - - '>='
137
154
  - !ruby/object:Gem::Version
138
155
  version: '0'
139
156
  required_rubygems_version: !ruby/object:Gem::Requirement
140
157
  requirements:
141
- - - ! '>='
158
+ - - '>='
142
159
  - !ruby/object:Gem::Version
143
160
  version: '0'
144
161
  requirements: []
@@ -1,258 +0,0 @@
1
- require 'mattock/command-line/command-run-result'
2
-
3
- module Mattock
4
- class CommandLine
5
- class << self
6
- def define_chain_op(opname, klass)
7
- define_method(opname) do |other|
8
- unless CommandLine === other
9
- other = CommandLine.new(*[*other])
10
- end
11
- chain = nil
12
- if klass === self
13
- chain = self
14
- else
15
- chain = klass.new
16
- chain.add(self)
17
- end
18
- chain.add(other)
19
- end
20
- end
21
-
22
- def define_op(opname)
23
- CommandLine.define_chain_op(opname, self)
24
- end
25
-
26
- attr_accessor :output_stream
27
- end
28
-
29
- def initialize(executable, *options)
30
- @output_stream = self.class.output_stream || $stderr
31
- @executable = executable
32
- @options = options
33
- @redirections = []
34
- @env = {}
35
- yield self if block_given?
36
- end
37
-
38
- attr_accessor :name, :executable, :options, :env, :output_stream
39
- attr_reader :redirections
40
-
41
- alias_method :command_environment, :env
42
-
43
- def set_env(name, value)
44
- command_environment[name] = value
45
- return self
46
- end
47
-
48
- def verbose
49
- ::Rake.verbose && ::Rake.verbose != ::Rake::FileUtilsExt::DEFAULT
50
- end
51
-
52
- def name
53
- @name || executable
54
- end
55
-
56
- def command
57
- ([executable] + options_composition + @redirections).join(" ")
58
- end
59
-
60
- def string_format
61
- (command_environment.map do |key, value|
62
- [key, value].join("=")
63
- end + [command]).join(" ")
64
- end
65
-
66
- def options_composition
67
- options
68
- end
69
-
70
- def redirect_to(stream, path)
71
- @redirections << "#{stream}>#{path}"
72
- end
73
-
74
- def redirect_from(path, stream)
75
- @redirections << "#{stream}<#{path}"
76
- end
77
-
78
- def copy_stream_to(from, to)
79
- @redirections << "#{from}>&#{to}"
80
- end
81
-
82
- def redirect_stdout(path)
83
- redirect_to(1, path)
84
- end
85
-
86
- def redirect_stderr(path)
87
- redirect_to(2, path)
88
- end
89
-
90
- def redirect_stdin(path)
91
- redirect_from(path, 0)
92
- end
93
-
94
- def replace_us
95
- output_steeam.puts "Ceding execution to: "
96
- output_stream.puts string_format
97
- Process.exec(command_environment, command)
98
- end
99
-
100
- def spawn_process
101
- host_stdout, cmd_stdout = IO.pipe
102
- host_stderr, cmd_stderr = IO.pipe
103
-
104
- pid = Process.spawn(command_environment, command, :out => cmd_stdout, :err => cmd_stderr)
105
- cmd_stdout.close
106
- cmd_stderr.close
107
-
108
- return pid, host_stdout, host_stderr
109
- end
110
-
111
- def collect_result(pid, host_stdout, host_stderr)
112
- result = CommandRunResult.new(pid, self)
113
- result.streams = {1 => host_stdout, 2 => host_stderr}
114
- result.wait
115
- return result
116
- end
117
-
118
- #If I wasn't worried about writing my own limited shell, I'd say e.g.
119
- #Pipeline would be an explicit chain of pipes... which is probably as
120
- #originally intended :/
121
- def execute
122
- collect_result(*spawn_process)
123
- end
124
-
125
- #Run a command in the background. The command can survive the caller
126
- def spin_off
127
- pid, out, err = spawn_process
128
- Process.detach(pid)
129
- return pid, out, err
130
- end
131
-
132
- #Run a command in parallel with the parent process - will kill it if it
133
- #outlasts us
134
- def background
135
- pid, out, err = spawn_process
136
- Process.detach(pid)
137
- at_exit do
138
- kill_process(pid)
139
- end
140
- return pid, out, err
141
- end
142
-
143
- def kill_process(pid)
144
- Process.kill("INT", pid)
145
- end
146
-
147
- def complete(pid, out, err)
148
- kill_process(pid)
149
- collect_result(pid, out, err)
150
- end
151
-
152
- def report(message, newline=true)
153
- output_stream.print(message + (newline ? "\n" : ""))
154
- end
155
-
156
- def run
157
- report string_format + " ", false
158
- result = execute
159
- report "=> #{result.exit_code}"
160
- report result.format_streams if verbose
161
- return result
162
- ensure
163
- report "" if verbose
164
- end
165
-
166
- def succeeds?
167
- run.succeeded?
168
- end
169
-
170
- def must_succeed!
171
- run.must_succeed!
172
- end
173
- end
174
-
175
- module CommandLineDSL
176
- def cmd(*args, &block)
177
- CommandLine.new(*args, &block)
178
- end
179
-
180
- def escaped_command(*args, &block)
181
- ShellEscaped.new(CommandLine.new(*args, &block))
182
- end
183
- end
184
-
185
- class ShellEscaped < CommandLine
186
- def initialize(cmd)
187
- @escaped = cmd
188
- end
189
-
190
- def command
191
- "'" + @escaped.string_format.gsub(/'/,"\'") + "'"
192
- end
193
-
194
- def command_environment
195
- {}
196
- end
197
-
198
- def name
199
- @name || @escaped.name
200
- end
201
-
202
- def to_s
203
- command
204
- end
205
- end
206
-
207
- class CommandChain < CommandLine
208
- def initialize
209
- @commands = []
210
- @command_environment = {}
211
- super(nil)
212
- end
213
-
214
- attr_reader :commands
215
-
216
- def add(cmd)
217
- yield cmd if block_given?
218
- @commands << cmd
219
- self
220
- end
221
-
222
- #Honestly this is sub-optimal - biggest driver for considering the
223
- #mini-shell approach here.
224
- def command_environment
225
- @command_environment = @commands.reverse.inject(@command_environment) do |env, command|
226
- env.merge(command.command_environment)
227
- end
228
- end
229
-
230
- def name
231
- @name || @commands.last.name
232
- end
233
- end
234
-
235
- class WrappingChain < CommandChain
236
- define_op('-')
237
-
238
- def command
239
- @commands.map{|cmd| cmd.command}.join(" -- ")
240
- end
241
- end
242
-
243
- class PrereqChain < CommandChain
244
- define_op('&')
245
-
246
- def command
247
- @commands.map{|cmd| cmd.command}.join(" && ")
248
- end
249
- end
250
-
251
- class PipelineChain < CommandChain
252
- define_op('|')
253
-
254
- def command
255
- @commands.map{|cmd| cmd.command}.join(" | ")
256
- end
257
- end
258
- end
@@ -1,131 +0,0 @@
1
- module Mattock
2
- class CommandLine
3
- class CommandRunResult
4
- def initialize(pid, command)
5
- @command = command
6
- @pid = pid
7
-
8
- #####
9
- @process_status = nil
10
- @streams = {}
11
- @consume_timeout = nil
12
- end
13
- attr_reader :process_status, :pid
14
- attr_accessor :consume_timeout, :streams
15
-
16
- def stdout
17
- @streams[1]
18
- end
19
-
20
- def stderr
21
- @streams[2]
22
- end
23
-
24
- def exit_code
25
- @process_status.exitstatus
26
- end
27
- alias exit_status exit_code
28
-
29
- def succeeded?
30
- must_succeed!
31
- return true
32
- rescue
33
- return false
34
- end
35
-
36
- def format_streams
37
- "stdout:#{stdout.nil? || stdout.empty? ? "[empty]\n" : "\n#{stdout}"}" +
38
- "stderr:#{stderr.nil? || stderr.empty? ? "[empty]\n" : "\n#{stderr}"}---"
39
- end
40
-
41
- def must_succeed!
42
- case exit_code
43
- when 0
44
- return exit_code
45
- else
46
- fail "Command #{@command.inspect} failed with exit status #{exit_code}: \n#{format_streams}"
47
- end
48
- end
49
-
50
- def wait
51
- @accumulators = {}
52
- waits = {}
53
- @buffered_echo = []
54
-
55
- ioes = streams.values
56
- ioes.each do |io|
57
- @accumulators[io] = []
58
- waits[io] = 3
59
- end
60
- begin_echoing = Time.now + (@consume_timeout || 3)
61
-
62
- @live_ioes = ioes.dup
63
-
64
- until @live_ioes.empty? do
65
- newpid, @process_status = Process.waitpid2(pid, Process::WNOHANG)
66
-
67
- unless @process_status.nil?
68
- consume_buffers(@live_ioes)
69
- break
70
- end
71
-
72
- timeout = 0
73
-
74
- if !@buffered_echo.nil?
75
- timeout = begin_echoing - Time.now
76
- if timeout < 0
77
- @command.report ""
78
- @command.report "Long running command output:"
79
- @command.report @buffered_echo.join
80
- @buffered_echo = nil
81
- end
82
- end
83
-
84
- if timeout > 0
85
- result = IO::select(@live_ioes, [], @live_ioes, timeout)
86
- else
87
- result = IO::select(@live_ioes, [], @live_ioes, 1)
88
- end
89
-
90
- unless result.nil? #timeout
91
- readable, _writeable, errored = *result
92
- unless errored.empty?
93
- raise "Error on IO: #{errored.inspect}"
94
- end
95
-
96
- consume_buffers(readable)
97
- end
98
- end
99
-
100
- if @process_status.nil?
101
- newpid, @process_status = Process.waitpid2(pid)
102
- end
103
-
104
- ioes.each do |io|
105
- io.close
106
- end
107
- @streams = Hash[ioes.each_with_index.map{|io, index| [index + 1, @accumulators[io].join]}]
108
- end
109
-
110
- def consume_buffers(readable)
111
- if not(readable.nil? or readable.empty?)
112
- readable.each do |io|
113
- begin
114
- while chunk = io.read_nonblock(4096)
115
- if @buffered_echo.nil?
116
- @command.report chunk, false
117
- else
118
- @buffered_echo << chunk
119
- end
120
- @accumulators[io] << chunk
121
- end
122
- rescue IO::WaitReadable => ex
123
- rescue EOFError => ex
124
- @live_ioes.delete(io)
125
- end
126
- end
127
- end
128
- end
129
- end
130
- end
131
- end
@@ -1,67 +0,0 @@
1
- require 'mattock/command-line'
2
-
3
- module Mattock
4
- class MockCommandResult < CommandLine::CommandRunResult
5
- def self.create(*args)
6
- if args.length == 1
7
- args = [args[0], {1 => ""}]
8
- end
9
-
10
- if String == args[1]
11
- args[1] = {1 => args[1]}
12
- end
13
-
14
- return self.new(*args)
15
- end
16
-
17
- def initialize(code, streams)
18
- @streams = streams
19
- @exit_code = code
20
- end
21
-
22
- attr_reader :exit_code, :streams
23
-
24
- alias exit_status exit_code
25
- end
26
-
27
- class CommandLine
28
- def self.execute(*args)
29
- fail "Command line executed in specs without 'expect_command' or 'expect_some_commands'"
30
- end
31
- end
32
-
33
- module CommandLineExampleGroup
34
- include CommandLineDSL
35
- module MockingExecute
36
- def execute
37
- Mattock::CommandLine.execute(command)
38
- end
39
- end
40
-
41
-
42
- def self.included(group)
43
- group.before :each do
44
- @original_execute = Mattock::CommandLine.instance_method(:execute)
45
- unless MockingExecute > Mattock::CommandLine
46
- Mattock::CommandLine.send(:include, MockingExecute)
47
- end
48
- Mattock::CommandLine.send(:remove_method, :execute)
49
- end
50
-
51
- group.after :each do
52
- Mattock::CommandLine.send(:define_method, :execute, @original_execute)
53
- end
54
- end
55
-
56
- #Registers indifference as to exactly what commands get called
57
- def expect_some_commands
58
- Mattock::CommandLine.should_receive(:execute).any_number_of_times.and_return(MockCommandResult.create(0))
59
- end
60
-
61
- #Registers an expectation about a command being run - expectations are
62
- #ordered
63
- def expect_command(cmd, *result)
64
- Mattock::CommandLine.should_receive(:execute, :expected_from => caller(1)[0]).with(cmd).ordered.and_return(MockCommandResult.create(*result))
65
- end
66
- end
67
- end
@@ -1,38 +0,0 @@
1
- require 'mattock/command-line'
2
-
3
- module Mattock
4
- class CommandLine
5
- @@commands = []
6
- alias original_execute execute
7
-
8
- def execute
9
- result = original_execute
10
- @@commands << [command, result]
11
- return result
12
- end
13
-
14
- class << self
15
- attr_accessor :command_recording_path
16
-
17
- def command_recording_path
18
- @command_recording_path ||= ENV['MATTOCK_CMDREC']
19
- end
20
-
21
- def emit_recording
22
- io = $stderr
23
- if command_recording_path
24
- io = File.open(command_recording_path, "w")
25
- else
26
- io.puts "Set MATTOCK_CMDREC to write to a path"
27
- end
28
- @@commands.each do |pair|
29
- io.puts "[/#{pair[0]}/, #{[pair[1].exit_code, pair[1].streams].inspect}]"
30
- end
31
- end
32
- end
33
- end
34
- end
35
-
36
- at_exit do
37
- Mattock::CommandLine.emit_recording
38
- end
data/spec/command-line.rb DELETED
@@ -1,162 +0,0 @@
1
- require 'mattock/command-line'
2
- require 'mattock/testing/rake-example-group'
3
- require 'mattock/testing/mock-command-line'
4
-
5
- require 'mattock/testing/record-commands'
6
-
7
- Mattock::CommandLine.command_recording_path = "/dev/null"
8
-
9
- describe Mattock::CommandLine do
10
- let :commandline do
11
- Mattock::CommandLine.new('echo', "-n") do |cmd|
12
- cmd.options << "Some text"
13
- end
14
- end
15
-
16
- it "should have a name set" do
17
- commandline.name.should == "echo"
18
- end
19
-
20
- it "should produce a command string" do
21
- commandline.command.should == "echo -n Some text"
22
- end
23
-
24
- it "should succeed" do
25
- commandline.succeeds?.should be_true
26
- end
27
-
28
- it "should not complain about success" do
29
- expect do
30
- commandline.must_succeed!
31
- end.to_not raise_error
32
- end
33
-
34
- describe Mattock::CommandLine::CommandRunResult do
35
- let :result do
36
- commandline.run
37
- end
38
-
39
- it "should have a result code" do
40
- result.exit_code.should == 0
41
- end
42
-
43
- it "should have stdout" do
44
- result.stdout.should == "Some text"
45
- end
46
- end
47
- end
48
-
49
- describe Mattock::CommandLine, "setting environment variables" do
50
- let :commandline do
51
- Mattock::CommandLine.new("env") do |cmd|
52
- cmd.env["TEST_ENV"] = "indubitably"
53
- end
54
- end
55
-
56
- let :result do
57
- commandline.run
58
- end
59
-
60
- it "should succeed" do
61
- result.succeeded?.should be_true
62
- end
63
-
64
- it "should alter the command's environment variables" do
65
- result.stdout.should =~ /TEST_ENV.*indubitably/
66
- end
67
-
68
- end
69
-
70
- describe Mattock::PipelineChain do
71
- let :commandline do
72
- Mattock::PipelineChain.new do |chain|
73
- chain.add Mattock::CommandLine.new("env")
74
- chain.add Mattock::CommandLine.new("cat") do |cmd|
75
- cmd.env["TEST_ENV"] = "indubitably"
76
- end
77
- end
78
- end
79
-
80
- let :result do
81
- commandline.run
82
- end
83
-
84
- it "should produce the right command" do
85
- commandline.command.should == 'env | cat'
86
- end
87
-
88
- it "should produce a runnable command with format_string" do
89
- commandline.string_format.should == 'TEST_ENV=indubitably env | cat'
90
- end
91
-
92
- it "should succeed" do
93
- result.succeeded?.should be_true
94
- end
95
-
96
- it "should alter the command's environment variables" do
97
- result.stdout.should =~ /TEST_ENV.*indubitably/
98
- end
99
- end
100
-
101
-
102
- describe Mattock::CommandLineDSL do
103
- include described_class
104
-
105
- describe "using the - operator" do
106
- let :command do
107
- cmd("sudo") - ["gem", "install", "bundler"]
108
- end
109
-
110
- it "should define commands" do
111
- command.should be_an_instance_of(Mattock::WrappingChain)
112
- command.should have(2).commands
113
- command.commands[0].should be_an_instance_of(Mattock::CommandLine)
114
- command.commands[1].should be_an_instance_of(Mattock::CommandLine)
115
- command.command.should == "sudo -- gem install bundler"
116
- end
117
- end
118
-
119
- describe "using the | operator" do
120
- let :command do
121
- cmd("cat", "/etc/passwd") | ["grep", "root"]
122
- end
123
-
124
- it "should define commands" do
125
- command.should be_an_instance_of(Mattock::PipelineChain)
126
- command.should have(2).commands
127
- command.commands[0].should be_an_instance_of(Mattock::CommandLine)
128
- command.commands[1].should be_an_instance_of(Mattock::CommandLine)
129
- command.command.should == "cat /etc/passwd | grep root"
130
- end
131
- end
132
-
133
- describe "using the & operator" do
134
- let :command do
135
- cmd("cd", "/tmp/trash") & %w{rm -rf *}
136
- end
137
-
138
- it "should define commands" do
139
- command.should be_an_instance_of(Mattock::PrereqChain)
140
- command.should have(2).commands
141
- command.commands[0].should be_an_instance_of(Mattock::CommandLine)
142
- command.commands[1].should be_an_instance_of(Mattock::CommandLine)
143
- command.command.should == "cd /tmp/trash && rm -rf *"
144
- end
145
- end
146
- end
147
-
148
- describe Mattock::CommandLine, "that fails" do
149
- let :commandline do
150
- Mattock::CommandLine.new("false")
151
- end
152
-
153
- it "should not succeed" do
154
- commandline.succeeds?.should == false
155
- end
156
-
157
- it "should raise error if succeed demanded" do
158
- expect do
159
- commandline.must_succeed
160
- end.to raise_error
161
- end
162
- end