strobe 0.0.1 → 0.0.2
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/bin/strobe +2 -12
- data/lib/strobe.rb +35 -88
- data/lib/strobe/association.rb +86 -0
- data/lib/strobe/cli.rb +39 -53
- data/lib/strobe/cli/action.rb +131 -0
- data/lib/strobe/cli/actions.rb +103 -0
- data/lib/strobe/cli/settings.rb +62 -0
- data/lib/strobe/collection.rb +53 -0
- data/lib/strobe/connection.rb +91 -0
- data/lib/strobe/resource/base.rb +235 -0
- data/lib/strobe/resource/collection.rb +50 -0
- data/lib/strobe/resource/singleton.rb +18 -0
- data/lib/strobe/resources/account.rb +12 -0
- data/lib/strobe/resources/application.rb +129 -0
- data/lib/strobe/resources/me.rb +11 -0
- data/lib/strobe/resources/signup.rb +27 -0
- data/lib/strobe/resources/team.rb +13 -0
- data/lib/strobe/resources/user.rb +11 -0
- data/lib/strobe/validations.rb +118 -0
- metadata +50 -124
- data/.gitignore +0 -5
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -69
- data/Rakefile +0 -36
- data/features/1_sign_up.feature +0 -16
- data/features/2_deploying.feature +0 -35
- data/features/3_deploying_sproutcore_apps.feature +0 -19
- data/features/step_definitions/cli_steps.rb +0 -8
- data/features/step_definitions/deploying_steps.rb +0 -58
- data/features/step_definitions/sign_up.rb +0 -74
- data/features/support/helpers.rb +0 -104
- data/features/support/strobe.rb +0 -57
- data/lib/strobe/account.rb +0 -67
- data/lib/strobe/deploy.rb +0 -131
- data/lib/strobe/errors.rb +0 -12
- data/lib/strobe/http.rb +0 -94
- data/lib/strobe/server.rb +0 -13
- data/lib/strobe/settings.rb +0 -56
- data/lib/strobe/ui.rb +0 -81
- data/lib/strobe/user.rb +0 -9
- data/lib/strobe/version.rb +0 -3
- data/strobe.gemspec +0 -35
data/bin/strobe
CHANGED
@@ -1,14 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
require 'strobe'
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
begin
|
6
|
-
Strobe::CLI.start
|
7
|
-
rescue Strobe::Error => e
|
8
|
-
Strobe.ui.error e.message
|
9
|
-
Strobe.ui.error e.backtrace.join("\n") if ENV["STROBE_DEBUG"]
|
10
|
-
exit e.status_code
|
11
|
-
rescue Interrupt
|
12
|
-
Strobe.ui.error "\nQuitting..."
|
13
|
-
exit 1
|
14
|
-
end
|
4
|
+
Strobe::CLI.start
|
data/lib/strobe.rb
CHANGED
@@ -1,100 +1,47 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def root
|
23
|
-
main.root
|
24
|
-
end
|
25
|
-
|
26
|
-
def app_root
|
27
|
-
main.app_root
|
28
|
-
end
|
29
|
-
|
30
|
-
def account
|
31
|
-
main.account
|
32
|
-
end
|
33
|
-
|
34
|
-
def settings
|
35
|
-
main.settings
|
36
|
-
end
|
37
|
-
|
38
|
-
def config_dir
|
39
|
-
main.config_dir
|
40
|
-
end
|
41
|
-
|
42
|
-
def local_config_dir
|
43
|
-
main.local_config_dir
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
attr_writer :ui
|
48
|
-
|
49
|
-
def ui
|
50
|
-
@ui ||= UI::Basic.new
|
1
|
+
require 'base64'
|
2
|
+
require 'active_model'
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'active_support/core_ext/hash/deep_merge'
|
5
|
+
require 'active_support/core_ext/hash/reverse_merge'
|
6
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
7
|
+
require 'active_support/core_ext/string/inflections'
|
8
|
+
|
9
|
+
module Strobe
|
10
|
+
autoload :Association, 'strobe/association'
|
11
|
+
autoload :CLI, 'strobe/cli'
|
12
|
+
autoload :Collection, 'strobe/collection'
|
13
|
+
autoload :Connection, 'strobe/connection'
|
14
|
+
autoload :Validations, 'strobe/validations'
|
15
|
+
|
16
|
+
module Resource
|
17
|
+
autoload :Base, 'strobe/resource/base'
|
18
|
+
autoload :Collection, 'strobe/resource/collection'
|
19
|
+
autoload :Singleton, 'strobe/resource/singleton'
|
51
20
|
end
|
52
21
|
|
53
|
-
|
54
|
-
|
55
|
-
|
22
|
+
# Resources
|
23
|
+
module Resources
|
24
|
+
autoload :Account, 'strobe/resources/account'
|
25
|
+
autoload :Application, 'strobe/resources/application'
|
26
|
+
autoload :Me, 'strobe/resources/me'
|
27
|
+
autoload :Signup, 'strobe/resources/signup'
|
28
|
+
autoload :Team, 'strobe/resources/team'
|
29
|
+
autoload :User, 'strobe/resources/user'
|
56
30
|
end
|
57
31
|
|
58
|
-
|
59
|
-
|
60
|
-
end
|
32
|
+
# Errors
|
33
|
+
class StrobeError < StandardError ; end
|
34
|
+
class UnauthenticatedError < StrobeError ; end
|
35
|
+
class ResourceNotFoundError < StrobeError ; end
|
61
36
|
|
62
|
-
def
|
63
|
-
@
|
64
|
-
dir = Pathname.new(File.join(Strobe.user_home, ".strobe"))
|
65
|
-
FileUtils.mkdir_p(dir) unless dir.exist?
|
66
|
-
dir
|
67
|
-
end
|
37
|
+
def self.connection
|
38
|
+
@connection
|
68
39
|
end
|
69
40
|
|
70
|
-
def
|
71
|
-
@
|
72
|
-
dir = Pathname.new(File.join(app_root, ".strobe"))
|
73
|
-
FileUtils.mkdir_p(dir) unless dir.exist?
|
74
|
-
dir
|
75
|
-
end
|
41
|
+
def self.connection=(connection)
|
42
|
+
@connection = connection
|
76
43
|
end
|
77
44
|
|
78
|
-
def settings
|
79
|
-
@settings ||= Settings.new
|
80
|
-
end
|
81
|
-
|
82
|
-
autoload :Account, "strobe/account"
|
83
|
-
autoload :CLI, "strobe/cli"
|
84
|
-
autoload :Deploy, "strobe/deploy"
|
85
|
-
autoload :Error, "strobe/errors"
|
86
|
-
autoload :HTTP, "strobe/http"
|
87
|
-
autoload :Server, "strobe/server"
|
88
|
-
autoload :Settings, "strobe/settings"
|
89
|
-
autoload :UI, "strobe/ui"
|
90
|
-
autoload :User, "strobe/user"
|
91
|
-
autoload :Version, "strobe/version"
|
92
|
-
|
93
|
-
# ERRORS
|
94
|
-
autoload :AccountError, "strobe/errors"
|
95
|
-
autoload :ApplicationError, "strobe/errors"
|
96
|
-
|
97
|
-
private
|
98
45
|
# sadly, copied from Rubygems
|
99
46
|
def self.user_home
|
100
47
|
unless RUBY_VERSION > '1.9' then
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Strobe
|
2
|
+
class Association
|
3
|
+
attr_reader :source, :name, :cardinality, :options
|
4
|
+
|
5
|
+
def initialize(source, cardinality, name, options)
|
6
|
+
@source = source
|
7
|
+
@cardinality = cardinality
|
8
|
+
@name = name.to_sym
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def target_name
|
13
|
+
'Strobe::Resources::' + name.to_s.classify
|
14
|
+
end
|
15
|
+
|
16
|
+
def target
|
17
|
+
@target ||= target_name.constantize
|
18
|
+
end
|
19
|
+
|
20
|
+
def collection?
|
21
|
+
cardinality == :n
|
22
|
+
end
|
23
|
+
|
24
|
+
def autoload?
|
25
|
+
!options.key?(:autoload) || options[:autoload]
|
26
|
+
end
|
27
|
+
|
28
|
+
def include?
|
29
|
+
options[:include]
|
30
|
+
end
|
31
|
+
|
32
|
+
def reader
|
33
|
+
ruby = []
|
34
|
+
ruby << "def #{name}"
|
35
|
+
|
36
|
+
if autoload? && collection?
|
37
|
+
|
38
|
+
ruby << " @__#{name} ||= Strobe::Collection.new( " \
|
39
|
+
" #{target_name}, '#{source.singular_resource_name}_id' " \
|
40
|
+
" => self[:id] ) if self[:id]"
|
41
|
+
|
42
|
+
elsif autoload?
|
43
|
+
|
44
|
+
ruby << " return @__#{name} if @__#{name}"
|
45
|
+
ruby << " return nil unless self[:#{name}_id]"
|
46
|
+
ruby << " @__#{name} = #{target_name}.get( self[:#{name}_id] )"
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
ruby << " @__#{name}"
|
51
|
+
|
52
|
+
ruby << "end"
|
53
|
+
ruby.join("\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
def writer
|
57
|
+
ruby = []
|
58
|
+
ruby << "def #{name}=(val)"
|
59
|
+
|
60
|
+
if collection?
|
61
|
+
|
62
|
+
ruby << " raise NotImplementedError"
|
63
|
+
|
64
|
+
else
|
65
|
+
|
66
|
+
ruby << " if val"
|
67
|
+
ruby << " if val.is_a?(Hash)"
|
68
|
+
ruby << " val = #{target_name}.new(val)"
|
69
|
+
ruby << " elsif !val.is_a?(#{target_name})"
|
70
|
+
ruby << " raise 'fail'"
|
71
|
+
ruby << " end"
|
72
|
+
|
73
|
+
ruby << " self[:#{name}_id] = val[:id]" if autoload?
|
74
|
+
ruby << " @__#{name} = val"
|
75
|
+
ruby << " else"
|
76
|
+
ruby << " self[:#{name}_id] = nil" if autoload?
|
77
|
+
ruby << " @__#{name} = nil"
|
78
|
+
ruby << " end"
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
ruby << "end"
|
83
|
+
ruby.join("\n")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/strobe/cli.rb
CHANGED
@@ -1,78 +1,64 @@
|
|
1
|
-
require
|
1
|
+
require 'thor'
|
2
|
+
require 'pathname'
|
3
|
+
require 'fileutils'
|
2
4
|
|
3
|
-
|
5
|
+
module Strobe
|
4
6
|
class CLI < Thor
|
5
|
-
|
7
|
+
autoload :Action, 'strobe/cli/action'
|
8
|
+
autoload :Settings, 'strobe/cli/settings'
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
def self.start(*)
|
11
|
+
super
|
12
|
+
rescue Strobe::StrobeError => e
|
13
|
+
raise if $STROBE_BACKTRACE
|
14
|
+
abort "[ERROR] #{e.message}"
|
15
|
+
end
|
16
|
+
|
17
|
+
class_option "backtrace", :type => :boolean, :banner => "Show a backtrace in case of an exception"
|
9
18
|
|
10
19
|
def initialize(*)
|
11
20
|
super
|
12
21
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
use_shell = options["no-color"] ? Thor::Shell::Basic.new : shell
|
17
|
-
Strobe.ui = UI::Shell.new(use_shell)
|
22
|
+
$STROBE_BACKTRACE = true if options[:backtrace]
|
23
|
+
_settings.connect!
|
18
24
|
end
|
19
25
|
|
20
|
-
|
26
|
+
# Load the CLI actions
|
27
|
+
require "strobe/cli/actions"
|
28
|
+
|
29
|
+
desc "signup", "signup for a new Strobe account"
|
21
30
|
def signup
|
22
|
-
|
31
|
+
_run :signup
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "login", "register this computer with an existing Strobe account"
|
35
|
+
def login
|
36
|
+
_run :login
|
23
37
|
end
|
24
38
|
|
25
39
|
desc "deploy", "deploy your application to Strobe"
|
40
|
+
method_option "path", :type => :string, :banner => "The path to the application"
|
26
41
|
def deploy
|
27
|
-
|
28
|
-
|
42
|
+
path = options[:path] || Dir.pwd
|
43
|
+
config = Settings.new(Pathname.new(path).join(".strobe/config"))
|
29
44
|
|
30
|
-
|
31
|
-
def preview
|
32
|
-
Server.new(options[:path]).start
|
45
|
+
_run :deploy, :config => config, :path => path
|
33
46
|
end
|
34
47
|
|
35
|
-
|
36
|
-
case command
|
37
|
-
when "gemfile" then command = "gemfile.5"
|
38
|
-
when nil then command = "bundle"
|
39
|
-
else command = "bundle-#{cli}"
|
40
|
-
end
|
41
|
-
|
42
|
-
root = File.expand_path("../man", __FILE__)
|
43
|
-
|
44
|
-
if manpages.include?(command)
|
45
|
-
if have_groff?
|
46
|
-
groff = "groff -Wall -mtty-char -mandoc -Tascii"
|
47
|
-
pager = ENV['MANPAGER'] || ENV['PAGER'] || 'more'
|
48
|
+
private
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
else
|
54
|
-
super
|
55
|
-
end
|
50
|
+
def _init_application
|
51
|
+
path = options[:path]
|
52
|
+
dir = Pathname.new(path).join(".strobe")
|
53
|
+
FileUtils.mkdir_p dir
|
56
54
|
end
|
57
55
|
|
58
|
-
|
59
|
-
|
60
|
-
man_root = File.expand_path("../man", __FILE__)
|
61
|
-
return [] unless File.directory?(man_root)
|
62
|
-
|
63
|
-
man_pages = []
|
64
|
-
Dir["#{man_root}/*"].each do |file|
|
65
|
-
base = File.basename(file)
|
66
|
-
next if base.include?(".")
|
67
|
-
man_pages << base
|
68
|
-
end
|
69
|
-
man_pages
|
56
|
+
def _run(name, opts = {})
|
57
|
+
Action.run name, _settings, opts
|
70
58
|
end
|
71
59
|
|
72
|
-
def
|
73
|
-
|
74
|
-
$? == 0
|
60
|
+
def _settings
|
61
|
+
@settings ||= Settings.new
|
75
62
|
end
|
76
63
|
end
|
77
64
|
end
|
78
|
-
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'highline'
|
2
|
+
|
3
|
+
module Strobe
|
4
|
+
class CLI::Action
|
5
|
+
def self.run(action, settings, options = {})
|
6
|
+
success = false
|
7
|
+
klass = action.to_s.classify + 'Action'
|
8
|
+
klass = CLI::Actions.const_get(klass)
|
9
|
+
|
10
|
+
until success == true
|
11
|
+
action = klass.new(settings, options)
|
12
|
+
action.steps
|
13
|
+
success = !action.restart
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
include Resources
|
18
|
+
|
19
|
+
attr_reader :actions, :settings, :restart, :options
|
20
|
+
|
21
|
+
def initialize(settings, options)
|
22
|
+
@settings = settings
|
23
|
+
@options = options
|
24
|
+
@highline = HighLine.new
|
25
|
+
@resource = nil
|
26
|
+
|
27
|
+
# State
|
28
|
+
@in_group = false
|
29
|
+
@restart = false
|
30
|
+
end
|
31
|
+
|
32
|
+
def resource(resource = nil)
|
33
|
+
@resource = resource if resource
|
34
|
+
@resource
|
35
|
+
end
|
36
|
+
|
37
|
+
def say(what)
|
38
|
+
puts what
|
39
|
+
end
|
40
|
+
|
41
|
+
def agree(msg, *args)
|
42
|
+
@highline.agree(msg, *args) do |q|
|
43
|
+
next unless STDIN.tty? # For testing
|
44
|
+
q.readline = true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def ask(key, options = {})
|
49
|
+
input key, options do |msg|
|
50
|
+
resp = @highline.ask msg do |q|
|
51
|
+
next unless STDIN.tty? # For testing
|
52
|
+
q.readline = true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def password(key, options = {})
|
58
|
+
input key, options do |msg|
|
59
|
+
@highline.ask msg do |q|
|
60
|
+
next unless STDIN.tty? # For testing
|
61
|
+
q.echo = '*'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def choose
|
67
|
+
@highline.choose do |menu|
|
68
|
+
yield menu
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def group(options = {}, &blk)
|
73
|
+
case
|
74
|
+
when key = options[:validate]
|
75
|
+
validation_group(key, &blk)
|
76
|
+
else
|
77
|
+
yield if block_given?
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def save(opts = {})
|
82
|
+
if resource.save
|
83
|
+
yield
|
84
|
+
else
|
85
|
+
display_errors
|
86
|
+
if opts[:on_error] == :restart
|
87
|
+
@restart = true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def run(action, opts = {})
|
93
|
+
CLI::Action.run(action, settings, opts)
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def input(key, options)
|
99
|
+
into = options[:into] || key
|
100
|
+
|
101
|
+
validation_group into do
|
102
|
+
msg = (key.to_s.humanize + ': ').ljust(25)
|
103
|
+
resource[into] = yield msg
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def validation_group(resource_key)
|
108
|
+
return yield if @in_group
|
109
|
+
|
110
|
+
begin
|
111
|
+
@in_group = true
|
112
|
+
while true
|
113
|
+
yield
|
114
|
+
|
115
|
+
break if resource.valid_attribute?(resource_key)
|
116
|
+
|
117
|
+
display_errors
|
118
|
+
end
|
119
|
+
ensure
|
120
|
+
@in_group = false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def display_errors
|
125
|
+
resource.errors.each do |k, msg|
|
126
|
+
key = k.to_s.split('.').last
|
127
|
+
say "[ERROR] #{key.humanize} #{msg}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|