blockspring-cli 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c647f46f6e49b14b2ba979986d7b6517628fb21
4
- data.tar.gz: f7df8fa46e4767ffa45c6ffce256720ef818994b
3
+ metadata.gz: 40fc4b8327edac4958e68b52e7e194b748b3b9f6
4
+ data.tar.gz: e36d3719f2fe7c13256ee9339f9cb97d2989d61c
5
5
  SHA512:
6
- metadata.gz: 5a91732d62b47962c6455d72d37e30016fcac7fd970072fd509146924e1c7d10fc9d1edf97e93fa2d7ea9a3bb48870226e01a4f346a4277e907de35a946e582a
7
- data.tar.gz: 0fdcc5444687a8489e64ae91c4e54631b8d8161ad37c055f060887927fac893e6dcac3f8a3a189005a7dc8c08765a15b21a08465c0333ae130d9397320fd81b3
6
+ metadata.gz: b36c9bff1f7765f623a54ca615e5e0e36c496c11b1e0663478944e5bc0b71568c3a281192e6bffd33e63dae873e1ed532758cc41ed3258724f3218ee90c09588
7
+ data.tar.gz: 72873bebf67836331326951cfca76c6a9da5f56535852377d8a47bcbcb21f5d7d8bcd428fcf9b673491b280a384f2a4f2f243095988a0d1434b35b29aa06ad99
@@ -5,6 +5,7 @@ require 'json'
5
5
  require "blockspring/cli/version"
6
6
  require "blockspring/cli/auth"
7
7
  require "blockspring/cli/command"
8
+ require "blockspring/cli/helpers"
8
9
 
9
10
  module Blockspring
10
11
  module CLI
@@ -36,9 +37,9 @@ module Blockspring
36
37
  else
37
38
  error("Command cancelled.")
38
39
  end
39
- rescue => error
40
- puts error.inspect
41
- exit(1)
40
+ # rescue => error
41
+ # puts error.inspect
42
+ # exit(1)
42
43
  end
43
44
  end
44
45
  end
@@ -1,5 +1,9 @@
1
+ require "blockspring/cli/helpers"
2
+
1
3
  class Blockspring::CLI::Auth
2
4
  class << self
5
+ include Blockspring::CLI::Helpers
6
+
3
7
  def host
4
8
  ENV['BLOCKSPRING_API_HOST'] || 'localhost:3000'
5
9
  end
@@ -46,6 +50,24 @@ class Blockspring::CLI::Auth
46
50
  return password
47
51
  end
48
52
 
53
+ def ask_for_password_on_windows
54
+ require "Win32API"
55
+ char = nil
56
+ password = ''
57
+
58
+ while char = Win32API.new("crtdll", "_getch", [ ], "L").Call do
59
+ break if char == 10 || char == 13 # received carriage return or newline
60
+ if char == 127 || char == 8 # backspace and delete
61
+ password.slice!(-1, 1)
62
+ else
63
+ # windows might throw a -1 at us so make sure to handle RangeError
64
+ (password << char.chr) rescue RangeError
65
+ end
66
+ end
67
+ puts
68
+ return password
69
+ end
70
+
49
71
  def ask_for_credentials
50
72
  puts "Enter your Blockspring credentials."
51
73
 
@@ -53,7 +75,7 @@ class Blockspring::CLI::Auth
53
75
  login = ask
54
76
 
55
77
  print "Password (typing will be hidden): "
56
- password = ask_for_password
78
+ password = running_on_windows? ? ask_for_password_on_windows : ask_for_password
57
79
 
58
80
  [login, api_key(login, password)]
59
81
  end
@@ -92,6 +114,9 @@ class Blockspring::CLI::Auth
92
114
  def write_credentials
93
115
  FileUtils.mkdir_p(File.dirname(netrc_path))
94
116
  FileUtils.touch(netrc_path)
117
+ unless running_on_windows?
118
+ FileUtils.chmod(0600, netrc_path)
119
+ end
95
120
  netrc[host] = @credentials
96
121
  netrc.save
97
122
  end
@@ -10,6 +10,10 @@ module Blockspring
10
10
  @@command_aliases ||= {}
11
11
  end
12
12
 
13
+ def self.files
14
+ @@files ||= Hash.new {|hash,key| hash[key] = File.readlines(key).map {|line| line.strip}}
15
+ end
16
+
13
17
  def self.load
14
18
  Dir[File.join(File.dirname(__FILE__), "command", "*.rb")].each do |file|
