borg-rb 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YmUyMjY1NWY1ZGQxY2IzMWI0NWY5OGJiZDA4ZWY1NzczM2ZhYzBkZA==
4
+ MWM1NWU1YWYzZGJmYjE1Y2NiNWU3NjllOTU3MDgyMTdiOTA0NzFlMQ==
5
5
  data.tar.gz: !binary |-
6
- NjQ2ZjUwN2I1MzU0ZGM3NmViNzFkY2QzNjZjNTMyMGNlMWRkNzQ5MA==
6
+ ZWVkNGIxM2VlZjE1NGU2YTI1MDNmYjM0NWJlMGExY2U3YTlmZTMxMA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- MTMxMDRmYTQ1ZWY2ZDk2NTEwMWM5NjhmNzExYjVlOWU0MGEyNmMzZDRhZWU5
10
- ZWQ4YTgyMGY3ZTAyZTUwY2Q0ZGJiN2I5N2ZiMGQ5YjE2NWQ2N2U5NTk4N2Fk
11
- ODJmZTNlZjhhYTAxMzFmOWI3NmVlMmQ3ZGU0ZjU4MWFjNWE4YzQ=
9
+ ZTFmNjM3Mjc0MmU2ZDFmOTNhNDY2NzQ3NWY3ZTQ0ODNiMDRjMzdjYjFiYWUx
10
+ MzBmM2I2MDkyMzI0YTQ0OTZlMGYwOWQ5ODQ3ZTdlM2Y4NjA5YzRjZmE4M2Rk
11
+ MDYyMmEwZjMxMDQ2YTgzZTJmZTIyNTRjZjdlZTQ1MTlkNjk3OTY=
12
12
  data.tar.gz: !binary |-
