relish 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,9 @@
1
1
  @announce
2
2
  Feature: Help
3
-
3
+
4
4
  The `relish help` command displays all available commands
5
5
  along with a description of each.
6
-
6
+
7
7
  Scenario: View all available commands with the help command
8
8
  When I successfully run "relish help"
9
9
  Then the output should contain exactly:
@@ -15,7 +15,7 @@ Feature: Help
15
15
 
16
16
  If you leave off the organization or user handle, then it defaults
17
17
  to the user (you).
18
-
18
+
19
19
  === Available Commands
20
20
 
21
21
  help # show this usage
@@ -32,10 +32,12 @@ Feature: Help
32
32
  # example: relish projects:visibility rspec/rspec-core:private
33
33
  projects:rename <project>:<new handle> # rename a project's handle
34
34
  # example: relish projects:rename rspec/rspec-core:rspec-corez
35
- push <project>:<version> # push features to relishapp.com
35
+ push <project>:<version> # push features to a project
36
36
  # <version> is optional
37
37
  # example: relish push rspec/rspec-core
38
38
  # example: relish push rspec/rspec-core:2.0
39
+ push:org <organization handle> # push markdown files to an organization
40
+ # example: relish push:org rspec
39
41
  collab # list the collaborators for a project
40
42
  collab:add <project>:<collaborator handle or email> # add a collaborator to a project
41
43
  # example: relish collab:add rspec/rspec-core:justin
@@ -46,13 +48,13 @@ Feature: Help
46
48
  # example: relish versions:add rspec/rspec-core:2.0
47
49
  versions:remove <project>:<version> # remove a version from a project
48
50
  # example: relish versions:remove rspec/rspec-core:2.0