15
19
  require file
@@ -34,6 +38,14 @@ module Blockspring
34
38
  def self.parse(cmd)
35
39
  commands[cmd] || commands[command_aliases[cmd]]
36
40
  end
41
+
42
+ def self.namespaces
43
+ @@namespaces ||= {}
44
+ end
45
+
46
+ def self.register_namespace(namespace)
47
+ namespaces[namespace[:name]] = namespace
48
+ end
37
49
  end
38
50
  end
39
51
  end
@@ -1,6 +1,12 @@
1
1
  require "blockspring/cli/command/base"
2
2
 
3
+ # authentication (login, logout)
4
+ #
3
5
  class Blockspring::CLI::Command::Auth < Blockspring::CLI::Command::Base
6
+
7
+ # auth
8
+ #
9
+ # Authenticate, display current user
4
10
  def index
5
11
  user, _key = Blockspring::CLI::Auth.get_credentials
6
12
  if user
@@ -8,6 +14,18 @@ class Blockspring::CLI::Command::Auth < Blockspring::CLI::Command::Base
8
14
  end
9
15
  end
10
16
 
17
+ # auth:login
18
+ #
19
+ # log in with your blockspring credentials
20
+ #
21
+ #Example:
22
+ #
23
+ # $ blockspring auth:login
24
+ # Enter your Blockspring credentials:
25
+ # Username or email: email@example.com
26
+ # Password (typing will be hidden):
27
+ # You are logged in as example
28
+ #
11
29
  def login
12
30
  user, _key = Blockspring::CLI::Auth.reauthorize
13
31
  if user
@@ -15,6 +33,14 @@ class Blockspring::CLI::Command::Auth < Blockspring::CLI::Command::Base
15
33
  end
16
34
  end
17
35
 
36
+ # auth:logout
37
+ #
38
+ # clear your blockspring credentials
39
+ #
40
+ #Example:
41
+ #
42
+ # $ blockspring auth:logout
43
+ #
18
44
  def logout
19
45
  Blockspring::CLI::Auth.delete_credentials
20
46
  puts "You have been logged out"
@@ -1,4 +1,6 @@
1
1
  class Blockspring::CLI::Command::Base
2
+ include Blockspring::CLI::Helpers
3
+
2
4
  attr_reader :args
3
5
  attr_reader :options
4
6
 
@@ -13,21 +15,99 @@ class Blockspring::CLI::Command::Base
13
15
 
14
16
  protected
15
17
 
18
+ def self.inherited(klass)
19
+ unless klass == Blockspring::CLI::Command::Base
20
+ help = extract_help_from_caller(caller.first)
21
+
22
+ Blockspring::CLI::Command.register_namespace(
23
+ :name => klass.namespace,
24
+ :description => help.first
25
+ )
26
+ end
27
+ end
28
+
16
29
  def self.method_added(method)
17
30
  return if self == Blockspring::CLI::Command::Base
18
31
  return if private_method_defined?(method)
19
32
  return if protected_method_defined?(method)
20
33
 
34
+ help = extract_help_from_caller(caller.first)
21
35
  resolved_method = (method.to_s == "index") ? nil : method.to_s
22
36
  command = [ self.namespace, resolved_method ].compact.join(":")
37
+ banner = extract_banner(help) || command
23
38
 
24
39
  Blockspring::CLI::Command.register_command(
25
40
  :klass => self,
26
41
  :method => method,
27
- :command => command
42
+ :command => command,
43
+ :namespace => self.namespace,
44
+ :banner => banner.strip,
45
+ :summary => extract_summary(help),
46
+ :description => extract_description(help),
47
+ :help => help.join("\n")
28
48
  )
29
49
  end
30
50
 
