git_tracking 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/.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
|