strobe 0.1.0.beta.2 → 0.1.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,14 @@
1
1
  module Strobe
2
2
  class CLI::Main < CLI
3
3
 
4
+ def help(*args)
5
+ if args.first == "users"
6
+ CLI::Users.start( [ "help" ] + args[1..-1] )
7
+ else
8
+ super
9
+ end
10
+ end
11
+
4
12
  action "users", 'manage users' do |*args|
5
13
  argv = $ARGV[1..-1]
6
14
  argv = [ 'list' ] + argv if args.empty?
@@ -55,7 +63,9 @@ module Strobe
55
63
  end
56
64
 
57
65
  application_path_option
58
- method_option :staging, :type => :boolean, :banner => "deploy to a staging environment"
66
+ method_option "staging", :type => :boolean, :banner => "deploy to a staging environment"
67
+ method_option "sc-build", :type => :boolean, :banner => "run `sc-build -c` before deploying"
68
+ method_option "no-sc-build", :type => :boolean, :banner => "skip the `sc-build -c` step"
59
69
  action "deploy", "deploy your application to Strobe" do
60
70
  ensure_computer_is_registered
61
71
 
@@ -77,17 +87,56 @@ module Strobe
77
87
  end
78
88
  end
79
89
 
80
- host = resource.deploy! :environment => options[:staging] && 'staging'
90
+ run_sc_build
91
+
92
+ if STDOUT.tty?
93
+ thread = nil
94
+ read, write = IO.pipe
95
+
96
+ upload_callback = lambda do |percentage|
97
+ if percentage
98
+ width = 50
99
+ left = ( percentage * width ).round
100
+ right = ( ( 1.0 - percentage ) * width ).round
101
+
102
+ if left < width
103
+ right -= 1
104
+ arrow = ">"
105
+ end
106
+
107
+ print "Uploading [#{'=' * left}#{arrow}#{' ' * right}]\r"
108
+ else
109
+ puts
110
+ thread = Thread.new do
111
+ print "Reticulating splines..."
112
+
113
+ while true
114
+ break if IO.select( [read ], nil, nil, 0.5 )
115
+ print "."
116
+ end
117
+
118
+ puts
119
+ end
120
+ end
121
+ end
122
+ else
123
+ upload_callback = nil
124
+ end
125
+
126
+ host = resource.deploy! :environment => options[:staging] && 'staging',
127
+ :upload_callback => upload_callback
128
+
129
+ if STDOUT.tty?
130
+ write << '1'
131
+ thread.join
132
+ end
133
+
81
134
  say "The application has successfully been deployed and is available at #{host}"
82
135
  end
83
136
 
84
137
  action "applications", "list all of your applications" do
85
138
  empty = "You do not have any applications. Try deploying one with `strobe deploy`."
86
- table Resources::Application.all, :empty => empty do |t|
87
- t.column :id
88
- t.column :name
89
- t.column :url
90
- end
139
+ list_applications :empty => empty
91
140
  end
92
141
 
93
142
  method_option "url", :type => :string
@@ -119,7 +168,7 @@ module Strobe
119
168
  end
120
169
 
121
170
  application_path_option
122
- method_option "id", :type => :numeric, :banner => "The ID of the remote application"
171
+ method_option "application-id", :type => :numeric, :banner => "The ID of the remote application"
123
172
  action "register", "registers a local application with an existing Strobe application" do
124
173
  if config[:application_id] && app = Application.get(config[:application_id])
125
174
  say "The directory is already registered with the application `#{app[:name]}`"
@@ -129,21 +178,81 @@ module Strobe
129
178
  config.delete
130
179
  end
131
180
 
132
- application = Application.get! options[:id]
181
+ application = options['application-id'] ? Application.get!(options['application-id']) : pick_application
182
+
133
183
  config[:application_id] = application[:id]
184
+
134
185
  say "You can now deploy to #{application[:name]} (http://#{application[:url]})"
135
186
  end
136
187
 
137
188
  private
138
189
 
190
+ def run_sc_build
191
+ return unless is_sproutcore? # Bail if this isn't a SC application
192
+
193
+ # Using both options at the same time makes no sense
194
+ if options["sc-build"] && options["no-sc-build"]
195
+ error! "--sc-build and --no-sc-build cannot be used at the same time"
196
+ end
197
+
198
+ # If the user explicitly says that they don't want to run sc-build,
199
+ # then just skip it
200
+ return if options["no-sc-build"]
201
+
202
+ # If the user doesn't ask either way, confirm first
203
+ unless options["sc-build"]
204
+ say "This appears to be a SproutCore application."
205
+ return unless agree "Run `sc-build -c`? [Yn] "
206
+ end
207
+
208
+ unless system "sc-build", "-c"
209
+ error! "Something went wrong while running `sc-build -c`"
210
+ end
211
+ end
212
+
213
+ def is_sproutcore?
214
+ File.exist?("#{path}/tmp/build")
215
+ end
216
+
139
217
  def determine_application_root
140
- if File.exist?("#{path}/tmp/build")
218
+ if is_sproutcore?
141
219
  return "#{path}/tmp/build"
142
220
  end
143
221
 
144
222
  path
145
223
  end
146
224
 
225
+ def list_applications(*args)
226
+ options = Hash === args.last ? args.pop : {}
227
+ applications = args.first || Resources::Application.all
228
+
229
+ table applications, options do |t|
230
+ t.column :id
231
+ t.column :name
232
+ t.column :url
233
+ end
234
+ end
235
+
236
+ def pick_application
237
+ applications = Resources::Application.all
238
+
239
+ if applications.empty?
240
+ error! "You currently do not have any applications. Create some with `strobe deploy`"
241
+ end
242
+
243
+ list_applications applications, :index => true
244
+
245
+ while true
246
+ index = ask "Pick an application: ", :direct => true
247
+
248
+ if index.to_i > 0 and application = applications[index.to_i - 1]
249
+ return application
250
+ end
251
+
252
+ say "Invalid entry. Please enter one of the numbers in brackets"
253
+ end
254
+ end
255
+
147
256
  def ensure_computer_is_registered
148
257
  unless settings[:token]
149
258
  say "This computer is not yet registered with a Strobe account."
@@ -1,10 +1,16 @@
1
1
  module Strobe
2
2
  class CLI::Table
3
+ class Index ; end
4
+
3
5
  def initialize(collection, opts = {})
4
6
  @collection = collection
5
7
  @columns = []
6
8
  @computed = []
7
9
  @opts = opts
10
+
11
+ if opts[:index]
12
+ @columns.unshift({ :key => Index, :max => 0 })
13
+ end
8
14
  end
9
15
 
10
16
  def column(key)
@@ -14,7 +20,8 @@ module Strobe
14
20
  def to_s
15
21
  @collection.each do |obj|
16
22
  @computed << @columns.map do |col|
17
- cell = obj[ col[:key] ].to_s
23
+ cell = obj [ col[:key] ] unless col[:key] == Index
24
+ cell = cell.to_s
18
25
  col[:max] = [ cell.length, col[:max] ].max
19
26
  cell
20
27
  end
@@ -27,14 +34,15 @@ module Strobe
27
34
  str = ""
28
35
 
29
36
  @columns.each do |col|
30
- str << cell_to_s(col, col[:key].to_s.upcase)
37
+ cell = col[:key].to_s.upcase unless col[:key] == Index
38
+ str << cell_to_s(col, cell)
31
39
  end
32
40
 
33
41
  str << "\n"
34
42
 
35
- @computed.each do |cells|
36
- cells.each_with_index do |cell, i|
37
- str << cell_to_s(@columns[i], cell)
43
+ @computed.each_with_index do |cells, i|
44
+ cells.each_with_index do |cell, j|
45
+ str << cell_to_s(@columns[j], cell, i)
38
46
  end
39
47
  str << "\n"
40
48
  end
@@ -43,9 +51,13 @@ module Strobe
43
51
 
44
52
  private
45
53
 
46
- def cell_to_s(col, cell)
54
+ def cell_to_s(col, cell, index = nil)
55
+ if index && col[:key] == Index
56
+ cell = "[#{index + 1}]"
57
+ end
58
+
47
59
  width = [ col[:max], 25 ].max + 5
48
- cell.ljust(width)
60
+ cell.to_s.ljust(width)
49
61
  end
50
62
  end
51
63
  end
data/lib/strobe/cli.rb CHANGED
@@ -27,7 +27,8 @@ module Strobe
27
27
  def self.action(name, *args, &blk)
28
28
  @haxliases ||= []
29
29
  @haxliases << name.to_s
30
- desc name, *args
30
+ usage = self == Users ? "users #{name}" : name
31
+ desc usage, *args
31
32
  define_method("__hax__#{name}", &blk)
32
33
  map name => "__hax__#{name}"
33
34
  end
@@ -119,6 +120,10 @@ module Strobe
119
120
  STDERR.puts "[ERROR] #{what}"
120
121
  end
121
122
 
123
+ def error!(what)
124
+ abort what
125
+ end
126
+
122
127
  def agree(msg, *args)
123
128
  @highline.agree(msg, *args) do |q|
124
129
  next unless STDIN.tty? # For testing
@@ -160,6 +165,8 @@ module Strobe
160
165
  end
161
166
 
162
167
  def input(key, options)
168
+ return yield key if options[:direct]
169
+
163
170
  into = options[:into] || key
164
171
 
165
172
  validation_group into do
@@ -27,6 +27,10 @@ module Strobe
27
27
  to_a.each { |r| yield r }
28
28
  end
29
29
 
30
+ def empty?
31
+ to_a.empty?
32
+ end
33
+
30
34
  def all
31
35
  self
32
36
  end
@@ -108,20 +108,18 @@ module Strobe
108
108
 
109
109
  if headers['content-type'] == 'application/json'
