ey-deploy 0.7.0 → 0.7.1

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.
Files changed (51) hide show
  1. data/lib/ey-deploy.rb +4 -0
  2. data/lib/ey-deploy/cli.rb +27 -16
  3. data/lib/ey-deploy/deploy.rb +13 -13
  4. data/lib/ey-deploy/deploy_hook.rb +13 -6
  5. data/lib/ey-deploy/logged_output.rb +58 -0
  6. data/lib/ey-deploy/server.rb +5 -5
  7. data/lib/ey-deploy/strategies/git.rb +5 -5
  8. data/lib/ey-deploy/task.rb +6 -12
  9. data/lib/ey-deploy/version.rb +1 -1
  10. data/lib/vendor/dataflow/HISTORY +52 -0
  11. data/lib/vendor/dataflow/LICENSE +19 -0
  12. data/lib/vendor/dataflow/README.textile +290 -0
  13. data/lib/vendor/dataflow/Rakefile +36 -0
  14. data/lib/vendor/dataflow/dataflow.rb +120 -0
  15. data/lib/vendor/dataflow/dataflow/actor.rb +22 -0
  16. data/lib/vendor/dataflow/dataflow/equality.rb +28 -0
  17. data/lib/vendor/dataflow/dataflow/future_queue.rb +24 -0
  18. data/lib/vendor/dataflow/dataflow/port.rb +54 -0
  19. data/lib/vendor/dataflow/examples/barrier.rb +9 -0
  20. data/lib/vendor/dataflow/examples/data_driven.rb +17 -0
  21. data/lib/vendor/dataflow/examples/dataflow_http_gets.rb +13 -0
  22. data/lib/vendor/dataflow/examples/flow.rb +20 -0
  23. data/lib/vendor/dataflow/examples/future_http_gets.rb +12 -0
  24. data/lib/vendor/dataflow/examples/future_queue.rb +11 -0
  25. data/lib/vendor/dataflow/examples/instance_variables.rb +15 -0
  26. data/lib/vendor/dataflow/examples/laziness.rb +9 -0
  27. data/lib/vendor/dataflow/examples/local_variables.rb +11 -0
  28. data/lib/vendor/dataflow/examples/messages.rb +26 -0
  29. data/lib/vendor/dataflow/examples/port_http_gets.rb +13 -0
  30. data/lib/vendor/dataflow/examples/port_send.rb +10 -0
  31. data/lib/vendor/dataflow/examples/ring.rb +21 -0
  32. data/lib/vendor/dataflow/spec/actor_spec.rb +28 -0
  33. data/lib/vendor/dataflow/spec/anonymous_variables_spec.rb +21 -0
  34. data/lib/vendor/dataflow/spec/barrier_spec.rb +25 -0
  35. data/lib/vendor/dataflow/spec/by_need_spec.rb +55 -0
  36. data/lib/vendor/dataflow/spec/dataflow_spec.rb +151 -0
  37. data/lib/vendor/dataflow/spec/equality_spec.rb +40 -0
  38. data/lib/vendor/dataflow/spec/flow_spec.rb +25 -0
  39. data/lib/vendor/dataflow/spec/forker_spec.rb +28 -0
  40. data/lib/vendor/dataflow/spec/future_queue_spec.rb +31 -0
  41. data/lib/vendor/dataflow/spec/inspect_spec.rb +19 -0
  42. data/lib/vendor/dataflow/spec/need_later_spec.rb +12 -0
  43. data/lib/vendor/dataflow/spec/port_spec.rb +26 -0
  44. data/lib/vendor/dataflow/spec/spec.opts +1 -0
  45. data/lib/vendor/dataflow/spec/spec_helper.rb +10 -0
  46. data/lib/vendor/open4/lib/open4.rb +403 -0
  47. data/spec/deploy_hook_spec.rb +16 -2
  48. data/spec/fixtures/invalid_hook.rb +1 -0
  49. data/spec/fixtures/valid_hook.rb +1 -0
  50. metadata +43 -4
  51. data/lib/ey-deploy/verbose_system.rb +0 -12
