caliph 0.1.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.
@@ -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