49
-
51
+
50
52
  """
51
-
53
+
52
54
  Scenario: Specifying no command runs the help command
53
55
  When I successfully run "relish"
54
56
  Then the output should contain "=== Available Commands"
55
-
57
+
56
58
  Scenario: Specifying an unknown command gives an error message
57
59
  When I run "relish baloney"
58
60
  Then it should fail with:
@@ -12,13 +12,13 @@ module Relish
12
12
  class Base
13
13
  include Relish::Helpers
14
14
  extend Dsl
15
-
15
+
16
16
  option :api_token, :default => lambda { get_and_store_api_token }
17
17
  option :host, :default => lambda { Relish.default_host }
18
-
18
+
19
19
  attr_writer :args
20
20
  attr_reader :cli_options
21
-
21
+
22
22
  def initialize(args = [])
23
23
  @args = clean_args(args)
24
24
  @param = get_param.extend(ParamMethods)
@@ -26,17 +26,17 @@ module Relish
26
26
 
27
27
  validate_cli_options
28
28
  end
29
-
29
+
30
30
  def url
31
31
  "http://#{host}/api"
32
32
  end
33
-
33
+
34
34
  def get_param
35
35
  @args.shift if @args.size.odd?
36
36
  end
37
37
 
38
38
  private
39
-
39
+
40
40
  def project
41
41
  merged_options['project'] || error(:project_blank)
42
42
  end
@@ -46,28 +46,28 @@ module Relish
46
46
  global_options_file.store('api_token' => api_token)
47
47
  api_token
48
48
  end
49
-
49
+
50
50
  def get_api_token
51
51
  email, password = ui.get_credentials
52
-
52
+
53
53
  raw_response = resource(:user => email, :password => password)['token'].get
54
54
  String.new(raw_response.to_s)
55
55
  end
56
-
56
+
57
57
  def resource(options = {})
58
58
  options[:user] ||= api_token
59
59
  options[:password] ||= 'X'
60
60
  RestClient::Resource.new(url, options)
61
61
  end
62
-
62
+
63
63
  def clean_args(args)
64
64
  args.inject([]) {|cleaned, arg| cleaned << arg.sub('--', '') }
65
65
  end
66
-
66
+
67
67
  def valid_option_names
68
68
  Dsl::Option.names
69
69
  end
70
-
70
+
71
71
  def validate_cli_options
72
72
  cli_options.keys.each do |option|
73
73
  unless valid_option_names.include?(option.to_s)
@@ -75,11 +75,11 @@ module Relish
75
75
  end
76
76
  end
77
77
  end
78
-
78
+
79
79
  def merged_options
80
80
  @merged_options ||= global_options_file.merge(local_options_file)
81
81
  end
82
-
82
+
83
83
  def global_options_file
84
84
  @global_options ||= OptionsFile.new(Relish.global_options_file)
85
85
  end
@@ -87,11 +87,11 @@ module Relish
87
87
  def local_options_file
88
88
  @local_options ||= OptionsFile.new(Relish.local_options_file)
89
89
  end
90
-
90
+
91
91
  def ui
92
92
  @ui ||= Ui.new
93
93
  end
94
-
94
+
95
95
  def json_parse(response, &block)
96
96
  JSON.parse(response).inject([]) do |parsed_output, hash|
97
97
  parsed_output << block.call(hash)
@@ -99,11 +99,11 @@ module Relish
99
99
  rescue JSON::ParserError
100
100
  response
101
101
  end
102
-
102
+
103
103
  def escape(str)
104
104
  CGI.escape(str)
105
105
  end
106
-
106
+
107
107
  end
108
108
  end
109
109
  end
@@ -3,38 +3,38 @@ module Relish
3
3
  class Collab < Base
4
4
  include ResourceMethods
5
5
  resource_path :memberships
6
-
6
+
7
7
  desc 'list the collaborators for a project'
8
8
  command :default do
9
9
  puts format(resource[resource_path_for_no_option].get(:accept => :json))
10
10
  end
11
-
11
+
12
12
  usage 'collab:add <project>:<collaborator handle or email>'
13
- desc ['add a collaborator to a project',
14
- 'example: relish collab:add rspec/rspec-core:justin']
13
+ desc 'add a collaborator to a project',
14
+ 'example: relish collab:add rspec/rspec-core:justin'
15
15
  command :add do
16
16
  puts resource[resource_path_for_option].post(:handle_or_email => handle_or_email)
17
17
  end
18
-
18
+
19
19
  usage 'collab:remove <project>:<collaborator handle or email>'
20
- desc ['remove a collaborator from a project',
21
- 'example: relish collab:remove rspec/rspec-core:justin']
20
+ desc 'remove a collaborator from a project',
21
+ 'example: relish collab:remove rspec/rspec-core:justin'
22
22
  command :remove do
23
23
  puts resource["#{resource_path_for_option}/#{handle_or_email}"].delete
24
24
  end
25
-
25
+
26
26
  private
27
-
27
+
28
28
  def handle_or_email
29
29
  @param.extract_option
30
30
  end
31
-
31
+
32
32
  def format(response)
33
33
  json_parse(response) do |hash|
34
34
  "#{hash['user']['handle']} (#{hash['user']['email']})"
35
35
  end
36
36
  end
37
-
37
+
38
38
  end
39
39
  end
40
40
  end
@@ -1,22 +1,22 @@
1
1
  module Relish
2
2
  module Command
3
3
  class Config < Base
4
-
4
+
5
5
  class Option
6
6
  VALID_OPTIONS = %w(project)
7
-
7
+
8
8
  def initialize(param)
9
9
  @option, @value = param.split(':')
10
10
  validate_option
11
11
  end
12
-
12
+
13
13
  def validate_option
14
14
  unless VALID_OPTIONS.include?(@option)
15
15
  Relish::Helpers.error "'#{@option}' is not a valid option." +
16
16
  " Valid options: #{VALID_OPTIONS.join(', ')}"
17
17
  end
18
18
  end
19
-
19
+
20
20
  def to_hash
21
21
  {@option => @value}
22
22
  end
@@ -30,16 +30,16 @@ module Relish
30
30
  "No #{Relish.local_options_file} file exists"
31
31
  end)
32
32
  end
33
-
33
+
34
34
  usage 'config:add <option>:<value>'
35
- desc ['add a configuration option to your options file',
36
- 'example: relish config:add project:rspec-core',
37
- "valid configuration options: #{Option::VALID_OPTIONS.join(', ')}"]
35
+ desc 'add a configuration option to your options file',
36
+ 'example: relish config:add project:rspec-core',
37
+ "valid configuration options: #{Option::VALID_OPTIONS.join(', ')}"
38
38
  command :add do
39
39
  option = Option.new(@param)
40
40
  OptionsFile.new(Relish.local_options_file).store(option.to_hash)
41
41
  end
42
-
42
+
43
43
  end
44
44
  end
45
45
  end
@@ -6,21 +6,20 @@ require 'relish/commands/dsl/help_text'
6
6
  module Relish
7
7
  module Command
8
8
  module Dsl
9
-
9
+
10
10
  def option(name, options = {})
11
11
  Option.new(self).define(name, options)
12
12
  Option.names << name.to_s
13
13
  end
14
-
14
+
15
15
  def usage(text)
16
16
  HelpText.next_usage = text
17
17
  end
18
-
19
- def desc(text)
20
- text = text.join("\n") if text.is_a?(Array)
21
- HelpText.next_description = text
18
+
19
+ def desc(*text)
20
+ HelpText.next_description = text.join("\n")
22
21
  end
23
-
22
+
24
23
  def command(arg, &block)
25
24
  case arg
26
25
  when Hash
@@ -31,10 +30,10 @@ module Relish
31
30
  else
32
31
  raise ArgumentError
33
32
  end
34
-
33
+
35
34
  Command.new(self).define(name, &block)
36
35
  end
37
-
36
+
38
37
  end
39
38
  end
40
39
  end
@@ -1,75 +1,75 @@
1
1
  module Relish
2
2
  module Command
3
3
  class Projects < Base
4
-
4
+
5
5
  desc 'list your projects'
6
6
  command :default do
7
7
  puts format(resource['projects'].get(:accept => :json))
8
8
  end
9
-
9
+
10
10
  usage 'projects:add <org or user handle>/<project handle>'
11
- desc ['add a project',
12
- 'append :private to make the project private',
13
- 'example: relish projects:add rspec/rspec-core:private']
11
+ desc 'add a project',
12
+ 'append :private to make the project private',
13
+ 'example: relish projects:add rspec/rspec-core:private'
14
14
  command :add do
15
15
  puts resource['projects'].post(:handle => handle_to_add, :private => private?)
16
16
  end
17
-
17
+
18
18
  usage 'projects:remove <project>'
19
19
  desc 'remove a project'
20
20
  command :remove do
21
21
  puts resource["projects/#{escape(handle_to_remove)}"].delete
22
22
  end
23
-
23
+
24
24
  usage 'projects:visibility <project>:<public or private>'
25
- desc ['set the status of a project',
26
- 'example: relish projects:visibility rspec/rspec-core:private']
25
+ desc 'set the status of a project',
26
+ 'example: relish projects:visibility rspec/rspec-core:private'
27
27
  command :visibility do
28
28
  puts resource["projects/#{escape(handle_to_update)}"].put(
29
29
  :project => { :private => private? }
30
30
  )
31
31
  end
32
-
32
+
33
33
  usage 'projects:rename <project>:<new handle>'
34
- desc ["rename a project's handle",
35
- 'example: relish projects:rename rspec/rspec-core:rspec-corez']
34
+ desc "rename a project's handle",
35
+ 'example: relish projects:rename rspec/rspec-core:rspec-corez'
36
36
  command :rename do
37
37
  puts resource["projects/#{escape(handle_to_update)}"].put(
38
38
  :project => { :handle => rename_handle }
39
39
  )
40
40
  end
41
-
41
+
42
42
  private
43
-
43
+
44
44
  def format(response)
45
- json_parse(response) do |hash|
45
+ json_parse(response) do |hash|
46
46
  result = hash['project']['full_handle']
47
47
  result << " (private)" if hash['project']['private']
48
48
  result
49
49
  end
50
50
  end
51
-
51
+
52
52
  def handle_to_add
53
53
  handle || error(:project_blank)
54
54
  end
55
55
  alias_method :handle_to_update, :handle_to_add
56
-
56
+
57
57
  def handle_to_remove
58
58
  handle || project
59
59
  end
60
-
60
+
61
61
  def handle
62
62
  @param.without_option if @param
63
63
  end
64
-
64
+
65
65
  def rename_handle
66
66
  @param.has_option? ? @param.extract_option : error(:handle_blank)
67
67
  end
68
-
68
+
69
69
  def private?
70
70
  @param.extract_option == 'private'
71
71
  end
72
-
72
+
73
73
  end
74
74
  end
75
75
  end
@@ -4,41 +4,52 @@ require 'stringio'
4
4
  require 'rest_client'
5
5
 
6
6
  module Relish
7
- module Command
7
+ module Command
8
8
  class Push < Base
9
-
9
+
10
10
  usage 'push <project>:<version>'
11
- desc ['push features to relishapp.com',
12
- '<version> is optional',
13
- 'example: relish push rspec/rspec-core',
14
- 'example: relish push rspec/rspec-core:2.0']
11
+ desc 'push features to a project',
12
+ '<version> is optional',
13
+ 'example: relish push rspec/rspec-core',
14
+ 'example: relish push rspec/rspec-core:2.0'
15
15
  command :default do
16
- post files_as_tar_gz
16
+ post files_as_tar_gz, project_params
17
+ end
18
+
19
+ usage 'push:org <organization handle>'
20
+ desc 'push markdown files to an organization',
21
+ 'example: relish push:org rspec'
22
+ command :org do
23
+ post files_as_tar_gz, organization_params
17
24
  end
18
-
25
+
19
26
  private
20
-
21
- def post(tar_gz_data)
22
- resource["pushes?#{parameters}"].post(tar_gz_data,
27
+
28
+ def post(tar_gz_data, params)
29
+ resource["pushes?#{params}"].post(tar_gz_data,
23
30
  :content_type => 'application/x-gzip')
24
31
  puts "sent:\n#{files.join("\n")}"
25
32
  end
26
-
27
- def parameters
33
+
34
+ def project_params
28
35
  "".tap do |str|
29
36
  str << "project_id=#{project}"
30
37
  str << "&version_id=#{version}" if version
31
38
  end
32
39
  end
33
-
40
+
41
+ def organization_params
42
+ "organization_id=#{@param}"
43
+ end
44
+
34
45
  def project
35
46
  (@param.without_option if @param) || super()
36
47
  end
37
-
48
+
38
49
  def version
39
50
  @param.extract_option if @param.has_option?
40
51
  end
41
-
52
+
42
53
  def files_as_tar_gz
43
54
  stream = StringIO.new
44
55
  begin
@@ -52,14 +63,14 @@ module Relish
52
63
  end
53
64
  stream.string
54
65
  end
55
-
66
+
56
67
  def files
57
68
  Dir["features/**/*.{feature,md,markdown}"] +
58
69
  Dir["features/**/.nav"]
59
70
  end
60
-
71
+
61
72
  end
62
-
73
+
63
74
 
64
75
  end
65
76
  end
@@ -3,40 +3,40 @@ module Relish
3
3
  class Versions < Base
4
4
  include ResourceMethods
5
5
  resource_path :versions
6
-
6
+
7
7
  desc 'list the versions for a project'
8
8
  command :default do
9
9
  puts format(resource[resource_path_for_no_option].get(:accept => :json))
10
10
  end
11
11
 
12
12
  usage 'versions:add <project>:<version>'
13
- desc ['add a version to a project',
14
- 'example: relish versions:add rspec/rspec-core:2.0']
13
+ desc 'add a version to a project',
14
+ 'example: relish versions:add rspec/rspec-core:2.0'
15
15
  command :add do
16
16
  puts resource[resource_path_for_option].post(
17
17
  :version => { :name => version_name }
18
18
  )
19
19
  end
20
-
20
+
21
21
  usage 'versions:remove <project>:<version>'
22
- desc ['remove a version from a project',
23
- 'example: relish versions:remove rspec/rspec-core:2.0']
22
+ desc 'remove a version from a project',
23
+ 'example: relish versions:remove rspec/rspec-core:2.0'
24
24
  command :remove do
25
25
  puts resource["#{resource_path_for_option}/#{version_name}"].delete
26
26
  end
27
-
27
+
28
28
  private
29
-
29
+
30
30
  def version_name
31
31
  @param && @param.extract_option || error(:version_blank)
32
32
  end
33
-
33
+
34
34
  def format(response)
35
35
  json_parse(response) do |hash|
36
36
  "#{hash['version']['name']}"
37
37
  end
38
38
  end
39
-
39
+
40
40
  end
41
41
  end
42
42
  end
data/relish.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "relish"
3
- s.version = "0.2.0"
3
+ s.version = "0.2.1"
4
4
 
5
5
  s.required_rubygems_version = '>= 1.3.5'
6
6
  s.authors = ["Matt Wynne", "Justin Ko"]
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
  s.rdoc_options = ["--charset=UTF-8"]
13
13
  s.rubygems_version = "1.3.6"
14
14
  s.summary = %q{Client gem for http://relishapp.com}
15
-
15
+
16
16
  s.require_path = "lib"
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
25
25
  }.each do |lib, version|
26
26
  s.add_runtime_dependency lib, version
27
27
  end
28
-
28
+
29
29
  {
30
30
  'bundler' => '~> 1.0.0',
31
31
  'rake' => '~> 0.8.7',
@@ -3,23 +3,22 @@ require 'spec_helper'
3
3
  module Relish
4
4
  module Command
5
5
  describe Config do
6
-
7
-
6
+
8
7
  describe '#default' do
9
8
  let(:config) { described_class.new }
10
-
9
+
11
10
  context 'with a local options file' do
12
11
  before do
13
12
  File.should_receive(:exists?).and_return(true)
14
13
  IO.should_receive(:read).and_return('options')
15
14
  end
16
-
15
+
17
16
  it 'outputs the contents' do
18
17
  config.should_receive(:puts).with('options')
19
18
  config.default
20
19
  end
21
20
  end
22
-
21
+
23
22
  context 'without a local options file' do
24
23
  it 'outputs the correct message' do
25
24
  config.should_receive(:puts).with('No .relish file exists')
@@ -27,7 +26,7 @@ module Relish
27
26
  end
28
27
  end
29
28
  end
30
-
29
+
31
30
  end
32
31
  end
33
32
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relish
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease: false
4
+ hash: 21
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 0
10
- version: 0.2.0
9
+ - 1
10
+ version: 0.2.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Wynne
@@ -212,8 +212,6 @@ files:
212
212
  - spec/relish/commands/dsl/command_spec.rb
213
213
  - spec/relish/commands/dsl/help_text_spec.rb
214
214
  - spec/relish/commands/dsl/option_spec.rb
215
- - spec/relish/commands/projects_spec.rb
216
- - spec/relish/commands/push_spec.rb
217
215
  - spec/relish/error_messages_spec.rb
218
216
  - spec/relish/options_file_spec.rb
219
217
  - spec/relish/param_methods_spec.rb
@@ -252,7 +250,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
252
250
  requirements: []
253
251
 
254
252
  rubyforge_project:
255
- rubygems_version: 1.3.7
253
+ rubygems_version: 1.4.2
256
254
  signing_key:
257
255
  specification_version: 3
258
256
  summary: Client gem for http://relishapp.com
@@ -269,8 +267,6 @@ test_files:
269
267
  - spec/relish/commands/dsl/command_spec.rb
270
268
  - spec/relish/commands/dsl/help_text_spec.rb
271
269
  - spec/relish/commands/dsl/option_spec.rb
272
- - spec/relish/commands/projects_spec.rb
273
- - spec/relish/commands/push_spec.rb
274
270
  - spec/relish/error_messages_spec.rb
275
271
  - spec/relish/options_file_spec.rb
276
272
  - spec/relish/param_methods_spec.rb
@@ -1,7 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Relish
4
- module Command
5
-
6
- end
7
- end
@@ -1,18 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Relish
4
- module Command
5
- describe Push do
6
-
7
- describe '#default' do
8
- let(:push) { described_class.new }
9
-
10
- it 'calls #post' do
11
- push.should_receive(:post)
12
- push.default
13
- end
14
- end
15
-
16
- end
17
- end
18
- end