51
+ #
52
+ # Parse the caller format and identify the file and line number as identified
53
+ # in : http://www.ruby-doc.org/core/classes/Kernel.html#M001397. This will
54
+ # look for a colon followed by a digit as the delimiter. The biggest
55
+ # complication is windows paths, which have a colon after the drive letter.
56
+ # This regex will match paths as anything from the beginning to a colon
57
+ # directly followed by a number (the line number).
58
+ #
59
+ def self.extract_help_from_caller(line)
60
+ # pull out of the caller the information for the file path and line number
61
+ if line =~ /^(.+?):(\d+)/
62
+ extract_help($1, $2)
63
+ else
64
+ raise("unable to extract help from caller: #{line}")
65
+ end
66
+ end
67
+
68
+ def self.extract_help(file, line_number)
69
+ buffer = []
70
+ lines = Blockspring::CLI::Command.files[file]
71
+
72
+ (line_number.to_i-2).downto(0) do |i|
73
+ line = lines[i]
74
+ case line[0..0]
75
+ when ""
76
+ when "#"
77
+ buffer.unshift(line[1..-1])
78
+ else
79
+ break
80
+ end
81
+ end
82
+
83
+ buffer
84
+ end
85
+
86
+ def self.extract_banner(help)
87
+ help.first
88
+ end
89
+
90
+ def self.extract_summary(help)
91
+ extract_description(help).split("\n")[2].to_s.split("\n").first
92
+ end
93
+
94
+ def self.extract_description(help)
95
+ help.reject do |line|
96
+ line =~ /^\s+-(.+)#(.+)/
97
+ end.join("\n")
98
+ end
99
+
100
+ def self.extract_options(help)
101
+ help.select do |line|
102
+ line =~ /^\s+-(.+)#(.+)/
103
+ end.inject([]) do |options, line|
104
+ args = line.split('#', 2).first
105
+ args = args.split(/,\s*/).map {|arg| arg.strip}.sort.reverse
106
+ name = args.last.split(' ', 2).first[2..-1]
107
+ options << { :name => name, :args => args }
108
+ end
109
+ end
110
+
31
111
  def self.alias_command(new, old)
32
112
  raise "no such command: #{old}" unless Blockspring::CLI::Command.commands[old]
33
113
  Blockspring::CLI::Command.command_aliases[new] = old
@@ -1,6 +1,20 @@
1
1
  require "blockspring/cli/command/base"
2
2
 
3
+ # manipulate blocks (get, push, pull, new)
4
+ #
3
5
  class Blockspring::CLI::Command::Block < Blockspring::CLI::Command::Base
6
+ # block:get BLOCKID
7
+ #
8
+ # pull down an existing block from blockspring
9
+ #
10
+ #Example:
11
+ #
12
+ # $ blockspring get testuser/f19512619b94678ea0b4bf383f3a9cf5
13
+ # Creating directory cool-block-f1951261
14
+ # Syncing script file cool-block-f1951261/block.py
15
+ # Syncing config file cool-block-f1951261/blockspring.json
16
+ # Done.
17
+ #
4
18
  def get
5
19
  block_parts = @args[0].split("/")
6
20
  block = get_block(block_parts[block_parts.length - 1])
@@ -14,6 +28,17 @@ class Blockspring::CLI::Command::Block < Blockspring::CLI::Command::Base
14
28
 
15
29
  end
16
30
 
31
+ # block:pull
32
+ #
33
+ # pull block changes from the server to current directory
34
+ #
35
+ #Example:
36
+ #
37
+ # $ blockspring pull
38
+ # Syncing script file block.py
39
+ # Syncing config file blockspring.json
40
+ # Done.
41
+ #
17
42
  def pull
18
43
  # load config file
19
44
  config_text = File.read('blockspring.json')
@@ -25,6 +50,17 @@ class Blockspring::CLI::Command::Block < Blockspring::CLI::Command::Base
25
50
  puts "Done."
26
51
  end
27
52
 
53
+ # block:push
54
+ #
55
+ # push local block changes or new block to the server
56
+ #
57
+ #Example:
58
+ #
59
+ # $ blockspring push
60
+ # Syncing script file block.py
61
+ # Syncing config file blockspring.json
62
+ # Done.
63
+ #
28
64
  def push
29
65
  _user, key = Blockspring::CLI::Auth.get_credentials
30
66
  config_text = File.read('blockspring.json')
@@ -49,6 +85,19 @@ class Blockspring::CLI::Command::Block < Blockspring::CLI::Command::Base
49
85
  save_block_files(json_response, '.')
50
86
  end
51
87
 
88
+ # block:new LANGUAGE "Block Name"
89
+ #
90
+ # generate a new block
91
+ #
92
+ # LANGUAGE: js|php|py|R|rb
93
+ #
94
+ #Example:
95
+ #
96
+ # $ blockspring new js "My Cool Block"
97
+ # Creating directory my-cool-block
98
+ # Syncing script file my-cool-block/block.js
99
+ # Syncing config file my-cool-block/blockspring.json
100
+ #
52
101
  def new
53
102
  user, key = Blockspring::CLI::Auth.get_credentials
54
103
  language = @args[0]
