relish 0.0.9 → 0.1.0

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.
@@ -4,24 +4,26 @@ Feature: Help
4
4
  The `relish help` command displays all available commands
5
5
  along with a description of each.
6
6
 
7
- The `relish help:<command>` option will display help text
8
- for that particular command.
9
-
10
7
  Scenario: View all available commands with the help command
11
8
  When I successfully run "relish help"
12
9
  Then the output should contain exactly:
13
10
  """
14
11
  === Available Commands
15
12
 
16
- help # show this usage
17
- config # display the contents of your options file
18
- config:show # display the contents of your options file
19
- config:add --<option> <value> # add a configuration option to your options file
20
- projects # list your projects
21
- projects:list # list your projects
22
- projects:add <org_or_user_handle>/<project_handle> # add a project
23
- projects:remove <org_or_user_handle>/<project_handle> # remove a project
24
- push # push features to relishapp.com
13
+ help # show this usage
14
+ config # display the contents of your options file
15
+ config:add --<option> <value> # add a configuration option to your options file
16
+ projects # list your projects
17
+ projects:add <org_or_user_handle>/<project_handle> # add a project
18
+ # append :private to make the project private
19
+ # example: relish projects:add rspec/rspec-core:private
20
+ projects:remove <org_or_user_handle>/<project_handle> # remove a project
21
+ push # push features to relishapp.com
22
+ collab # list the collaborators for a project
23
+ collab:add <org_or_user_handle>/<project_handle>:<collaborator_handle_or_email> # add a collaborator to a project
24
+ # example: relish collab:add rspec/rspec-core:justin
25
+ collab:remove <org_or_user_handle>/<project_handle>:<collaborator_handle_or_email> # remove a collaborator from a project
26
+ # example: relish collab:remove rspec/rspec-core:justin
25
27
 
26
28
  """
27
29
 
@@ -1,3 +1,5 @@
1
+ require 'relish/core_ext'
2
+
1
3
  module Relish
2
4
  class << self
3
5
 
@@ -1,10 +1,11 @@
1
1
  require 'relish'
2
2
  require 'relish/helpers'
3
3
  require 'relish/commands/base'
4
- require 'relish/commands/push'
4
+ require 'relish/commands/collab'
5
5
  require 'relish/commands/config'
6
- require 'relish/commands/projects'
7
6
  require 'relish/commands/help'
7
+ require 'relish/commands/projects'
8
+ require 'relish/commands/push'
8
9
 
9
10
  module Relish
10
11
  module Command
@@ -1,4 +1,5 @@
1
1
  require 'yaml'
2
+ require 'json'
2
3
  require 'relish/ui'
3
4
  require 'relish/options_file'
4
5
  require 'relish/commands/dsl'
@@ -81,6 +82,14 @@ module Relish
81
82
  @ui ||= Ui.new
82
83
  end
83
84
 
85
+ def json_parse(response, &block)
86
+ JSON.parse(response).inject([]) do |parsed_output, hash|
87
+ parsed_output << block.call(hash)
88
+ end.join("\n")
89
+ rescue JSON::ParserError
90
+ response
91
+ end
92
+
84
93
  end
85
94
  end
86
95
  end
@@ -0,0 +1,44 @@
1
+ module Relish
2
+ module Command
3
+ class Collab < Base
4
+
5
+ desc 'list the collaborators for a project'
6
+ command :default do
7
+ puts format(resource[resource_path].get(:accept => :json))
8
+ end
9
+
10
+ usage 'collab:add <org_or_user_handle>/<project_handle>:' +
11
+ '<collaborator_handle_or_email>'
12
+ desc ['add a collaborator to a project',
13
+ 'example: relish collab:add rspec/rspec-core:justin'].join("\n")
14
+ command :add do
15
+ puts resource[resource_path].post(:handle_or_email => handle_or_email)
16
+ end
17
+
18
+ usage 'collab:remove <org_or_user_handle>/<project_handle>:' +
19
+ '<collaborator_handle_or_email>'
20
+ desc ['remove a collaborator from a project',
21
+ 'example: relish collab:remove rspec/rspec-core:justin'].join("\n")
22
+ command :remove do
23
+ puts resource["#{resource_path}/#{handle_or_email}"].delete
24
+ end
25
+
26
+ private
27
+
28
+ def resource_path
29
+ "projects/#{@param.remove_option}/memberships"
30
+ end
31
+
32
+ def handle_or_email
33
+ @param.extract_option
34
+ end
35
+
36
+ def format(response)
37
+ json_parse(response) do |hash|
38
+ "#{hash['user']['handle']} (#{hash['user']['email']})"
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -3,11 +3,7 @@ module Relish
3
3
  class Config < Base
