git_workflow 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/README.markdown +77 -0
  2. data/Rakefile +33 -0
  3. data/bin/git-finish +4 -0
  4. data/bin/git-start +4 -0
  5. data/bin/git-workflow-setup +4 -0
  6. data/features/core_functionality/4049578_need_the_ability_to_start_a_new_branch.feature +15 -0
  7. data/features/core_functionality/4049611_need_the_ability_to_finish_a_specified_branch.feature +17 -0
  8. data/features/core_functionality/4056359_start_with_local_branch_already_present.feature +16 -0
  9. data/features/core_functionality/4056363_finish_the_current_branch.feature +17 -0
  10. data/features/core_functionality/4056389_changes_to_pt_story_name_cause_branch_issues.feature +25 -0
  11. data/features/core_functionality/4135658_control_output_verbosity_using_v_switch.feature +32 -0
  12. data/features/core_functionality/4468313_get_config_value_for_is_producing_an_error_log.feature +43 -0
  13. data/features/extensions/4058326_display_story_description_on_start.feature +14 -0
  14. data/features/git_branching/4135501_allow_branch_start_point_to_be_specified_from_command_line.feature +27 -0
  15. data/features/hooks/4069174_investigate_the_effort_required_to_add_pre_amp_post_hooks.feature +24 -0
  16. data/features/hooks/4199841_need_hooks_for_my_workflow.feature +51 -0
  17. data/features/hooks/4199845_need_hooks_for_sanger_workflow.feature +66 -0
  18. data/features/hooks/4205913_output_from_rake_tests_should_be_seen.feature +19 -0
  19. data/features/hooks/4424828_git_start_is_missing_pt_integration_for_my_hooks.feature +15 -0
  20. data/features/pivotal_tracker_api/4133291_chores_go_straight_to_accepted_not_to_finished.feature +15 -0
  21. data/features/release/4132264_fix_the_libxml_warnings_from_nokogiri.feature +20 -0
  22. data/features/step_definitions/aruba_extensions.rb +4 -0
  23. data/features/step_definitions/configuration_steps.rb +38 -0
  24. data/features/step_definitions/git_steps.rb +102 -0
  25. data/features/step_definitions/misc_steps.rb +3 -0
  26. data/features/step_definitions/pivotal_tracker_steps.rb +43 -0
  27. data/features/step_definitions/project_code_steps.rb +35 -0
  28. data/features/support/aruba.rb +1 -0
  29. data/features/support/hooks/configuration.rb +4 -0
  30. data/features/support/hooks/environment.rb +49 -0
  31. data/features/support/hooks/pivotal_tracker.rb +170 -0
  32. data/lib/git_workflow.rb +5 -0
  33. data/lib/git_workflow/callbacks.rb +16 -0
  34. data/lib/git_workflow/callbacks/pivotal_tracker_support.rb +64 -0
  35. data/lib/git_workflow/callbacks/remote_git_branch_support.rb +9 -0
  36. data/lib/git_workflow/callbacks/styles/debug.rb +58 -0
  37. data/lib/git_workflow/callbacks/styles/default.rb +43 -0
  38. data/lib/git_workflow/callbacks/styles/mine.rb +52 -0
  39. data/lib/git_workflow/callbacks/styles/sanger.rb +48 -0
  40. data/lib/git_workflow/callbacks/test_code_support.rb +29 -0
  41. data/lib/git_workflow/command_line.rb +46 -0
  42. data/lib/git_workflow/commands.rb +4 -0
  43. data/lib/git_workflow/commands/base.rb +31 -0
  44. data/lib/git_workflow/commands/finish.rb +36 -0
  45. data/lib/git_workflow/commands/setup.rb +157 -0
  46. data/lib/git_workflow/commands/start.rb +30 -0
  47. data/lib/git_workflow/configuration.rb +93 -0
  48. data/lib/git_workflow/core_ext.rb +106 -0
  49. data/lib/git_workflow/git.rb +143 -0
  50. data/lib/git_workflow/logger.yaml +27 -0
  51. data/lib/git_workflow/logging.rb +77 -0
  52. data/lib/git_workflow/story.rb +96 -0
  53. data/spec/core_functionality/4056539_support_http_proxy_spec.rb +68 -0
  54. data/spec/core_functionality/4058365_bad_request_on_story_update_spec.rb +13 -0
  55. data/spec/core_functionality/4058394_make_commands_more_verbose_spec.rb +41 -0
  56. data/spec/core_functionality/4058719_error_if_none_of_the_required_configuration_values_are_set_spec.rb +21 -0
  57. data/spec/core_functionality/4058861_git_config_returns_empty_strings_which_should_be_nil_spec.rb +59 -0
  58. data/spec/core_functionality/4172431_add_git_workflow_setup_command_to_make_setup_easier_spec.rb +148 -0
  59. data/spec/core_functionality/4199841_need_callbacks_for_my_workflow_spec.rb +97 -0
  60. data/spec/extensions/4199841_need_callbacks_for_my_workflow_spec.rb +167 -0
  61. data/spec/extensions/4205913_output_from_rake_tests_should_be_seen_spec.rb +34 -0
  62. data/spec/git_branching/4058723_branches_end_in_if_the_last_character_is_invalid_spec.rb +40 -0
  63. data/spec/git_branching/4059824_code_is_not_using_workflow_localbranchconvention_to_decode_branch_names_on_finish_spec.rb +115 -0
  64. data/spec/git_branching/4216087_support_pushing_branches_spec.rb +44 -0
  65. data/spec/hooks/4199845_need_hooks_for_sanger_workflow_spec.rb +27 -0
  66. data/spec/pivotal_tracker_api/4056381_pt_api_token_not_being_passed_in_headers_spec.rb +40 -0
  67. data/spec/pivotal_tracker_api/4056638_library_code_using_localhost_spec.rb +16 -0
  68. data/spec/pivotal_tracker_api/4056661_content_type_header_should_be_text_xml_on_updates_spec.rb +16 -0
  69. data/spec/pivotal_tracker_api/4058718_if_pt_username_is_not_set_use_user_name_spec.rb +26 -0
  70. data/spec/pivotal_tracker_api/4146016_decode_the_xml_encoded_text_of_description_and_name_spec.rb +63 -0
  71. data/spec/shared_examples/configuration.rb +10 -0
  72. data/spec/shared_examples/story.rb +17 -0
  73. data/spec/spec_helper.rb +18 -0
  74. metadata +220 -0
@@ -0,0 +1,27 @@
1
+ log4r_config:
2
+ # Here we define all of the loggers that are going to be used across all of the
3
+ # possible configurations.
4
+ loggers:
5
+ - name: Console
6
+ level: DEBUG
7
+ outputters:
8
+ - normal_information
9
+ - verbose_information
10
+
11
+ # And here are the outputters and with their associated formatters.
12
+ outputters:
13
+ - name: normal_information
14
+ type: StdoutOutputter
15
+ only_at:
16
+ - INFO
17
+ - FATAL
18
+ formatter:
19
+ type: PatternFormatter
20
+ pattern: '%l: %m'
21
+
22
+ - name: verbose_information
23
+ type: StderrOutputter
24
+ level: FATAL
25
+ formatter:
26
+ type: PatternFormatter
27
+ pattern: '%l: %m'
@@ -0,0 +1,77 @@
1
+ require 'log4r'
2
+ require 'log4r/yamlconfigurator'
3
+
4
+ module Log4r
5
+ class Outputter
6
+ def initialize_with_multiple_levels(name, hash = {})
7
+ initialize_without_multiple_levels(name, hash)
8
+ self.only_at(*hash[ :only_at ]) if hash.key?(:only_at)
9
+ end
10
+ alias_method_chain(:initialize, :multiple_levels)
11
+ end
12
+ end
13
+
14
+ module GitWorkflow
15
+ module Logging
16
+ # Causes the loading of the logging information before anything else is done.
17
+ Log4r::YamlConfigurator.load_yaml_file(File.expand_path(File.join(File.dirname(__FILE__), 'logger.yaml')))
18
+
19
+ def self.included(base)
20
+ base.instance_eval do
21
+ extend ClassMethods
22
+
23
+ [ :debug, :info, :error ].each do |level|
24
+ class_eval <<-END_OF_LOGGING_METHOD
25
+ def #{ level }(message, &block)
26
+ self.class.#{ level }(message, &block)
27
+ end
28
+
29
+ def self.#{ level }(message, &block)
30
+ self.log(#{ level.inspect }, message, &block)
31
+ end
32
+ END_OF_LOGGING_METHOD
33
+ end
34
+ end
35
+ end
36
+
37
+ class << self
38
+ def logger=(logger)
39
+ @logger = logger
40
+ end
41
+
42
+ def logger
43
+ @logger ||= default_logger
44
+ end
45
+
46
+ def default_logger
47
+ Log4r::Logger['Console']
48
+ end
49
+ end
50
+
51
+ module ClassMethods
52
+ def logger=(logger)
53
+ @logger = logger
54
+ end
55
+
56
+ def logger
57
+ @logger || GitWorkflow::Logging.logger
58
+ end
59
+
60
+ def log(level, message, &block)
61
+ if block_given?
62
+ begin
63
+ logger.send(level, "(start): #{ message }")
64
+ rc = yield
65
+ logger.send(level, "(finish): #{ message }")
66
+ rc
67
+ rescue => exception
68
+ logger.error("#{ message } (#{ exception.message })")
69
+ raise
70
+ end
71
+ else
72
+ logger.send(level, message)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,96 @@
1
+ require 'rest_client'
2
+ require 'builder'
3
+
4
+ # On MacOSX systems you can have a dodgy LibXML2 which Nokogiri warns about. Hide this warning
5
+ # by setting the following constant:
6
+ I_KNOW_I_AM_USING_AN_OLD_AND_BUGGY_VERSION_OF_LIBXML2 = true
7
+ require 'nokogiri'
8
+
9
+ module GitWorkflow
10
+ class Story
11
+ include Logging
12
+
13
+ attr_reader :story_id
14
+ attr_reader :name
15
+ attr_reader :description
16
+
17
+ def initialize(service)
18
+ @service = service
19
+ load_story!
20
+ end
21
+
22
+ def branch_name
23
+ @local_branch_name ||= GitWorkflow::Configuration.instance.local_branch_convention.to(self)
24
+ end
25
+
26
+ def remote_branch_name
27
+ @remote_branch_name ||= GitWorkflow::Configuration.instance.remote_branch_convention.to(self)
28
+ end
29
+
30
+ def start_state
31
+ 'started'
32
+ end
33
+
34
+ def finish_state
35
+ @story_type == 'chore' ? 'accepted' : 'finished'
36
+ end
37
+
38
+ def comment(message)
39
+ _service!(:post, 'notes') do |xml|
40
+ xml.note {
41
+ xml.text(message)
42
+ }
43
+ end
44
+ end
45
+
46
+ def service!(&block)
47
+ _service!(:put) do |xml|
48
+ xml.story {
49
+ xml.owned_by(GitWorkflow::Configuration.instance.username)
50
+ yield(xml) if block_given?
51
+ }
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def _service!(action, subresource = nil, &block)
58
+ xml = Builder::XmlMarkup.new
59
+ yield(xml)
60
+ service = @service
61
+ service = service[subresource] unless subresource.nil?
62
+ service.send(action, xml.target!, :content_type => 'application/xml')
63
+ rescue RestClient::ExceptionWithResponse => exception
64
+ error('Cannot seem to perform operation with PT:')
65
+ error(exception.response)
66
+ raise
67
+ end
68
+
69
+ class XmlWrapper
70
+ def initialize(xml)
71
+ @xml = Nokogiri::XML(xml)
72
+ end
73
+
74
+ def required!(element)
75
+ value = optional(element)
76
+ raise MissingElement, "Missing '#{ element }' in the PT XML" if value.blank?
77
+ value
78
+ end
79
+
80
+ def optional(element)
81
+ values = @xml.xpath("/story/#{ element }/text()")
82
+ values.empty? ? nil : values.first.content
83
+ end
84
+ end
85
+
86
+ def load_story!
87
+ info("Retrieving story information") do
88
+ xml = XmlWrapper.new(@service.get)
89
+ @story_id = xml.required!(:id).to_i
90
+ @story_type = xml.required!(:story_type)
91
+ @name = xml.required!(:name)
92
+ @description = xml.optional(:description)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ require 'git_workflow/callbacks/pivotal_tracker_support'
3
+
4
+ describe GitWorkflow::Callbacks::PivotalTrackerSupport::ClassMethods do
5
+ before(:each) do
6
+ @command = Object.new
7
+ @command.stub!(:debug).with(any_args)
8
+ @command.extend(GitWorkflow::Callbacks::PivotalTrackerSupport::ClassMethods)
9
+ end
10
+
11
+ describe '.value_of_environment_variable' do
12
+ before(:each) do
13
+ ENV['somevariable'] = 'this is the value'
14
+ end
15
+
16
+ after(:each) do
17
+ ENV['somevariable'] = nil
18
+ end
19
+
20
+ it 'returns the value of the environment variable' do
21
+ @command.value_of_environment_variable('somevariable').should == 'this is the value'
22
+ end
23
+ end
24
+
25
+ describe '.enable_http_proxy_if_present' do
26
+ after(:each) do
27
+ @command.enable_http_proxy_if_present
28
+ end
29
+
30
+ it 'uses the $http_proxy environment variable first' do
31
+ @command.stub!(:value_of_environment_variable).with('http_proxy').and_return('http_proxy value')
32
+ RestClient.should_receive(:proxy=).with('http_proxy value')
33
+ end
34
+
35
+ it 'falls back to $HTTP_PROXY' do
36
+ @command.stub!(:value_of_environment_variable).with('http_proxy').and_return(nil)
37
+ @command.stub!(:value_of_environment_variable).with('HTTP_PROXY').and_return('HTTP_PROXY value')
38
+ RestClient.should_receive(:proxy=).with('HTTP_PROXY value')
39
+ end
40
+
41
+ it 'does not set the HTTP proxy if neither is set' do
42
+ @command.stub!(:value_of_environment_variable).with('http_proxy').and_return(nil)
43
+ @command.stub!(:value_of_environment_variable).with('HTTP_PROXY').and_return(nil)
44
+ RestClient.should_receive(:proxy=).with(anything).never
45
+ end
46
+ end
47
+ end
48
+
49
+ describe GitWorkflow::Callbacks::PivotalTrackerSupport do
50
+ before(:each) do
51
+ @command = Class.new.new
52
+ @command.stub!(:debug).with(any_args)
53
+ @command.extend(GitWorkflow::Callbacks::PivotalTrackerSupport)
54
+ end
55
+
56
+ describe '#pivotal_tracker_service' do
57
+ it_should_behave_like 'it needs configuration'
58
+
59
+ it 'enables the HTTP proxy' do
60
+ @command.class.instance_eval do
61
+ should_receive(:enable_http_proxy_if_present).once
62
+ should_receive(:pivotal_tracker_url_for).with('project_id', 'story_id').and_return('url')
63
+ end
64
+ RestClient::Resource.stub!(:new).with(any_args).and_return(:ok)
65
+ @command.pivotal_tracker_service_for('story_id')
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitWorkflow do
4
+ it_should_behave_like 'it needs configuration'
5
+ it_should_behave_like 'it needs a working Story'
6
+
7
+ describe '#service!' do
8
+ it 'generates valid XML' do
9
+ @service.should_receive(:put).with('<story><owned_by>username</owned_by></story>', anything)
10
+ @story.service!
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitWorkflow::Logging::ClassMethods do
4
+ before(:each) do
5
+ @object = Class.new(Object).new
6
+ @object.class.send(:include, GitWorkflow::Logging::ClassMethods)
7
+
8
+ @logger = mock('Logger')
9
+ @object.logger = @logger
10
+ end
11
+
12
+ describe '#log' do
13
+ it 'displays just the message and the level if no block given' do
14
+ @logger.should_receive(:debug).with('my message')
15
+ @object.log(:debug, 'my message')
16
+ end
17
+
18
+ it 'displays messages around the given block' do
19
+ @logger.should_receive(:debug).with('(start): my message').once
20
+ @logger.should_receive(:debug).with('(finish): my message').once
21
+
22
+ callback = mock('callback')
23
+ callback.should_receive(:called).and_return(:ok)
24
+
25
+ @object.log(:debug, 'my message') do
26
+ callback.called
27
+ end.should == :ok
28
+ end
29
+
30
+ it 'displays errors when block raises' do
31
+ @logger.should_receive(:debug).with('(start): my message').once
32
+ @logger.should_receive(:error).with('my message (Broken)').once
33
+
34
+ lambda do
35
+ @object.log(:debug, 'my message') do
36
+ raise StandardError, 'Broken'
37
+ end
38
+ end.should raise_error(StandardError)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitWorkflow::Git do
4
+ before(:each) do
5
+ @git, @repository = Class.new, mock('Repository')
6
+ @git.send(:extend, GitWorkflow::Git)
7
+ @git.stub(:repository).and_return(@repository)
8
+ end
9
+
10
+ describe '.get_config_value_for!' do
11
+ it 'returns the value if set' do
12
+ @git.should_receive(:get_config_value_for).with('key').and_return('value')
13
+ @git.get_config_value_for!('key').should == 'value'
14
+ end
15
+
16
+ it 'raises an exception if the value is not set' do
17
+ @git.should_receive(:get_config_value_for).with('key').and_return(nil)
18
+ lambda { @git.get_config_value_for!('key') }.should raise_error(StandardError)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ class GitWorkflow::Git::Repository
4
+ def self.for_testing
5
+ new
6
+ end
7
+ end
8
+
9
+ describe GitWorkflow::Git::Repository do
10
+ before(:each) do
11
+ @repository = described_class.for_testing
12
+ end
13
+
14
+ describe '#config_get' do
15
+ it 'raises ConfigError on command failure' do
16
+ @repository.should_receive(:execute_command).with(anything).and_raise(Execution::CommandFailure.new('command', :failure))
17
+ lambda { @repository.config_get('key') }.should raise_error(GitWorkflow::Git::Repository::ConfigError)
18
+ end
19
+
20
+ context 'when command succeeds' do
21
+ after(:each) do
22
+ @repository.should_receive(:execute_command).with('git config key').and_return(@value)
23
+ @repository.config_get('key').should == @expected
24
+ end
25
+
26
+ it 'returns the value that is set' do
27
+ @value = @expected = 'value'
28
+ end
29
+
30
+ it 'strips whitespace from the value' do
31
+ @value, @expected = ' value ', 'value'
32
+ end
33
+
34
+ it 'returns nil if value is empty' do
35
+ @value, @expected = '', nil
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ describe GitWorkflow::Git do
42
+ before(:each) do
43
+ @git, @repository = Class.new, mock('Repository')
44
+ @git.send(:extend, GitWorkflow::Git)
45
+ @git.stub(:repository).and_return(@repository)
46
+ end
47
+
48
+ describe '#get_config_value_for' do
49
+ it 'returns whatever is set' do
50
+ @repository.should_receive(:config_get).with('key').and_return(:ok)
51
+ @git.get_config_value_for('key').should == :ok
52
+ end
53
+
54
+ it 'returns nil for failure' do
55
+ @repository.should_receive(:config_get).with('key').and_raise(GitWorkflow::Git::Repository::ConfigError)
56
+ @git.get_config_value_for('key').should == nil
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ class GitWorkflow::Commands::Setup
4
+ public :set_value_through
5
+ public :ask
6
+ public :choose
7
+
8
+ public :enquire_about_name
9
+ public :enquire_about_token
10
+ public :enquire_about_project_id
11
+ public :enquire_about_workflow
12
+ public :enquire_about_branches
13
+ public :choose_branch_convention
14
+
15
+ public :get_config_value_for
16
+ public :set_config_value
17
+ end
18
+
19
+ describe GitWorkflow::Commands::Setup do
20
+ before(:each) do
21
+ @command, @highline = described_class.new([]), mock('HighLine')
22
+ @command.stub(:highline).and_return(@highline)
23
+
24
+ @question = mock('Question')
25
+ @question.stub(:question=).with(anything)
26
+ end
27
+
28
+ describe '#execute' do
29
+ it 'asks the right questions' do
30
+ [ :name, :token, :project_id, :workflow, :branches ].each do |query|
31
+ @command.should_receive(:"enquire_about_#{ query }").ordered
32
+ end
33
+ @command.execute
34
+ end
35
+ end
36
+
37
+ describe '#ask' do
38
+ it 'calls through to set the value' do
39
+ callback = mock('callback')
40
+ callback.should_receive(:called)
41
+
42
+ @command.should_receive(:set_value_through).with(:ask, :setting, 'Dummy', :options).and_yield
43
+ @command.ask(:setting, :options) { callback.called }
44
+ end
45
+ end
46
+
47
+ describe '#choose' do
48
+ it 'calls through to set the value' do
49
+ callback = mock('callback')
50
+ callback.should_receive(:called)
51
+
52
+ @command.should_receive(:set_value_through).with(:choose, :setting, :options).and_yield
53
+ @command.choose(:setting, :options) { callback.called }
54
+ end
55
+ end
56
+
57
+ describe '#set_value_through' do
58
+ before(:each) do
59
+ @question.should_receive(:default=).with(:default)
60
+
61
+ @callback = mock('callback')
62
+ @callback.should_receive(:called).with(@question)
63
+
64
+ @command.should_receive(:get_config_value_for).with(:setting).and_return(:default)
65
+ end
66
+
67
+ it 'unspecified answer type sets value' do
68
+ @highline.should_receive(:question_user).with(:arg1, :arg2).and_yield(@question).and_return(:ok)
69
+ @command.should_receive(:set_config_value).with(:setting, :ok)
70
+ @command.set_value_through(:question_user, :setting, :arg1, :arg2) { |question| @callback.called(question) }
71
+ end
72
+
73
+ context 'when answer is optional' do
74
+ after(:each) do
75
+ @command.set_value_through(:question_user, :setting, :arg1, :arg2, :optional => true) { |question| @callback.called(question) }
76
+ end
77
+
78
+ it 'does not set the value if answer is blank' do
79
+ @highline.should_receive(:question_user).with(:arg1, :arg2).and_yield(@question).and_return('')
80
+ end
81
+
82
+ it 'sets the value if answer is non-blank' do
83
+ @highline.should_receive(:question_user).with(:arg1, :arg2).and_yield(@question).and_return('OK')
84
+ @command.should_receive(:set_config_value).with(:setting, 'OK')
85
+ end
86
+ end
87
+ end
88
+
89
+ describe '#enquire_about_name' do
90
+ it 'optionally prompts for the user.name' do
91
+ @command.should_receive(:get_config_value_for).with('user.name').and_return('John Smith')
92
+ @command.should_receive(:ask).with('pt.username', hash_including(:optional => true))
93
+ @command.enquire_about_name
94
+ end
95
+ end
96
+
97
+ describe '#enquire_about_token' do
98
+ it 'prompts for the pt.token' do
99
+ @question.should_receive(:validate=).with(/^[A-Fa-f0-9]{32}$/)
100
+
101
+ @command.should_receive(:ask).with('pt.token').and_yield(@question)
102
+ @command.enquire_about_token
103
+ end
104
+ end
105
+
106
+ describe '#enquire_about_project_id' do
107
+ it 'prompts for the pt.projectid numeric' do
108
+ @question.should_receive(:answer_type=).with(Integer)
109
+
110
+ @command.should_receive(:ask).with('pt.projectid').and_yield(@question)
111
+ @command.enquire_about_project_id
112
+ end
113
+ end
114
+
115
+ describe '#enquire_about_workflow' do
116
+ it 'prompts for the workflow.callbacks value' do
117
+ @command.should_receive(:ask).with('workflow.callbacks')
118
+ @command.enquire_about_workflow
119
+ end
120
+ end
121
+
122
+ describe '#enquire_about_branches' do
123
+ it 'prompts for branch conventions' do
124
+ @command.should_receive(:choose_branch_convention).with(:local)
125
+ @command.should_receive(:choose_branch_convention).with(:remote)
126
+
127
+ @command.enquire_about_branches
128
+ end
129
+ end
130
+
131
+ describe '#choose_branch_convention' do
132
+ it 'works with the correct setting' do
133
+ @command.should_receive(:choose).with('workflow.foobarbranchconvention')
134
+ @command.choose_branch_convention(:foobar)
135
+ end
136
+
137
+ it 'sets up the menu correctly' do
138
+ menu = mock('menu')
139
+ menu.stub(:header=).with(anything)
140
+ menu.should_receive(:prompt=).with(/\bfoobar\b/)
141
+ menu.should_receive(:menu_option).with(/number\b.+title/, '${number}_${name}')
142
+ menu.should_receive(:menu_option).with(/title\b.+number/, '${name}_${number}')
143
+ @command.should_receive(:choose).with(anything).and_yield(menu)
144
+
145
+ @command.choose_branch_convention(:foobar)
146
+ end
147
+ end
148
+ end