@@ -1,9 +1,155 @@
1
1
  require "blockspring/cli/command/base"
2
2
 
3
+ # Get information about commands
4
+ #
3
5
  class Blockspring::CLI::Command::Help < Blockspring::CLI::Command::Base
6
+
7
+ PRIMARY_NAMESPACES = %w( auth block run )
8
+
9
+ # help [COMMAND]
10
+ #
11
+ # "Yo dawg. I heard you liked help..." -Xzibit
12
+ #
13
+ #Examples:
14
+ #
15
+ # $ blockspring help
16
+ # Usage: blockspring COMMAND [command-specific-options]
17
+ #
18
+ # Primary help topics, type "blockspring help TOPIC" for more details:
19
+ #
20
+ # auth # authentication (login, logout)
21
+ # block # manipulate blocks (get, push, pull, new)
22
+ # run # set BLOCKSPRING_API_KEY environment variable and run command
23
+ #
24
+ # Additional topics:
25
+ #
26
+ # help # huh?
27
+ # version # display version
28
+ #
29
+ # $ blockspring help block:new
30
+ # Usage: blockspring block:new LANGUAGE "Block Name"
31
+ #
32
+ # generate a new block
33
+ #
34
+ # LANGUAGE: js|php|py|R|rb
35
+ #
36
+ # Example:
37
+ #
38
+ # $ blockspring new js "My Cool Block"
39
+ # Creating directory my-cool-block
40
+ # Syncing script file my-cool-block/block.js
41
+ # Syncing config file my-cool-block/blockspring.json
42
+
43
+
4
44
  def index
5
- puts "Usage: blockspring COMMAND [options]"
45
+ if command = args.shift
46
+ help_for_command(command)
47
+ else
48
+ help_for_root
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def help_for_root
55
+ puts "Usage: blockspring COMMAND [command-specific-options]"
56
+ puts
57
+ puts "Primary help topics, type \"blockspring help TOPIC\" for more details:"
58
+ puts
59
+ summary_for_namespaces(primary_namespaces)
6
60
  puts
7
- puts "More info at http://www.blockspring.com/documentation/cli"
61
+ puts "Additional topics:"
62
+ puts
63
+ summary_for_namespaces(additional_namespaces)
64
+ puts
65
+ end
66
+
67
+ def commands
68
+ Blockspring::CLI::Command.commands
69
+ end
70
+
71
+ def help_for_command(name)
72
+ if command_alias = Blockspring::CLI::Command.command_aliases[name]
73
+ display("Alias: #{name} redirects to #{command_alias}")
74
+ name = command_alias
75
+ end
76
+ if command = commands[name]
77
+ puts "Usage: blockspring #{command[:banner]}"
78
+
79
+ if command[:help].strip.length > 0
80
+ help = command[:help].split("\n").reject do |line|
81
+ line =~ /HIDDEN/
82
+ end
83
+ puts help[1..-1].join("\n")
84
+ end
85
+ puts
86
+ end
87
+
88
+ namespace_commands = commands_for_namespace(name).reject do |command|
89
+ command[:help] =~ /DEPRECATED/
90
+ end
91
+
92
+ if !namespace_commands.empty?
93
+ puts "Additional commands, type \"blockspring help COMMAND\" for more details:"
94
+ puts
95
+ help_for_namespace(name)
96
+ puts
97
+ elsif command.nil?
98
+ error "#{name} is not a blockspring command. See `heroku help`."
99
+ end
100
+ end
101
+
102
+ def commands_for_namespace(name)
103
+ Blockspring::CLI::Command.commands.values.select do |command|
104
+ command[:namespace] == name && command[:command] != name
105
+ end
106
+ end
107
+
108
+ def help_for_namespace(name)
109
+ namespace_commands = commands_for_namespace(name)
110
+
111
+ unless namespace_commands.empty?
112
+ size = longest(namespace_commands.map { |c| c[:banner] })
113
+ namespace_commands.sort_by { |c| c[:banner].to_s }.each do |command|
114
+ next if skip_command?(command)
115
+ command[:summary] ||= ""
116
+ puts " %-#{size}s # %s" % [ command[:banner], command[:summary] ]
117
+ end
118
+ end
119
+ end
120
+
121
+ def skip_namespace?(ns)
122
+ return true if ns[:description] =~ /DEPRECATED:/
123
+ return true if ns[:description] =~ /HIDDEN:/
124
+ false
125
+ end
126
+
127
+ def skip_command?(command)
128
+ return true if command[:help] =~ /DEPRECATED:/
129
+ return true if command[:help] =~ /^ HIDDEN:/
130
+ false
131
+ end
132
+
133
+ def namespaces
134
+ namespaces = Blockspring::CLI::Command.namespaces
135
+ namespaces
136
+ end
137
+
138
+ def primary_namespaces
139
+ PRIMARY_NAMESPACES.map { |name| namespaces[name] }.compact
140
+ end
141
+
142
+ def additional_namespaces
143
+ (namespaces.values - primary_namespaces)
144
+ end
145
+
146
+ def summary_for_namespaces(namespaces)
147
+ size = longest(namespaces.map { |n| n[:name] })
148
+ namespaces.sort_by {|namespace| namespace[:name]}.each do |namespace|
149
+ next if skip_namespace?(namespace)
150
+ name = namespace[:name]
151
+ namespace[:description] ||= ""
152
+ puts " %-#{size}s # %s" % [ name, namespace[:description] ]
153
+ end
8
154
  end
9
155
  end
@@ -1,5 +1,7 @@
1
1
  require "blockspring/cli/command/base"
2
2
 
3
+ # set BLOCKSPRING_API_KEY environment variable and run command
4
+ #
3
5
  class Blockspring::CLI::Command::Run < Blockspring::CLI::Command::Base
4
6
  def index
5
7
  if ENV['BLOCKSPRING_API_KEY'].to_s.strip.empty?
@@ -1,6 +1,17 @@
1
1
  require "blockspring/cli/command/base"
2
2
 
3
+ # display version
4
+ #
3
5
  class Blockspring::CLI::Command::Version < Blockspring::CLI::Command::Base
6
+
7
+ # version
8
+ #
9
+ # show blockspring command line tool version
10
+ #
11
+ #Example:
12
+ #
13
+ # blockspring version
14
+ # blockspring-cli-gem/1.0.4 (x86_64-darwin13.0) ruby/2.1.2
4
15
  def index
5
16
  puts Blockspring::CLI.user_agent
6
17
  end
@@ -0,0 +1,58 @@
1
+ module Blockspring
2
+ module CLI
3
+ module Helpers
4
+
5
+ def home_directory
6
+ running_on_windows? ? ENV['USERPROFILE'].gsub("\\","/") : ENV['HOME']
7
+ end
8
+
9
+ def running_on_windows?
10
+ RUBY_PLATFORM =~ /mswin32|mingw32/
11
+ end
12
+
13
+ def running_on_a_mac?
14
+ RUBY_PLATFORM =~ /-darwin\d/
15
+ end
16
+
17
+ def display(msg="", new_line=true)
18
+ if new_line
19
+ puts(msg)
20
+ else
21
+ print(msg)
22
+ end
23
+ $stdout.flush
24
+ end
25
+
26
+ def longest(items)
27
+ items.map { |i| i.to_s.length }.sort.last
28
+ end
29
+
30
+ def format_with_bang(message)
31
+ return '' if message.to_s.strip == ""
32
+ " ! " + message.split("\n").join("\n ! ")
33
+ end
34
+
35
+ def output_with_bang(message="", new_line=true)
36
+ return if message.to_s.strip == ""
37
+ display(format_with_bang(message), new_line)
38
+ end
39
+
40
+ def error(message)
41
+ if Blockspring::CLI::Helpers.error_with_failure
42
+ display("failed")
43
+ Blockspring::CLI::Helpers.error_with_failure = false
44
+ end
45
+ $stderr.puts(format_with_bang(message))
46
+ exit(1)
47
+ end
48
+
49
+ def self.error_with_failure
50
+ @@error_with_failure ||= false
51
+ end
52
+
53
+ def self.error_with_failure=(new_error_with_failure)
54
+ @@error_with_failure = new_error_with_failure
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,5 +1,5 @@
1
1
  module Blockspring
2
2
  module CLI
3
- VERSION = "0.0.4"
3
+ VERSION = "0.0.5"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blockspring-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blockspring
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-23 00:00:00.000000000 Z
11
+ date: 2014-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -104,6 +104,7 @@ files:
104
104
  - lib/blockspring/cli/command/help.rb
105
105
  - lib/blockspring/cli/command/run.rb
106
106
  - lib/blockspring/cli/command/version.rb
107
+ - lib/blockspring/cli/helpers.rb
107
108
  - lib/blockspring/cli/version.rb
108
109
  homepage: http://www.blockspring.com
109
110
  licenses: