tango 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ pkg/*
2
2
  *.gem
3
3
  .bundle
4
4
  .DS_Store
5
+ .rvmrc
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tango (0.0.4)
4
+ tango (0.0.5)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -15,17 +15,17 @@ Example
15
15
 
16
16
  class Homebrew < Tango::Namespace
17
17
  def installed?(formula)
18
- `brew info #{formula}` !~ /Not installed/
18
+ shell("brew", "info", formula, :echo => false).output !~ /Not installed/
19
19
  end
20
20
 
21
21
  step "bootstrap" do
22
- met? { system "brew info" }
23
- meet { system %{ruby -e "$(curl -fsSL https://gist.github.com/raw/323731/install_homebrew.rb)"} }
22
+ met? { shell("brew info").succeeded? }
23
+ meet { shell(%{ruby -e "$(curl -fsSL https://gist.github.com/raw/323731/install_homebrew.rb)"}) }
24
24
  end
25
25
 
26
26
  step "install" do |formula|
27
27
  met? { installed?(formula) }
28
- meet { system "brew install #{formula}" }
28
+ meet { shell("brew, "install", formula) }
29
29
  end
30
30
  end
31
31
 
@@ -39,7 +39,7 @@ Example
39
39
 
40
40
  step "install mtr" do
41
41
  met? { Homebrew.installed?("mtr") }
42
- meet { system "brew install --no-gtk mtr" }
42
+ meet { shell("brew install --no-gtk mtr") }
43
43
  end
44
44
  end
45
45
 
@@ -10,17 +10,21 @@ module Tango
10
10
  end
11
11
 
12
12
  def enter(step_name)
13
- @io.puts "#{indent}#{step_name} {\n"
13
+ log "#{step_name} {"
14
14
  @depth += 1
15
15
  end
16
16
 
17
+ def leave(step_name)
18
+ @depth -= 1
19
+ log "} √ #{step_name}"
20
+ end
21
+
17
22
  def log(message)
18
- @io.puts "#{indent}#{message}\n"
23
+ @io.puts "#{indent}#{message}"
19
24
  end
20
25
 
21
- def leave(step_name)
22
- @depth -= 1
23
- @io.puts "#{indent}} √ #{step_name}\n"
26
+ def log_raw(message)
27
+ @io.write message
24
28
  end
25
29
 
26
30
  private
@@ -31,3 +35,4 @@ module Tango
31
35
 
32
36
  end
33
37
  end
38
+
@@ -1,10 +1,12 @@
1
1
  require 'tango/as_user'
2
2
  require 'tango/met_and_meet'
3
+ require 'tango/shell'
3
4
 
4
5
  module Tango
5
6
  class Namespace
6
7
  include AsUser
7
8
  include MetAndMeet
9
+ include Shell
8
10
 
9
11
  def self.step(step_name, &block)
10
12
  define_method(step_name, &block)
@@ -27,6 +29,10 @@ module Tango
27
29
  self.class.logger.log(message)
28
30
  end
29
31
 
32
+ def log_raw(message)
33
+ self.class.logger.log_raw(message)
34
+ end
35
+
30
36
  def self.method_missing(method, *args)
31
37
  new.send(method, *args)
32
38
  end
@@ -0,0 +1,57 @@
1
+ require 'ostruct'
2
+
3
+ module Tango
4
+ module Shell
5
+
6
+ def shell(command, *args)
7
+ options = { :echo => true }
8
+ options.merge!(args.pop) if args.last.is_a?(Hash)
9
+
10
+ log "% #{command} #{args.join(' ')}\n\n" if options[:echo]
11
+
12
+ pid, pipe = fork_and_exec(command, *args)
13
+ output = collect_output(pipe, options[:echo])
14
+ Process.waitpid(pid)
15
+ pipe.close
16
+
17
+ OpenStruct.new(
18
+ :output => output,
19
+ :status => $?.exitstatus,
20
+ :succeeded? => $?.success?,
21
+ :failed? => !$?.success?
22
+ )
23
+ end
24
+
25
+ private
26
+
27
+ def fork_and_exec(command, *args)
28
+ read_end, write_end = IO.pipe
29
+ pid = fork do
30
+ read_end.close
31
+ STDOUT.reopen(write_end)
32
+ STDERR.reopen(write_end)
33
+ exec(command, *args)
34
+ end
35
+ write_end.close
36
+
37
+ return pid, read_end
38
+ end
39
+
40
+ def collect_output(pipe, echo = true)
41
+ output = ""
42
+
43
+ begin
44
+ loop do
45
+ partial = pipe.readpartial(4096)
46
+ log_raw(partial) if echo
47
+ output << partial
48
+ end
49
+ rescue EOFError
50
+ end
51
+
52
+ output
53
+ end
54
+
55
+ end
56
+ end
57
+
@@ -1,3 +1,3 @@
1
1
  module Tango
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -0,0 +1,51 @@
1
+ require 'tango'
2
+
3
+ module Tango
4
+ describe Shell do
5
+
6
+ before do
7
+ @stub_class = Class.new do
8
+ include Tango::Shell
9
+ def log(message); end
10
+ def log_raw(message); end
11
+ end
12
+ end
13
+
14
+ it "should return the right info for a successful command" do
15
+ result = @stub_class.new.shell("echo", "Hello, world!")
16
+ result.output.should == "Hello, world!\n"
17
+ result.status.should == 0
18
+ result.succeeded?.should be_true
19
+ result.failed?.should be_false
20
+ end
21
+
22
+ it "should return the right info for a failing command" do
23
+ result = @stub_class.new.shell("test", "a", "=", "b")
24
+ result.status.should == 1
25
+ result.succeeded?.should be_false
26
+ result.failed?.should be_true
27
+ end
28
+
29
+ it "should accept commands as a single argument" do
30
+ result = @stub_class.new.shell("echo Hello, world!")
31
+ result.output.should == "Hello, world!\n"
32
+ end
33
+
34
+ it "should echo the command and its output" do
35
+ @stub = @stub_class.new
36
+ @stub.should_receive(:log).with("% echo Hello, world!\n\n")
37
+ @stub.should_receive(:log_raw).with("Hello, world!\n")
38
+
39
+ @stub.shell("echo", "Hello, world!")
40
+ end
41
+
42
+ it "should allow echo to be turned off" do
43
+ @stub = @stub_class.new
44
+ @stub.should_not_receive(:log)
45
+ @stub.should_not_receive(:log_raw)
46
+
47
+ @stub.shell("echo", "Hello, world!", :echo => false).output.should == "Hello, world!\n"
48
+ end
49
+
50
+ end
51
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tango
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease: false
4
+ hash: 21
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Pete Yandell
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-30 00:00:00 +11:00
18
+ date: 2011-04-01 00:00:00 +11:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -54,10 +54,12 @@ files:
54
54
  - lib/tango/logger.rb
55
55
  - lib/tango/met_and_meet.rb
56
56
  - lib/tango/namespace.rb
57
+ - lib/tango/shell.rb
57
58
  - lib/tango/version.rb
58
59
  - spec/logger_spec.rb
59
60
  - spec/met_and_meet_spec.rb
60
61
  - spec/namespace_spec.rb
62
+ - spec/shell_spec.rb
61
63
  - tango.gemspec
62
64
  has_rdoc: true
63
65
  homepage: ""
@@ -89,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
91
  requirements: []
90
92
 
91
93
  rubyforge_project: tango
92
- rubygems_version: 1.3.7
94
+ rubygems_version: 1.6.2
93
95
  signing_key:
94
96
  specification_version: 3
95
97
  summary: Experiment in deployment tools.
@@ -97,3 +99,4 @@ test_files:
97
99
  - spec/logger_spec.rb
98
100
  - spec/met_and_meet_spec.rb
99
101
  - spec/namespace_spec.rb
102
+ - spec/shell_spec.rb