@@ -0,0 +1,290 @@
1
+ h1. What's this?
2
+
3
+ A Ruby library that adds Dataflow variables (inspired by the Oz
4
+ language). Dataflow variables have the property that they can only
5
+ be bound/assigned to once, or have an equivalent value as an existing
6
+ assignment (see "unification").
7
+
8
+ Dataflow variables must be declared before they are used, and can be
9
+ passed around as data without actually being bound. If the variable
10
+ gets used (in this library this means a method call) while being
11
+ unbound then the currently executing thread will suspend.
12
+
13
+ h1. What's the point?
14
+
15
+ Ruby is Object Oriented (with the ability to mutate local, instance,
16
+ class, and global variables, and even constants), and on top of that
17
+ it has powerful reflection and meta-programming abilities. While these
18
+ features are useful for certain problems, they are not within the
19
+ declarative model. Staying in the declarative model gives one 2 advantages:
20
+ # It is easy to reason about what the program does
21
+ # Simple but powerful concurrency is possible
22
+
23
+ Ruby, like many other OO languages, is facing the hurdles of taking
24
+ advantage of the increase of processor cores within a simple parallel
25
+ programming model. This library lets you program Ruby in the
26
+ declarative concurrent model when you need to take advantage of multiple cores
27
+ (assuming a Ruby implementation that uses native threads in one way or
28
+ another).
29
+
30
+ The trick to this kind of programming is binding variables from other
31
+ threads. The nice thing is that many existing
32
+ libraries/classes/methods can still be used, just avoid
33
+ side-effects. Use regular Ruby threading to create threads, use
34
+ "local" or "declare" to create new variables, and use "unify" to bind
35
+ variables.
36
+
37
+ h1. Install
38
+
39
+ To install the latest release as a gem:
40
+ <pre>sudo gem install dataflow</pre>
41
+
42
+ h1. IRC
43
+
44
+ <pre>#dataflow-gem @ freenode.net</pre>
45
+
46
+ h1. Examples
47
+
48
+ <pre>
49
+ # Local variables
50
+ include Dataflow
51
+
52
+ local do |x, y, z|
53
+ # notice how the order automatically gets resolved
54
+ Thread.new { unify y, x + 2 }
55
+ Thread.new { unify z, y + 3 }
56
+ Thread.new { unify x, 1 }
57
+ z #=> 6
58
+ end
59
+ </pre>
60
+
61
+ <pre>
62
+ # Module methods version
63
+
64
+ Dataflow.local do |x, y, z|
65
+ # notice how the order automatically gets resolved
66
+ Thread.new { Dataflow.unify y, x + 2 }
67
+ Thread.new { Dataflow.unify z, y + 3 }
68
+ Thread.new { Dataflow.unify x, 1 }
69
+ z #=> 6
70
+ end
71
+
72
+ # Note that a gobal Dataflow.declare is not supported
73
+ </pre>
74
+
75
+ <pre>
76
+ # Instance variables
77
+ class AnimalHouse
78
+ include Dataflow
79
+ declare :small_cat, :big_cat
80
+
81
+ def fetch_big_cat
82
+ Thread.new { unify big_cat, small_cat.upcase }
83
+ unify small_cat, 'cat'
84
+ big_cat
85
+ end
86
+ end
87
+
88
+ AnimalHouse.new.fetch_big_cat #=> 'CAT'
89
+ </pre>
90
+
91
+ <pre>
92
+ # Data-driven concurrency
93
+ include Dataflow
94
+
95
+ local do |stream, doubles, triples, squares|
96
+ unify stream, Array.new(5) { Dataflow::Variable.new }
97
+
98
+ Thread.new { unify doubles, stream.map {|n| n*2 } }
99
+ Thread.new { unify triples, stream.map {|n| n*3 } }
100
+ Thread.new { unify squares, stream.map {|n| n**2 } }
101
+
102
+ Thread.new { stream.each {|x| unify x, rand(100) } }
103
+
104
+ puts "original: #{stream.inspect}"
105
+ puts "doubles: #{doubles.inspect}"
106
+ puts "triples: #{triples.inspect}"
107
+ puts "squares: #{squares.inspect}"
108
+ end
109
+ </pre>
110
+
111
+ <pre>
112
+ # By-need trigger laziness
113
+ include Dataflow
114
+
115
+ local do |x, y, z|
116
+ Thread.new { unify y, by_need { 4 } }
117
+ Thread.new { unify z, x + y }
118
+ Thread.new { unify x, by_need { 3 } }
119
+ z #=> 7
120
+ end
121
+ </pre>
122
+
123
+ <pre>
124
+ # Need-later future expressions
125
+ include Dataflow
126
+
127
+ local do |x, y, z|
128
+ unify y, need_later { 4 }
129
+ unify z, need_later { x + y }
130
+ unify x, need_later { 3 }
131
+ z #=> 7
132
+ end
133
+ </pre>
134
+
135
+ <pre>
136
+ include Dataflow
137
+
138
+ # flow without parameters
139
+ local do |x|
140
+ flow do
141
+ # other stuff
142
+ unify x, 1337
143
+ end
144
+ x #=> 1337
145
+ end
146
+
147
+ # flow with an output parameter
148
+ local do |x|
149
+ flow(x) do
150
+ # other stuff
151
+ 1337
152
+ end
153
+ x #=> 1337
154
+ end
155
+ </pre>
156
+
157
+ <pre>
158
+ # barrier
159
+ include Dataflow
160
+
161
+ local do |lock1, lock2|
162
+ flow { unify lock1, :unlocked }
163
+ flow { unify lock2, :unlocked }
164
+ barrier lock1, lock2
165
+ puts "Barrier broken!"
166
+ end
167
+ </pre>
168
+
169
+ <pre>
170
+ # FutureQueue
171
+ include Dataflow
172
+
173
+ local do |queue, first, second|
174
+ unify queue, Dataflow::FutureQueue.new
175
+ queue.pop first
176
+ queue.push 1
177
+ queue.push 2
178
+ queue.pop second
179
+ first #=> 1
180
+ second #=> 2
181
+ end
182
+ </pre>
183
+
184
+ h1. Anonymous variables
185
+
186
+ Sometimes you may want to pack a data structure with variables that do not need to be referenced with labels. For those cases anonymous variables are a good choice, here are some options:
187
+
188
+ <pre>
189
+ include Dataflow
190
+ Array.new(3) { Dataflow::Variable.new }
191
+ Array.new(3) { Dataflow.local }
192
+ Array.new(3) { local }
193
+ # and technically not anonymous
194
+ Array.new(3) { local {|v| v } }
195
+ </pre>
196
+
197
+ h1. Debugging
198
+
199
+ If you are having trouble and need to debug dataflow variables, simply call #inspect.
200
+
201
+ If the variable has already been bound, it call inspect on its bound value like normal.However, if the variable is not bound yet then you will get a special string that contains the proxies #__id__ that you can use to track down which proxy objects are being passed around to which parts of your program:
202
+ <pre>
203
+ include Dataflow
204
+ local do |my_var|
205
+ my_var.inspect # => #<Dataflow::Variable:2637860 unbound>
206
+ end
207
+ </pre>
208
+
209
+ h1. Fork method customization
210
+
211
+ By default both #flow and #need_later use Thread.fork as their fork method. Youc an access the fork method via Dataflow.forker.
212
+
213
+ If you would like to use a custom forker, simple set it to an object that responds to #call and internally calls a block passed to it (for an example of a synchronous forker, see spec/forker_spec.rb):
214
+ <pre>
215
+ Dataflow.forker = MyClass.method(:fork_with_threadpool)
216
+ </pre>
217
+
218
+ Also note that #flow is used interally by #need_later, in case you want to override that specifically.
219
+
220
+ h1. Ports using Dataflow
221
+
222
+ Ports are an extension of the declarative concurrent model to support nondeterministic behavior. They accomplish this through the use of a single state variable. Ports are also inspired by the Oz language.
223
+
224
+ An Actor class in the style of Erlang message-passing processes is also provided. It makes use of the asynchronous behavior of ports, but otherwise uses no state variables.
225
+
226
+ h1. Examples using Ports
227
+
228
+ <pre>
229
+ include Dataflow
230
+
231
+ local do |port, stream|
232
+ unify port, Dataflow::Port.new(stream)
233
+ Thread.new {port.send 2}
234
+ Thread.new {port.send 8}
235
+ Thread.new {port.send 1024}
236
+ stream.take(3).sort #=> [2, 8, 1024]
237
+ end
238
+ </pre>
239
+
240
+ h1. Examples using Actors
241
+
242
+ <pre>
243
+ include Dataflow
244
+
245
+ Ping = Actor.new {
246
+ 3.times {
247
+ case receive
248
+ when "Ping"
249
+ puts "Ping"
250
+ Pong.send "Pong"
251
+ end
252
+ }
253
+ }
254
+
255
+ Pong = Actor.new {
256
+ 3.times {
257
+ case receive
258
+ when "Pong"
259
+ puts "Pong"
260
+ Ping.send "Ping"
261
+ end
262
+ }
263
+ }
264
+
265
+ Actor.new { Ping.send "Ping" }
266
+
267
+ Ping.join
268
+ Pong.join
269
+ </pre>
270
+
271
+ h1. Equality
272
+
273
+ Most Ruby implmentations will not use method calls for equality
274
+ operations in base types/classes. This means equality between dataflow
275
+ variables and those base types will not behave as expected. Require
276
+ the following to get equality on base types that uses method calls,
277
+ while still passing rubyspec:
278
+
279
+ <pre>require "dataflow/equality"</pre>
280
+
281
+ h1. References
282
+
283
+ The basis of dataflow variables around a language is not common among
284
+ popular languages and may be confusing to some. For an in-depth
285
+ introduction to the Oz language and the techniques used in this
286
+ library (including by_need triggers, port objects, and comparisons to Erlang message passing) see the book "Concepts, Techniques, and Models of Computer Programming":http://en.wikipedia.org/wiki/Concepts,_Techniques,_and_Models_of_Computer_Programming
287
+
288
+ h1. Contributors
289
+
290
+ larrytheliquid, amiller
@@ -0,0 +1,36 @@
1
+ require "rubygems"
2
+ require "rake/gempackagetask"
3
+ require "rake/clean"
4
+ require "spec/rake/spectask"
5
+ require File.expand_path("./dataflow")
6
+
7
+ Spec::Rake::SpecTask.new do |t|
8
+ t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
9
+ end
10
+
11
+ desc "Run the specs"
12
+ task :default => :spec
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.name = "dataflow"
16
+ s.rubyforge_project = s.name
17
+ s.version = Dataflow::VERSION
18
+ s.author = "Larry Diehl"
19
+ s.email = "larrytheliquid" + "@" + "gmail.com"
20
+ s.homepage = "http://github.com/larrytheliquid/dataflow"
21
+ s.summary = "Dataflow concurrency for Ruby (inspired by the Oz language)"
22
+ s.description = s.summary
23
+ s.files = %w[LICENSE HISTORY Rakefile README.textile dataflow.rb] + Dir["dataflow/**/*"] + Dir["examples/**/*"]
24
+ s.require_path = '.'
25
+ s.test_files = Dir["spec/**/*"]
26
+ end
27
+
28
+ Rake::GemPackageTask.new(spec) do |package|
29
+ package.gem_spec = spec
30
+ end
31
+
32
+ desc 'Install the package as a gem.'
33
+ task :install => [:clean, :package] do
34
+ gem = Dir['pkg/*.gem'].first
35
+ sh "sudo gem install --no-rdoc --no-ri --local #{gem}"
36
+ end
@@ -0,0 +1,120 @@
1
+ require 'monitor'
2
+
3
+ module Dataflow
4
+ VERSION = "0.3.1"
5
+ class << self
6
+ attr_accessor :forker
7
+ end
8
+ self.forker = Thread.method(:fork)
9
+
10
+ def self.included(cls)
11
+ class << cls
12
+ def declare(*readers)
13
+ readers.each do |name|
14
+ class_eval <<-RUBY
15
+ def #{name}
16
+ return @__dataflow_#{name}__ if defined? @__dataflow_#{name}__
17
+ Variable::LOCK.synchronize { @__dataflow_#{name}__ ||= Variable.new }
18
+ end
19
+ RUBY
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def local(&block)
26
+ return Variable.new unless block_given?
27
+ vars = Array.new(block.arity) { Variable.new }
28
+ block.call *vars
29
+ end
30
+
31
+ def unify(variable, value)
32
+ variable.__unify__ value
33
+ end
34
+
35
+ def by_need(&block)
36
+ Variable.new &block
37
+ end
38
+
39
+ def barrier(*variables)
40
+ variables.each{|v| v.__wait__ }
41
+ end
42
+
43
+ def flow(output=nil, &block)
44
+ Dataflow.forker.call do
45
+ result = block.call
46
+ unify output, result if output
47
+ end
48
+ end
49
+
50
+ def need_later(&block)
51
+ local do |future|
52
+ flow(future) { block.call }
53
+ future
54
+ end
55
+ end
56
+
57
+ extend self
58
+
59
+ # Note that this class uses instance variables directly rather than nicely
60
+ # initialized instance variables in get/set methods for memory and
61
+ # performance reasons
62
+ class Variable
63
+ instance_methods.each { |m| undef_method m unless m =~ /^__/ }
64
+ LOCK = Monitor.new
65
+ def initialize(&block) @__trigger__ = block if block_given? end
66
+
67
+ # Lazy-load conditions to be nice on memory usage
68
+ def __binding_condition__() @__binding_condition__ ||= LOCK.new_cond end
69
+
70
+ def __unify__(value)
71
+ LOCK.synchronize do
72
+ __activate_trigger__ if @__trigger__
73
+ if @__bound__
74
+ return @__value__.__unify__(value) if @__value__.__dataflow__? rescue nil
75
+ raise UnificationError, "#{@__value__.inspect} != #{value.inspect}" if self != value
76
+ else
77
+ @__value__ = value
78
+ @__bound__ = true
79
+ __binding_condition__.broadcast # wakeup all method callers
80
+ @__binding_condition__ = nil # GC
81
+ end
82
+ end
83
+ @__value__
84
+ end
85
+
86
+ def __activate_trigger__
87
+ @__value__ = @__trigger__.call
88
+ @__bound__ = true
89
+ @__trigger__ = nil # GC
90
+ end
91
+
92
+ def __wait__
93
+ LOCK.synchronize do
94
+ unless @__bound__
95
+ if @__trigger__
96
+ __activate_trigger__
97
+ else
98
+ __binding_condition__.wait
99
+ end
100
+ end
101
+ end unless @__bound__
102
+ end
103
+
104
+ def method_missing(name, *args, &block)
105
+ return "#<Dataflow::Variable:#{__id__} unbound>" if !@__bound__ && name == :inspect
106
+ __wait__
107
+ @__value__.__send__(name, *args, &block)
108
+ end
109
+
110
+ def __dataflow__?
111
+ true
112
+ end
113
+ end
114
+
115
+ UnificationError = Class.new StandardError
116
+ end
117
+
118
+ require "#{File.dirname(__FILE__)}/dataflow/port"
119
+ require "#{File.dirname(__FILE__)}/dataflow/actor"
120
+ require "#{File.dirname(__FILE__)}/dataflow/future_queue"
@@ -0,0 +1,22 @@
1
+ module Dataflow
2
+ class Actor < Thread
3
+ def initialize(&block)
4
+ @stream = Variable.new
5
+ @port = Port.new(@stream)
6
+ # Run this block in a new thread
7
+ super { instance_eval &block }
8
+ end
9
+
10
+ def send message
11
+ @port.send message
12
+ end
13
+
14
+ private
15
+
16
+ def receive
17
+ result = @stream.head
18
+ @stream = @stream.tail
19
+ result
20
+ end
21
+ end
22
+ end