caliph 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2b0f24364e478c354208e04a309d201339ebaa57
4
+ data.tar.gz: 1de70f9e8bb89ee483b7d28ffbcbb76d10428687
5
+ SHA512:
6
+ metadata.gz: 94590b96bf71222807e9b9c96c3a5ea52cd89a826191169608d02603879edb3bc02948bea3f92e97fdf0366baedcf1ad1403c0a6248f857ee79051ffaa24de13
7
+ data.tar.gz: 255d5824af358a59fdfb92b8798bd62015f81cfe9f242d51e9f1ac9c0318c50bfa9ae20dd9bce372567eea5775927db1e48c947daabbd4f0cd84f60cf8c80e6f
@@ -0,0 +1,4 @@
1
+ require 'caliph/command-line'
2
+ require 'caliph/command-chain'
3
+ require 'caliph/command-line-dsl'
4
+ require 'caliph/shell-escaped'
@@ -0,0 +1,58 @@
1
+ require 'caliph/define-op'
2
+
3
+ module Caliph
4
+ class CommandChain < CommandLine
5
+ include DefineOp
6
+
7
+ def initialize
8
+ @commands = []
9
+ @command_environment = {}
10
+ super(nil)
11
+ end
12
+
13
+ attr_reader :commands
14
+
15
+ def add(cmd)
16
+ yield cmd if block_given?
17
+ @commands << cmd
18
+ self
19
+ end
20
+
21
+ #Honestly this is sub-optimal - biggest driver for considering the
22
+ #mini-shell approach here.
23
+ def command_environment
24
+ @command_environment = @commands.reverse.inject(@command_environment) do |env, command|
25
+ env.merge(command.command_environment)
26
+ end
27
+ end
28
+
29
+ def name
30
+ @name || @commands.last.name
31
+ end
32
+ end
33
+
34
+ class WrappingChain < CommandChain
35
+ define_op('-')
36
+
37
+ def command
38
+ @commands.map{|cmd| cmd.command}.join(" -- ")
39
+ end
40
+ end
41
+
42
+ class PrereqChain < CommandChain
43
+ define_op('&')
44
+
45
+ def command
46
+ @commands.map{|cmd| cmd.command}.join(" && ")
47
+ end
48
+ end
49
+
50
+ class PipelineChain < CommandChain
51
+ define_op('|')
52
+
53
+ def command
54
+ @commands.map{|cmd| cmd.command}.join(" | ")
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,11 @@
1
+ module Caliph
2
+ module CommandLineDSL
3
+ def cmd(*args, &block)
4
+ CommandLine.new(*args, &block)
5
+ end
6
+
7
+ def escaped_command(*args, &block)
8
+ ShellEscaped.new(CommandLine.new(*args, &block))
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,185 @@
1
+ require 'caliph/define-op'
2
+ require 'caliph/command-run-result'
3
+
4
+ module Caliph
5
+ class CommandLine
6
+ include DefineOp
7
+
8
+ class << self
9
+ attr_accessor :output_stream
10
+ end
11
+
12
+ def initialize(executable, *options)
13
+ @output_stream = self.class.output_stream || $stderr
14
+ @executable = executable.to_s
15
+ @options = options
16
+ @redirections = []
17
+ @env = {}
18
+ yield self if block_given?
19
+ end
20
+
21
+ attr_accessor :name, :executable, :options, :env, :output_stream
22
+ attr_reader :redirections
23
+
24
+ alias_method :command_environment, :env
25
+
26
+ def set_env(name, value)
27
+ command_environment[name] = value
28
+ return self
29
+ end
30
+
31
+ def verbose
32
+ #::Rake.verbose && ::Rake.verbose != ::Rake::FileUtilsExt::DEFAULT
33
+ end
34
+
35
+ def name
36
+ @name || executable
37
+ end
38
+
39
+ # The command as a string, including arguments and options
40
+ def command
41
+ ([executable] + options_composition + @redirections).join(" ")
42
+ end
43
+
44
+ # The command as a string, including arguments and options, plus prefixed
45
+ # environment variables.
46
+ def string_format
47
+ (command_environment.map do |key, value|
48
+ [key, value].join("=")
49
+ end + [command]).join(" ")
50
+ end
51
+
52
+ def options_composition
53
+ options
54
+ end
55
+
56
+ def redirect_to(stream, path)
57
+ @redirections << "#{stream}>#{path}"
58
+ self
59
+ end
60
+
61
+ def redirect_from(path, stream)
62
+ @redirections << "#{stream}<#{path}"
63
+ end
64
+
65
+ def copy_stream_to(from, to)
66
+ @redirections << "#{from}>&#{to}"
67
+ end
68
+
69
+ def redirect_stdout(path)
70
+ redirect_to(1, path)
71
+ end
72
+
73
+ def redirect_stderr(path)
74
+ redirect_to(2, path)
75
+ end
76
+
77
+ def redirect_stdin(path)
78
+ redirect_from(path, 0)
79
+ end
80
+
81
+ def redirect_both(path)
82
+ redirect_stdout(path).redirect_stderr(path)
83
+ end
84
+
85
+ # Run the command, wait for termination, and collect the results.
86
+ # Returns an instance of CommandRunResult that contains the output
87
+ # and exit code of the command.
88
+ #
89
+ # This version adds some information to STDOUT to document that the
90
+ # command is running. For a terser version, call #execute directly
91
+ def run
92
+ report string_format + " ", false
93
+ result = execute
94
+ report "=> #{result.exit_code}"
95
+ report result.format_streams if verbose
96
+ return result
97
+ ensure
98
+ report "" if verbose
99
+ end
100
+
101
+ # Fork a new process for the command, then terminate our process.
102
+ def run_as_replacement
103
+ output_stream.puts "Ceding execution to: "
104
+ output_stream.puts string_format
105
+ Process.exec(command_environment, command)
106
+ end
107
+ alias replace_us run_as_replacement
108
+
109
+ # Run the command in the background. The command can survive the caller.
110
+ def run_detached
111
+ pid, out, err = spawn_process
112
+ Process.detach(pid)
113
+ return pid, out, err
114
+ end
115
+ alias spin_off run_detached
116
+
117
+ # Run the command, wait for termination, and collect the results.
118
+ # Returns an instance of CommandRunResult that contains the output
119
+ # and exit code of the command.
120
+ #
121
+ def execute
122
+ collect_result(*spawn_process)
123
+ end
124
+
125
+ # Run the command in parallel with the parent process - will kill it if it
126
+ # outlasts us
127
+ def run_in_background
128
+ pid, out, err = spawn_process
129
+ Process.detach(pid)
130
+ at_exit do
131
+ kill_process(pid)
132
+ end
133
+ return pid, out, err
134
+ end
135
+ alias background run_in_background
136
+
137
+ # Given a process ID for a running command and a pair of stdout/stdin
138
+ # streams, records the results of the command and returns them in a
139
+ # CommandRunResult instance.
140
+ def collect_result(pid, host_stdout, host_stderr)
141
+ result = CommandRunResult.new(pid, self)
142
+ result.streams = {1 => host_stdout, 2 => host_stderr}
143
+ result.wait
144
+ return result
145
+ end
146
+
147
+
148
+ def kill_process(pid)
149
+ Process.kill("INT", pid)
150
+ end
151
+
152
+ def complete(pid, out, err)
153
+ kill_process(pid)
154
+ collect_result(pid, out, err)
155
+ end
156
+
157
+ def report(message, newline=true)
158
+ output_stream.print(message + (newline ? "\n" : ""))
159
+ end
160
+
161
+
162
+ def succeeds?
163
+ run.succeeded?
164
+ end
165
+
166
+ def must_succeed!
167
+ run.must_succeed!
168
+ end
169
+
170
+ def spawn_process
171
+ host_stdout, cmd_stdout = IO.pipe
172
+ host_stderr, cmd_stderr = IO.pipe
173
+
174
+ pid = Process.spawn(command_environment, command, :out => cmd_stdout, :err => cmd_stderr)
175
+ cmd_stdout.close
176
+ cmd_stderr.close
177
+
178
+ return pid, host_stdout, host_stderr
179
+ end
180
+
181
+
182
+ end
183
+
184
+
185
+ end
@@ -0,0 +1,129 @@
1
+ module Caliph
2
+ class CommandRunResult
3
+ def initialize(pid, command)
4
+ @command = command
5
+ @pid = pid
6
+
7
+ #####
8
+ @process_status = nil
9
+ @streams = {}
10
+ @consume_timeout = nil
11
+ end
12
+ attr_reader :process_status, :pid
13
+ attr_accessor :consume_timeout, :streams
14
+
15
+ def stdout
16
+ @streams[1]
17
+ end
18
+
19
+ def stderr
20
+ @streams[2]
21
+ end
22
+
23
+ def exit_code
24
+ @process_status.exitstatus
25
+ end
26
+ alias exit_status exit_code
27
+
28
+ def succeeded?
29
+ must_succeed!
30
+ return true
31
+ rescue
32
+ return false
33
+ end
34
+
35
+ def format_streams
36
+ "stdout:#{stdout.nil? || stdout.empty? ? "[empty]\n" : "\n#{stdout}"}" +
37
+ "stderr:#{stderr.nil? || stderr.empty? ? "[empty]\n" : "\n#{stderr}"}---"
38
+ end
39
+
40
+ def must_succeed!
41
+ case exit_code
42
+ when 0
43
+ return exit_code
44
+ else
45
+ fail "Command #{@command.inspect} failed with exit status #{exit_code}: \n#{format_streams}"
46
+ end
47
+ end
48
+
49
+ def wait
50
+ @accumulators = {}
51
+ waits = {}
52
+ @buffered_echo = []
53
+
54
+ ioes = streams.values
55
+ ioes.each do |io|
56
+ @accumulators[io] = []
57
+ waits[io] = 3
58
+ end
59
+ begin_echoing = Time.now + (@consume_timeout || 3)
60
+
61
+ @live_ioes = ioes.dup
62
+
63
+ until @live_ioes.empty? do
64
+ newpid, @process_status = Process.waitpid2(pid, Process::WNOHANG)
65
+
66
+ unless @process_status.nil?
67
+ consume_buffers(@live_ioes)
68
+ break
69
+ end
70
+
71
+ timeout = 0
72
+
73
+ if !@buffered_echo.nil?
74
+ timeout = begin_echoing - Time.now
75
+ if timeout < 0
76
+ @command.report ""
77
+ @command.report "Long running command output:"
78
+ @command.report @buffered_echo.join
79
+ @buffered_echo = nil
80
+ end
81
+ end
82
+
83
+ if timeout > 0
84
+ result = IO::select(@live_ioes, [], @live_ioes, timeout)
85
+ else
86
+ result = IO::select(@live_ioes, [], @live_ioes, 1)
87
+ end
88
+
89
+ unless result.nil? #timeout
90
+ readable, _writeable, errored = *result
91
+ unless errored.empty?
92
+ raise "Error on IO: #{errored.inspect}"
93
+ end
94
+
95
+ consume_buffers(readable)
96
+ end
97
+ end
98
+
99
+ if @process_status.nil?
100
+ newpid, @process_status = Process.waitpid2(pid)
101
+ end
102
+
103
+ ioes.each do |io|
104
+ io.close
105
+ end
106
+ @streams = Hash[ioes.each_with_index.map{|io, index| [index + 1, @accumulators[io].join]}]
107
+ end
108
+
109
+ def consume_buffers(readable)
110
+ if not(readable.nil? or readable.empty?)
111
+ readable.each do |io|
112
+ begin
113
+ while chunk = io.read_nonblock(4096)
114
+ if @buffered_echo.nil?
115
+ @command.report chunk, false
116
+ else
117
+ @buffered_echo << chunk
118
+ end
119
+ @accumulators[io] << chunk
120
+ end
121
+ rescue IO::WaitReadable => ex
122
+ rescue EOFError => ex
123
+ @live_ioes.delete(io)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,29 @@
1
+ module Caliph
2
+ module DefineOp
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def define_chain_op(opname, klass)
9
+ define_method(opname) do |other|
10
+ unless CommandLine === other
11
+ other = CommandLine.new(*[*other])
12
+ end
13
+ chain = nil
14
+ if klass === self
15
+ chain = self
16
+ else
17
+ chain = klass.new
18
+ chain.add(self)
19
+ end
20
+ chain.add(other)
21
+ end
22
+ end
23
+
24
+ def define_op(opname)
25
+ CommandLine.define_chain_op(opname, self)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ require 'caliph/command-line'
2
+
3
+ module Caliph
4
+ class ShellEscaped < CommandLine
5
+ def initialize(cmd)
6
+ @escaped = cmd
7
+ end
8
+
9
+ def command
10
+ "'" + @escaped.string_format.gsub(/'/,"\'") + "'"
11
+ end
12
+
13
+ def command_environment
14
+ {}
15
+ end
16
+
17
+ def name
18
+ @name || @escaped.name
19
+ end
20
+
21
+ def to_s
22
+ command
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,67 @@
1
+ require 'caliph/command-line'
2
+
3
+ module Caliph
4
+ class MockCommandResult < 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
+ Caliph::CommandLine.execute(command)
38
+ end
39
+ end
40
+
41
+
42
+ def self.included(group)
43
+ group.before :each do
44
+ @original_execute = Caliph::CommandLine.instance_method(:execute)
45
+ unless MockingExecute > Caliph::CommandLine
46
+ Caliph::CommandLine.send(:include, MockingExecute)
47
+ end
48
+ Caliph::CommandLine.send(:remove_method, :execute)
49
+ end
50
+
51
+ group.after :each do
52
+ Caliph::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
+ Caliph::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
+ Caliph::CommandLine.should_receive(:execute, :expected_from => caller(1)[0]).with(cmd).ordered.and_return(MockCommandResult.create(*result))
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,38 @@
1
+ require 'caliph/command-line'
2
+
3
+ module Caliph
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['CALIPH_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 CALIPH_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
+ Caliph::CommandLine.emit_recording
38
+ end
@@ -0,0 +1,9 @@
1
+ require 'caliph'
2
+
3
+ describe Caliph::CommandChain do
4
+
5
+ it "should initialize" do
6
+ Caliph::CommandChain.new
7
+ end
8
+
9
+ end
@@ -0,0 +1,48 @@
1
+ require 'caliph/command-line-dsl'
2
+
3
+ describe Caliph::CommandLineDSL do
4
+ include described_class
5
+
6
+ describe "using the - operator" do
7
+ let :command do
8
+ cmd("sudo") - ["gem", "install", "bundler"]
9
+ end
10
+
11
+ it "should define commands" do
12
+ command.should be_an_instance_of(Caliph::WrappingChain)
13
+ command.should have(2).commands
14
+ command.commands[0].should be_an_instance_of(Caliph::CommandLine)
15
+ command.commands[1].should be_an_instance_of(Caliph::CommandLine)
16
+ command.command.should == "sudo -- gem install bundler"
17
+ end
18
+ end
19
+
20
+ describe "using the | operator" do
21
+ let :command do
22
+ cmd("cat", "/etc/passwd") | ["grep", "root"]
23
+ end
24
+
25
+ it "should define commands" do
26
+ command.should be_an_instance_of(Caliph::PipelineChain)
27
+ command.should have(2).commands
28
+ command.commands[0].should be_an_instance_of(Caliph::CommandLine)
29
+ command.commands[1].should be_an_instance_of(Caliph::CommandLine)
30
+ command.command.should == "cat /etc/passwd | grep root"
31
+ end
32
+ end
33
+
34
+ describe "using the & operator" do
35
+ let :command do
36
+ p method(:cmd).source_location
37
+ cmd("cd", "/tmp/trash") & %w{rm -rf *}
38
+ end
39
+
40
+ it "should define commands" do
41
+ command.should be_an_instance_of(Caliph::PrereqChain)
42
+ command.should have(2).commands
43
+ command.commands[0].should be_an_instance_of(Caliph::CommandLine)
44
+ command.commands[1].should be_an_instance_of(Caliph::CommandLine)
45
+ command.command.should == "cd /tmp/trash && rm -rf *"
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,135 @@
1
+ require 'caliph'
2
+ require 'caliph/testing/mock-command-line'
3
+
4
+ require 'caliph/testing/record-commands'
5
+
6
+ Caliph::CommandLine.command_recording_path = "/dev/null"
7
+
8
+ describe Caliph::CommandLine do
9
+ let :commandline do
10
+ Caliph::CommandLine.new('echo', "-n") do |cmd|
11
+ cmd.options << "Some text"
12
+ end
13
+ end
14
+
15
+ it "should have a name set" do
16
+ commandline.name.should == "echo"
17
+ end
18
+
19
+ it "should produce a command string" do
20
+ commandline.command.should == "echo -n Some text"
21
+ end
22
+
23
+ it "should succeed" do
24
+ commandline.succeeds?.should be_true
25
+ end
26
+
27
+ it "should not complain about success" do
28
+ expect do
29
+ commandline.must_succeed!
30
+ end.to_not raise_error
31
+ end
32
+
33
+ end
34
+
35
+ describe Caliph::CommandLine, "setting environment variables" do
36
+ let :commandline do
37
+ Caliph::CommandLine.new("env") do |cmd|
38
+ cmd.env["TEST_ENV"] = "indubitably"
39
+ end
40
+ end
41
+
42
+ let :result do
43
+ commandline.run
44
+ end
45
+
46
+ it "should succeed" do
47
+ result.succeeded?.should be_true
48
+ end
49
+
50
+ it "should alter the command's environment variables" do
51
+ result.stdout.should =~ /TEST_ENV.*indubitably/
52
+ end
53
+
54
+ end
55
+
56
+ describe Caliph::CommandLine, 'redirecting' do
57
+ let :commandline do
58
+ Caliph::CommandLine.new("env")
59
+ end
60
+
61
+ let :result do
62
+ commandline.string_format
63
+ end
64
+
65
+ it 'should allow redirect stdout' do
66
+ commandline.redirect_stdout('some_file')
67
+ result.should =~ /1>some_file$/
68
+ end
69
+
70
+ it 'should allow redirect stderr' do
71
+ commandline.redirect_stderr('some_file')
72
+ result.should =~ /2>some_file$/
73
+ end
74
+
75
+ it 'should allow chain redirects' do
76
+ commandline.redirect_stdout('stdout_file').redirect_stderr('stderr_file')
77
+ result.should =~ /\b1>stdout_file\b/
78
+ result.should =~ /\b2>stderr_file\b/
79
+ end
80
+
81
+ it 'should redirect both' do
82
+ commandline.redirect_both('output_file')
83
+ result.should =~ /\b1>output_file\b/
84
+ result.should =~ /\b2>output_file\b/
85
+ end
86
+ end
87
+
88
+ describe Caliph::PipelineChain do
89
+ let :commandline do
90
+ Caliph::PipelineChain.new do |chain|
91
+ chain.add Caliph::CommandLine.new("env")
92
+ chain.add Caliph::CommandLine.new("cat") do |cmd|
93
+ cmd.env["TEST_ENV"] = "indubitably"
94
+ end
95
+ end
96
+ end
97
+
98
+ let :result do
99
+ commandline.run
100
+ end
101
+
102
+ it "should produce the right command" do
103
+ commandline.command.should == 'env | cat'
104
+ end
105
+
106
+ it "should produce a runnable command with format_string" do
107
+ commandline.string_format.should == 'TEST_ENV=indubitably env | cat'
108
+ end
109
+
110
+ it "should succeed" do
111
+ result.succeeded?.should be_true
112
+ end
113
+
114
+ it "should alter the command's environment variables" do
115
+ result.stdout.should =~ /TEST_ENV.*indubitably/
116
+ end
117
+ end
118
+
119
+
120
+
121
+ describe Caliph::CommandLine, "that fails" do
122
+ let :commandline do
123
+ Caliph::CommandLine.new("false")
124
+ end
125
+
126
+ it "should not succeed" do
127
+ commandline.succeeds?.should == false
128
+ end
129
+
130
+ it "should raise error if succeed demanded" do
131
+ expect do
132
+ commandline.must_succeed
133
+ end.to raise_error
134
+ end
135
+ end
@@ -0,0 +1,17 @@
1
+ puts Dir::pwd
2
+ require 'test/unit'
3
+ begin
4
+ require 'spec'
5
+ rescue LoadError
6
+ false
7
+ end
8
+
9
+ class RSpecTest < Test::Unit::TestCase
10
+ def test_that_rspec_is_available
11
+ assert_nothing_raised("\n\n * RSpec isn't available - please run: gem install rspec *\n\n"){ ::Spec }
12
+ end
13
+
14
+ def test_that_specs_pass
15
+ assert(system(*%w{spec -f e -p **/*.rb spec}),"\n\n * Specs failed *\n\n")
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspec'
2
+ require 'rspec/core/formatters/base_formatter'
3
+
4
+ require 'caliph'
5
+ require 'cadre/rspec'
6
+
7
+ RSpec.configure do |config|
8
+ config.run_all_when_everything_filtered = true
9
+ config.add_formatter(Cadre::RSpec::NotifyOnCompleteFormatter)
10
+ config.add_formatter(Cadre::RSpec::QuickfixFormatter)
11
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: caliph
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Evan Dorn
8
+ - Judson Lester
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-06-12 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: |2
15
+ TDD-suitable Ruby tool for generating command-line commands via an OOP interface.
16
+ email:
17
+ - evan@lrdesign.com
18
+ - judson@lrdesign.com
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - lib/caliph.rb
24
+ - lib/caliph/command-chain.rb
25
+ - lib/caliph/command-line-dsl.rb
26
+ - lib/caliph/command-line.rb
27
+ - lib/caliph/command-run-result.rb
28
+ - lib/caliph/define-op.rb
29
+ - lib/caliph/shell-escaped.rb
30
+ - lib/caliph/testing/mock-command-line.rb
31
+ - lib/caliph/testing/record-commands.rb
32
+ - spec/command-chain.rb
33
+ - spec/command-line-dsl.rb
34
+ - spec/command-line.rb
35
+ - spec_help/gem_test_suite.rb
36
+ - spec_help/spec_helper.rb
37
+ homepage: ''
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --inline-source
44
+ - --main
45
+ - doc/README
46
+ - --title
47
+ - caliph-0.1.0 Documentation
48
+ require_paths:
49
+ - lib/
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project: caliph
62
+ rubygems_version: 2.2.2
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: TDD-suitable Ruby tool for generating command-line commands via an OOP interface.
66
+ test_files:
67
+ - spec_help/gem_test_suite.rb