git_tracking 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.git_tracking +7 -0
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +66 -0
- data/README +70 -0
- data/Rakefile +2 -0
- data/bin/git_tracking +50 -0
- data/git_tracking.gemspec +24 -0
- data/hooks/post-commit +9 -0
- data/hooks/pre-commit +9 -0
- data/hooks/prepare-commit-msg +9 -0
- data/lib/git_tracking/config.rb +81 -0
- data/lib/git_tracking/detect.rb +26 -0
- data/lib/git_tracking/version.rb +3 -0
- data/lib/git_tracking.rb +161 -0
- data/spec/config_spec.rb +199 -0
- data/spec/detect_spec.rb +95 -0
- data/spec/git_tracking_spec.rb +254 -0
- metadata +117 -0
data/.git_tracking
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--debug
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
git_tracking (0.0.1)
|
5
|
+
highline
|
6
|
+
pivotal-tracker
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
archive-tar-minitar (0.5.2)
|
12
|
+
builder (2.1.2)
|
13
|
+
columnize (0.3.1)
|
14
|
+
diff-lcs (1.1.2)
|
15
|
+
happymapper (0.3.2)
|
16
|
+
libxml-ruby (~> 1.1.3)
|
17
|
+
highline (1.6.1)
|
18
|
+
libxml-ruby (1.1.4)
|
19
|
+
linecache (0.43)
|
20
|
+
linecache19 (0.5.11)
|
21
|
+
ruby_core_source (>= 0.1.4)
|
22
|
+
mime-types (1.16)
|
23
|
+
nokogiri (1.4.3.1)
|
24
|
+
pivotal-tracker (0.2.2)
|
25
|
+
builder
|
26
|
+
happymapper (>= 0.3.2)
|
27
|
+
nokogiri (~> 1.4.3.1)
|
28
|
+
rest-client (~> 1.6.0)
|
29
|
+
rest-client (1.6.1)
|
30
|
+
mime-types (>= 1.16)
|
31
|
+
rspec (2.0.1)
|
32
|
+
rspec-core (~> 2.0.1)
|
33
|
+
rspec-expectations (~> 2.0.1)
|
34
|
+
rspec-mocks (~> 2.0.1)
|
35
|
+
rspec-core (2.0.1)
|
36
|
+
rspec-expectations (2.0.1)
|
37
|
+
diff-lcs (>= 1.1.2)
|
38
|
+
rspec-mocks (2.0.1)
|
39
|
+
rspec-core (~> 2.0.1)
|
40
|
+
rspec-expectations (~> 2.0.1)
|
41
|
+
ruby-debug (0.10.3)
|
42
|
+
columnize (>= 0.1)
|
43
|
+
ruby-debug-base (~> 0.10.3.0)
|
44
|
+
ruby-debug-base (0.10.3)
|
45
|
+
linecache (>= 0.3)
|
46
|
+
ruby-debug-base19 (0.11.24)
|
47
|
+
columnize (>= 0.3.1)
|
48
|
+
linecache19 (>= 0.5.11)
|
49
|
+
ruby_core_source (>= 0.1.4)
|
50
|
+
ruby-debug19 (0.11.6)
|
51
|
+
columnize (>= 0.3.1)
|
52
|
+
linecache19 (>= 0.5.11)
|
53
|
+
ruby-debug-base19 (>= 0.11.19)
|
54
|
+
ruby_core_source (0.1.4)
|
55
|
+
archive-tar-minitar (>= 0.5.2)
|
56
|
+
|
57
|
+
PLATFORMS
|
58
|
+
ruby
|
59
|
+
|
60
|
+
DEPENDENCIES
|
61
|
+
git_tracking!
|
62
|
+
highline
|
63
|
+
pivotal-tracker
|
64
|
+
rspec (>= 2.0)
|
65
|
+
ruby-debug
|
66
|
+
ruby-debug19
|
data/README
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
Git Tracking!
|
2
|
+
============
|
3
|
+
|
4
|
+
## Purpose
|
5
|
+
`git_tracking` is a gem whose primary purpose is to
|
6
|
+
provide (and enforce) tight integration between
|
7
|
+
Pivotal Tracker and git for your project.
|
8
|
+
|
9
|
+
At my office, we have all agreed that we shouldn't
|
10
|
+
commit code that doesn't have an associated story
|
11
|
+
in Pivotal Tracker. Further, we tend to work on
|
12
|
+
code at our glamorous (and blazingly fast) iMac
|
13
|
+
pairing stations. Therefore, we have two needs which
|
14
|
+
this gem aims to satisfy:
|
15
|
+
|
16
|
+
1. To always know *who* was the author of a given
|
17
|
+
commit. ('Pairingstation1' is not good enough.)
|
18
|
+
2. To always know *which* story a given commit was
|
19
|
+
intended to fix/implement.
|
20
|
+
3. Bonus: While in Tracker, to be able to see
|
21
|
+
which commits are tied to a given story.
|
22
|
+
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
gem install git_tracking
|
26
|
+
git_tracking # this installs the git hooks and .git_tracking config file
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
Just use git as normal, and you will be prompted for
|
30
|
+
stuff.
|
31
|
+
|
32
|
+
For example:
|
33
|
+
|
34
|
+
! g commit -m "Making detect ignore .git_tracking file"
|
35
|
+
The following files have 'debugger' statements in them:
|
36
|
+
spec/detect_spec.rb
|
37
|
+
Git Author (default will be: Steve & Ghost Co-Pilot):
|
38
|
+
1. Enter new
|
39
|
+
? 1
|
40
|
+
New git author: Steve
|
41
|
+
Pivotal Tracker email (default is: ):
|
42
|
+
1. Enter new
|
43
|
+
? 1
|
44
|
+
New Email: john@doe.net
|
45
|
+
Enter your PivotalTracker password: xxxxxxx
|
46
|
+
Please enter the PivotalTracker project id for this project
|
47
|
+
137119
|
48
|
+
Found a valid story id in your branch or commit: 6131989 - Bugfixing
|
49
|
+
Hit enter to confirm story id 6131989, or enter some other story id: |6131989| 6132035
|
50
|
+
[master 2162139] [#6132035] Make sure that detect_* ignores .git_tracking file
|
51
|
+
2 files changed, 17 insertions(+), 8 deletions(-)
|
52
|
+
|
53
|
+
You can set `git_tracking` to raise (ie reject your
|
54
|
+
commit) when it detects that you are about to commit
|
55
|
+
a `debugger` or an incomplete merge (`<<<<<<<` or `>>>>>>>`).
|
56
|
+
|
57
|
+
All config options are in the `.git_tracking` file.
|
58
|
+
|
59
|
+
## BEWARE!!
|
60
|
+
|
61
|
+
`git_tracking` will store your api token for tracker
|
62
|
+
in the `.git_tracking` file. This is probably fine
|
63
|
+
for private repo's where you know everyone who
|
64
|
+
has access, but if you are committing to a public
|
65
|
+
repo, you may want to put the `.git_tracking` file
|
66
|
+
in your .gitignore.
|
67
|
+
|
68
|
+
If you do accidentally make your PivotalTracker
|
69
|
+
token public, I believe you request that they
|
70
|
+
generate a new one for you.
|
data/Rakefile
ADDED
data/bin/git_tracking
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'git_tracking'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems'
|
7
|
+
require 'git_tracking'
|
8
|
+
end
|
9
|
+
|
10
|
+
puts "Thanks for installing the git_tracking gem!"
|
11
|
+
|
12
|
+
if File.exists?(".git") && File.directory?(".git")
|
13
|
+
GitTracking.config
|
14
|
+
|
15
|
+
unless File.exists?(".git_tracking")
|
16
|
+
GitTracking::Config.new.write_to_file
|
17
|
+
else
|
18
|
+
puts "Not writing .git_tracking config file, as it already exists"
|
19
|
+
end
|
20
|
+
|
21
|
+
unless File.exists?(".git/hooks/pre-commit") && File.read(".git/hooks/pre-commit").include?("GitTracking")
|
22
|
+
File.open(".git/hooks/pre-commit", "a") do |file|
|
23
|
+
file.print File.read(File.expand_path("../../hooks/pre-commit", __FILE__))
|
24
|
+
end
|
25
|
+
system "chmod +x .git/hooks/pre-commit"
|
26
|
+
else
|
27
|
+
puts "Not writing pre-commit hook, as it already exists"
|
28
|
+
end
|
29
|
+
|
30
|
+
unless File.exists?(".git/hooks/prepare-commit-msg") && File.read(".git/hooks/prepare-commit-msg").include?("GitTracking")
|
31
|
+
File.open(".git/hooks/prepare-commit-msg", "a") do |file|
|
32
|
+
file.print File.read(File.expand_path("../../hooks/prepare-commit-msg", __FILE__))
|
33
|
+
end
|
34
|
+
system "chmod +x .git/hooks/prepare-commit-msg"
|
35
|
+
else
|
36
|
+
puts "Not writing prepare-commit-msg hook, as it already exists"
|
37
|
+
end
|
38
|
+
|
39
|
+
unless File.exists?(".git/hooks/post-commit") && File.read(".git/hooks/post-commit").include?("GitTracking")
|
40
|
+
File.open(".git/hooks/post-commit", "a") do |file|
|
41
|
+
file.print File.read(File.expand_path("../../hooks/post-commit", __FILE__))
|
42
|
+
end
|
43
|
+
system "chmod +x .git/hooks/post-commit"
|
44
|
+
else
|
45
|
+
puts "Not writing post-commit hook, as it already exists"
|
46
|
+
end
|
47
|
+
else
|
48
|
+
puts "Error: No .git directory found. The git_tracking gem can only be used in a project tracked by git"
|
49
|
+
exit 1
|
50
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "git_tracking/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "git_tracking"
|
7
|
+
s.version = GitTracking::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Steve Hull", "Derrick Camerino"]
|
10
|
+
s.email = ["p.witty@gmail.com", "robustdj@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/git_tracking"
|
12
|
+
s.summary = %q{Better integration between git and PivotalTracker}
|
13
|
+
s.description = %q{Usage: after installing the gem, in your project directory, run: git_tracking}
|
14
|
+
|
15
|
+
s.rubyforge_project = "git_tracking"
|
16
|
+
|
17
|
+
s.add_dependency('highline')
|
18
|
+
s.add_dependency('pivotal-tracker')
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
data/hooks/post-commit
ADDED
data/hooks/pre-commit
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
class GitTracking
|
2
|
+
class Config
|
3
|
+
def initialize
|
4
|
+
@config = {
|
5
|
+
:raise_on_incomplete_merge => true,
|
6
|
+
:raise_on_debugger => true,
|
7
|
+
:authors => [],
|
8
|
+
:keys => {}
|
9
|
+
}
|
10
|
+
if File.exists? ".git_tracking"
|
11
|
+
@config.merge! YAML.load_file(".git_tracking")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def raise_on_debugger
|
16
|
+
@config[:raise_on_debugger]
|
17
|
+
end
|
18
|
+
|
19
|
+
def raise_on_incomplete_merge
|
20
|
+
@config[:raise_on_incomplete_merge]
|
21
|
+
end
|
22
|
+
|
23
|
+
def emails
|
24
|
+
@config[:keys].keys
|
25
|
+
end
|
26
|
+
|
27
|
+
def last_email
|
28
|
+
@config[:keys].invert[last_api_key]
|
29
|
+
end
|
30
|
+
|
31
|
+
def last_commit_info
|
32
|
+
info = `git log -n 1`.split("\n")
|
33
|
+
info = "#{info.first}\n#{info.last}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def author
|
37
|
+
`git config user.name`.chomp
|
38
|
+
end
|
39
|
+
|
40
|
+
def authors
|
41
|
+
@config[:authors]
|
42
|
+
end
|
43
|
+
|
44
|
+
def author=(new_author)
|
45
|
+
@config[:authors].push(new_author).uniq!
|
46
|
+
write_to_file
|
47
|
+
system "git config user.name '#{new_author}'"
|
48
|
+
end
|
49
|
+
|
50
|
+
[:last_story_id, :last_api_key].each do |config_item|
|
51
|
+
git_config_key = config_item.to_s.gsub("_","-")
|
52
|
+
define_method(config_item) do
|
53
|
+
`git config git-tracking.#{git_config_key}`.chomp
|
54
|
+
end
|
55
|
+
|
56
|
+
define_method("#{config_item}=") do |value|
|
57
|
+
system "git config git-tracking.#{git_config_key} '#{value}'"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def key_for_email(email, key=nil)
|
62
|
+
return (self.last_api_key = @config[:keys][email]) if key.nil?
|
63
|
+
self.last_api_key = key
|
64
|
+
@config[:keys][email] = key
|
65
|
+
write_to_file
|
66
|
+
end
|
67
|
+
|
68
|
+
def project_id(id=nil)
|
69
|
+
return @config[:project_id] if id.nil?
|
70
|
+
@config[:project_id] = id
|
71
|
+
write_to_file
|
72
|
+
id
|
73
|
+
end
|
74
|
+
|
75
|
+
def write_to_file
|
76
|
+
File.open(".git_tracking", "w") do |file|
|
77
|
+
YAML.dump(@config, file)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class GitTracking
|
2
|
+
class << self
|
3
|
+
def detect_debuggers
|
4
|
+
file_names = `git diff-index --cached -Sdebugger --name-only HEAD`.chomp
|
5
|
+
file_names = file_names.gsub(".git_tracking\n",'')
|
6
|
+
if file_names != ""
|
7
|
+
highline.say highline.color("The following files have 'debugger' statements in them: ", :red)
|
8
|
+
highline.say file_names
|
9
|
+
raise DebuggerException,
|
10
|
+
"Please remove debuggers prior to committing" if config.raise_on_debugger
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def detect_incomplete_merges
|
15
|
+
file_names = `git diff-index --cached -S'<<<<<<<' --name-only HEAD`.chomp.split
|
16
|
+
file_names += `git diff-index --cached -S'>>>>>>>' --name-only HEAD`.chomp.split
|
17
|
+
file_names = file_names.uniq.join("\n")
|
18
|
+
if file_names != ""
|
19
|
+
highline.say highline.color("The following files have incomplete merges: ", :red)
|
20
|
+
highline.say file_names
|
21
|
+
raise IncompleteMergeException,
|
22
|
+
"Please complete your merge prior to committing" if config.raise_on_incomplete_merge
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/git_tracking.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
2
|
+
$:.unshift this_dir unless $:.include? this_dir
|
3
|
+
|
4
|
+
# stdlib
|
5
|
+
if RUBY_VERSION.match "1.9"
|
6
|
+
require 'fileutils'
|
7
|
+
else
|
8
|
+
require 'ftools'
|
9
|
+
end
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
# gems
|
13
|
+
require 'highline'
|
14
|
+
require 'pivotal-tracker'
|
15
|
+
|
16
|
+
# stuff frm this library
|
17
|
+
require 'git_tracking/config'
|
18
|
+
require 'git_tracking/detect'
|
19
|
+
|
20
|
+
class PreCommitException < Exception; end
|
21
|
+
class DebuggerException < PreCommitException; end
|
22
|
+
class IncompleteMergeException < PreCommitException; end
|
23
|
+
|
24
|
+
HighLine.track_eof = false
|
25
|
+
|
26
|
+
class GitTracking
|
27
|
+
class << self
|
28
|
+
def highline
|
29
|
+
@highline ||= HighLine.new($stdin.reopen("/dev/tty", "a+"), $stdout)
|
30
|
+
end
|
31
|
+
|
32
|
+
def config
|
33
|
+
@config ||= Config.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def commit_message
|
37
|
+
@commit_message ||= File.read(ARGV[0])
|
38
|
+
end
|
39
|
+
|
40
|
+
def pre_commit
|
41
|
+
detect_debuggers
|
42
|
+
detect_incomplete_merges
|
43
|
+
end
|
44
|
+
|
45
|
+
def prepare_commit_msg
|
46
|
+
author
|
47
|
+
commit_message
|
48
|
+
File.open(ARGV[0], "w") do |f|
|
49
|
+
f.puts story_info
|
50
|
+
f.puts
|
51
|
+
f.puts " - #{commit_message}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def post_commit
|
56
|
+
@api_key = config.last_api_key
|
57
|
+
story = get_story(config.last_story_id)
|
58
|
+
story.notes.create(:text => config.last_commit_info)
|
59
|
+
end
|
60
|
+
|
61
|
+
def pivotal_project
|
62
|
+
return @pivotal_project if @pivotal_project
|
63
|
+
PivotalTracker::Client.token = api_key
|
64
|
+
@pivotal_project = PivotalTracker::Project.find(project_id)
|
65
|
+
end
|
66
|
+
|
67
|
+
def project_id
|
68
|
+
return config.project_id if config.project_id
|
69
|
+
id = highline.ask("Please enter the PivotalTracker project id for this project") do |q|
|
70
|
+
q.validate = lambda do |a|
|
71
|
+
PivotalTracker::Client.token = api_key
|
72
|
+
PivotalTracker::Project.find(a) rescue false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
config.project_id(id)
|
76
|
+
end
|
77
|
+
|
78
|
+
def story_info
|
79
|
+
"[##{story.id}] #{story.name}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def story
|
83
|
+
return @story if @story
|
84
|
+
|
85
|
+
if story_id && story = get_story(story_id)
|
86
|
+
highline.say("Found a valid story id in your branch or commit: #{story.id} - #{story.name}")
|
87
|
+
@story = highline.ask("Hit enter to confirm story id #{story.id}, or enter some other story id: ", lambda{|a| get_story(a)}) do |q|
|
88
|
+
q.default = story.id
|
89
|
+
q.validate = lambda{|a| check_story_id(a)}
|
90
|
+
end
|
91
|
+
else
|
92
|
+
@story = highline.ask("Please enter a valid Pivotal Tracker story id: ", lambda{|a| get_story(a)}) do |q|
|
93
|
+
q.validate = lambda{|a| check_story_id(a)}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
config.last_story_id = @story.id
|
97
|
+
|
98
|
+
@story
|
99
|
+
end
|
100
|
+
|
101
|
+
def branch
|
102
|
+
`git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'`.chomp.gsub("* ", "")
|
103
|
+
end
|
104
|
+
|
105
|
+
def story_id
|
106
|
+
@story_id ||= (extract_story_id(commit_message) || extract_story_id(branch) || config.last_story_id)
|
107
|
+
end
|
108
|
+
|
109
|
+
def extract_story_id(string)
|
110
|
+
the_story_id = string.match(/\d{5,}/)[0] if string.match(/\d{5,}/)
|
111
|
+
return the_story_id if check_story_id(the_story_id)
|
112
|
+
end
|
113
|
+
|
114
|
+
def author
|
115
|
+
return @author if @author
|
116
|
+
@author = highline.choose(*config.authors) do |menu|
|
117
|
+
menu.header = "Git Author (default will be: #{config.author})"
|
118
|
+
menu.default = config.author
|
119
|
+
menu.choice("Enter new") { highline.ask("New git author: ") }
|
120
|
+
end
|
121
|
+
config.author = @author
|
122
|
+
end
|
123
|
+
|
124
|
+
def api_key
|
125
|
+
return @api_key if @api_key
|
126
|
+
message, retry_count = nil, 0
|
127
|
+
email = highline.choose(*config.emails) do |menu|
|
128
|
+
menu.header = "Pivotal Tracker email (default is: #{config.last_email})"
|
129
|
+
menu.default = config.last_email
|
130
|
+
menu.choice("Enter new") { highline.ask("New Email: ") }
|
131
|
+
end
|
132
|
+
unless @api_key = config.key_for_email(email.to_s)
|
133
|
+
begin
|
134
|
+
highline.say message if message
|
135
|
+
password = highline.ask("Enter your PivotalTracker password: ") {|q| q.echo = "x" }
|
136
|
+
@api_key = PivotalTracker::Client.token(email, password)
|
137
|
+
config.key_for_email(email, @api_key)
|
138
|
+
rescue RestClient::Request::Unauthorized
|
139
|
+
retry_count += 1
|
140
|
+
message = "401 Unauthorized. Please try again."
|
141
|
+
if retry_count < 3
|
142
|
+
retry
|
143
|
+
else
|
144
|
+
highline.say("Unable to authenticate to Pivotal Tracker. Exiting...")
|
145
|
+
raise RestClient::Request::Unauthorized
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
@api_key
|
151
|
+
end
|
152
|
+
|
153
|
+
def check_story_id(id)
|
154
|
+
return true if get_story(id)
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_story(id)
|
158
|
+
pivotal_project.stories.find(id.to_i) rescue nil
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'lib/git_tracking'
|
2
|
+
|
3
|
+
describe GitTracking::Config do
|
4
|
+
before(:all) do
|
5
|
+
File.rename ".git_tracking", ".git_tracking.real" if File.exists?(".git_tracking")
|
6
|
+
@orig_author = `git config user.name`.chomp
|
7
|
+
@orig_last_api_key = `git config git-tracking.last-api-key`.chomp
|
8
|
+
@orig_last_story_id = `git config git-tracking.last-story-id`.chomp
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:all) do
|
12
|
+
File.rename ".git_tracking.real", ".git_tracking" if File.exists?(".git_tracking.real")
|
13
|
+
system "git config user.name '#{@orig_author}'"
|
14
|
+
system "git config git-tracking.last-api-key '#{@orig_last_api_key}'"
|
15
|
+
system "git config git-tracking.last-story-id '#{@orig_last_story_id}'"
|
16
|
+
end
|
17
|
+
|
18
|
+
after(:each) { File.delete(".git_tracking") if File.exists?(".git_tracking") }
|
19
|
+
let(:config) { GitTracking::Config.new }
|
20
|
+
|
21
|
+
it "#initialize should merge in config from .git_tracking file" do
|
22
|
+
config_hash = config.instance_variable_get("@config")
|
23
|
+
config_hash.should == {
|
24
|
+
:raise_on_incomplete_merge => true,
|
25
|
+
:raise_on_debugger => true,
|
26
|
+
:authors => [],
|
27
|
+
:keys => {}
|
28
|
+
}
|
29
|
+
special_options = {
|
30
|
+
:raise_on_incomplete_merge => false,
|
31
|
+
:raise_on_debugger => false
|
32
|
+
}
|
33
|
+
File.open(".git_tracking", "w") do |file|
|
34
|
+
YAML.dump(special_options, file)
|
35
|
+
end
|
36
|
+
GitTracking::Config.new.instance_variable_get("@config").should == config_hash.merge(special_options)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "#raise_on_debugger should return the correct config value" do
|
40
|
+
config.instance_eval { @config[:raise_on_debugger] = true }
|
41
|
+
config.raise_on_debugger.should be_true
|
42
|
+
config.instance_eval { @config[:raise_on_debugger] = false }
|
43
|
+
config.raise_on_debugger.should be_false
|
44
|
+
end
|
45
|
+
|
46
|
+
it "#raise_on_incomplete_merge should return the correct config value" do
|
47
|
+
config.instance_eval { @config[:raise_on_incomplete_merge] = true }
|
48
|
+
config.raise_on_incomplete_merge.should be_true
|
49
|
+
config.instance_eval { @config[:raise_on_incomplete_merge] = false }
|
50
|
+
config.raise_on_incomplete_merge.should be_false
|
51
|
+
end
|
52
|
+
|
53
|
+
it "#emails should return an array of email addresses" do
|
54
|
+
config.instance_eval do
|
55
|
+
@config[:keys] = {
|
56
|
+
"foo@bar.com" => "alsdkjf91",
|
57
|
+
"baz@bang.com" => "dsgkj39dk3"
|
58
|
+
}
|
59
|
+
end
|
60
|
+
config.emails.should == ["foo@bar.com", "baz@bang.com"]
|
61
|
+
end
|
62
|
+
|
63
|
+
it "#author should return the user.name value from the git config" do
|
64
|
+
system "git config user.name 'Steve'"
|
65
|
+
config.author.should == 'Steve'
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#author=" do
|
69
|
+
it "should set the user.name in the git config" do
|
70
|
+
(config.author='Ghost').should == "Ghost"
|
71
|
+
`git config user.name`.chomp.should == "Ghost"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should add the author to the list in .git_tracking file" do
|
75
|
+
config.instance_eval { @config[:authors] = ["Joe"] }
|
76
|
+
config.author = "Steve"
|
77
|
+
config.authors.should include("Steve")
|
78
|
+
YAML.load_file(".git_tracking")[:authors].should include("Steve")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should not add the author more than once" do
|
82
|
+
config.instance_eval { @config[:authors] = ["Joe"] }
|
83
|
+
config.author = "Joe"
|
84
|
+
config.authors.should == ["Joe"]
|
85
|
+
YAML.load_file(".git_tracking")[:authors].should == ["Joe"]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it "#authors should return an array of authors" do
|
90
|
+
config.instance_eval { @config[:authors] = ["Joe", "Bob", "Steve"] }
|
91
|
+
config.authors.should == ["Joe", "Bob", "Steve"]
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#last_commit_info" do
|
95
|
+
before(:all) do
|
96
|
+
File.rename ".git", ".git_old" if File.exists? ".git"
|
97
|
+
end
|
98
|
+
before(:each) do
|
99
|
+
system "git init; git add README; git commit -m 'initial commit'"
|
100
|
+
end
|
101
|
+
after(:each) do
|
102
|
+
File.delete "foo.txt" if File.exists? "foo.txt"
|
103
|
+
system "rm -rf .git" if File.exists? ".git"
|
104
|
+
end
|
105
|
+
after(:all) do
|
106
|
+
File.rename ".git_old", ".git" if File.exists? ".git_old"
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return info about the last commit" do
|
110
|
+
f = File.new("foo.txt", "w") {|f| f.puts "lalala"}
|
111
|
+
system "git add foo.txt"
|
112
|
+
system "git commit -m '[#1235] Story info\n - best commit evar'"
|
113
|
+
config.last_commit_info.should match(/commit \w{40,40}\n - best commit evar/)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it "#last_story_id should return the git-tracking.last-story-id from git config" do
|
118
|
+
system "git config git-tracking.last-story-id '736741'"
|
119
|
+
config.last_story_id.should == '736741'
|
120
|
+
end
|
121
|
+
|
122
|
+
it "#last_story_id= should set the git-tracking.last-story-id in git config" do
|
123
|
+
(config.last_story_id='234900').should == '234900'
|
124
|
+
`git config git-tracking.last-story-id`.chomp.should == '234900'
|
125
|
+
end
|
126
|
+
|
127
|
+
it "#last_api_key should return the git-tracking.last-api-key from git config" do
|
128
|
+
system "git config git-tracking.last-api-key '736741'"
|
129
|
+
config.last_api_key.should == '736741'
|
130
|
+
end
|
131
|
+
|
132
|
+
it "#last_api_key= should set the git-tracking.last-api-key in git config" do
|
133
|
+
(config.last_api_key='123444').should == '123444'
|
134
|
+
`git config git-tracking.last-api-key`.chomp.should == '123444'
|
135
|
+
end
|
136
|
+
|
137
|
+
it "#last_email should return the email that corresponds to the last api key used" do
|
138
|
+
config.instance_eval do
|
139
|
+
@config[:keys] = {
|
140
|
+
"foo@bar.com" => "987125jf"
|
141
|
+
}
|
142
|
+
end
|
143
|
+
system "git config git-tracking.last-api-key '987125jf'"
|
144
|
+
config.last_email.should == "foo@bar.com"
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "#project_id" do
|
148
|
+
it "should return the project_id" do
|
149
|
+
config.instance_eval { @config[:project_id] = '7472' }
|
150
|
+
config.project_id.should == '7472'
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should set the project id and store it" do
|
154
|
+
config.project_id('8765').should == '8765'
|
155
|
+
YAML.load_file(".git_tracking")[:project_id].should == '8765'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "#key_for_email" do
|
160
|
+
it "should return the pivotal api key" do
|
161
|
+
config.instance_eval do
|
162
|
+
@config[:keys] = {
|
163
|
+
"foo@bar.com" => "alsdkjf91",
|
164
|
+
"baz@bang.com" => "dsgkj39dk3"
|
165
|
+
}
|
166
|
+
end
|
167
|
+
config.key_for_email("foo@bar.com").should == 'alsdkjf91'
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should set the pivotal api key and store it" do
|
171
|
+
config.key_for_email("foo@bar.com", 'kdslghj348')
|
172
|
+
YAML.load_file(".git_tracking")[:keys]["foo@bar.com"].should == 'kdslghj348'
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should set the last_api_key as well" do
|
176
|
+
config.should_receive(:last_api_key=).with('kdslghj348').ordered
|
177
|
+
config.should_receive(:last_api_key=).with('dsgkj39dk3').ordered
|
178
|
+
config.key_for_email("foo@bar.com", 'kdslghj348')
|
179
|
+
config.instance_eval do
|
180
|
+
@config[:keys] = {
|
181
|
+
"baz@bang.com" => "dsgkj39dk3"
|
182
|
+
}
|
183
|
+
end
|
184
|
+
config.key_for_email("baz@bang.com")
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
it "#write_to_file should write the @config var to the file" do
|
189
|
+
special_options = {
|
190
|
+
:raise_on_incomplete_merge => false,
|
191
|
+
:raise_on_debugger => false,
|
192
|
+
:emails => ["your@mom.com"]
|
193
|
+
}
|
194
|
+
config.instance_variable_set("@config", special_options)
|
195
|
+
config.write_to_file
|
196
|
+
YAML.load_file(".git_tracking") == special_options
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
data/spec/detect_spec.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'lib/git_tracking'
|
2
|
+
|
3
|
+
describe GitTracking, "detect" do
|
4
|
+
before(:all) do
|
5
|
+
File.rename ".git_tracking", ".git_tracking.real" if File.exists?(".git_tracking")
|
6
|
+
File.rename ".git", ".git_old" if File.exists? ".git"
|
7
|
+
end
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
do_cmd "git init; git add README; git commit -m 'initial commit'"
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:each) do
|
14
|
+
File.delete "foo.txt" if File.exists? "foo.txt"
|
15
|
+
File.delete ".git_tracking" if File.exists? ".git_tracking"
|
16
|
+
do_cmd "rm -rf .git" if File.exists? ".git"
|
17
|
+
end
|
18
|
+
|
19
|
+
after(:all) do
|
20
|
+
File.rename ".git_old", ".git" if File.exists? ".git_old"
|
21
|
+
File.rename ".git_tracking.real", ".git_tracking" if File.exists?(".git_tracking.real")
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".detect_debuggers" do
|
25
|
+
context "configured to reject commits with debuggers" do
|
26
|
+
it "should detect debuggers and raise DebuggerException" do
|
27
|
+
GitTracking.config.stub(:raise_on_debugger).and_return(true)
|
28
|
+
make_file "foo.txt", "debugger"
|
29
|
+
make_file ".git_tracking", "debugger"
|
30
|
+
do_cmd "git add foo.txt"
|
31
|
+
do_cmd "git add .git_tracking"
|
32
|
+
GitTracking.highline.should_receive("say")
|
33
|
+
GitTracking.highline.should_receive("say").with("foo.txt")
|
34
|
+
lambda{GitTracking.detect_debuggers}.should(
|
35
|
+
raise_error(DebuggerException, "Please remove debuggers prior to committing"))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "configured to simply warn about commits with debuggers" do
|
40
|
+
it "should detect debuggers" do
|
41
|
+
GitTracking.config.stub(:raise_on_debugger).and_return(false)
|
42
|
+
make_file "foo.txt", "debugger"
|
43
|
+
make_file ".git_tracking", "debugger"
|
44
|
+
do_cmd "git add foo.txt"
|
45
|
+
do_cmd "git add .git_tracking"
|
46
|
+
GitTracking.highline.should_receive("say")
|
47
|
+
GitTracking.highline.should_receive("say").with("foo.txt")
|
48
|
+
lambda{GitTracking.detect_debuggers}.should_not raise_error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe ".detect_incomplete_merges" do
|
54
|
+
context "configured to reject commits with incomplete merges" do
|
55
|
+
it "should detect incomplete merges and raise IncompleteMergeException" do
|
56
|
+
GitTracking.config.stub(:raise_on_incomplete_merge).and_return(true)
|
57
|
+
make_file "foo.txt", "<<<<<<<", "your changes", "=======", "my changes", ">>>>>>>"
|
58
|
+
do_cmd "git add foo.txt"
|
59
|
+
GitTracking.highline.should_receive("say")
|
60
|
+
GitTracking.highline.should_receive("say").with("foo.txt")
|
61
|
+
lambda{GitTracking.detect_incomplete_merges}.should(
|
62
|
+
raise_error(IncompleteMergeException, "Please complete your merge prior to committing"))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "configured to simply warn about commits with incomplete merges" do
|
67
|
+
it "should detect incomplete merges and raise IncompleteMergeException" do
|
68
|
+
GitTracking.config.stub(:raise_on_incomplete_merge).and_return(false)
|
69
|
+
make_file "foo.txt", "<<<<<<<", "your changes", "=======", "my changes", ">>>>>>>"
|
70
|
+
do_cmd "git add foo.txt"
|
71
|
+
GitTracking.highline.should_receive("say")
|
72
|
+
GitTracking.highline.should_receive("say").with("foo.txt")
|
73
|
+
lambda{GitTracking.detect_incomplete_merges}.should_not(
|
74
|
+
raise_error(IncompleteMergeException, "Please complete your merge prior to committing"))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def make_file(name, *content)
|
81
|
+
f = File.new(name, "w")
|
82
|
+
f.puts *content
|
83
|
+
f.close
|
84
|
+
end
|
85
|
+
|
86
|
+
def do_cmd(command)
|
87
|
+
orig_stdout = $stdout
|
88
|
+
|
89
|
+
# redirect stdout to /dev/null
|
90
|
+
$stdout = File.new('/dev/null', 'w')
|
91
|
+
system command
|
92
|
+
ensure
|
93
|
+
# restore stdout
|
94
|
+
$stdout = orig_stdout
|
95
|
+
end
|
@@ -0,0 +1,254 @@
|
|
1
|
+
require 'git_tracking'
|
2
|
+
require 'ruby-debug'
|
3
|
+
|
4
|
+
describe GitTracking do
|
5
|
+
before(:all) do
|
6
|
+
@original_git_author = `git config --global user.name`.chomp
|
7
|
+
end
|
8
|
+
|
9
|
+
after(:all) do
|
10
|
+
system "git config --global user.name '#{@original_git_author}'"
|
11
|
+
File.delete("foo.txt") if File.exists?("foo.txt")
|
12
|
+
end
|
13
|
+
|
14
|
+
it ".pre_commit should call detect_debuggers and detect_incomplete_merges" do
|
15
|
+
GitTracking.should_receive(:detect_debuggers)
|
16
|
+
GitTracking.should_receive(:detect_incomplete_merges)
|
17
|
+
GitTracking.pre_commit
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".prepare_commit_msg" do
|
21
|
+
it "should get the message" do
|
22
|
+
old_argv = ARGV
|
23
|
+
File.open("foo.txt", "w") do |f|
|
24
|
+
f.print "My awesome commit msg!"
|
25
|
+
end
|
26
|
+
ARGV = ["foo.txt"]
|
27
|
+
GitTracking.stub(:story_info).and_return "[#12345] Best feature evar"
|
28
|
+
GitTracking.stub(:author).and_return "Steve & Ghost Co-Pilot"
|
29
|
+
GitTracking.prepare_commit_msg
|
30
|
+
commit_msg = File.open("foo.txt", "r").read
|
31
|
+
commit_msg.should == <<STRING
|
32
|
+
[#12345] Best feature evar
|
33
|
+
|
34
|
+
- My awesome commit msg!
|
35
|
+
STRING
|
36
|
+
ARGV = old_argv
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should call story_info and author" do
|
40
|
+
ARGV = ["foo.txt"]
|
41
|
+
GitTracking.should_receive(:story_info).and_return "[#12345] Best feature evar"
|
42
|
+
GitTracking.should_receive(:author)
|
43
|
+
GitTracking.prepare_commit_msg
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it ".post_commit should create a comment on the story with the commit msg and hash" do
|
48
|
+
story = mock("story")
|
49
|
+
notes = mock("notes")
|
50
|
+
GitTracking.stub(:get_story).and_return(story)
|
51
|
+
GitTracking.should_not_receive(:story_id)
|
52
|
+
story.should_receive(:notes).and_return(notes)
|
53
|
+
GitTracking.config.should_receive(:last_commit_info).and_return("984752 [#27491] Best commit evar")
|
54
|
+
notes.should_receive(:create).with(:text => "984752 [#27491] Best commit evar")
|
55
|
+
GitTracking.post_commit
|
56
|
+
end
|
57
|
+
|
58
|
+
describe ".story" do
|
59
|
+
before do
|
60
|
+
GitTracking.class_eval{@story = nil}
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should require a story" do
|
64
|
+
the_story = mock('story', :name => 'Best feature evar', :id => 12345)
|
65
|
+
GitTracking.stub(:story_id).and_return("")
|
66
|
+
GitTracking.stub(:get_story).and_return(nil)
|
67
|
+
GitTracking.highline.should_receive(:ask).with("Please enter a valid Pivotal Tracker story id: ", an_instance_of(Proc)).and_return(the_story)
|
68
|
+
GitTracking.config.should_receive(:last_story_id=).with(12345)
|
69
|
+
GitTracking.story.should == the_story
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should not prompt once a story has been confirmed" do
|
73
|
+
the_story = mock('story', :name => 'Best feature evar', :id => 12345)
|
74
|
+
GitTracking.class_eval {@story = the_story}
|
75
|
+
GitTracking.should_not_receive(:highline)
|
76
|
+
GitTracking.story.should == the_story
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should allow you to enter an alternate story when it finds a story_id" do
|
80
|
+
the_story = mock('story', :name => 'Best feature evar', :id => 85918)
|
81
|
+
GitTracking.stub(:story_id).and_return(the_story.id)
|
82
|
+
GitTracking.stub(:get_story).and_return(the_story)
|
83
|
+
GitTracking.config.should_receive(:last_story_id=).with(85918)
|
84
|
+
GitTracking.highline.should_receive(:say).
|
85
|
+
with("Found a valid story id in your branch or commit: 85918 - Best feature evar")
|
86
|
+
GitTracking.highline.should_receive(:ask).
|
87
|
+
with("Hit enter to confirm story id 85918, or enter some other story id: ", an_instance_of(Proc)).
|
88
|
+
and_return(the_story)
|
89
|
+
GitTracking.story.should == the_story
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe ".story_id" do
|
94
|
+
before(:each) do
|
95
|
+
GitTracking.stub(:check_story_id).and_return(true)
|
96
|
+
GitTracking.instance_eval{@story_id = nil}
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should check the commit message for a story id" do
|
100
|
+
GitTracking.stub!(:commit_message).and_return("54261 - Fixing Javascript")
|
101
|
+
GitTracking.story_id.should == '54261'
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should check the branch name for a story id" do
|
105
|
+
GitTracking.stub!(:commit_message).and_return("Fixing Javascript")
|
106
|
+
GitTracking.stub!(:branch).and_return("64371-js-bug")
|
107
|
+
GitTracking.story_id.should == '64371'
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should check the .git/config file for the last story id" do
|
111
|
+
GitTracking.stub!(:commit_message).and_return("Fixing Javascript")
|
112
|
+
GitTracking.config.should_receive(:last_story_id).and_return('35236')
|
113
|
+
GitTracking.story_id.should == '35236'
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should verify the story_id with the pivotal tracker API" do
|
117
|
+
GitTracking.stub!(:commit_message).and_return("Generating 55654 monkeys")
|
118
|
+
GitTracking.stub!(:branch).and_return("64371-js-bug")
|
119
|
+
GitTracking.should_receive(:check_story_id).with('55654').and_return(false)
|
120
|
+
GitTracking.should_receive(:check_story_id).with('64371').and_return(true)
|
121
|
+
GitTracking.story_id.should == "64371"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe ".extract_story_id" do
|
126
|
+
it "should extract any number that is 5 digits or longer and return it" do
|
127
|
+
GitTracking.stub(:check_story_id).and_return(true)
|
128
|
+
GitTracking.extract_story_id("45674 - The best feature evar").should == "45674"
|
129
|
+
GitTracking.extract_story_id("90873 - The best feature evar").should == "90873"
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should return nil if there is no number that is 5 digits or longer" do
|
133
|
+
GitTracking.stub(:check_story_id).and_return(true)
|
134
|
+
GitTracking.extract_story_id("The best feature evar").should be_nil
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should return nil if it's not a valid Pivotal Tracker story id" do
|
138
|
+
GitTracking.stub(:check_story_id).and_return(false)
|
139
|
+
GitTracking.extract_story_id("45674 - The best feature evar").should be_nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe ".pivotal_project" do
|
144
|
+
before(:each) { GitTracking.instance_variable_set("@pivotal_project", nil) }
|
145
|
+
it "should get the token" do
|
146
|
+
project = mock("project")
|
147
|
+
PivotalTracker::Project.should_receive(:find).and_return(project)
|
148
|
+
GitTracking.should_receive(:api_key).and_return("alksjd9123lka")
|
149
|
+
GitTracking.pivotal_project.should == project
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should get and use the project_id from config" do
|
153
|
+
project = mock("project")
|
154
|
+
GitTracking.stub(:api_key)
|
155
|
+
GitTracking.should_receive(:project_id).and_return(1235)
|
156
|
+
PivotalTracker::Project.should_receive(:find).with(1235).and_return(project)
|
157
|
+
GitTracking.pivotal_project.should == project
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe ".project_id" do
|
162
|
+
it "should prompt you to enter the project id if there is none defined" do
|
163
|
+
GitTracking.config.stub(:project_id).ordered.and_return(nil)
|
164
|
+
GitTracking.config.stub(:project_id).with(54876).ordered.and_return(54876)
|
165
|
+
GitTracking.highline.should_receive(:ask).with("Please enter the PivotalTracker project id for this project").and_return(54876)
|
166
|
+
GitTracking.project_id.should == 54876
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should get the project id from the config" do
|
170
|
+
GitTracking.config.should_receive(:project_id).twice.and_return(9712)
|
171
|
+
GitTracking.project_id.should == 9712
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe ".check_story_id" do
|
176
|
+
before(:each) do
|
177
|
+
GitTracking.stub(:api_key).and_return(5678)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should return true for story id that can be found in tracker" do
|
181
|
+
PivotalTracker::Project.stub(:find).and_return(mock("project"))
|
182
|
+
GitTracking.pivotal_project.should_receive(:stories).and_return(mock("stories", :find => mock("story")))
|
183
|
+
GitTracking.check_story_id(5678).should be_true
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should return false for a valid story id" do
|
187
|
+
PivotalTracker::Project.stub(:find).and_return(mock("project"))
|
188
|
+
GitTracking.pivotal_project.should_receive(:stories).and_return(mock("stories", :find => nil))
|
189
|
+
GitTracking.check_story_id(5678).should be_false
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe ".api_key" do
|
194
|
+
before(:each) { GitTracking.instance_eval{ @api_key = nil} }
|
195
|
+
|
196
|
+
it "should prompt for a pivotal login" do
|
197
|
+
GitTracking.config.stub(:emails).and_return(["steve@home.com", "john@doe.com"])
|
198
|
+
GitTracking.config.should_receive(:key_for_email).with("other@work.net").ordered.and_return(nil)
|
199
|
+
GitTracking.config.should_receive(:key_for_email).with("other@work.net", "0987654567").ordered
|
200
|
+
GitTracking.highline.should_receive(:choose).with("steve@home.com", "john@doe.com").and_return("other@work.net")
|
201
|
+
GitTracking.highline.should_receive(:ask).with("Enter your PivotalTracker password: ").and_return("password")
|
202
|
+
PivotalTracker::Client.should_receive(:token).with("other@work.net", "password").and_return("0987654567")
|
203
|
+
GitTracking.api_key.should == "0987654567"
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should prompt you to enter an alternate pivotal login" do
|
207
|
+
GitTracking.config.stub(:emails).and_return(["steve@home.com", "john@doe.com"])
|
208
|
+
GitTracking.config.stub(:key_for_email).and_return("8876567898")
|
209
|
+
GitTracking.highline.should_receive(:choose).with("steve@home.com", "john@doe.com").and_return("steve@home.com")
|
210
|
+
GitTracking.api_key.should == "8876567898"
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should allow you to re-enter your password if authentication fails" do
|
214
|
+
GitTracking.config.stub(:emails).and_return(["steve@home.com", "john@doe.com"])
|
215
|
+
GitTracking.config.stub(:key_for_email).and_return(nil)
|
216
|
+
GitTracking.highline.should_receive(:choose).and_return("other@work.net")
|
217
|
+
GitTracking.highline.should_receive(:ask).exactly(3).times.and_return("password")
|
218
|
+
PivotalTracker::Client.should_receive(:token).exactly(3).times.and_raise(RestClient::Request::Unauthorized)
|
219
|
+
lambda{GitTracking.api_key}.should raise_error(RestClient::Request::Unauthorized)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe ".get_story" do
|
224
|
+
before(:each) do
|
225
|
+
GitTracking.stub(:api_key).and_return(5678)
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should return true for story id that can be found in tracker" do
|
229
|
+
story = mock("story")
|
230
|
+
PivotalTracker::Project.stub(:find).and_return(mock("project"))
|
231
|
+
GitTracking.pivotal_project.should_receive(:stories).and_return(mock("stories", :find => story))
|
232
|
+
GitTracking.get_story(5678).should == story
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should return false for a valid story id" do
|
236
|
+
PivotalTracker::Project.stub(:find).and_return(mock("project"))
|
237
|
+
GitTracking.pivotal_project.should_receive(:stories).and_return(mock("stories", :find => nil))
|
238
|
+
GitTracking.get_story(5678).should be_nil
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
it ".author should present you with an author menu" do
|
243
|
+
GitTracking.instance_eval{ @author = nil }
|
244
|
+
GitTracking.config.stub(:authors).and_return(["Ghost", "Steve"])
|
245
|
+
GitTracking.highline.should_receive(:choose).with("Ghost", "Steve").and_return("Derrick")
|
246
|
+
GitTracking.config.should_receive(:author=).with("Derrick")
|
247
|
+
GitTracking.author.should == "Derrick"
|
248
|
+
end
|
249
|
+
|
250
|
+
it ".story_info should format the story info appropriately" do
|
251
|
+
GitTracking.should_receive(:story).twice.and_return(mock("story", :name => "Best feature evar", :id => "12345"))
|
252
|
+
GitTracking.story_info.should == "[#12345] Best feature evar"
|
253
|
+
end
|
254
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git_tracking
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Steve Hull
|
14
|
+
- Derrick Camerino
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2010-11-08 00:00:00 -08:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: highline
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 3
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
version: "0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: pivotal-tracker
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 3
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
description: "Usage: after installing the gem, in your project directory, run: git_tracking"
|
51
|
+
email:
|
52
|
+
- p.witty@gmail.com
|
53
|
+
- robustdj@gmail.com
|
54
|
+
executables:
|
55
|
+
- git_tracking
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files: []
|
59
|
+
|
60
|
+
files:
|
61
|
+
- .git_tracking
|
62
|
+
- .gitignore
|
63
|
+
- .rspec
|
64
|
+
- Gemfile
|
65
|
+
- Gemfile.lock
|
66
|
+
- README
|
67
|
+
- Rakefile
|
68
|
+
- bin/git_tracking
|
69
|
+
- git_tracking.gemspec
|
70
|
+
- hooks/post-commit
|
71
|
+
- hooks/pre-commit
|
72
|
+
- hooks/prepare-commit-msg
|
73
|
+
- lib/git_tracking.rb
|
74
|
+
- lib/git_tracking/config.rb
|
75
|
+
- lib/git_tracking/detect.rb
|
76
|
+
- lib/git_tracking/version.rb
|
77
|
+
- spec/config_spec.rb
|
78
|
+
- spec/detect_spec.rb
|
79
|
+
- spec/git_tracking_spec.rb
|
80
|
+
has_rdoc: true
|
81
|
+
homepage: http://rubygems.org/gems/git_tracking
|
82
|
+
licenses: []
|
83
|
+
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
requirements: []
|
108
|
+
|
109
|
+
rubyforge_project: git_tracking
|
110
|
+
rubygems_version: 1.3.7
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: Better integration between git and PivotalTracker
|
114
|
+
test_files:
|
115
|
+
- spec/config_spec.rb
|
116
|
+
- spec/detect_spec.rb
|
117
|
+
- spec/git_tracking_spec.rb
|