blockspring-cli 0.0.4 → 0.0.5

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.
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: