strobe 0.1.4 → 0.1.6
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/CHANGELOG.md +41 -0
- data/README.md +0 -0
- data/lib/strobe/cli.rb +14 -16
- data/lib/strobe/cli/input.rb +125 -0
- data/lib/strobe/cli/main.rb +43 -11
- data/lib/strobe/cli/settings.rb +48 -10
- data/lib/strobe/cli/table.rb +9 -4
- data/lib/strobe/collection.rb +5 -1
- data/lib/strobe/connection.rb +20 -24
- data/lib/strobe/middleware/proxy.rb +44 -6
- data/lib/strobe/resource/base.rb +9 -2
- data/lib/strobe/resource/collection.rb +9 -1
- data/lib/strobe/resources/application.rb +26 -26
- metadata +16 -45
data/CHANGELOG.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
## 0.1.6 (March, 23rd, 2011)
|
2
|
+
|
3
|
+
Bugfixes:
|
4
|
+
|
5
|
+
- Fix `strobe open` so that it actually opens stuff.
|
6
|
+
|
7
|
+
## 0.1.5 - yanked (March, 22nd, 2011)
|
8
|
+
|
9
|
+
Features:
|
10
|
+
|
11
|
+
- `strobe open` will open the application that was just deployed
|
12
|
+
- Pass the -r flag to sc-build
|
13
|
+
- The CLI tool will use a default value if none is provided when
|
14
|
+
requesting for input.
|
15
|
+
- You may now specify custom 404 pages by providing a 404.html page
|
16
|
+
at the root of the project.
|
17
|
+
- Add the ability to delete arbitrary applications by passing
|
18
|
+
--application-id=X to `strobe delete`.
|
19
|
+
- `strobe delete` when not in an application root and no application
|
20
|
+
is specified will become interactive.
|
21
|
+
- Speed up `strobe deploy` in certain cases.
|
22
|
+
- `strobe applications` will show the local path to the application if
|
23
|
+
it is known.
|
24
|
+
|
25
|
+
Bugfixes:
|
26
|
+
|
27
|
+
- `strobe set` without any options will no longer set the
|
28
|
+
application URL to a random value.
|
29
|
+
- Pressing CTRL-C when the strobe CLI tool is requesting input
|
30
|
+
will now exit.
|
31
|
+
- Fix redirects in the `strobe preview` proxy.
|
32
|
+
|
33
|
+
## 0.1.4 (January 11th, 2011)
|
34
|
+
|
35
|
+
Features:
|
36
|
+
|
37
|
+
- Deploy applications to Strobe Platform w/ `strobe deploy`
|
38
|
+
- Basic account management
|
39
|
+
- Basic user management
|
40
|
+
- Basic application management
|
41
|
+
- `strobe preview` provides the proxy
|
data/README.md
ADDED
File without changes
|
data/lib/strobe/cli.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require 'pathname'
|
3
3
|
require 'fileutils'
|
4
|
-
require '
|
4
|
+
require 'launchy'
|
5
5
|
|
6
6
|
module Strobe
|
7
7
|
class CLI < Thor
|
@@ -12,6 +12,7 @@ module Strobe
|
|
12
12
|
autoload :Table, 'strobe/cli/table'
|
13
13
|
autoload :Ticker, 'strobe/cli/ticker'
|
14
14
|
autoload :Users, 'strobe/cli/users'
|
15
|
+
autoload :Input, 'strobe/cli/input'
|
15
16
|
|
16
17
|
include Resources
|
17
18
|
|
@@ -26,6 +27,8 @@ module Strobe
|
|
26
27
|
rescue Strobe::StrobeError => e
|
27
28
|
raise if $ARGV.include?('--backtrace')
|
28
29
|
abort "[ERROR] #{e.message}"
|
30
|
+
rescue Interrupt
|
31
|
+
abort "\nQuitting..."
|
29
32
|
end
|
30
33
|
|
31
34
|
def self.action(name, *args, &blk)
|
@@ -57,7 +60,7 @@ module Strobe
|
|
57
60
|
super
|
58
61
|
|
59
62
|
@resource = nil
|
60
|
-
@
|
63
|
+
@input = Input.new
|
61
64
|
|
62
65
|
# State
|
63
66
|
@in_group = false
|
@@ -72,7 +75,11 @@ module Strobe
|
|
72
75
|
options[:path] || Dir.pwd
|
73
76
|
end
|
74
77
|
|
75
|
-
def config
|
78
|
+
def config(app = nil)
|
79
|
+
if app
|
80
|
+
@config = settings.configs.find { |c| c[:application_id] = app[:id] }
|
81
|
+
end
|
82
|
+
|
76
83
|
@config ||= Settings.application(path)
|
77
84
|
end
|
78
85
|
|
@@ -130,32 +137,23 @@ module Strobe
|
|
130
137
|
|
131
138
|
def agree(msg, *args)
|
132
139
|
return true if options[:yes]
|
133
|
-
@
|
134
|
-
next unless STDIN.tty? # For testing
|
135
|
-
q.readline = true
|
136
|
-
end
|
140
|
+
@input.agree(msg, *args)
|
137
141
|
end
|
138
142
|
|
139
143
|
def ask(key, options = {})
|
140
144
|
input key, options do |msg|
|
141
|
-
resp = @
|
142
|
-
next unless STDIN.tty? # For testing
|
143
|
-
q.readline = true
|
144
|
-
end
|
145
|
+
resp = @input.ask msg
|
145
146
|
end
|
146
147
|
end
|
147
148
|
|
148
149
|
def password(key, options = {})
|
149
150
|
input key, options do |msg|
|
150
|
-
@
|
151
|
-
next unless STDIN.tty? # For testing
|
152
|
-
q.echo = '*'
|
153
|
-
end
|
151
|
+
@input.ask_for_password msg
|
154
152
|
end
|
155
153
|
end
|
156
154
|
|
157
155
|
def choose
|
158
|
-
@
|
156
|
+
@input.choose do |menu|
|
159
157
|
yield menu
|
160
158
|
end
|
161
159
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Strobe
|
2
|
+
class CLI::Input
|
3
|
+
|
4
|
+
class Menu
|
5
|
+
class NoSuchOptionError < StandardError; end
|
6
|
+
|
7
|
+
attr_reader :choices, :actions, :input
|
8
|
+
|
9
|
+
def initialize(input)
|
10
|
+
@input = input
|
11
|
+
@choices = []
|
12
|
+
@actions = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def choice(name, &block)
|
16
|
+
choices << name
|
17
|
+
actions[name] = block
|
18
|
+
end
|
19
|
+
|
20
|
+
def display
|
21
|
+
choices.each_with_index do |choice, i|
|
22
|
+
input.puts "#{i+1}. #{choice}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def ask
|
27
|
+
display
|
28
|
+
|
29
|
+
begin
|
30
|
+
input.print "? "
|
31
|
+
|
32
|
+
option = input.gets.strip.to_i
|
33
|
+
if option < 1 || option > choices.length
|
34
|
+
input.puts "Please enter a number between 1 and #{choices.length}"
|
35
|
+
raise NoSuchOptionError
|
36
|
+
end
|
37
|
+
|
38
|
+
actions[choices[option - 1]].call
|
39
|
+
rescue NoSuchOptionError
|
40
|
+
retry
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :stdin, :stdout
|
46
|
+
|
47
|
+
def initialize(stdin = STDIN, stdout = STDOUT)
|
48
|
+
@stdin, @stdout = stdin, stdout
|
49
|
+
end
|
50
|
+
|
51
|
+
def ask(msg = nil)
|
52
|
+
print msg if msg
|
53
|
+
gets.strip
|
54
|
+
end
|
55
|
+
|
56
|
+
def agree(msg = nil)
|
57
|
+
print msg if msg
|
58
|
+
c = gets.strip.downcase
|
59
|
+
c == "y" || c.strip.blank?
|
60
|
+
end
|
61
|
+
|
62
|
+
def choose(&block)
|
63
|
+
m = Menu.new(self)
|
64
|
+
yield m
|
65
|
+
m.ask
|
66
|
+
end
|
67
|
+
|
68
|
+
def ask_for_password(msg = nil)
|
69
|
+
print msg if msg
|
70
|
+
running_on_windows? ? ask_for_password_on_windows : ask_for_password_on_others
|
71
|
+
end
|
72
|
+
|
73
|
+
def puts(*args)
|
74
|
+
stdout.puts(*args)
|
75
|
+
end
|
76
|
+
|
77
|
+
def print(*args)
|
78
|
+
stdout.print(*args)
|
79
|
+
end
|
80
|
+
|
81
|
+
def gets(*args)
|
82
|
+
stdin.gets(*args)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
def running_on_windows?
|
87
|
+
RUBY_PLATFORM =~ /mswin32|mingw32/
|
88
|
+
end
|
89
|
+
|
90
|
+
def echo_off
|
91
|
+
system "stty -echo"
|
92
|
+
end
|
93
|
+
|
94
|
+
def echo_on
|
95
|
+
system "stty echo"
|
96
|
+
end
|
97
|
+
|
98
|
+
def ask_for_password_on_windows
|
99
|
+
require "Win32API"
|
100
|
+
char = nil
|
101
|
+
password = ''
|
102
|
+
|
103
|
+
while char = Win32API.new("crtdll", "_getch", [ ], "L").Call do
|
104
|
+
break if char == 10 || char == 13 # received carriage return or newline
|
105
|
+
if char == 127 || char == 8 # backspace and delete
|
106
|
+
password.slice!(-1, 1)
|
107
|
+
else
|
108
|
+
# windows might throw a -1 at us so make sure to handle RangeError
|
109
|
+
(password << char.chr) rescue RangeError
|
110
|
+
end
|
111
|
+
end
|
112
|
+
puts
|
113
|
+
return password
|
114
|
+
end
|
115
|
+
|
116
|
+
def ask_for_password_on_others
|
117
|
+
echo_off if stdin.tty?
|
118
|
+
password = ask
|
119
|
+
puts if stdin.tty?
|
120
|
+
password
|
121
|
+
ensure
|
122
|
+
echo_on if stdin.tty?
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/strobe/cli/main.rb
CHANGED
@@ -16,6 +16,13 @@ module Strobe
|
|
16
16
|
CLI::Users.start(argv)
|
17
17
|
end
|
18
18
|
|
19
|
+
action "open", "opens application in browser" do
|
20
|
+
resource get_application
|
21
|
+
url = resource['url']
|
22
|
+
|
23
|
+
Launchy.open("http://#{url}")
|
24
|
+
end
|
25
|
+
|
19
26
|
action "signup", "signup for a new Strobe account" do
|
20
27
|
resource Signup.new :account => { :name => 'default' }
|
21
28
|
|
@@ -71,12 +78,18 @@ module Strobe
|
|
71
78
|
method_option "staging", :type => :boolean, :banner => "deploy to a staging environment"
|
72
79
|
method_option "sc-build", :type => :boolean, :banner => "run `sc-build -c` before deploying"
|
73
80
|
method_option "no-sc-build", :type => :boolean, :banner => "skip the `sc-build -c` step"
|
81
|
+
method_option "url", :banner => "set application's url"
|
74
82
|
action "deploy", "deploy your application to Strobe" do
|
75
83
|
ensure_computer_is_registered
|
76
84
|
|
77
85
|
if application_id = config[:application_id]
|
78
86
|
resource Application.get! application_id, :lazy => true
|
79
87
|
|
88
|
+
if options[:url]
|
89
|
+
resource[:url] = options[:url]
|
90
|
+
save {}
|
91
|
+
end
|
92
|
+
|
80
93
|
host = resource[:url]
|
81
94
|
host = "staging.#{host}" if options[:staging]
|
82
95
|
|
@@ -85,7 +98,7 @@ module Strobe
|
|
85
98
|
exit
|
86
99
|
end
|
87
100
|
else
|
88
|
-
resource Account.first.applications.new
|
101
|
+
resource Account.first.applications.new(:url => options[:url])
|
89
102
|
end
|
90
103
|
|
91
104
|
resource[:path] = determine_application_root
|
@@ -97,13 +110,15 @@ module Strobe
|
|
97
110
|
|
98
111
|
save do
|
99
112
|
config[:application_id] ||= resource[:id]
|
113
|
+
settings.register_app_path(config.filename)
|
100
114
|
end
|
101
115
|
end
|
102
116
|
|
103
117
|
run_sc_build
|
104
118
|
|
105
119
|
host = resource.deploy! :environment => options[:staging] && 'staging',
|
106
|
-
:callback => CLI::DeployProgress.new
|
120
|
+
:callback => CLI::DeployProgress.new,
|
121
|
+
:sproutcore => is_sproutcore?
|
107
122
|
|
108
123
|
say "The application has successfully been deployed and is available at #{host}"
|
109
124
|
end
|
@@ -118,16 +133,23 @@ module Strobe
|
|
118
133
|
application_path_option
|
119
134
|
action "set", "update the settings for the application" do
|
120
135
|
resource get_application
|
121
|
-
resource['url'] = options['url']
|
122
136
|
|
123
|
-
|
124
|
-
say "
|
137
|
+
if options['url'].blank?
|
138
|
+
say "[ERROR] You need to specify what to set"
|
139
|
+
else
|
140
|
+
resource['url'] = options['url']
|
141
|
+
|
142
|
+
save do
|
143
|
+
say "The application is now running at #{resource[:url]}"
|
144
|
+
end
|
125
145
|
end
|
126
146
|
end
|
127
147
|
|
128
148
|
application_path_option
|
149
|
+
method_option "application-id", :type => :numeric, :banner => "Delete application with given id"
|
129
150
|
action "delete", "delete a specific application" do
|
130
|
-
|
151
|
+
id = options['application-id'] || config[:application_id]
|
152
|
+
resource(id ? Application.get!(id) : pick_application)
|
131
153
|
|
132
154
|
say "Deleting application '#{resource[:name]}'"
|
133
155
|
|
@@ -137,7 +159,7 @@ module Strobe
|
|
137
159
|
end
|
138
160
|
|
139
161
|
delete do
|
140
|
-
config.delete
|
162
|
+
config(resource).delete
|
141
163
|
say "The application has been deleted"
|
142
164
|
end
|
143
165
|
end
|
@@ -156,6 +178,7 @@ module Strobe
|
|
156
178
|
application = options['application-id'] ? Application.get!(options['application-id']) : pick_application
|
157
179
|
|
158
180
|
config[:application_id] = application[:id]
|
181
|
+
settings.register_app_path(config.filename)
|
159
182
|
|
160
183
|
say "You can now deploy to #{application[:name]} (http://#{application[:url]})"
|
161
184
|
end
|
@@ -174,14 +197,17 @@ module Strobe
|
|
174
197
|
# then just skip it
|
175
198
|
return if options["no-sc-build"]
|
176
199
|
|
200
|
+
apps = Dir['apps/*'].map{|d| d.split('/')[1] }
|
201
|
+
cmd = "sc-build -cr #{apps.join(' ')}".strip
|
202
|
+
|
177
203
|
# If the user doesn't ask either way, confirm first
|
178
204
|
unless options["sc-build"]
|
179
205
|
say "This appears to be a SproutCore application."
|
180
|
-
return unless agree "Run
|
206
|
+
return unless agree "Run `#{cmd}`? [Yn] "
|
181
207
|
end
|
182
208
|
|
183
|
-
unless CLI::Ticker.tick("Running `
|
184
|
-
error! "Something went wrong while running `
|
209
|
+
unless CLI::Ticker.tick("Running `#{cmd}`", 2) { system cmd }
|
210
|
+
error! "Something went wrong while running `#{cmd}`"
|
185
211
|
end
|
186
212
|
end
|
187
213
|
|
@@ -205,6 +231,12 @@ module Strobe
|
|
205
231
|
t.column :id
|
206
232
|
t.column :name
|
207
233
|
t.column :url
|
234
|
+
t.column :path do |app|
|
235
|
+
config = settings.configs.find do |c|
|
236
|
+
c[:application_id] == app[:id]
|
237
|
+
end
|
238
|
+
config.application_path if config
|
239
|
+
end
|
208
240
|
end
|
209
241
|
end
|
210
242
|
|
@@ -240,7 +272,7 @@ module Strobe
|
|
240
272
|
end
|
241
273
|
|
242
274
|
def get_application(opts = {})
|
243
|
-
unless id = config[:application_id]
|
275
|
+
unless id = opts.delete(:application_id) || config[:application_id]
|
244
276
|
error "No application found. Are you currently in the correct directory?"
|
245
277
|
exit 1
|
246
278
|
end
|
data/lib/strobe/cli/settings.rb
CHANGED
@@ -16,8 +16,10 @@ module Strobe
|
|
16
16
|
new application_config_file(root)
|
17
17
|
end
|
18
18
|
|
19
|
+
attr_reader :filename
|
20
|
+
|
19
21
|
def initialize(filename = self.class.global_config_file)
|
20
|
-
@filename = filename
|
22
|
+
@filename = Pathname.new(filename)
|
21
23
|
|
22
24
|
if @filename.exist?
|
23
25
|
@hash = YAML.load_file(@filename)
|
@@ -26,26 +28,24 @@ module Strobe
|
|
26
28
|
@hash = {} unless Hash === @hash
|
27
29
|
end
|
28
30
|
|
31
|
+
def application_path
|
32
|
+
filename.sub %r[/.strobe/config(\.[a-z]+)?$]i, ''
|
33
|
+
end
|
34
|
+
|
29
35
|
def [](k)
|
30
36
|
ENV[key(k)] || @hash[key(k)]
|
31
37
|
end
|
32
38
|
|
33
39
|
def []=(k, val)
|
34
40
|
@hash[key(k)] = val
|
35
|
-
|
36
|
-
# Persist the setting
|
37
|
-
FileUtils.mkdir_p(@filename.dirname)
|
38
|
-
File.open(@filename, "wb") do |file|
|
39
|
-
file.puts @hash.to_yaml
|
40
|
-
end
|
41
|
-
|
41
|
+
persist!
|
42
42
|
val
|
43
43
|
end
|
44
44
|
|
45
45
|
def connection
|
46
46
|
return @connection if @connection
|
47
|
-
|
48
|
-
@connection = Connection.new(host)
|
47
|
+
url = self[:url] || "http://api.strobeapp.com/"
|
48
|
+
@connection = Connection.new(url, 'host' => self[:host])
|
49
49
|
end
|
50
50
|
|
51
51
|
def connect!
|
@@ -63,10 +63,48 @@ module Strobe
|
|
63
63
|
FileUtils.rm_f(@filename)
|
64
64
|
end
|
65
65
|
|
66
|
+
def configs
|
67
|
+
@configs ||= begin
|
68
|
+
self[:applications] ||= []
|
69
|
+
self[:applications].map do |path|
|
70
|
+
next unless File.file?(path)
|
71
|
+
self.class.new(path)
|
72
|
+
end.compact
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def register_app_path(path)
|
77
|
+
self[:applications] ||= []
|
78
|
+
self[:applications] |= [File.expand_path(path.to_s)]
|
79
|
+
self[:applications] = self[:applications].select do |path|
|
80
|
+
File.file?(path)
|
81
|
+
end
|
82
|
+
|
83
|
+
persist!
|
84
|
+
end
|
85
|
+
|
86
|
+
def unregister_app_path(path)
|
87
|
+
self[:applications] ||= []
|
88
|
+
self[:applications].delete File.expand_path(path.to_s)
|
89
|
+
self[:applications] = self[:applications].select do |path|
|
90
|
+
File.file?(path)
|
91
|
+
end
|
92
|
+
|
93
|
+
persist!
|
94
|
+
end
|
95
|
+
|
66
96
|
private
|
67
97
|
|
68
98
|
def key(key)
|
69
99
|
"STROBE_#{key}".upcase
|
70
100
|
end
|
101
|
+
|
102
|
+
def persist!
|
103
|
+
# Persist the setting
|
104
|
+
FileUtils.mkdir_p(@filename.dirname)
|
105
|
+
File.open(@filename, "wb") do |file|
|
106
|
+
file.puts @hash.to_yaml
|
107
|
+
end
|
108
|
+
end
|
71
109
|
end
|
72
110
|
end
|
data/lib/strobe/cli/table.rb
CHANGED
@@ -13,14 +13,19 @@ module Strobe
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def column(key)
|
17
|
-
@columns << { :key => key, :max => 0 }
|
16
|
+
def column(key, opts = {}, &blk)
|
17
|
+
@columns << { :key => key, :max => 0, :blk => blk }.merge(opts)
|
18
18
|
end
|
19
19
|
|
20
20
|
def to_s
|
21
21
|
@collection.each do |obj|
|
22
22
|
@computed << @columns.map do |col|
|
23
|
-
|
23
|
+
if col[:blk]
|
24
|
+
cell = col[:blk].call(obj)
|
25
|
+
elsif col[:key] != Index
|
26
|
+
cell = obj[ col[:key] ]
|
27
|
+
end
|
28
|
+
|
24
29
|
cell = cell.to_s
|
25
30
|
col[:max] = [ cell.length, col[:max] ].max
|
26
31
|
cell
|
@@ -34,7 +39,7 @@ module Strobe
|
|
34
39
|
str = ""
|
35
40
|
|
36
41
|
@columns.each do |col|
|
37
|
-
cell = col[:key].to_s.upcase unless col[:key] == Index
|
42
|
+
cell = (col[:header] || col[:key]).to_s.upcase unless col[:key] == Index
|
38
43
|
str << cell_to_s(col, cell)
|
39
44
|
end
|
40
45
|
|
data/lib/strobe/collection.rb
CHANGED
@@ -8,13 +8,17 @@ module Strobe
|
|
8
8
|
@klass, @params = klass, params
|
9
9
|
end
|
10
10
|
|
11
|
+
def where(params)
|
12
|
+
Strobe::Collection.new(klass, params)
|
13
|
+
end
|
14
|
+
|
11
15
|
def to_a
|
12
16
|
@to_a ||= begin
|
13
17
|
resp = Strobe.connection.get klass.resource_uri, params
|
14
18
|
resp.validate!
|
15
19
|
|
16
20
|
if resp.status == 200
|
17
|
-
resp.body[klass.
|
21
|
+
resp.body[klass.pluralized_root].map do |hash|
|
18
22
|
klass.new(hash)
|
19
23
|
end
|
20
24
|
else
|
data/lib/strobe/connection.rb
CHANGED
@@ -3,12 +3,19 @@ require 'net/http'
|
|
3
3
|
|
4
4
|
module Strobe
|
5
5
|
class Connection
|
6
|
-
|
6
|
+
def self.host_and_port(uri)
|
7
|
+
uri = "http://#{uri}" unless uri =~ %r[^https?://]
|
8
|
+
uri = URI(uri)
|
9
|
+
[ uri.host, uri.port ]
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :host, :port
|
7
13
|
|
8
|
-
def initialize(url)
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
14
|
+
def initialize(url, headers = {})
|
15
|
+
@host, @port = self.class.host_and_port(url)
|
16
|
+
@headers = headers
|
17
|
+
@user = nil
|
18
|
+
@password = nil
|
12
19
|
end
|
13
20
|
|
14
21
|
def authenticate_with_token(token)
|
@@ -98,7 +105,13 @@ module Strobe
|
|
98
105
|
|
99
106
|
def request(method, path, body = nil, headers = {})
|
100
107
|
headers.keys.each do |key|
|
101
|
-
headers[key.downcase] = headers.delete(key)
|
108
|
+
headers[key.to_s.downcase] = headers.delete(key)
|
109
|
+
end
|
110
|
+
|
111
|
+
# add connection-global headers, which will be
|
112
|
+
# overwritten by request-specific headers
|
113
|
+
@headers.each do |k, v|
|
114
|
+
headers[k.to_s.downcase] ||= v if v
|
102
115
|
end
|
103
116
|
|
104
117
|
headers['authorization'] ||= authorization_header
|
@@ -126,7 +139,7 @@ module Strobe
|
|
126
139
|
private
|
127
140
|
|
128
141
|
def build_http
|
129
|
-
http = Net::HTTP.new
|
142
|
+
http = Net::HTTP.new host, port || 80
|
130
143
|
http.read_timeout = 60
|
131
144
|
http.open_timeout = 10
|
132
145
|
http
|
@@ -142,22 +155,5 @@ module Strobe
|
|
142
155
|
def authorize?
|
143
156
|
@user
|
144
157
|
end
|
145
|
-
|
146
|
-
def json_connection
|
147
|
-
@json_connection ||= Faraday::Connection.new(:url => @url) do |b|
|
148
|
-
b.use Faraday::Request::ActiveSupportJson
|
149
|
-
b.use Faraday::Adapter::NetHttp
|
150
|
-
b.use Faraday::Response::ActiveSupportJson
|
151
|
-
b.headers['authorization'] = authorization_header if authorize?
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def reg_connection
|
156
|
-
@reg_connection ||= Faraday::Connection.new(:url => @url) do |b|
|
157
|
-
b.use Faraday::Adapter::NetHttp
|
158
|
-
b.use Faraday::Response::ActiveSupportJson
|
159
|
-
b.headers['authorization'] = authorization_header if authorize?
|
160
|
-
end
|
161
|
-
end
|
162
158
|
end
|
163
159
|
end
|
@@ -7,8 +7,9 @@ module Strobe
|
|
7
7
|
# A wrapper around the Net/HTTP response body
|
8
8
|
# that allows rack to stream the result down
|
9
9
|
class Body
|
10
|
-
def initialize(queue)
|
10
|
+
def initialize(queue, options = {})
|
11
11
|
@queue = queue
|
12
|
+
@options = options
|
12
13
|
end
|
13
14
|
|
14
15
|
def each
|
@@ -16,9 +17,24 @@ module Strobe
|
|
16
17
|
if Exception === chunk
|
17
18
|
raise chunk
|
18
19
|
else
|
19
|
-
yield chunk
|
20
|
+
yield prepare_chunk(chunk)
|
20
21
|
end
|
21
22
|
end
|
23
|
+
|
24
|
+
yield "0\r\n\r\n" if chunked?
|
25
|
+
end
|
26
|
+
|
27
|
+
def prepare_chunk(chunk)
|
28
|
+
if chunked?
|
29
|
+
size = chunk.respond_to?(:bytesize) ? chunk.bytesize : chunk.length
|
30
|
+
"#{size.to_s(16)}\r\n#{chunk}\r\n"
|
31
|
+
else
|
32
|
+
chunk
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def chunked?
|
37
|
+
@options[:chunked]
|
22
38
|
end
|
23
39
|
end
|
24
40
|
|
@@ -26,18 +42,34 @@ module Strobe
|
|
26
42
|
@app = app
|
27
43
|
end
|
28
44
|
|
45
|
+
def redirect?(status)
|
46
|
+
status >= 300 && status < 400
|
47
|
+
end
|
48
|
+
|
29
49
|
def call(env)
|
30
50
|
if env['PATH_INFO'] =~ proxy_path
|
31
51
|
host, port = $1.split(':')
|
52
|
+
path = $2 || '/'
|
53
|
+
|
54
|
+
running = true
|
55
|
+
while running
|
56
|
+
queue = run_request(env, host, ( port || 80 ).to_i, path)
|
32
57
|
|
33
|
-
|
58
|
+
msg = queue.pop
|
59
|
+
status = msg[0].to_i
|
34
60
|
|
35
|
-
|
61
|
+
if redirect?(status) && location = msg[1]['location']
|
62
|
+
uri = URI.parse(location)
|
63
|
+
host, port, path = uri.host, uri.port, uri.path
|
64
|
+
else
|
65
|
+
running = false
|
66
|
+
end
|
67
|
+
end
|
36
68
|
|
37
69
|
if Exception === msg
|
38
70
|
raise msg
|
39
71
|
else
|
40
|
-
[ msg[0], msg[1], Body.new(queue) ]
|
72
|
+
[ msg[0], msg[1], Body.new(queue, :chunked => chunked?(msg[1])) ]
|
41
73
|
end
|
42
74
|
else
|
43
75
|
@app.call(env)
|
@@ -46,11 +78,15 @@ module Strobe
|
|
46
78
|
|
47
79
|
private
|
48
80
|
|
81
|
+
def chunked?(headers)
|
82
|
+
headers["transfer-encoding"] == "chunked"
|
83
|
+
end
|
84
|
+
|
49
85
|
def proxy_path
|
50
86
|
%r[/_strobe/proxy/([^/]+)(/.*)?$]
|
51
87
|
end
|
52
88
|
|
53
|
-
KEEP = [ 'CONTENT_LENGTH', 'CONTENT_TYPE' ]
|
89
|
+
KEEP = [ 'CONTENT_LENGTH', 'CONTENT_TYPE', 'Connection' ]
|
54
90
|
|
55
91
|
def run_request(env, host, port, path)
|
56
92
|
queue = Queue.new
|
@@ -59,6 +95,8 @@ module Strobe
|
|
59
95
|
body = env['rack.input']
|
60
96
|
end
|
61
97
|
|
98
|
+
env["Connection"] = "keep-alive"
|
99
|
+
|
62
100
|
unless env['QUERY_STRING'].blank?
|
63
101
|
path += "?#{env['QUERY_STRING']}"
|
64
102
|
end
|
data/lib/strobe/resource/base.rb
CHANGED
@@ -65,6 +65,12 @@ module Strobe
|
|
65
65
|
def uri_prefix
|
66
66
|
@uri_prefix ||= "/#{resource_name}"
|
67
67
|
end
|
68
|
+
|
69
|
+
def root(root = nil)
|
70
|
+
@root ||= singular_resource_name
|
71
|
+
@root = root if root
|
72
|
+
@root
|
73
|
+
end
|
68
74
|
end
|
69
75
|
|
70
76
|
attr_reader :response
|
@@ -112,6 +118,7 @@ module Strobe
|
|
112
118
|
inst[parts[1..-1]]
|
113
119
|
else
|
114
120
|
parts.inject(params) do |param, key|
|
121
|
+
return unless param
|
115
122
|
param[key]
|
116
123
|
end
|
117
124
|
end
|
@@ -178,7 +185,7 @@ module Strobe
|
|
178
185
|
|
179
186
|
def request
|
180
187
|
@response = yield
|
181
|
-
root = self.class.
|
188
|
+
root = self.class.root
|
182
189
|
|
183
190
|
@response.validate!
|
184
191
|
|
@@ -209,7 +216,7 @@ module Strobe
|
|
209
216
|
|
210
217
|
def request_params
|
211
218
|
filter = self.class.filter
|
212
|
-
{ self.class.
|
219
|
+
{ self.class.root => params.except(*filter) }
|
213
220
|
end
|
214
221
|
|
215
222
|
def create
|
@@ -27,6 +27,10 @@ module Strobe
|
|
27
27
|
singular_resource_name.pluralize
|
28
28
|
end
|
29
29
|
|
30
|
+
def pluralized_root
|
31
|
+
root.pluralize
|
32
|
+
end
|
33
|
+
|
30
34
|
def resource_uri
|
31
35
|
uri_prefix
|
32
36
|
end
|
@@ -37,6 +41,10 @@ module Strobe
|
|
37
41
|
|
38
42
|
alias all collection
|
39
43
|
|
44
|
+
def where(params)
|
45
|
+
Strobe::Collection.new(self, params)
|
46
|
+
end
|
47
|
+
|
40
48
|
def new(params = {})
|
41
49
|
inst = IdentityMap.identify(self, key.key_for(params)) do
|
42
50
|
super({})
|
@@ -91,7 +99,7 @@ module Strobe
|
|
91
99
|
resp.validate! if opts[:validate]
|
92
100
|
|
93
101
|
if resp.success?
|
94
|
-
self.params = resp.body[self.class.
|
102
|
+
self.params = resp.body[self.class.root]
|
95
103
|
self
|
96
104
|
end
|
97
105
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'zlib'
|
2
2
|
require 'digest/sha1'
|
3
|
-
require 'mime/types'
|
4
3
|
|
5
4
|
module Strobe
|
6
5
|
module Resources
|
@@ -55,36 +54,34 @@ module Strobe
|
|
55
54
|
PackFile.build(opts) do |m|
|
56
55
|
Dir["**/*"].each do |filename|
|
57
56
|
next unless File.file?(filename)
|
58
|
-
|
59
|
-
mime_type = MIME::Types.type_for(filename).first
|
60
|
-
mime_type ||= "application/octet-stream"
|
61
|
-
|
62
|
-
m.file filename, mime_type.to_s, read(filename)
|
57
|
+
m.file filename, read(filename)
|
63
58
|
end
|
64
59
|
|
65
60
|
picked_root_app = false
|
66
61
|
|
67
|
-
|
68
|
-
|
62
|
+
if opts[:sproutcore]
|
63
|
+
Dir["static/*"].each do |appdir|
|
64
|
+
next if File.file?(appdir)
|
69
65
|
|
70
|
-
|
71
|
-
|
66
|
+
app_name = File.basename(appdir)
|
67
|
+
index = Dir["#{appdir}/*/*/index.html"].first
|
72
68
|
|
73
|
-
|
69
|
+
next unless index && File.file?(index)
|
74
70
|
|
75
|
-
|
76
|
-
|
77
|
-
|
71
|
+
manifest = "#{File.dirname(index)}/app.manifest"
|
72
|
+
manifest = read(manifest) if File.file?(manifest)
|
73
|
+
content = read(index)
|
78
74
|
|
79
|
-
|
80
|
-
|
75
|
+
m.file "#{app_name}/index.html", content
|
76
|
+
m.file "#{app_name}/app.manifest", manifest if manifest
|
81
77
|
|
82
|
-
|
78
|
+
next if picked_root_app
|
83
79
|
|
84
|
-
|
85
|
-
|
80
|
+
m.file "index.html", content
|
81
|
+
m.file "app.manifest", manifest
|
86
82
|
|
87
|
-
|
83
|
+
picked_root_app = true
|
84
|
+
end
|
88
85
|
end
|
89
86
|
end
|
90
87
|
end
|
@@ -107,14 +104,17 @@ module Strobe
|
|
107
104
|
@callback = opts[:callback]
|
108
105
|
end
|
109
106
|
|
110
|
-
def file(path,
|
111
|
-
@files << [path,
|
107
|
+
def file(path, body)
|
108
|
+
@files << [path, body]
|
112
109
|
end
|
113
110
|
|
114
111
|
def headers
|
115
|
-
{
|
112
|
+
{
|
113
|
+
'Content-Type' => 'application/x-strobe-deploy',
|
116
114
|
'Content-Length' => size.to_s,
|
117
|
-
'Content-Encoding' => 'deflate'
|
115
|
+
'Content-Encoding' => 'deflate',
|
116
|
+
'X-Strobe-Deploy-Protocol-Version' => '2'
|
117
|
+
}
|
118
118
|
end
|
119
119
|
|
120
120
|
def each(*args, &blk)
|
@@ -166,9 +166,9 @@ module Strobe
|
|
166
166
|
head = ""
|
167
167
|
body = ""
|
168
168
|
|
169
|
-
@files.each do |path,
|
169
|
+
@files.each do |path, data|
|
170
170
|
size = data.respond_to?(:bytesize) ? data.bytesize : data.size
|
171
|
-
head << "#{Digest::SHA1.hexdigest(
|
171
|
+
head << "#{Digest::SHA1.hexdigest("blob #{size}\0#{data}")}\0#{size}\0#{path}\n"
|
172
172
|
body << data
|
173
173
|
end
|
174
174
|
|
metadata
CHANGED
@@ -1,21 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strobe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 1
|
8
|
-
- 4
|
9
|
-
version: 0.1.4
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.6
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
|
-
- Yehuda Katz
|
13
8
|
- Carl Lerche
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2011-
|
13
|
+
date: 2011-03-23 00:00:00 -07:00
|
19
14
|
default_executable:
|
20
15
|
dependencies:
|
21
16
|
- !ruby/object:Gem::Dependency
|
@@ -26,76 +21,55 @@ dependencies:
|
|
26
21
|
requirements:
|
27
22
|
- - ~>
|
28
23
|
- !ruby/object:Gem::Version
|
29
|
-
segments:
|
30
|
-
- 3
|
31
|
-
- 0
|
32
|
-
- 0
|
33
24
|
version: 3.0.0
|
34
25
|
type: :runtime
|
35
26
|
version_requirements: *id001
|
36
27
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
28
|
+
name: mime-types
|
38
29
|
prerelease: false
|
39
30
|
requirement: &id002 !ruby/object:Gem::Requirement
|
40
31
|
none: false
|
41
32
|
requirements:
|
42
33
|
- - ~>
|
43
34
|
- !ruby/object:Gem::Version
|
44
|
-
|
45
|
-
- 1
|
46
|
-
- 6
|
47
|
-
- 0
|
48
|
-
version: 1.6.0
|
35
|
+
version: 1.16.0
|
49
36
|
type: :runtime
|
50
37
|
version_requirements: *id002
|
51
38
|
- !ruby/object:Gem::Dependency
|
52
|
-
name:
|
39
|
+
name: rack
|
53
40
|
prerelease: false
|
54
41
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
42
|
none: false
|
56
43
|
requirements:
|
57
44
|
- - ~>
|
58
45
|
- !ruby/object:Gem::Version
|
59
|
-
|
60
|
-
- 1
|
61
|
-
- 16
|
62
|
-
- 0
|
63
|
-
version: 1.16.0
|
46
|
+
version: 1.2.0
|
64
47
|
type: :runtime
|
65
48
|
version_requirements: *id003
|
66
49
|
- !ruby/object:Gem::Dependency
|
67
|
-
name:
|
50
|
+
name: thor
|
68
51
|
prerelease: false
|
69
52
|
requirement: &id004 !ruby/object:Gem::Requirement
|
70
53
|
none: false
|
71
54
|
requirements:
|
72
55
|
- - ~>
|
73
56
|
- !ruby/object:Gem::Version
|
74
|
-
|
75
|
-
- 1
|
76
|
-
- 2
|
77
|
-
- 0
|
78
|
-
version: 1.2.0
|
57
|
+
version: 0.14.0
|
79
58
|
type: :runtime
|
80
59
|
version_requirements: *id004
|
81
60
|
- !ruby/object:Gem::Dependency
|
82
|
-
name:
|
61
|
+
name: launchy
|
83
62
|
prerelease: false
|
84
63
|
requirement: &id005 !ruby/object:Gem::Requirement
|
85
64
|
none: false
|
86
65
|
requirements:
|
87
|
-
- -
|
66
|
+
- - ">="
|
88
67
|
- !ruby/object:Gem::Version
|
89
|
-
|
90
|
-
- 0
|
91
|
-
- 14
|
92
|
-
- 0
|
93
|
-
version: 0.14.0
|
68
|
+
version: "0"
|
94
69
|
type: :runtime
|
95
70
|
version_requirements: *id005
|
96
71
|
description: The client library for deploying applications to Strobe's HTML5 deployment platform
|
97
72
|
email:
|
98
|
-
- wycats@strobecorp.com
|
99
73
|
- carl@strobecorp.com
|
100
74
|
executables:
|
101
75
|
- strobe
|
@@ -106,6 +80,7 @@ extra_rdoc_files: []
|
|
106
80
|
files:
|
107
81
|
- lib/strobe/association.rb
|
108
82
|
- lib/strobe/cli/deploy_progress.rb
|
83
|
+
- lib/strobe/cli/input.rb
|
109
84
|
- lib/strobe/cli/main.rb
|
110
85
|
- lib/strobe/cli/preview.rb
|
111
86
|
- lib/strobe/cli/settings.rb
|
@@ -134,6 +109,8 @@ files:
|
|
134
109
|
- lib/strobe/sproutcore.rb
|
135
110
|
- lib/strobe/validations.rb
|
136
111
|
- lib/strobe.rb
|
112
|
+
- CHANGELOG.md
|
113
|
+
- README.md
|
137
114
|
- bin/strobe
|
138
115
|
has_rdoc: true
|
139
116
|
homepage: http://rubygems.org/gems/strobe
|
@@ -149,23 +126,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
149
126
|
requirements:
|
150
127
|
- - ">="
|
151
128
|
- !ruby/object:Gem::Version
|
152
|
-
segments:
|
153
|
-
- 0
|
154
129
|
version: "0"
|
155
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
131
|
none: false
|
157
132
|
requirements:
|
158
133
|
- - ">="
|
159
134
|
- !ruby/object:Gem::Version
|
160
|
-
segments:
|
161
|
-
- 1
|
162
|
-
- 3
|
163
|
-
- 6
|
164
135
|
version: 1.3.6
|
165
136
|
requirements: []
|
166
137
|
|
167
138
|
rubyforge_project: strobe
|
168
|
-
rubygems_version: 1.
|
139
|
+
rubygems_version: 1.6.2
|
169
140
|
signing_key:
|
170
141
|
specification_version: 3
|
171
142
|
summary: A deployment tool for HTML5 applications
|