mattock 0.7.1 → 0.8.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.
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