13
- YzBkOTZjZmIyM2NiNGM5NDE2NDA2OGJlMDdiZjc3MmE5NmQyMmQ4Yjk3ODVh
14
- NTJmMjQ5ODYxNWI1ZWQzODRjOGJlYTBlNmVjYTA4MDZhMGM3Y2ZhYTgxNjlj
15
- MmIwMjA4NDQ5ZjY4MTQ2Yzk5YWIyYmNkNzhhYzk5NGFlNWEwZDg=
13
+ M2E4OTY5ZmFhMzFlMTYxMjFiZWY2ZmRhNDJlMWFmNmY4NDVmOGRjYjM2ZWFh
14
+ Mzg2NDBmMDAyZGFlODNmOWU2YmIxOTMyYjMwNjkxYzM2ZTc0MmYwZTdjMzU4
15
+ ZjBjZGFhMDA4ZjQwMzVmMzA2ODJhMDE2ODc0ODQxNzNkMTRhMWM=
data/.travis.yml CHANGED
@@ -1,6 +1,12 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - jruby-19mode # JRuby in 1.9 mode
5
- - rbx-19mode
4
+ - 2.0.0
5
+ - ruby-head
6
+ - jruby-19mode # JRuby in 1.9 mode
7
+ - rbx-19mode # Rubinius in 1.9 mode
8
+ matrix:
9
+ allow_failures:
10
+ - rvm: ruby-head
11
+
6
12
  script: bundle exec rspec spec
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ ## Current (Unreleased)
2
+
3
+ ## 0.0.2 / 3-22-2013
4
+
5
+ * Fix load problem in Capfile in generated skeleton
6
+
7
+
8
+ ## 0.0.1 / 3-21-2013
9
+
10
+ * Created initial project skeleton: application config, multi-stage app config
11
+ * Created initial plugin skeleton for adding recipes
data/README.md CHANGED
@@ -6,8 +6,8 @@ deployment.
6
6
  [![Dependency Status](https://gemnasium.com/B0RG/borg.png)](https://gemnasium.com/B0RG/borg)
7
7
  [![Code Climate](https://codeclimate.com/github/B0RG/borg.png)](https://codeclimate.com/github/B0RG/borg)
8
8
 
9
- # Setup
10
- ## Deployer Package
9
+ ## Setup
10
+ ### Deployer Package
11
11
 
12
12
  `borgify` Sets up the following structure
13
13
 
@@ -18,11 +18,11 @@ my-deployer-package
18
18
  | | ├── application1.rb
19
19
  │ | └── application2.rb
20
20
  | ├── initilizers
21
- | | ├── initilizer1.rb
22
- │ | └── initilizer2.rb
21
+ | | ├── initializer1.rb
22
+ │ | └── initializer2.rb
23
23
  | └── recipies
24
- | ├── recipie1.rb
25
- │ └── recipie2.rb
24
+ | ├── recipe1.rb
25
+ │ └── recipe2.rb
26
26
  ├── Capfile
27
27
  ├── Gemfile
28
28
  └── Gemfile.lock
@@ -42,18 +42,18 @@ load 'borg'
42
42
 
43
43
  ```
44
44
 
45
- ## Services Package
45
+ ### Services Package
46
46
  `borgify plugin` Sets up the following structure
47
47
 
48
48
  ```
49
49
  my-service-package
50
50
  ├── cap
51
51
  | ├── initilizers
52
- | | ├── initilizer1.rb
53
- │ | └── initilizer2.rb
52
+ | | ├── initializer1.rb
53
+ │ | └── initializer2.rb
54
54
  | └── recipies
55
- | ├── recipie1.rb
56
- │ └── recipie2.rb
55
+ | ├── recipe1.rb
56
+ │ └── recipe2.rb
57
57
  ├── my-service-package.gemspec
58
58
  ├── Gemfile
59
59
  └── Gemfile.lock
@@ -83,3 +83,11 @@ then all the blocks will be run for that application/stage.
83
83
  The CLI enforces that all configs be specified at the start. Consider the command `borg app1:stage1 app2 deploy`
84
84
  will result in config app1:stage1, all configs for app2 (1 config for each stage, if there is no stage it assumes the app is the only stage)
85
85
  to be load and the deploy task be run against all of them.
86
+
87
+ ## Contributing
88
+
89
+ 1. Fork it
90
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
91
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
92
+ 4. Push to the branch (`git push origin my-new-feature`)
93
+ 5. Create new Pull Request
data/borg.gemspec CHANGED
@@ -18,10 +18,12 @@ Gem::Specification.new do |s|
18
18
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_dependency "capistrano"
21
+ s.add_dependency "capistrano", "~> 2.14.2"
22
22
  s.add_dependency "capistrano_colors"
23
23
  s.add_dependency "colored"
24
24
  s.add_dependency "term-ansicolor"
25
25
 
26
26
  s.add_development_dependency "rspec"
27
+ s.add_development_dependency "childprocess"
28
+
27
29
  end
data/lib/borg/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Borg
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/skeleton/Capfile CHANGED
@@ -4,6 +4,7 @@
4
4
  # runs on :exit events when ctrl-c is hit
5
5
  # set :borg_sigint_triggers_exit, true
6
6
 
7
- load 'borg.rb'
7
+ load "#{Gem::Specification.find_by_name('borg-rb').gem_dir}/lib/borg.rb"
8
+
8
9
  # load any other borg gems here.
9
10
  # NOTE: require ends up causing the initializers to be called every time a config is loaded.
@@ -0,0 +1,49 @@
1
+ require 'acceptance_spec_helper'
2
+
3
+ describe "borgify" do
4
+ include_context "acceptance"
5
+
6
+ before do
7
+ assert_execute("borgify")
8
+ @workdir = environment.workdir_path
9
+ end
10
+
11
+ it "creates the right files and directories" do
12
+ # Gemfile
13
+ gemfile = @workdir.join("Gemfile")
14
+ expect(gemfile.exist?).to be_true
15
+ expect(gemfile.read).to match(/^source "https:\/\/rubygems.org"$/)
16
+ expect(gemfile.read).to match(/borg-rb/)
17
+
18
+ # Capfile
19
+ capfile = @workdir.join("Capfile")
20
+ expect(capfile.exist?).to be_true
21
+
22
+ # lib directory
23
+ capfile = @workdir.join("lib")
24
+ expect(capfile.exist?).to be_true
25
+
26
+ # cap directory with the subdirectories: applications, initializers, recipes
27
+ cap_dir = @workdir.join("cap")
28
+ expect(cap_dir.exist?).to be_true
29
+ expect(cap_dir.join("applications")).to be_true
30
+ expect(cap_dir.join("initializers")).to be_true
31
+ expect(cap_dir.join("recipes")).to be_true
32
+ end
33
+ end
34
+
35
+ describe "borgify plugin" do
36
+ include_context "acceptance"
37
+
38
+ before do
39
+ assert_execute("borgify", "plugin")
40
+ @workdir = environment.workdir_path
41
+ end
42
+
43
+ it "creates the right files and directories" do
44
+ # the gemspec
45
+ directory_name = File.basename(@workdir = environment.workdir_path)
46
+ gemspec = @workdir = environment.workdir_path.join("#{directory_name}.gemspec")
47
+ expect(gemspec.exist?).to be_true
48
+ end
49
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
4
+
5
+ RSpec.configure do |config|
6
+ config.treat_symbols_as_metadata_keys_with_true_values = true
7
+ config.run_all_when_everything_filtered = true
8
+ config.filter_run :focus
9
+
10
+ # Run specs in random order to surface order dependencies. If you find an
11
+ # order dependency and want to debug it, you can fix the order by providing
12
+ # the seed, which is printed after each run.
13
+ # --seed 1234
14
+ config.order = 'random'
15
+
16
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,2 @@
1
1
  require 'capistrano/cli'
2
-
3
2
  require 'yaml'
@@ -0,0 +1,58 @@
1
+ require "fileutils"
2
+ require "pathname"
3
+ require "childprocess"
4
+
5
+ module Support
6
+ # This class creates a temporary directory to act as the working directory
7
+ #
8
+ # Modified from: https://github.com/mitchellh/vagrant/blob/master/spec/support/isolated_environment.rb
9
+ class IsolatedEnvironment
10
+ ROOT_DIR = Pathname.new(File.expand_path("../../", __FILE__))
11
+
12
+ attr_reader :workdir, :workdir_path
13
+
14
+ def initialize
15
+ # Create a temporary directory for our work
16
+ @workdir = TempDir.new("borg")
17
+ @workdir_path = Pathname.new(TempDir.new("borg").path)
18
+ # puts "Initialize isolated environment: #{@workdir_path.to_s}"
19
+ end
20
+
21
+ # Copies a skeleton into this isolated environment. This is useful
22
+ # for testing environments that require a complex setup.
23
+ #
24
+ # @param [String] name Name of the skeleton in the root directory.
25
+ def skeleton!(name)
26
+ # Copy all the files into the home directory
27
+ source = Dir.glob(ROOT_DIR.join(name).join("*").to_s)
28
+ FileUtils.cp_r(source, @workdir.to_s)
29
+ end
30
+
31
+ # Executes a command in the context of this isolated environment.
32
+ # Any command executed will therefore see our temporary directory
33
+ # as the home directory.
34
+ def execute(command, *argN)
35
+ # Determine the options
36
+ options = argN.last.is_a?(Hash) ? argN.pop : {}
37
+ options = {
38
+ workdir: @workdir_path,
39
+ notify: [:stdin, :stderr, :stdout]
40
+ }.merge(options)
41
+
42
+ # Add the options to be passed on
43
+ argN << options
44
+
45
+ # Execute, logging out the stdout/stderr as we get it
46
+ # puts("Executing: #{[command].concat(argN).inspect}")
47
+ Support::Subprocess.execute(command, *argN) do |type, data|
48
+ yield type, data if block_given?
49
+ end
50
+ end
51
+
52
+ # Closes the environment and cleans it up
53
+ def close
54
+ # puts "Removing isolated environment: #{@workdir.path}"
55
+ FileUtils.rm_rf(@workdir.path)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,14 @@
1
+ # Matcher that verifies that a process succeeds.
2
+ RSpec::Matchers.define :succeed do
3
+ match do |thing|
4
+ expect(thing.exit_code).to eq 0
5
+ end
6
+
7
+ failure_message_for_should do |actual|
8
+ "expected process to succeed. exit code: #{actual.exit_code}"
9
+ end
10
+
11
+ failure_message_for_should_not do |actual|
12
+ "expected process to fail. exit code: #{actual.exit_code}"
13
+ end
14
+ end
@@ -0,0 +1,81 @@
1
+ module Support
2
+ # This class just contains some platform checking code.
3
+ # source: https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/util/platform.rb)
4
+ class Platform
5
+ class << self
6
+ def tiger?
7
+ platform.include?("darwin8")
8
+ end
9
+
10
+ def leopard?
11
+ platform.include?("darwin9")
12
+ end
13
+
14
+ def cygwin?
15
+ platform.include?("cygwin")
16
+ end
17
+
18
+ [:darwin, :bsd, :freebsd, :linux, :solaris].each do |type|
19
+ define_method("#{type}?") do
20
+ platform.include?(type.to_s)
21
+ end
22
+ end
23
+
24
+ def windows?
25
+ %W[mingw mswin].each do |text|
26
+ return true if platform.include?(text)
27
+ end
28
+
29
+ false
30
+ end
31
+
32
+ # Returns boolean noting whether this is a 64-bit CPU. This
33
+ # is not 100% accurate and there could easily be false negatives.
34
+ #
35
+ # @return [Boolean]
36
+ def bit64?
37
+ ["x86_64", "amd64"].include?(RbConfig::CONFIG["host_cpu"])
38
+ end
39
+
40
+ # Returns boolean noting whether this is a 32-bit CPU. This
41
+ # can easily throw false positives since it relies on {#bit64?}.
42
+ #
43
+ # @return [Boolean]
44
+ def bit32?
45
+ !bit64?
46
+ end
47
+
48
+ # This takes as input a path as a string and converts it into
49
+ # a platform-friendly version of the path. This is most important
50
+ # when using the path in shell environments with Cygwin.
51
+ #
52
+ # @param [String] path
53
+ # @return [String]
54
+ def platform_path(path)
55
+ return path if !cygwin?
56
+
57
+ process = Subprocess.execute("cygpath", "-u", path.to_s)
58
+ process.stdout.chomp
59
+ end
60
+
61
+ # Returns a boolean noting whether the terminal supports color.
62
+ # output.
63
+ def terminal_supports_colors?
64
+ if windows?
65
+ return ENV.has_key?("ANSICON")
66
+ end
67
+
68
+ true
69
+ end
70
+
71
+ def tar_file_options
72
+ # create, write only, fail if the file exists, binary if windows
73
+ File::WRONLY | File::EXCL | File::CREAT | (windows? ? File::BINARY : 0)
74
+ end
75
+
76
+ def platform
77
+ RbConfig::CONFIG["host_os"].downcase
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,28 @@
1
+ require "support/isolated_environment"
2
+
3
+ shared_context "acceptance" do
4
+ # Setup the environment so that we have an isolated area to run our acceptance tests
5
+ let!(:environment) { Support::IsolatedEnvironment.new }
6
+
7
+ after do
8
+ environment.close
9
+ end
10
+
11
+ # Executes the given command in the context of the isolated environment.
12
+ #
13
+ # @return [Object]
14
+ def execute(*args, &block)
15
+ environment.execute(*args, &block)
16
+ end
17
+
18
+ # This method is an assertion helper for asserting that a process
19
+ # succeeds. It is a wrapper around `execute` that asserts that the
20
+ # exit status was successful.
21
+ def assert_execute(*args, &block)
22
+ result = execute(*args, &block)
23
+ expect(result).to succeed
24
+ #assert(result.exit_code == 0, "expected '#{args.join(" ")}' to succeed")
25
+ result
26
+ end
27
+
28
+ end
@@ -0,0 +1,259 @@
1
+ require 'childprocess'
2
+
3
+ module Support
4
+ # Execute a command in a subprocess, gathering the results and
5
+ # exit status.
6
+ #
7
+ # This class also allows you to read the data as it is outputted
8
+ # from the subprocess in real time, by simply passing a block to
9
+ # the execute method.
10
+ #
11
+ # Modified from: https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/util/subprocess.rb
12
+ class Subprocess
13
+ # The chunk size for reading from subprocess IO.
14
+ READ_CHUNK_SIZE = 4096
15
+
16
+ # Convenience method for executing a method.
17
+ def self.execute(*command, &block)
18
+ new(*command).execute(&block)
19
+ end
20
+
21
+ def initialize(*command)
22
+ @options = command.last.is_a?(Hash) ? command.pop : {}
23
+ @command = command
24
+ end
25
+
26
+ def execute
27
+ # Get the timeout, if we have one
28
+ timeout = @options[:timeout]
29
+
30
+ # Get the working directory
31
+ workdir = @options[:workdir] || Dir.pwd
32
+
33
+ # Get what we're interested in being notified about
34
+ notify = @options[:notify] || []
35
+ notify = [notify] if !notify.is_a?(Array)
36
+ if notify.empty? && block_given?
37
+ # If a block is given, subscribers must be given, otherwise the
38
+ # block is never called. This is usually NOT what you want, so this
39
+ # is an error.
40
+ message = "A list of notify subscriptions must be given if a block is given"
41
+ raise ArgumentError, message
42
+ end
43
+
44
+ # Let's get some more useful booleans that we access a lot so
45
+ # we're not constantly calling an `include` check
46
+ notify_table = {}
47
+ notify_table[:stderr] = notify.include?(:stderr)
48
+ notify_table[:stdout] = notify.include?(:stdout)
49
+ notify_stdin = notify.include?(:stdin)
50
+
51
+ # Build the ChildProcess
52
+ process = ChildProcess.build(*@command)
53
+
54
+ # Create the pipes so we can read the output in real time as
55
+ # we execute the command.
56
+ stdout, stdout_writer = IO.pipe
57
+ stderr, stderr_writer = IO.pipe
58
+ process.io.stdout = stdout_writer
59
+ process.io.stderr = stderr_writer
60
+ process.duplex = true
61
+
62
+ # Set the environment on the process if we must
63
+ if @options[:env]
64
+ @options[:env].each do |k, v|
65
+ process.environment[k] = v
66
+ end
67
+ end
68
+
69
+ # Start the process
70
+ begin
71
+ Dir.chdir(workdir) do
72
+ process.start
73
+ end
74
+ rescue ChildProcess::LaunchError => ex
75
+ # Raise our own version of the error so that users of the class
76
+ # don't need to be aware of ChildProcess
77
+ raise LaunchError.new(ex.message)
78
+ end
79
+
80
+ # Make sure the stdin does not buffer
81
+ process.io.stdin.sync = true
82
+
83
+ if RUBY_PLATFORM != "java"
84
+ # On Java, we have to close after. See down the method...
85
+ # Otherwise, we close the writers right here, since we're
86
+ # not on the writing side.
87
+ stdout_writer.close
88
+ stderr_writer.close
89
+ end
90
+
91
+ # Create a dictionary to store all the output we see.
92
+ io_data = { :stdout => "", :stderr => "" }
93
+
94
+ # Record the start time for timeout purposes
95
+ start_time = Time.now.to_i
96
+
97
+ while true
98
+ writers = notify_stdin ? [process.io.stdin] : []
99
+ results = IO.select([stdout, stderr], writers, nil, timeout || 0.1)
100
+ results ||= []
101
+ readers = results[0]
102
+ writers = results[1]
103
+
104
+ # Check if we have exceeded our timeout
105
+ raise TimeoutExceeded, process.pid if timeout && (Time.now.to_i - start_time) > timeout
106
+
107
+ # Check the readers to see if they're ready
108
+ if readers && !readers.empty?
109
+ readers.each do |r|
110
+ # Read from the IO object
111
+ data = read_io(r)
112
+
113
+ # We don't need to do anything if the data is empty
114
+ next if data.empty?
115
+
116
+ io_name = r == stdout ? :stdout : :stderr
117
+
118
+ io_data[io_name] += data
119
+ yield io_name, data if block_given? && notify_table[io_name]
120
+ end
121
+ end
122
+
123
+ # Break out if the process exited. We have to do this before
124
+ # attempting to write to stdin otherwise we'll get a broken pipe
125
+ # error.
126
+ break if process.exited?
127
+
128
+ # Check the writers to see if they're ready, and notify any listeners
129
+ if writers && !writers.empty?
130
+ yield :stdin, process.io.stdin if block_given?
131
+ end
132
+ end
133
+
134
+ # Wait for the process to end.
135
+ begin
136
+ remaining = (timeout || 32000) - (Time.now.to_i - start_time)
137
+ remaining = 0 if remaining < 0
138
+
139
+ process.poll_for_exit(remaining)
140
+ rescue ChildProcess::TimeoutError
141
+ raise TimeoutExceeded, process.pid
142
+ end
143
+
144
+ # Read the final output data, since it is possible we missed a small
145
+ # amount of text between the time we last read data and when the
146
+ # process exited.
147
+ [stdout, stderr].each do |io|
148
+ # Read the extra data, ignoring if there isn't any
149
+ extra_data = read_io(io)
150
+ next if extra_data == ""
151
+
152
+ # Log it out and accumulate
153
+ io_name = io == stdout ? :stdout : :stderr
154
+ io_data[io_name] += extra_data
155
+
156
+ # Yield to any listeners any remaining data
157
+ yield io_name, extra_data if block_given?
158
+ end
159
+
160
+ if RUBY_PLATFORM == "java"
161
+ # On JRuby, we need to close the writers after the process,
162
+ # for some reason. See GH-711.
163
+ stdout_writer.close
164
+ stderr_writer.close
165
+ end
166
+
167
+ # Return an exit status container
168
+ Result.new(process.exit_code, io_data[:stdout], io_data[:stderr])
169
+ end
170
+
171
+ protected
172
+
173
+ # Reads data from an IO object while it can, returning the data it reads.
174
+ # When it encounters a case when it can't read anymore, it returns the
175
+ # data.
176
+ #
177
+ # @return [String]
178
+ def read_io(io)
179
+ data = ""
180
+
181
+ while true
182
+ begin
183
+ if Platform.windows?
184
+ # Windows doesn't support non-blocking reads on
185
+ # file descriptors or pipes so we have to get
186
+ # a bit more creative.
187
+
188
+ # Check if data is actually ready on this IO device.
189
+ # We have to do this since `readpartial` will actually block
190
+ # until data is available, which can cause blocking forever
191
+ # in some cases.
192
+ results = IO.select([io], nil, nil, 0.1)
193
+ break if !results || results[0].empty?
194
+
195
+ # Read!
196
+ data << io.readpartial(READ_CHUNK_SIZE)
197
+ else
198
+ # Do a simple non-blocking read on the IO object
199
+ data << io.read_nonblock(READ_CHUNK_SIZE)
200
+ end
201
+ rescue Exception => e
202
+ # The catch-all rescue here is to support multiple Ruby versions,
203
+ # since we use some Ruby 1.9 specific exceptions.
204
+
205
+ breakable = false
206
+ if e.is_a?(EOFError)
207
+ # An `EOFError` means this IO object is done!
208
+ breakable = true
209
+ elsif defined?(IO::WaitReadable) && e.is_a?(IO::WaitReadable)
210
+ # IO::WaitReadable is only available on Ruby 1.9+
211
+
212
+ # An IO::WaitReadable means there may be more IO but this
213
+ # IO object is not ready to be read from yet. No problem,
214
+ # we read as much as we can, so we break.
215
+ breakable = true
216
+ elsif e.is_a?(Errno::EAGAIN)
217
+ # Otherwise, we just look for the EAGAIN error which should be
218
+ # all that IO::WaitReadable does in Ruby 1.9.
219
+ breakable = true
220
+ end
221
+
222
+ # Break out if we're supposed to. Otherwise re-raise the error
223
+ # because it is a real problem.
224
+ break if breakable
225
+ raise
226
+ end
227
+ end
228
+
229
+ data
230
+ end
231
+
232
+ # An error which raises when a process fails to start
233
+ class LaunchError < StandardError; end
234
+
235
+ # An error which occurs when the process doesn't end within
236
+ # the given timeout.
237
+ class TimeoutExceeded < StandardError
238
+ attr_reader :pid
239
+
240
+ def initialize(pid)
241
+ super()
242
+ @pid = pid
243
+ end
244
+ end
245
+
246
+ # Container class to store the results of executing a subprocess.
247
+ class Result
248
+ attr_reader :exit_code
249
+ attr_reader :stdout
250
+ attr_reader :stderr
251
+
252
+ def initialize(exit_code, stdout, stderr)
253
+ @exit_code = exit_code
254
+ @stdout = stdout
255
+ @stderr = stderr
256
+ end
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,33 @@
1
+ require 'fileutils'
2
+ require 'tempfile'
3
+
4
+ module Support
5
+ # This class provides an easy way of creating a temporary
6
+ # directory and having it removed when the application exits.
7
+ #
8
+ # Modified from: https://github.com/mitchellh/vagrant/blob/master/spec/support/tempdir.rb
9
+ class TempDir
10
+ attr_reader :path
11
+
12
+ def initialize(basename = "borg")
13
+ @path = Dir.mktmpdir(basename)
14
+
15
+ # Setup a finalizer to delete the directory. This is the same way
16
+ # that Tempfile and friends do this...
17
+ @cleanup_proc = lambda do
18
+ FileUtils.rm_rf(@path) if File.directory?(@path)
19
+ end
20
+
21
+ ObjectSpace.define_finalizer(self, @cleanup_proc)
22
+ end
23
+
24
+ # This deletes the temporary directory.
25
+ def unlink
26
+ # Delete the directory
27
+ @cleanup_proc.call
28
+
29
+ # Undefine the finalizer since we're all cleaned up
30
+ ObjectSpace.undefine_finalizer(self)
31
+ end
32
+ end
33
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: borg-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Identified
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-03-21 00:00:00.000000000 Z
11
+ date: 2013-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capistrano
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 2.14.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 2.14.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: capistrano_colors
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ! '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: childprocess
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: Ruby-based software provisioning and deployment framework
84
98
  email:
85
99
  - phil@identified.com
@@ -92,6 +106,7 @@ extra_rdoc_files: []
92
106
  files:
93
107
  - .gitignore
94
108
  - .travis.yml
109
+ - CHANGELOG.md
95
110
  - Capfile
96
111
  - Gemfile
97
112
  - README.md
@@ -119,11 +134,19 @@ files:
119
134
  - skeleton/cap/recipies/.gitkeep
120
135
  - skeleton/lib/.gitkeep
121
136
  - skeleton/mygem.gemspec.skeleton
137
+ - spec/acceptance/borgify_spec.rb
138
+ - spec/acceptance_spec_helper.rb
122
139
  - spec/lib/borg/cli/applications_spec.rb
123
140
  - spec/lib/borg/configuration/applications_spec.rb
124
141
  - spec/lib/borg/configuration/assimilator_spec.rb
125
142
  - spec/lib/borg/configuration/stages_spec.rb
126
143
  - spec/spec_helper.rb
144
+ - spec/support/isolated_environment.rb
145
+ - spec/support/matchers/succeed.rb
146
+ - spec/support/platform.rb
147
+ - spec/support/shared_contexts/acceptance.rb
148
+ - spec/support/subprocess.rb
149
+ - spec/support/temp_dir.rb
127
150
  homepage: https://github.com/B0RG/borg
128
151
  licenses:
129
152
  - MIT
@@ -149,9 +172,17 @@ signing_key:
149
172
  specification_version: 4
150
173
  summary: Ruby-based software provisioning and deployment framework
151
174
  test_files:
175
+ - spec/acceptance/borgify_spec.rb
176
+ - spec/acceptance_spec_helper.rb
152
177
  - spec/lib/borg/cli/applications_spec.rb
153
178
  - spec/lib/borg/configuration/applications_spec.rb
154
179
  - spec/lib/borg/configuration/assimilator_spec.rb
155
180
  - spec/lib/borg/configuration/stages_spec.rb
156
181
  - spec/spec_helper.rb
182
+ - spec/support/isolated_environment.rb
183
+ - spec/support/matchers/succeed.rb
184
+ - spec/support/platform.rb
185
+ - spec/support/shared_contexts/acceptance.rb
186
+ - spec/support/subprocess.rb
187
+ - spec/support/temp_dir.rb
157
188
  has_rdoc: