git-pivotal 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.
- data/.gitignore +2 -0
- data/LICENSE +21 -0
- data/Rakefile +32 -0
- data/VERSION +1 -0
- data/bin/git-pick +8 -0
- data/git-pivotal.gemspec +80 -0
- data/lib/commands/pick.rb +116 -0
- data/lib/pivotal/api.rb +17 -0
- data/lib/pivotal/associations.rb +17 -0
- data/lib/pivotal/base.rb +37 -0
- data/lib/pivotal/collection.rb +63 -0
- data/lib/pivotal/project.rb +7 -0
- data/lib/pivotal/story.rb +9 -0
- data/lib/pivotal.rb +7 -0
- data/readme.markdown +33 -0
- data/spec/commands/pick_spec.rb +7 -0
- data/spec/pivotal/api_spec.rb +18 -0
- data/spec/pivotal/associations_spec.rb +13 -0
- data/spec/pivotal/base_spec.rb +36 -0
- data/spec/pivotal/collection_spec.rb +22 -0
- data/spec/pivotal/project_spec.rb +19 -0
- data/spec/pivotal/story_spec.rb +15 -0
- data/spec/spec_helper.rb +24 -0
- metadata +113 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2010 Jeff Tucker
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'spec/rake/spectask'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift('lib')
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |gemspec|
|
10
|
+
gemspec.name = "git-pivotal"
|
11
|
+
gemspec.summary = "A collection of git utilities to ease integration with Pivotal Tracker"
|
12
|
+
gemspec.description = "A collection of git utilities to ease integration with Pivotal Tracker"
|
13
|
+
gemspec.email = "jeff@trydionel.com"
|
14
|
+
gemspec.homepage = "http://github.com/trydionel/git-pivotal"
|
15
|
+
gemspec.authors = ["Jeff Tucker"]
|
16
|
+
|
17
|
+
gemspec.executables = ["git-pick"]
|
18
|
+
|
19
|
+
gemspec.add_dependency "nokogiri"
|
20
|
+
gemspec.add_dependency "rest-client"
|
21
|
+
|
22
|
+
gemspec.add_development_dependency "rspec"
|
23
|
+
end
|
24
|
+
|
25
|
+
Jeweler::GemcutterTasks.new
|
26
|
+
rescue
|
27
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
28
|
+
end
|
29
|
+
|
30
|
+
Spec::Rake::SpecTask.new do |t|
|
31
|
+
t.warning = true
|
32
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/bin/git-pick
ADDED
data/git-pivotal.gemspec
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{git-pivotal}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Jeff Tucker"]
|
12
|
+
s.date = %q{2010-01-27}
|
13
|
+
s.default_executable = %q{git-pick}
|
14
|
+
s.description = %q{A collection of git utilities to ease integration with Pivotal Tracker}
|
15
|
+
s.email = %q{jeff@trydionel.com}
|
16
|
+
s.executables = ["git-pick"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"bin/git-pick",
|
26
|
+
"git-pivotal.gemspec",
|
27
|
+
"lib/commands/pick.rb",
|
28
|
+
"lib/pivotal.rb",
|
29
|
+
"lib/pivotal/api.rb",
|
30
|
+
"lib/pivotal/associations.rb",
|
31
|
+
"lib/pivotal/base.rb",
|
32
|
+
"lib/pivotal/collection.rb",
|
33
|
+
"lib/pivotal/project.rb",
|
34
|
+
"lib/pivotal/story.rb",
|
35
|
+
"readme.markdown",
|
36
|
+
"spec/commands/pick_spec.rb",
|
37
|
+
"spec/pivotal/api_spec.rb",
|
38
|
+
"spec/pivotal/associations_spec.rb",
|
39
|
+
"spec/pivotal/base_spec.rb",
|
40
|
+
"spec/pivotal/collection_spec.rb",
|
41
|
+
"spec/pivotal/project_spec.rb",
|
42
|
+
"spec/pivotal/story_spec.rb",
|
43
|
+
"spec/spec_helper.rb"
|
44
|
+
]
|
45
|
+
s.homepage = %q{http://github.com/trydionel/git-pivotal}
|
46
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
47
|
+
s.require_paths = ["lib"]
|
48
|
+
s.rubygems_version = %q{1.3.5}
|
49
|
+
s.summary = %q{A collection of git utilities to ease integration with Pivotal Tracker}
|
50
|
+
s.test_files = [
|
51
|
+
"spec/commands/pick_spec.rb",
|
52
|
+
"spec/pivotal/api_spec.rb",
|
53
|
+
"spec/pivotal/associations_spec.rb",
|
54
|
+
"spec/pivotal/base_spec.rb",
|
55
|
+
"spec/pivotal/collection_spec.rb",
|
56
|
+
"spec/pivotal/project_spec.rb",
|
57
|
+
"spec/pivotal/story_spec.rb",
|
58
|
+
"spec/spec_helper.rb"
|
59
|
+
]
|
60
|
+
|
61
|
+
if s.respond_to? :specification_version then
|
62
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
63
|
+
s.specification_version = 3
|
64
|
+
|
65
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
66
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
67
|
+
s.add_runtime_dependency(%q<rest-client>, [">= 0"])
|
68
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
69
|
+
else
|
70
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
71
|
+
s.add_dependency(%q<rest-client>, [">= 0"])
|
72
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
73
|
+
end
|
74
|
+
else
|
75
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
76
|
+
s.add_dependency(%q<rest-client>, [">= 0"])
|
77
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
class Pick
|
4
|
+
|
5
|
+
attr_accessor :api
|
6
|
+
|
7
|
+
def initialize(*args)
|
8
|
+
@options = {}
|
9
|
+
parse_gitconfig
|
10
|
+
parse_argv(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
connect_to_pivotal
|
15
|
+
|
16
|
+
story = find_story
|
17
|
+
build_feature_branch story
|
18
|
+
start_story story
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def sys(cmd)
|
24
|
+
puts cmd if @options[:verbose]
|
25
|
+
system cmd
|
26
|
+
end
|
27
|
+
|
28
|
+
def get(cmd)
|
29
|
+
puts cmd if @options[:verbose]
|
30
|
+
`#{cmd}`
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_gitconfig
|
34
|
+
token = get("git config --get pivotal.api-token").strip
|
35
|
+
id = get("git config --get pivotal.project-id").strip
|
36
|
+
|
37
|
+
@options[:api_token] = token if token
|
38
|
+
@options[:project_id] = id if id
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_argv(*args)
|
42
|
+
OptionParser.new do |opts|
|
43
|
+
opts.banner = "Usage: git pick [options]"
|
44
|
+
opts.on("-k", "--api-key=", "Pivotal Tracker API key") { |k| @options[:api_token] = k }
|
45
|
+
opts.on("-p", "--project-id=", "Pivotal Trakcer project id") { |p| @options[:project_id] = p }
|
46
|
+
opts.on("-q", "--quiet", "Quiet, no-interaction mode") { |q| @options[:quiet] = q }
|
47
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") { |v| @options[:verbose] = v }
|
48
|
+
opts.on_tail("-h", "--help", "This usage guide") { puts opts; exit 0 }
|
49
|
+
end.parse!(args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def connect_to_pivotal
|
53
|
+
unless @options[:api_token] && @options[:project_id]
|
54
|
+
puts "Pivotal Tracker API Token and Project ID are required"
|
55
|
+
exit 0
|
56
|
+
end
|
57
|
+
|
58
|
+
puts "Retrieving latest stories from Pivotal Tracker..."
|
59
|
+
@api = Pivotal::Api.new(:api_token => @options[:api_token])
|
60
|
+
end
|
61
|
+
|
62
|
+
def agrees?(selection)
|
63
|
+
selection =~ /y/i || selection == ""
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_story
|
67
|
+
project = @api.projects.find(:id => @options[:project_id])
|
68
|
+
story = project.stories.find(:conditions => { :story_type => :feature, :current_state => :unstarted }, :limit => 1).first
|
69
|
+
|
70
|
+
unless story
|
71
|
+
puts "No stories available!"
|
72
|
+
exit 0
|
73
|
+
end
|
74
|
+
|
75
|
+
puts "Story: #{story.name}"
|
76
|
+
puts "URL: #{story.url}"
|
77
|
+
print "Accept this story? (Yn): "
|
78
|
+
selection = gets.chomp
|
79
|
+
|
80
|
+
exit 0 if !agrees?(selection)
|
81
|
+
|
82
|
+
story
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_branch(branch)
|
86
|
+
unless branch_exists?(branch)
|
87
|
+
puts "Creating #{branch} branch..."
|
88
|
+
sys "git checkout -b #{branch}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def branch_exists?(branch)
|
93
|
+
!get("git branch").match(branch).nil?
|
94
|
+
end
|
95
|
+
|
96
|
+
def build_feature_branch(story)
|
97
|
+
branch = "feature-#{story.id}"
|
98
|
+
|
99
|
+
puts "Suggested branch name: #{branch}"
|
100
|
+
print "Accept this name? (Yn): "
|
101
|
+
selection = gets.chomp
|
102
|
+
|
103
|
+
unless agrees?(selection)
|
104
|
+
print "Enter new name (will be prepended by #{story.id}): "
|
105
|
+
branch = "#{story.id}-" + gets.chomp
|
106
|
+
end
|
107
|
+
|
108
|
+
create_branch branch
|
109
|
+
end
|
110
|
+
|
111
|
+
def start_story(story)
|
112
|
+
puts "Updating story status in Pivotal Tracker..."
|
113
|
+
story.start!
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
data/lib/pivotal/api.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Pivotal
|
2
|
+
class Api < Base
|
3
|
+
|
4
|
+
attr_accessor :api_token
|
5
|
+
has_collection :projects, :of => Pivotal::Project
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
super(options)
|
9
|
+
@api_url = "https://www.pivotaltracker.com/services/v3"
|
10
|
+
end
|
11
|
+
|
12
|
+
def resource
|
13
|
+
@resource ||= RestClient::Resource.new @api_url, :headers => { 'X-TrackerToken' => api_token, 'Content-Type' => 'application/xml' }
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Pivotal
|
2
|
+
module Associations
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def has_collection(name, options = {})
|
10
|
+
define_method name do
|
11
|
+
Pivotal::Collection.new resource[name], options[:of]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
data/lib/pivotal/base.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rest_client'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module Pivotal
|
6
|
+
class Base
|
7
|
+
include Pivotal::Associations
|
8
|
+
|
9
|
+
attr_accessor :resource, :xml
|
10
|
+
undef id
|
11
|
+
|
12
|
+
def initialize(params = {})
|
13
|
+
params.each do |key, value|
|
14
|
+
send("#{key}=", value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def xml
|
19
|
+
@xml ||= resource.get
|
20
|
+
end
|
21
|
+
|
22
|
+
def parsed_resource
|
23
|
+
@parsed_resource ||= Nokogiri::XML(xml)
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_missing(method, *args)
|
27
|
+
parsed_resource.css(method.to_s).text
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def xpath
|
32
|
+
'//' + self.name.gsub(/.+\:\:/, '').downcase
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Pivotal
|
4
|
+
class Collection
|
5
|
+
|
6
|
+
attr_accessor :resource, :component_class
|
7
|
+
|
8
|
+
def initialize(resource, component_class)
|
9
|
+
@resource, @component_class = resource, component_class
|
10
|
+
end
|
11
|
+
|
12
|
+
# Param queries will break our REST structure,
|
13
|
+
# so if we find an :id parameter, accept it and
|
14
|
+
# ignore all other params.
|
15
|
+
def find(*args)
|
16
|
+
params = args.last.is_a?(Hash) ? args.pop : {}
|
17
|
+
finder = args.first
|
18
|
+
|
19
|
+
return item(params[:id]) if params[:id]
|
20
|
+
return item(finder) if finder.is_a?(Numeric)
|
21
|
+
|
22
|
+
all(params)
|
23
|
+
end
|
24
|
+
|
25
|
+
def first
|
26
|
+
all.first
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def item(id)
|
32
|
+
component_class.new :resource => resource[id]
|
33
|
+
end
|
34
|
+
|
35
|
+
def filters(params = {})
|
36
|
+
return "" if params.empty?
|
37
|
+
|
38
|
+
param_url = []
|
39
|
+
if params[:conditions]
|
40
|
+
condition_string = params[:conditions].map { |k,v| "#{k}:#{v}" }.join " "
|
41
|
+
param_url << "filter=#{CGI::escape(condition_string)}"
|
42
|
+
end
|
43
|
+
|
44
|
+
if params[:limit]
|
45
|
+
param_url << "limit=#{params[:limit]}&offset=#{params[:offset]||0}"
|
46
|
+
end
|
47
|
+
|
48
|
+
"?" + param_url.join("&")
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_collection_from_xml(xml = "")
|
52
|
+
Nokogiri::XML(xml).xpath(component_class.xpath).map do |item|
|
53
|
+
item_id = item.xpath("//id").text
|
54
|
+
component_class.new :resource => resource[item_id], :xml => item.to_xml
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def all(params = {})
|
59
|
+
build_collection_from_xml resource[filters(params)].get
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
data/lib/pivotal.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'pivotal', 'collection')
|
2
|
+
require File.join(File.dirname(__FILE__),'pivotal', 'associations')
|
3
|
+
|
4
|
+
require File.join(File.dirname(__FILE__),'pivotal','base')
|
5
|
+
require File.join(File.dirname(__FILE__),'pivotal','story')
|
6
|
+
require File.join(File.dirname(__FILE__),'pivotal','project')
|
7
|
+
require File.join(File.dirname(__FILE__),'pivotal','api')
|
data/readme.markdown
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#Git Pivotal
|
2
|
+
|
3
|
+
##Prelude
|
4
|
+
You might want to have [this song]("http://www.dailymotion.com/video/x9vzh0_olivia-newton-john-lets-get-physica_music") running in the background while you read this.
|
5
|
+
|
6
|
+
##Let's Git Pivotal
|
7
|
+
Inspired by [Hashrocket's blend of git and Pivotal Tracker]("http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-teams.html"), I set off to create a set of utilities to simplify the workflow between the two.
|
8
|
+
|
9
|
+
###Git Pick
|
10
|
+
This selects the top-most available feature from your Pivotal Tracker, and offers to create a feature branch.
|
11
|
+
|
12
|
+
1 git-pick:master % git pick
|
13
|
+
Collecting latest stories from Pivotal Tracker...
|
14
|
+
Story: Test git pivotal
|
15
|
+
URL: http://www.pivotaltracker.com/story/show/1234567
|
16
|
+
Accept this story? (Yn): y
|
17
|
+
Suggested branch: feature-1234567
|
18
|
+
Accept this name? (Yn): y
|
19
|
+
Creating feature-1234567 branch...
|
20
|
+
Updating story status in Pivotal Tracker...
|
21
|
+
2 git-pick:feature-1234567 %
|
22
|
+
|
23
|
+
##Installation
|
24
|
+
Some long process to actually install it. Working on that.
|
25
|
+
Once installed, git pivotal needs two bits of info: your Pivotal Tracker API Token and your Pivotal Tracker project id. The former is best set as a global git config option:
|
26
|
+
|
27
|
+
git config --global pivotal.api-token 9a9a9a9a9a9a9a9a9a9a
|
28
|
+
|
29
|
+
The project id is best placed within your project's git config:
|
30
|
+
|
31
|
+
git config -f .git/config pivotal.project-id 88888
|
32
|
+
|
33
|
+
If you're not interested in storing these options in git, you can pass them into git pivotal as command line arguments. See the usage guides for more details.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pivotal::Api do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@api = pivotal_api
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should connect to Pivotal Tracker's API" do
|
10
|
+
@api.resource.url.should == "https://www.pivotaltracker.com/services/v3"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should have a collection of projects" do
|
14
|
+
@api.projects.should be_a(Pivotal::Collection)
|
15
|
+
@api.projects.component_class.should == Pivotal::Project
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pivotal::Associations do
|
4
|
+
|
5
|
+
it "should load the #has_collection method into a class" do
|
6
|
+
@base = Object
|
7
|
+
@base.should_not respond_to(:has_collection)
|
8
|
+
|
9
|
+
@base.send(:include, Pivotal::Associations)
|
10
|
+
@base.should respond_to(:has_collection)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
describe Pivotal::Base do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@base = pivotal_api
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should expose a REST resource" do
|
11
|
+
@base.resource.should be_a(RestClient::Resource)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should expose the resource's XML" do
|
15
|
+
@base.resource.expects(:get).returns("")
|
16
|
+
@base.xml.should be_a(String)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should expose the resource's XML parse tree" do
|
20
|
+
@base.parsed_resource.should be_a(Nokogiri::XML::Document)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should forward undefined methods to the XML parse tree" do
|
24
|
+
@base.should_not respond_to(:id)
|
25
|
+
@base.id.should == "1"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should present the class's item xpath" do
|
29
|
+
@base.class.xpath.should == "//api"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should expose association methods" do
|
33
|
+
@base.class.should include(Pivotal::Associations)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pivotal::Collection do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@api = pivotal_api
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should find a single item given an id" do
|
10
|
+
@api.projects.find(1).should be_a(Pivotal::Project)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should find a collection of items giving a set of conditions" do
|
14
|
+
@api.projects.find(:all).should be_a(Array)
|
15
|
+
@api.projects.first.should be_a(Pivotal::Project)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return the first item of a collection" do
|
19
|
+
@api.projects.first.should be_a(Pivotal::Project)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pivotal::Project do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@api = pivotal_api
|
7
|
+
@project = Pivotal::Project.new :resource => @api.resource["projects"][1]
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be connected to the project resource" do
|
11
|
+
@project.resource.url.should == "https://www.pivotaltracker.com/services/v3/projects/1"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have a collection of stories" do
|
15
|
+
@project.stories.should be_a(Pivotal::Collection)
|
16
|
+
@project.stories.component_class.should == Pivotal::Story
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pivotal::Story do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@api = pivotal_api
|
7
|
+
@project = Pivotal::Project.new :resource => @api.resource["projects"][1]
|
8
|
+
@story = Pivotal::Story.new :resource => @project.resource["stories"][1]
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should be connected to the story resource" do
|
12
|
+
@story.resource.url.should == "https://www.pivotaltracker.com/services/v3/projects/1/stories/1"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mocha'
|
3
|
+
require 'builder'
|
4
|
+
require 'pivotal'
|
5
|
+
require 'commands/pick'
|
6
|
+
|
7
|
+
Spec::Runner.configure do |config|
|
8
|
+
config.mock_with :mocha
|
9
|
+
end
|
10
|
+
|
11
|
+
def demo_xml
|
12
|
+
Builder::XmlMarkup.new.project do |project|
|
13
|
+
project.id 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def stub_connection_to_pivotal
|
18
|
+
RestClient::Resource.any_instance.stubs(:get).returns(demo_xml)
|
19
|
+
end
|
20
|
+
|
21
|
+
def pivotal_api
|
22
|
+
stub_connection_to_pivotal
|
23
|
+
Pivotal::Api.new :api_token => 1
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-pivotal
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeff Tucker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-27 00:00:00 -05:00
|
13
|
+
default_executable: git-pick
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: nokogiri
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rest-client
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: A collection of git utilities to ease integration with Pivotal Tracker
|
46
|
+
email: jeff@trydionel.com
|
47
|
+
executables:
|
48
|
+
- git-pick
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- LICENSE
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- LICENSE
|
56
|
+
- Rakefile
|
57
|
+
- VERSION
|
58
|
+
- bin/git-pick
|
59
|
+
- git-pivotal.gemspec
|
60
|
+
- lib/commands/pick.rb
|
61
|
+
- lib/pivotal.rb
|
62
|
+
- lib/pivotal/api.rb
|
63
|
+
- lib/pivotal/associations.rb
|
64
|
+
- lib/pivotal/base.rb
|
65
|
+
- lib/pivotal/collection.rb
|
66
|
+
- lib/pivotal/project.rb
|
67
|
+
- lib/pivotal/story.rb
|
68
|
+
- readme.markdown
|
69
|
+
- spec/commands/pick_spec.rb
|
70
|
+
- spec/pivotal/api_spec.rb
|
71
|
+
- spec/pivotal/associations_spec.rb
|
72
|
+
- spec/pivotal/base_spec.rb
|
73
|
+
- spec/pivotal/collection_spec.rb
|
74
|
+
- spec/pivotal/project_spec.rb
|
75
|
+
- spec/pivotal/story_spec.rb
|
76
|
+
- spec/spec_helper.rb
|
77
|
+
has_rdoc: true
|
78
|
+
homepage: http://github.com/trydionel/git-pivotal
|
79
|
+
licenses: []
|
80
|
+
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options:
|
83
|
+
- --charset=UTF-8
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: "0"
|
91
|
+
version:
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: "0"
|
97
|
+
version:
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 1.3.5
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: A collection of git utilities to ease integration with Pivotal Tracker
|
105
|
+
test_files:
|
106
|
+
- spec/commands/pick_spec.rb
|
107
|
+
- spec/pivotal/api_spec.rb
|
108
|
+
- spec/pivotal/associations_spec.rb
|
109
|
+
- spec/pivotal/base_spec.rb
|
110
|
+
- spec/pivotal/collection_spec.rb
|
111
|
+
- spec/pivotal/project_spec.rb
|
112
|
+
- spec/pivotal/story_spec.rb
|
113
|
+
- spec/spec_helper.rb
|