4
4
 
5
5
  desc 'display the contents of your options file'
6
- command :default => :show
7
-
8
- usage 'config:show'
9
- desc 'display the contents of your options file'
10
- command :show do
6
+ command :default do
11
7
  puts(if File.exists?(Relish.local_options_file)
12
8
  IO.read(Relish.local_options_file)
13
9
  else
@@ -1,4 +1,4 @@
1
- require 'relish/commands/dsl/base'
1
+ require 'relish/commands/dsl/context_class'
2
2
  require 'relish/commands/dsl/option'
3
3
  require 'relish/commands/dsl/command'
4
4
  require 'relish/commands/dsl/help_text'
@@ -1,10 +1,11 @@
1
1
  module Relish
2
2
  module Command
3
3
  module Dsl
4
- class Command < Base
4
+ class Command
5
+ include ContextClass
5
6
 
6
7
  def define(name, &block)
7
- context_eval do
8
+ context_class_eval do
8
9
  define_method(name) do
9
10
  begin
10
11
  instance_exec(&block)
@@ -14,7 +15,7 @@ module Relish
14
15
  end
15
16
  end
16
17
  end
17
- HelpText.add(name, context_name)
18
+ HelpText.add(name, context_class_name)
18
19
  end
19
20
 
20
21
  end
@@ -0,0 +1,23 @@
1
+ module Relish
2
+ module Command
3
+ module Dsl
4
+ module ContextClass
5
+
6
+ attr_reader :context_class
7
+
8
+ def initialize(context_class)
9
+ @context_class = context_class
10
+ end
11
+
12
+ def context_class_eval(&block)
13
+ context_class.class_eval(&block)
14
+ end
15
+
16
+ def context_class_name
17
+ context_class.name.split('::').last.downcase
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -34,6 +34,12 @@ module Relish
34
34
  def clear_commands
35
35
  @commands = {}
36
36
  end
37
+
38
+ def max_usage_length
39
+ commands.values.map {|v|
40
+ v.map {|v| v.keys.to_s.length }.max
41
+ }.max
42
+ end
37
43
  end
38
44
 
39
45
  end
@@ -1,13 +1,14 @@
1
1
  module Relish
2
2
  module Command
3
3
  module Dsl
4
- class Option < Base
4
+ class Option
5
+ include ContextClass
5
6
 
6
7
  def define(name, options = {})
7
8
  name = name.to_s
8
9
  default_proc = options[:default] || Proc.new {}
9
10
 
10
- context_eval do
11
+ context_class_eval do
11
12
  define_method(name) do
12
13
  cli_options[name] ||
13
14
  local_options_file[name] ||
@@ -1,29 +1,46 @@
1
- require 'yaml'
2
-
3
1
  module Relish
4
2
  module Command
5
3
  class Help < Base
6
4
 
7
- desc 'show this usage'
5
+ desc 'show this usage'
8
6
  command :default do
9
7
  puts "=== Available Commands\n\n"
10
-
11
8
  Dsl::HelpText.commands.each do |command, list|
12
- list.each do |hash|
13
- usage, description = *hash.to_a.flatten
14
- usage = command if usage == 'default'
15
- puts "#{usage.ljust(max_command_length)} # #{description}"
16
- end
9
+ list.each {|hash| Formatter.new(command, hash).format }
17
10
  end
18
11
  end
19
12
 
20
- private
13
+ class Formatter
14
+ attr_reader :command, :usage, :description
15
+
16
+ def initialize(command, hash)
17
+ @command = command
18
+ @usage, @description = *hash.to_a.flatten
19
+ end
20
+
21
+ def usage
22
+ @usage == 'default' ? @command : @usage
23
+ end
24
+
25
+ def format
26
+ description.split("\n").each_with_index do |part, index|
27
+ puts "#{format_usage(index)} # #{part}"
28
+ end
29
+ end
30
+
31
+ def format_usage(index)
32
+ if index.zero?
33
+ usage.ljust(max_usage_length)
34
+ else
35
+ " " * max_usage_length
36
+ end
37
+ end
21
38
 
22
- def max_command_length
23
- Dsl::HelpText.commands.values.map {|v|
24
- v.map {|v| v.keys.to_s.length }.max
25
- }.max
39
+ def max_usage_length
40
+ Dsl::HelpText.max_usage_length
41
+ end
26
42
  end
43
+
27
44
  end
28
45
  end
29
46
  end
@@ -1,24 +1,18 @@
1
- require 'rubygems'
2
- require 'json'
3
-
4
1
  module Relish
5
2
  module Command
6
3
  class Projects < Base
7
-
8
- desc 'list your projects'
9
- command :default => :list
10
-
11
- usage 'projects:list'
4
+
12
5
  desc 'list your projects'
13
- command :list do
14
- response = resource['projects'].get(:accept => :json)
15
- puts format(response)
6
+ command :default do
7
+ puts format(resource['projects'].get(:accept => :json))
16
8
  end
17
9
 
18
10
  usage 'projects:add <org_or_user_handle>/<project_handle>'
19
- desc 'add a project'
11
+ desc ['add a project',
12
+ 'append :private to make the project private',
13
+ 'example: relish projects:add rspec/rspec-core:private'].join("\n")
20
14
  command :add do
21
- puts resource['projects'].post(:handle => @param)
15
+ puts resource['projects'].post(:handle => handle, :private => private?)
22
16
  end
23
17
 
24
18
  usage 'projects:remove <org_or_user_handle>/<project_handle>'
@@ -29,12 +23,19 @@ module Relish
29
23
 
30
24
  private
31
25
  def format(response)
32
- json = JSON.parse(response)
33
- json.map do |hash|
26
+ json_parse(response) do |hash|
34
27
  result = hash['project']['full_handle']
35
28
  result << " (private)" if hash['project']['private']
36
29
  result
37
- end.join("\n")
30
+ end
31
+ end
32
+
33
+ def handle
34
+ @param.remove_option
35
+ end
36
+
37
+ def private?
38
+ @param.extract_option == 'private'
38
39
  end
39
40
 
40
41
  end
@@ -1,9 +1,7 @@
1
- require 'rubygems'
2
1
  require 'zlib'
3
2
  require 'archive/tar/minitar'
4
3
  require 'stringio'
5
4
  require 'rest_client'
6
- require 'relish/commands/help'
7
5
 
8
6
  module Relish
9
7
  module Command
@@ -0,0 +1,15 @@
1
+ module Relish
2
+ module StringExtensions
3
+ def extract_option
4
+ split(':')[1]
5
+ end
6
+
7
+ def remove_option
8
+ split(':')[0]
9
+ end
10
+ end
11
+ end
12
+
13
+ class String
14
+ include Relish::StringExtensions
15
+ end
@@ -1,10 +1,10 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "relish"
3
- s.version = "0.0.9"
3
+ s.version = "0.1.0"
4
4
 
5
5
  s.required_rubygems_version = '>= 1.3.5'
6
6
  s.authors = ["Matt Wynne", "Justin Ko"]
7
- s.date = "2010-09-23"
7
+ s.date = "2010-11-13"
8
8
  s.description = %q{Client gem for http://relishapp.com}
9
9
  s.email = "jko170@gmail.com"
10
10
 
@@ -4,16 +4,8 @@ module Relish
4
4
  module Command
5
5
  describe Config do
6
6
 
7
- describe '#default' do
8
- let(:config) { described_class.new }
9
-
10
- it 'calls #show' do
11
- config.should_receive(:show)
12
- config.default
13
- end
14
- end
15
7
 
16
- describe '#show' do
8
+ describe '#default' do
17
9
  let(:config) { described_class.new }
18
10
 
19
11
  context 'with a local options file' do
@@ -24,14 +16,14 @@ module Relish
24
16
 
25
17
  it 'outputs the contents' do
26
18
  config.should_receive(:puts).with('options')
27
- config.show
19
+ config.default
28
20
  end
29
21
  end
30
22
 
31
23
  context 'without a local options file' do
32
24
  it 'outputs the correct message' do
33
25
  config.should_receive(:puts).with('No .relish file exists')
34
- config.show
26
+ config.default
35
27
  end
36
28
  end
37
29
  end
@@ -5,6 +5,8 @@ module Relish
5
5
  module Dsl
6
6
  describe Command do
7
7
 
8
+ it_should_behave_like 'a Dsl that utilizes ContextClass'
9
+
8
10
  describe '#define' do
9
11
  let(:context_class) { Class.new }
10
12
  let(:command) { described_class.new(context_class) }
@@ -5,6 +5,8 @@ module Relish
5
5
  module Dsl
6
6
  describe Option do
7
7
 
8
+ it_should_behave_like 'a Dsl that utilizes ContextClass'
9
+
8
10
  describe '#define' do
9
11
  let(:context_class) { Class.new }
10
12
  let(:option) { described_class.new(context_class) }
@@ -2,17 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  module Relish
4
4
  module Command
5
- describe Projects do
6
-
7
- describe '#default' do
8
- let(:projects) { described_class.new }
9
-
10
- it 'calls #list' do
11
- projects.should_receive(:list)
12
- projects.default
13
- end
14
- end
15
-
16
- end
5
+
17
6
  end
18
7
  end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe String do
4
+ describe '#extract_option' do
5
+ specify { 'foo:bar'.extract_option.should eq('bar') }
6
+ end
7
+
8
+ describe '#remove_option' do
9
+ specify { 'foo:bar'.remove_option.should eq('foo') }
10
+ end
11
+ end
@@ -4,7 +4,8 @@ Bundler.setup
4
4
 
5
5
  require 'relish/command'
6
6
 
7
+ Dir['./spec/support/*.rb'].map {|f| require f }
8
+
7
9
  RSpec.configure do |config|
8
10
  config.color_enabled = true
9
-
10
11
  end
@@ -0,0 +1,24 @@
1
+ shared_examples_for 'a Dsl that utilizes ContextClass' do
2
+
3
+ describe '#context_class_eval' do
4
+ let(:context_class) { Class.new }
5
+ let(:base) { described_class.new(context_class) }
6
+ let(:the_block) { Proc.new { "Hi, I'm a block" } }
7
+
8
+ it 'calls class_eval on the context_class with the given block' do
9
+ context_class.should_receive(:class_eval).with(&the_block)
10
+ base.context_class_eval(&the_block)
11
+ end
12
+ end
13
+
14
+ describe '#context_class_name' do
15
+ let(:context_class) { Class.new }
16
+ let(:base) { described_class.new(context_class) }
17
+ before { context_class.should_receive(:name).and_return('::Dog') }
18
+
19
+ it 'returns the class name downcased' do
20
+ base.context_class_name.should eq('dog')
21
+ end
22
+ end
23
+
24
+ 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: 13
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 9
10
- version: 0.0.9
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Wynne
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-09-23 00:00:00 -06:00
19
+ date: 2010-11-13 00:00:00 -07:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -189,15 +189,17 @@ files:
189
189
  - lib/relish.rb
190
190
  - lib/relish/command.rb
191
191
  - lib/relish/commands/base.rb
192
+ - lib/relish/commands/collab.rb
192
193
  - lib/relish/commands/config.rb
193
194
  - lib/relish/commands/dsl.rb
194
- - lib/relish/commands/dsl/base.rb
195
195
  - lib/relish/commands/dsl/command.rb
196
+ - lib/relish/commands/dsl/context_class.rb
196
197
  - lib/relish/commands/dsl/help_text.rb
197
198
  - lib/relish/commands/dsl/option.rb
198
199
  - lib/relish/commands/help.rb
199
200
  - lib/relish/commands/projects.rb
200
201
  - lib/relish/commands/push.rb
202
+ - lib/relish/core_ext.rb
201
203
  - lib/relish/helpers.rb
202
204
  - lib/relish/options_file.rb
203
205
  - lib/relish/ui.rb
@@ -205,15 +207,16 @@ files:
205
207
  - spec/relish/command_spec.rb
206
208
  - spec/relish/commands/base_spec.rb
207
209
  - spec/relish/commands/config_spec.rb
208
- - spec/relish/commands/dsl/base_spec.rb
209
210
  - spec/relish/commands/dsl/command_spec.rb
210
211
  - spec/relish/commands/dsl/help_text_spec.rb
211
212
  - spec/relish/commands/dsl/option_spec.rb
212
213
  - spec/relish/commands/projects_spec.rb
213
214
  - spec/relish/commands/push_spec.rb
215
+ - spec/relish/core_ext_spec.rb
214
216
  - spec/relish/options_file_spec.rb
215
217
  - spec/relish_spec.rb
216
218
  - spec/spec_helper.rb
219
+ - spec/support/context_class_examples.rb
217
220
  has_rdoc: true
218
221
  homepage: http://relishapp.com
219
222
  licenses: []
@@ -261,12 +264,13 @@ test_files:
261
264
  - spec/relish/command_spec.rb
262
265
  - spec/relish/commands/base_spec.rb
263
266
  - spec/relish/commands/config_spec.rb
264
- - spec/relish/commands/dsl/base_spec.rb
265
267
  - spec/relish/commands/dsl/command_spec.rb
266
268
  - spec/relish/commands/dsl/help_text_spec.rb
267
269
  - spec/relish/commands/dsl/option_spec.rb
268
270
  - spec/relish/commands/projects_spec.rb
269
271
  - spec/relish/commands/push_spec.rb
272
+ - spec/relish/core_ext_spec.rb
270
273
  - spec/relish/options_file_spec.rb
271
274
  - spec/relish_spec.rb
272
275
  - spec/spec_helper.rb
276
+ - spec/support/context_class_examples.rb
@@ -1,23 +0,0 @@
1
- module Relish
2
- module Command
3
- module Dsl
4
- class Base
5
-
6
- attr_reader :context
7
-
8
- def initialize(context)
9
- @context = context
10
- end
11
-
12
- def context_eval(&block)
13
- context.class_eval(&block)
14
- end
15
-
16
- def context_name
17
- context.name.split('::').last.downcase
18
- end
19
-
20
- end
21
- end
22
- end
23
- end
@@ -1,32 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Relish
4
- module Command
5
- module Dsl
6
- describe Base do
7
-
8
- describe '#context_eval' do
9
- let(:context_class) { Class.new }
10
- let(:base) { described_class.new(context_class) }
11
- let(:the_block) { Proc.new { "Hi, I'm a block" } }
12
-
13
- it 'calls class_eval on the context_class with the given block' do
14
- context_class.should_receive(:class_eval).with(&the_block)
15
- base.context_eval(&the_block)
16
- end
17
- end
18
-
19
- describe '#context_name' do
20
- let(:context_class) { Class.new }
21
- let(:base) { described_class.new(context_class) }
22
- before { context_class.should_receive(:name).and_return('::Dog') }
23
-
24
- it 'returns the class name downcased' do
25
- base.context_name.should eq('dog')
26
- end
27
- end
28
-
29
- end
30
- end
31
- end
32
- end