git-pivotal-tracker-centro 1.0.0.rc1

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.
Files changed (69) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +3 -0
  5. data/CHANGELOG +54 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +82 -0
  8. data/LICENSE +21 -0
  9. data/Rakefile +49 -0
  10. data/VERSION +1 -0
  11. data/bin/git-finish +7 -0
  12. data/bin/git-info +7 -0
  13. data/bin/git-start +8 -0
  14. data/features/finish.feature +88 -0
  15. data/features/info.feature +99 -0
  16. data/features/start.feature +113 -0
  17. data/features/step_definitions/steps.rb +119 -0
  18. data/features/support/dsl/assertions.rb +11 -0
  19. data/features/support/dsl/data.rb +11 -0
  20. data/features/support/dsl/pivotal.rb +77 -0
  21. data/features/support/env.rb +6 -0
  22. data/features/support/git-pivotal.rb +68 -0
  23. data/features/test_repo/origin.git/COMMIT_EDITMSG +1 -0
  24. data/features/test_repo/origin.git/HEAD +1 -0
  25. data/features/test_repo/origin.git/config +8 -0
  26. data/features/test_repo/origin.git/description +1 -0
  27. data/features/test_repo/origin.git/hooks/applypatch-msg.sample +15 -0
  28. data/features/test_repo/origin.git/hooks/commit-msg.sample +24 -0
  29. data/features/test_repo/origin.git/hooks/post-commit.sample +8 -0
  30. data/features/test_repo/origin.git/hooks/post-receive.sample +15 -0
  31. data/features/test_repo/origin.git/hooks/post-update.sample +8 -0
  32. data/features/test_repo/origin.git/hooks/pre-applypatch.sample +14 -0
  33. data/features/test_repo/origin.git/hooks/pre-commit.sample +46 -0
  34. data/features/test_repo/origin.git/hooks/pre-rebase.sample +169 -0
  35. data/features/test_repo/origin.git/hooks/prepare-commit-msg.sample +36 -0
  36. data/features/test_repo/origin.git/hooks/update.sample +128 -0
  37. data/features/test_repo/origin.git/index +0 -0
  38. data/features/test_repo/origin.git/info/exclude +6 -0
  39. data/features/test_repo/origin.git/logs/HEAD +1 -0
  40. data/features/test_repo/origin.git/logs/refs/heads/master +1 -0
  41. data/features/test_repo/origin.git/objects/0c/6f7b1384910d1a2f137590095f008a06c7e00c +0 -0
  42. data/features/test_repo/origin.git/objects/10/ecf2b7ce989f01f3f7266e712b48d9275f2635 +0 -0
  43. data/features/test_repo/origin.git/objects/a5/71d56305df09fb060f6ccb730b46080d305beb +0 -0
  44. data/features/test_repo/origin.git/refs/heads/master +1 -0
  45. data/features/test_repo/readme +1 -0
  46. data/git-pivotal-tracker-centro.gemspec +29 -0
  47. data/lib/commands/base.rb +120 -0
  48. data/lib/commands/bug.rb +19 -0
  49. data/lib/commands/card.rb +32 -0
  50. data/lib/commands/chore.rb +19 -0
  51. data/lib/commands/feature.rb +19 -0
  52. data/lib/commands/finish.rb +67 -0
  53. data/lib/commands/info.rb +58 -0
  54. data/lib/commands/map.rb +10 -0
  55. data/lib/commands/pick.rb +94 -0
  56. data/lib/commands/start.rb +39 -0
  57. data/lib/git-pivotal-tracker.rb +11 -0
  58. data/readme.markdown +106 -0
  59. data/spec/commands/base_spec.rb +137 -0
  60. data/spec/commands/bug_spec.rb +24 -0
  61. data/spec/commands/chore_spec.rb +24 -0
  62. data/spec/commands/feature_spec.rb +24 -0
  63. data/spec/commands/finish_spec.rb +134 -0
  64. data/spec/commands/map_spec.rb +14 -0
  65. data/spec/commands/start_spec.rb +28 -0
  66. data/spec/factories.rb +13 -0
  67. data/spec/factory.rb +26 -0
  68. data/spec/spec_helper.rb +24 -0
  69. metadata +291 -0
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ describe Commands::Base do
4
+
5
+ before(:each) do
6
+ @input = mock('input')
7
+ @output = mock('output')
8
+
9
+ # stub out git config requests
10
+ Commands::Base.any_instance.stubs(:get).with { |v| v =~ /git config/ }.returns("")
11
+ end
12
+
13
+ it "should set the api key with the -k option" do
14
+ @pick = Commands::Base.new("-k", "1234").with(@input, @output)
15
+ @pick.options[:api_token].should == "1234"
16
+ end
17
+
18
+ it "should set the api key with the --api-token= option" do
19
+ @pick = Commands::Base.new("--api-key=1234").with(@input, @output)
20
+ @pick.options[:api_token].should == "1234"
21
+ end
22
+
23
+ it "should set the project id with the -p option" do
24
+ @pick = Commands::Base.new("-p", "1").with(@input, @output)
25
+ @pick.options[:project_id].should == "1"
26
+ end
27
+
28
+ it "should set the project id with the --project-id= option" do
29
+ @pick = Commands::Base.new("--project-id=1").with(@input, @output)
30
+ @pick.options[:project_id].should == "1"
31
+ end
32
+
33
+ it "should set the full name with the -n option" do
34
+ @pick = Commands::Base.new("-n", "Jeff Tucker").with(@input, @output)
35
+ @pick.options[:full_name].should == "Jeff Tucker"
36
+ end
37
+
38
+ it "should set the full name with the --full-name= option" do
39
+ @pick = Commands::Base.new(@input, @output,"--full-name=Jeff Tucker")
40
+ @pick.options[:full_name].should == "Jeff Tucker"
41
+ end
42
+
43
+ it "should set the quiet flag with the -q option" do
44
+ @pick = Commands::Base.new("-q").with(@input, @output)
45
+ @pick.options[:quiet].should be_true
46
+ end
47
+
48
+ it "should set the quiet flag with the --quiet option" do
49
+ @pick = Commands::Base.new("--quiet").with(@input, @output)
50
+ @pick.options[:quiet].should be_true
51
+ end
52
+
53
+ it "should set the force flag with the -f option" do
54
+ @pick = Commands::Base.new("-f").with(@input, @output)
55
+ @pick.options[:force].should be_true
56
+ end
57
+
58
+ it "should set the force flag with the --force option" do
59
+ @pick = Commands::Base.new("--force").with(@input, @output)
60
+ @pick.options[:force].should be_true
61
+ end
62
+
63
+ it "should set the verbose flag with the -v option" do
64
+ @pick = Commands::Base.new("-v").with(@input, @output)
65
+ @pick.options[:verbose].should be_true
66
+ end
67
+
68
+ it "should set the verbose flag with the --verbose option" do
69
+ @pick = Commands::Base.new("--verbose").with(@input, @output)
70
+ @pick.options[:verbose].should be_true
71
+ end
72
+
73
+ it "should unset the verbose flag with the --no-verbose option" do
74
+ @pick = Commands::Base.new("--no-verbose").with(@input, @output)
75
+ @pick.options[:verbose].should be_false
76
+ end
77
+
78
+ it "should respect verbose from git config if it's set true (case insensitive)" do
79
+ Commands::Base.any_instance.stubs(:get).with("git config --get pivotal.verbose").returns("truE")
80
+ @pick = Commands::Base.new
81
+ @pick.options[:verbose].should be_true
82
+ end
83
+
84
+ it "should respect verbose from git config if it's set true (case insensitive)" do
85
+ Commands::Base.any_instance.stubs(:get).with("git config --get pivotal.verbose").returns("falSe")
86
+ @pick = Commands::Base.new
87
+ @pick.options[:verbose].should be_false
88
+ end
89
+
90
+ it "should be verbose by default" do
91
+ Commands::Base.any_instance.stubs(:get).with("git config --get pivotal.verbose").returns("")
92
+ @pick = Commands::Base.new
93
+ @pick.options[:verbose].should be_true
94
+ end
95
+
96
+ it "should print a message if the API token is missing" do
97
+ @output.expects(:print).with("Pivotal Tracker API Token and Project ID are required\n")
98
+
99
+ @pick = Commands::Base.new("-p", "1").with(@input, @output)
100
+ @pick.run!
101
+ end
102
+
103
+ it "should print a message if the project ID is missing" do
104
+ @output.expects(:print).with("Pivotal Tracker API Token and Project ID are required\n")
105
+
106
+ @pick = Commands::Base.new("-k", "1").with(@input, @output)
107
+ @pick.run!
108
+ end
109
+
110
+ it "should set use_ssl to true with --use-ssl" do
111
+ @pick = Commands::Base.new("--use-ssl").with(@input, @output)
112
+ @pick.options[:use_ssl].should be_true
113
+ end
114
+
115
+ it "should set use_ssl to true with -S" do
116
+ @pick = Commands::Base.new("-S").with(@input, @output)
117
+ @pick.options[:use_ssl].should be_true
118
+ end
119
+
120
+ it "should set use_ssl to false by default" do
121
+ @pick = Commands::Base.new("").with(@input, @output)
122
+ @pick.options[:use_ssl].should be_false
123
+ end
124
+
125
+ it "should respect use_ssl from git config if it's set true (case insensitive)" do
126
+ Commands::Base.any_instance.stubs(:get).with("git config --get pivotal.use-ssl").returns("truE")
127
+ @pick = Commands::Base.new
128
+ @pick.options[:use_ssl].should be_true
129
+ end
130
+
131
+ it "should respect use_ssl from git config if it's set to anything but true" do
132
+ Commands::Base.any_instance.stubs(:get).with("git config --get pivotal.use-ssl").returns("not true")
133
+ @pick = Commands::Base.new
134
+ @pick.options[:use_ssl].should be_false
135
+ end
136
+
137
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Commands::Bug do
4
+
5
+ before(:each) do
6
+ # stub out git config requests
7
+ Commands::Bug.any_instance.stubs(:get).with { |v| v =~ /git config/ }.returns("")
8
+
9
+ @bug = Commands::Bug.new
10
+ end
11
+
12
+ it "should specify its story type" do
13
+ @bug.type.should == "bug"
14
+ end
15
+
16
+ it "should specify a plural for its story types" do
17
+ @bug.plural_type.should == "bugs"
18
+ end
19
+
20
+ it "should specify its branch suffix" do
21
+ @bug.branch_suffix.should == "bugfix"
22
+ end
23
+
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Commands::Chore do
4
+
5
+ before(:each) do
6
+ # stub out git config requests
7
+ Commands::Chore.any_instance.stubs(:get).with { |v| v =~ /git config/ }.returns("")
8
+
9
+ @chore = Commands::Chore.new
10
+ end
11
+
12
+ it "should specify its story type" do
13
+ @chore.type.should == "chore"
14
+ end
15
+
16
+ it "should specify a plural for its story types" do
17
+ @chore.plural_type.should == "chores"
18
+ end
19
+
20
+ it "should specify its branch suffix" do
21
+ @chore.branch_suffix.should == "chore"
22
+ end
23
+
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Commands::Feature do
4
+
5
+ before(:each) do
6
+ # stub out git config requests
7
+ Commands::Feature.any_instance.stubs(:get).with { |v| v =~ /git config/ }.returns("")
8
+
9
+ @feature = Commands::Feature.new
10
+ end
11
+
12
+ it "should specify its story type" do
13
+ @feature.type.should == "feature"
14
+ end
15
+
16
+ it "should specify a plural for its story types" do
17
+ @feature.plural_type.should == "features"
18
+ end
19
+
20
+ it "should specify its branch suffix" do
21
+ @feature.branch_suffix.should == "feature"
22
+ end
23
+
24
+ end
@@ -0,0 +1,134 @@
1
+ require 'spec_helper'
2
+
3
+ describe Commands::Finish do
4
+
5
+ def mock_project_id
6
+ @mock_project_id ||= '4321'
7
+ end
8
+
9
+ def mock_projects
10
+ if @mock_projects.nil?
11
+ @mock_projects = mock("mock project")
12
+ @mock_projects.stubs(:stories).returns(mock_stories)
13
+ end
14
+ @mock_projects
15
+ end
16
+
17
+ def mock_stories
18
+ if @mock_stories.nil?
19
+ @mock_stories = mock("mock story list")
20
+ @mock_stories.stubs(:find).with(mock_story_id).returns(mock_story)
21
+ end
22
+ @mock_stories
23
+ end
24
+
25
+ def mock_story_id
26
+ @mock_story_id ||= 1234
27
+ end
28
+
29
+ def mock_story
30
+ if @mock_story.nil?
31
+ @mock_story = mock("mock story")
32
+ end
33
+ @mock_story
34
+ end
35
+
36
+ def branch_name
37
+ "#{mock_story_id}-feature-branch-name"
38
+ end
39
+
40
+ before(:each) do
41
+ # stub out git config requests
42
+ Commands::Finish.any_instance.stubs(:get).with { |v| v =~ /git config/ }.returns("")
43
+
44
+ PivotalTracker::Project.stubs(:find).returns(mock_projects)
45
+
46
+ @finish = Commands::Finish.new(nil, nil, "-p", mock_project_id)
47
+ @finish.stubs(:put)
48
+ @finish.stubs(:get_char).returns('y')
49
+ end
50
+
51
+ context "where the branch name does not contain a valid story id" do
52
+ before(:each) do
53
+ # stub out git status request to identify the branch
54
+ branch_name = "invalid-branch-name-without-story-id"
55
+ Commands::Finish.any_instance.stubs(:get).with { |v| v =~ /git status/ }.returns("# On branch #{branch_name}")
56
+ Commands::Finish.any_instance.stubs(:get).with { |v| v == "git symbolic-ref HEAD" }.returns(branch_name)
57
+ end
58
+
59
+ it "should return an exit status of one" do
60
+ @finish.run!.should == 1
61
+ end
62
+
63
+ it "should print an error message" do
64
+ @finish.expects(:put).with("Branch name must contain a Pivotal Tracker story id").once
65
+ @finish.run!
66
+ end
67
+ end
68
+
69
+ context "where the branch name does contain a valid story id" do
70
+ before(:each) do
71
+ # stub out git status request to identify the branch
72
+ Commands::Finish.any_instance.stubs(:get).with { |v| v =~ /git status/ }.returns("# On branch #{branch_name}")
73
+ Commands::Finish.any_instance.stubs(:get).with { |v| v == "git symbolic-ref HEAD" }.returns(branch_name)
74
+ end
75
+
76
+ it "should exit if the user does not wish to proceed" do
77
+ @finish.stubs(:get_char).returns('n')
78
+ @finish.expects(:sys).never
79
+ @finish.run!
80
+ end
81
+
82
+ it "should checkout the master branch, delete the local branch, and delete the remote branch" do
83
+ @finish.expects(:sys).with() { |value| value == "git checkout master" }
84
+ @finish.expects(:sys).with("git branch -d #{branch_name}").returns(true)
85
+ @finish.expects(:sys).with("git push origin :#{branch_name}")
86
+ mock_story.stubs(:story_type).returns("finished")
87
+ mock_story.stubs(:update)
88
+ @finish.run!
89
+ end
90
+
91
+ it "should attempt to update the story status to the stories finished_state" do
92
+ @finish.stubs(:sys).returns(true)
93
+ mock_story.stubs(:story_type).returns("finished")
94
+ mock_story.expects(:update).with(:current_state => "finished")
95
+ @finish.run!
96
+ end
97
+
98
+ it "should not delete the remote branch and update the story if the local branch could not be deleted" do
99
+ @finish.expects(:sys).with() { |value| value == "git checkout master" }
100
+ @finish.expects(:sys).with("git branch -d #{branch_name}").returns(false)
101
+ @finish.expects(:sys).with("git push origin :#{branch_name}").never
102
+ @finish.run!
103
+ end
104
+
105
+ context "and the story is successfully marked as finished in PT" do
106
+ before(:each) do
107
+ @finish.stubs(:sys).returns(true)
108
+ mock_story.stubs(:story_type).returns("finished")
109
+ mock_story.stubs(:update).with(:current_state => "finished").returns(true)
110
+ end
111
+
112
+ it "should succeed with an exist status of zero" do
113
+ @finish.run!.should == 0
114
+ end
115
+ end
116
+
117
+ context "and the story fails to be marked as finished in PT" do
118
+ before(:each) do
119
+ @finish.stubs(:sys).returns(true)
120
+ mock_story.stubs(:story_type).returns("finished")
121
+ mock_story.stubs(:update).with(:current_state => "finished").returns(false)
122
+ end
123
+
124
+ it "should fail with an exist status of one" do
125
+ @finish.run!.should == 1
126
+ end
127
+
128
+ it "should print an error message" do
129
+ @finish.expects(:put).with("Unable to mark Story #{mock_story_id} as finished").once
130
+ @finish.run!
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Commands::Map do
4
+
5
+ describe "#[]" do
6
+ it "retrieves values when a specific key matches a regular expression" do
7
+ subject[/^\d+$/] = "w00t"
8
+ subject["1234"].should eq("w00t")
9
+ subject["9123423423"].should eq("w00t")
10
+ subject["a9123423423"].should be_nil
11
+ subject["1234f"].should be_nil
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Commands::Start do
4
+
5
+ describe '.for' do
6
+ it "returns the Command::Bug when the first argument is bug" do
7
+ Commands::Start.for("bug").should be_instance_of(Commands::Bug)
8
+ end
9
+
10
+ it "returns the Command::Chore when the first argument is chore" do
11
+ Commands::Start.for("chore").should be_instance_of(Commands::Chore)
12
+ end
13
+
14
+ it "returns the Command::Feature when the first argument is feature" do
15
+ Commands::Start.for("feature").should be_instance_of(Commands::Feature)
16
+ end
17
+
18
+ it "returns the Command::Card when the first argument is a card id" do
19
+ Commands::Start.for("123456").should be_instance_of(Commands::Card)
20
+ end
21
+
22
+ it "raises when the command is unknown card type" do
23
+ Commands::Start.expects(:display_usage_instructions_and_quit)
24
+ Commands::Start.for("unknown")
25
+ end
26
+ end
27
+
28
+ end
data/spec/factories.rb ADDED
@@ -0,0 +1,13 @@
1
+ require File.join(File.dirname(__FILE__), 'factory')
2
+
3
+ Factory.define :story, {
4
+ :id => 1,
5
+ :current_state => :unstarted,
6
+ :story_type => :feature,
7
+ :estimate => 1,
8
+ }
9
+
10
+ Factory.define :project, {
11
+ :id => 1,
12
+ :name => "Project"
13
+ }
data/spec/factory.rb ADDED
@@ -0,0 +1,26 @@
1
+ class Factory
2
+ class << self
3
+ def factories
4
+ @@factories ||= {}
5
+ end
6
+
7
+ def define(type, attributes)
8
+ factories[type] = attributes
9
+ end
10
+ end
11
+ end
12
+
13
+
14
+ def Factory(type, attrs = {})
15
+ defaults = Factory.factories[type]
16
+ attrs = defaults.merge(attrs)
17
+
18
+ markup = Builder::XmlMarkup.new
19
+ markup.__send__(type) do
20
+ attrs.each do |attribute, value|
21
+ markup.__send__(attribute, value.to_s)
22
+ end
23
+ end
24
+
25
+ markup.target!
26
+ end
@@ -0,0 +1,24 @@
1
+ require 'mocha'
2
+ require 'builder'
3
+
4
+ # This file was generated by the `rspec --init` command. Conventionally, all
5
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
6
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
7
+ # loaded once.
8
+ #
9
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
10
+ RSpec.configure do |config|
11
+ config.mock_with :mocha
12
+ config.treat_symbols_as_metadata_keys_with_true_values = true
13
+ config.run_all_when_everything_filtered = true
14
+ config.filter_run :focus
15
+ end
16
+
17
+ specdir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
18
+ require File.join(specdir, 'lib','git-pivotal-tracker')
19
+
20
+ require File.join(File.dirname(__FILE__), 'factories')
21
+
22
+ def stub_connection_to_pivotal
23
+ RestClient::Resource.any_instance.stubs(:get).returns("")
24
+ end