110
110
  body = ActiveSupport::JSON.encode(body)
111
- else
112
- body = body.to_s
113
111
  end
114
112
  end
115
113
 
114
+ http = build_http
115
+ request = Net::HTTPGenericRequest.new(
116
+ method.to_s.upcase, !!body, true, path, headers)
117
+
116
118
  if body.respond_to?(:read)
117
119
  request.body_stream = body
118
120
  body = nil
119
121
  end
120
122
 
121
- http = build_http
122
- request = Net::HTTPGenericRequest.new(
123
- method.to_s.upcase, !!body, true, path, headers)
124
-
125
123
  Response.new(http.request(request, body))
126
124
  end
127
125
 
@@ -1,3 +1,4 @@
1
+ require 'zlib'
1
2
  require 'digest/sha1'
2
3
  require 'mime/types'
3
4
 
@@ -22,8 +23,8 @@ module Strobe
22
23
 
23
24
  request do
24
25
  qs = "?environment=#{environment}" if environment
25
- packfile = build_packfile
26
- connection.put("#{http_uri}/deploy#{qs}", packfile.to_s, packfile.headers)
26
+ packfile = build_packfile(opts)
27
+ connection.put("#{http_uri}/deploy#{qs}", packfile, packfile.headers)
27
28
  end
28
29
 
29
30
  [ environment, self['url'] ].compact.join('.')
@@ -46,9 +47,9 @@ module Strobe
46
47
  end
47
48
  end
48
49
 
49
- def build_packfile
50
+ def build_packfile(opts)
50
51
  Dir.chdir self[:path] do
51
- PackFile.build do |m|
52
+ PackFile.build(opts) do |m|
52
53
  Dir["**/*"].each do |filename|
53
54
  next unless File.file?(filename)
54
55
 
@@ -91,13 +92,14 @@ module Strobe
91
92
  end
92
93
 
93
94
  class PackFile
94
- def self.build
95
- inst = new
95
+ def self.build(opts)
96
+ inst = new(opts)
96
97
  yield inst
97
98
  inst
98
99
  end
99
100
 
100
- def initialize
101
+ def initialize(opts)
102
+ @opts = opts
101
103
  @files = []
102
104
  end
103
105
 
@@ -106,20 +108,66 @@ module Strobe
106
108
  end
107
109
 
108
110
  def headers
109
- { 'Content-Type' => 'application/x-strobe-deploy' }
111
+ { 'Content-Type' => 'application/x-strobe-deploy',
112
+ 'Content-Length' => size.to_s,
113
+ 'Content-Encoding' => 'deflate' }
110
114
  end
111
115
 
112
- def to_s
113
- head = ""
114
- body = ""
116
+ def each(*args, &blk)
117
+ to_io.each(*args, &blk)
118
+ end
119
+
120
+ def read(*args)
121
+ ret = to_io.read(*args)
115
122
 
116
- @files.each do |path, type, data|
117
- size = data.respond_to?(:bytesize) ? data.bytesize : data.size
118
- head << "#{Digest::SHA1.hexdigest(data)} #{size} #{path} #{type}\n"
119
- body << data
123
+ if callback = @opts[:upload_callback]
124
+ ret ? callback.call(pos.to_f / size.to_f) : callback.call(nil)
120
125
  end
121
126
 
122
- "#{head}\n#{body}"
127
+ ret
128
+ end
129
+
130
+ def rewind
131
+ to_io.rewind
132
+ end
133
+
134
+ def seek(*args)
135
+ to_io.seek(*args)
136
+ end
137
+
138
+ def pos
139
+ to_io.pos
140
+ end
141
+
142
+ def size
143
+ to_io.size
144
+ end
145
+
146
+ def eof
147
+ to_io.eof
148
+ end
149
+
150
+ alias eof? eof
151
+
152
+ def to_io
153
+ @to_io ||= StringIO.new(to_s)
154
+ end
155
+
156
+ private
157
+
158
+ def to_s
159
+ @to_s ||= begin
160
+ head = ""
161
+ body = ""
162
+
163
+ @files.each do |path, type, data|
164
+ size = data.respond_to?(:bytesize) ? data.bytesize : data.size
165
+ head << "#{Digest::SHA1.hexdigest(data)} #{size} #{path} #{type}\n"
166
+ body << data
167
+ end
168
+
169
+ Zlib::Deflate.deflate("#{head}\n#{body}", 9)
170
+ end
123
171
  end
124
172
  end
125
173
  end
metadata CHANGED
@@ -7,8 +7,8 @@ version: !ruby/object:Gem::Version
7
7
  - 1
8
8
  - 0
9
9
  - beta
10
- - 2
11
- version: 0.1.0.beta.2
10
+ - 3
11
+ version: 0.1.0.beta.3
12
12
  platform: ruby
13
13
  authors:
14
14
  - Yehuda Katz
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2011-01-02 00:00:00 -08:00
20
+ date: 2011-01-03 00:00:00 -08:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency