git-blame-game 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .idea
6
+ test/fixtures/sample_git_repo
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.3
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'rake'
4
+
5
+ # Specify your gem's dependencies in git-blame-game.gemspec
6
+ gemspec
data/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # git-blame-game
2
+
3
+ <img src="https://github.com/charleseff/git-blame-game/raw/master/public/pensive-kanye.png" />
4
+
5
+ git-blame-game is an interactive command-line tool for chaining 'git blame' calls to drill-down to the real culprit for the line of code you care about. When one `git blame` does not tell the whole story.
6
+
7
+ ## Installation:
8
+
9
+ gem install git-blame-game
10
+
11
+ ## Usage:
12
+
13
+ git-blame-game --help
14
+
15
+ ## Example:
16
+
17
+ $ git-blame-game add.rb
18
+
19
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 1) module Add
20
+ 5087eab5 (Danny Dover 2012-01-14 14:50:06 -0800 2) def add_4(y)
21
+ 5087eab5 (Danny Dover 2012-01-14 14:50:06 -0800 3) y + 5
22
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 4) end
23
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 5) end
24
+
25
+ Which line are you concerned with? (1 to 5) > 3
26
+
27
+ commit 5087eab56af9b0901a1b190de14f29867307c140 (HEAD, master)
28
+ Author: Danny Dover <developers+danny@foo.com>
29
+ Date: Sat Jan 14 14:50:06 2012 -0800
30
+
31
+ I like y's better
32
+
33
+ diff --git a/add.rb b/add.rb
34
+ index 44be98f..898a812 100644
35
+ --- a/add.rb
36
+ +++ b/add.rb
37
+ @@ -1,5 +1,5 @@
38
+ module Add
39
+ - def add_4(x)
40
+ - x + 5
41
+ + def add_4(y)
42
+ + y + 5
43
+ end
44
+ end
45
+
46
+
47
+ Do you need to git blame chain further (y/n) > y
48
+
49
+ 1) add.rb
50
+
51
+ Enter the number (from 1 to 1) of the file to git blame chain into > 1
52
+
53
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 1) module Add
54
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 2) def add_4(x)
55
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 3) x + 5
56
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 4) end
57
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 5) end
58
+
59
+ Which line are you concerned with? (1 to 5) > 3
60
+
61
+ commit de2a1d78f80e02a515cdd3aa0420dd6ee35b510b
62
+ Author: Carmen Cummings <developers+carmen@foo.com>
63
+ Date: Sat Jan 14 14:49:00 2012 -0800
64
+
65
+ moving add_4 to module
66
+
67
+ diff --git a/add.rb b/add.rb
68
+ new file mode 100644
69
+ index 0000000..44be98f
70
+ --- /dev/null
71
+ +++ b/add.rb
72
+ @@ -0,0 +1,5 @@
73
+ +module Add
74
+ + def add_4(x)
75
+ + x + 5
76
+ + end
77
+ +end
78
+
79
+ diff --git a/blah.rb b/blah.rb
80
+ index 0424947..38b7511 100644
81
+ --- a/blah.rb
82
+ +++ b/blah.rb
83
+ @@ -1,5 +1,5 @@
84
+ -def add_4(x)
85
+ - x + 5
86
+ -end
87
+ +$:.unshift(File.dirname(__FILE__))
88
+ +require 'add'
89
+ +include Add
90
+
91
+ puts add_4(9) # should be 13
92
+
93
+
94
+ Do you need to git blame chain further (y/n) > y
95
+
96
+ 1) add.rb
97
+ 2) blah.rb
98
+
99
+ Enter the number (from 1 to 2) of the file to git blame chain into > 2
100
+
101
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 1) def add_4(x)
102
+ 63b41ee4 (Bob Barker 2012-01-14 14:46:53 -0800 2) x + 5
103
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 3) end
104
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 4)
105
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 5) puts add_4(9) # should be 13
106
+
107
+ Which line are you concerned with? (1 to 5) > 2
108
+
109
+ commit 63b41ee41653991aa00ce9687e3f403efd4c29d4
110
+ Author: Bob Barker <developers+bob@foo.com>
111
+ Date: Sat Jan 14 14:46:53 2012 -0800
112
+
113
+ being bad
114
+
115
+ diff --git a/blah.rb b/blah.rb
116
+ index 626a42b..0424947 100644
117
+ --- a/blah.rb
118
+ +++ b/blah.rb
119
+ @@ -1,5 +1,5 @@
120
+ def add_4(x)
121
+ - x + 4
122
+ + x + 5
123
+ end
124
+
125
+ puts add_4(9) # should be 13
126
+
127
+
128
+ Do you need to git blame chain further (y/n) > n
129
+
130
+ The responsible commit is:
131
+
132
+ commit 63b41ee41653991aa00ce9687e3f403efd4c29d4
133
+ Author: Bob Barker <developers+bob@foo.com>
134
+ Date: Sat Jan 14 14:46:53 2012 -0800
135
+
136
+ being bad
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
3
+
4
+ require "rubygems"
5
+ require 'colorize'
6
+ require 'optparse'
7
+ require 'git-blame-game/git_blame_game'
8
+
9
+ options = {}
10
+ OptionParser.new do |opts|
11
+ opts.banner = <<-END.gsub(/^[ \t]+/m, '')
12
+ Usage: git-blame-game [options] path/to/filename
13
+ END
14
+
15
+ opts.separator ""
16
+ opts.separator "Options:"
17
+
18
+ opts.on("-s", "--sha", "--SHA [SHA]", String, "Set initial SHA (defaults to HEAD)") do |sha|
19
+ options[:sha] = sha
20
+ end
21
+
22
+ opts.on_tail("-h", "--help", "Show this message") do
23
+ puts opts
24
+ exit
25
+ end
26
+
27
+ end.parse!
28
+
29
+ path_to_file = ARGV[0]
30
+ raise OptionParser::MissingArgument.new("You must specify a path to a file ") if not path_to_file
31
+
32
+ GitBlameGame.new(path_to_file, options).run
@@ -0,0 +1,195 @@
1
+ Feature: Blaming
2
+
3
+ Scenario: Getting help
4
+ When I run `bin/git-blame-game --help`
5
+ Then it should pass with:
6
+ """
7
+ Usage: git-blame-game [options] path/to/filename
8
+ """
9
+
10
+ Scenario: Without a filepath:
11
+ When I run `bin/git-blame-game`
12
+ Then it should fail with:
13
+ """
14
+ missing argument: You must specify a path to a file
15
+ """
16
+
17
+ Scenario: Specifying a file that doesn't exist:
18
+ When I run `bin/git-blame-game file/that/doesnt/exist.rb`
19
+ Then it should fail with:
20
+ """
21
+ fatal: no such path file/that/doesnt/exist.rb in HEAD
22
+ """
23
+
24
+ Scenario: Without a SHA:
25
+ Given I cd to "test/fixtures/sample_git_repo"
26
+ When I run `../../../bin/git-blame-game add.rb` interactively
27
+ When I type "foobar"
28
+ When I type "3"
29
+ When I type "blah"
30
+ When I type "y"
31
+ When I type "1"
32
+ When I type "3"
33
+ When I type "y"
34
+ When I type "2"
35
+ When I type "2"
36
+ When I type "n"
37
+ Then the output should contain, ignoring spaces:
38
+ """
39
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 1) module Add
40
+ 5087eab5 (Danny Dover 2012-01-14 14:50:06 -0800 2) def add_4(y)
41
+ 5087eab5 (Danny Dover 2012-01-14 14:50:06 -0800 3) y + 5
42
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 4) end
43
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 5) end
44
+
45
+ Which line are you concerned with? (1 to 5) >
46
+ Invalid input. Enter a number from 1 to 5 >
47
+ commit 5087eab56af9b0901a1b190de14f29867307c140 (HEAD, master)
48
+ Author: Danny Dover <developers+danny@foo.com>
49
+ Date: Sat Jan 14 14:50:06 2012 -0800
50
+
51
+ I like y's better
52
+
53
+ diff --git a/add.rb b/add.rb
54
+ index 44be98f..898a812 100644
55
+ --- a/add.rb
56
+ +++ b/add.rb
57
+ @@ -1,5 +1,5 @@
58
+ module Add
59
+ - def add_4(x)
60
+ - x + 5
61
+ + def add_4(y)
62
+ + y + 5
63
+ end
64
+ end
65
+
66
+
67
+ Do you need to git blame chain further (y/n) >
68
+ Invalid input. Enter y or n >
69
+ 1) add.rb
70
+
71
+ Enter the number (from 1 to 1) of the file to git blame chain into >
72
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 1) module Add
73
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 2) def add_4(x)
74
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 3) x + 5
75
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 4) end
76
+ de2a1d78 (Carmen Cummings 2012-01-14 14:49:00 -0800 5) end
77
+
78
+ Which line are you concerned with? (1 to 5) >
79
+ commit de2a1d78f80e02a515cdd3aa0420dd6ee35b510b
80
+ Author: Carmen Cummings <developers+carmen@foo.com>
81
+ Date: Sat Jan 14 14:49:00 2012 -0800
82
+
83
+ moving add_4 to module
84
+
85
+ diff --git a/add.rb b/add.rb
86
+ new file mode 100644
87
+ index 0000000..44be98f
88
+ --- /dev/null
89
+ +++ b/add.rb
90
+ @@ -0,0 +1,5 @@
91
+ +module Add
92
+ + def add_4(x)
93
+ + x + 5
94
+ + end
95
+ +end
96
+
97
+ diff --git a/blah.rb b/blah.rb
98
+ index 0424947..38b7511 100644
99
+ --- a/blah.rb
100
+ +++ b/blah.rb
101
+ @@ -1,5 +1,5 @@
102
+ -def add_4(x)
103
+ - x + 5
104
+ -end
105
+ +$:.unshift(File.dirname(__FILE__))
106
+ +require 'add'
107
+ +include Add
108
+
109
+ puts add_4(9) # should be 13
110
+
111
+
112
+ Do you need to git blame chain further (y/n) >
113
+ 1) add.rb
114
+ 2) blah.rb
115
+
116
+ Enter the number (from 1 to 2) of the file to git blame chain into >
117
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 1) def add_4(x)
118
+ 63b41ee4 (Bob Barker 2012-01-14 14:46:53 -0800 2) x + 5
119
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 3) end
120
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 4)
121
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 5) puts add_4(9) # should be 13
122
+
123
+ Which line are you concerned with? (1 to 5) >
124
+ commit 63b41ee41653991aa00ce9687e3f403efd4c29d4
125
+ Author: Bob Barker <developers+bob@foo.com>
126
+ Date: Sat Jan 14 14:46:53 2012 -0800
127
+
128
+ being bad
129
+
130
+ diff --git a/blah.rb b/blah.rb
131
+ index 626a42b..0424947 100644
132
+ --- a/blah.rb
133
+ +++ b/blah.rb
134
+ @@ -1,5 +1,5 @@
135
+ def add_4(x)
136
+ - x + 4
137
+ + x + 5
138
+ end
139
+
140
+ puts add_4(9) # should be 13
141
+
142
+
143
+ Do you need to git blame chain further (y/n) >
144
+ The responsible commit is:
145
+
146
+ commit 63b41ee41653991aa00ce9687e3f403efd4c29d4
147
+ Author: Bob Barker <developers+bob@foo.com>
148
+ Date: Sat Jan 14 14:46:53 2012 -0800
149
+
150
+ being bad
151
+
152
+ """
153
+
154
+ Scenario: With a SHA:
155
+ Given I cd to "test/fixtures/sample_git_repo"
156
+ When I run `../../../bin/git-blame-game blah.rb --sha=63b41ee41653991aa00ce9687e3f403efd4c29d4` interactively
157
+ When I type "2"
158
+ When I type "n"
159
+ Then the output should contain, ignoring spaces:
160
+ """
161
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 1) def add_4(x)
162
+ 63b41ee4 (Bob Barker 2012-01-14 14:46:53 -0800 2) x + 5
163
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 3) end
164
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 4)
165
+ ^f603a9a (Alice Amos 2012-01-14 14:46:18 -0800 5) puts add_4(9) # should be 13
166
+
167
+ Which line are you concerned with? (1 to 5) >
168
+ commit 63b41ee41653991aa00ce9687e3f403efd4c29d4
169
+ Author: Bob Barker <developers+bob@foo.com>
170
+ Date: Sat Jan 14 14:46:53 2012 -0800
171
+
172
+ being bad
173
+
174
+ diff --git a/blah.rb b/blah.rb
175
+ index 626a42b..0424947 100644
176
+ --- a/blah.rb
177
+ +++ b/blah.rb
178
+ @@ -1,5 +1,5 @@
179
+ def add_4(x)
180
+ - x + 4
181
+ + x + 5
182
+ end
183
+
184
+ puts add_4(9) # should be 13
185
+
186
+
187
+ Do you need to git blame chain further (y/n) >
188
+ The responsible commit is:
189
+
190
+ commit 63b41ee41653991aa00ce9687e3f403efd4c29d4
191
+ Author: Bob Barker <developers+bob@foo.com>
192
+ Date: Sat Jan 14 14:46:53 2012 -0800
193
+
194
+ being bad
195
+ """
@@ -0,0 +1,3 @@
1
+ Then /^the output should contain, ignoring spaces:$/ do |expected|
2
+ assert_partial_output(expected.gsub("\s",''), all_output.gsub("\s",''))
3
+ end
@@ -0,0 +1,20 @@
1
+ require 'aruba/cucumber'
2
+
3
+ def unzip_git_repo_if_needed!
4
+ fixtures_dir = File.expand_path(File.dirname(__FILE__)) + '/../../test/fixtures'
5
+ unless File.directory? fixtures_dir + '/sample_git_repo'
6
+ `unzip #{fixtures_dir}/sample_git_repo.zip -d #{fixtures_dir}`
7
+ end
8
+ end
9
+
10
+ # for some reason Aruba sets the default dir to 'tmp/aruba'. Override this:
11
+ def set_relative_dir_for_aruba!
12
+ root_dir = File.expand_path("../../../", __FILE__)
13
+ self.instance_variable_set('@dirs', [root_dir])
14
+ end
15
+
16
+ Before do
17
+ unzip_git_repo_if_needed!
18
+
19
+ set_relative_dir_for_aruba!
20
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "git-blame-game/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "git-blame-game"
7
+ s.version = Git::Blame::Game::VERSION
8
+ s.authors = ["Charles Finkel"]
9
+ s.email = ["charles.finkel@gmail.com"]
10
+ s.homepage = "https://github.com/charleseff/git-blame-game"
11
+ s.summary = %q{git-blame-game is an interactive command for chaining 'git blame' calls to get to the real culprit for the line of code you care about, when one `git blame` does not tell the whole story.}
12
+ s.description = %q{When one `git blame` is not enough}
13
+
14
+ s.rubyforge_project = "git-blame-game"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency 'aruba'
22
+ s.add_runtime_dependency 'colorize'
23
+ end
@@ -0,0 +1,80 @@
1
+ class GitBlameGame
2
+ def initialize(path_to_file, opts={})
3
+ @path_to_file = path_to_file
4
+ @sha = !opts[:sha].nil? ? opts[:sha] : 'HEAD'
5
+ end
6
+
7
+ def run
8
+ while loop;
9
+ end
10
+ end
11
+
12
+ GIT_BLAME_REGEX = /(.+?) /
13
+
14
+ def loop
15
+ puts
16
+ out = run_idempotent_git_command("git blame #{@sha} -- #{@path_to_file}")
17
+ exit $?.exitstatus unless $?.success?
18
+
19
+ lines = out.split("\n")
20
+ count = lines.count
21
+
22
+ line = prompt_for_line(count)
23
+ sha_to_show = lines[line-1][GIT_BLAME_REGEX, 1]
24
+
25
+ puts
26
+ system "git show #{sha_to_show}"
27
+ files_changed = `git show --pretty="format:" --name-only #{sha_to_show}`.split("\n")[1..-1]
28
+
29
+ @path_to_file = prompt_for_file(files_changed,sha_to_show)
30
+ @sha = "#{sha_to_show}^"
31
+
32
+ true
33
+ end
34
+
35
+ def prompt_for_file(files_changed,sha)
36
+ print "\n" + gbc_color("Do you need to git blame chain further (y/n) >") + ' '
37
+ input = $stdin.gets.strip.downcase
38
+ until %w{y n}.include?(input)
39
+ print "\n" + gbc_color("Invalid input. Enter y or n >") + ' '
40
+ input = $stdin.gets.strip.downcase
41
+ end
42
+
43
+ if input == 'n'
44
+ print "\n" + gbc_color("The responsible commit is:") + "\n\n"
45
+ system "git log #{sha} -n 1"
46
+ exit 0
47
+ end
48
+
49
+ puts
50
+ files_changed.each_with_index do |file,index|
51
+ "%-10s %-12s %-15s %-48s %-s\n"
52
+ printf("%3d) #{file}\n", index+1)
53
+ end
54
+
55
+ print "\n" + gbc_color("Enter the number (from 1 to #{files_changed.size}) of the file to git blame chain into >") + ' '
56
+ until (input = $stdin.gets.strip.to_i) >= 1 && input <= files_changed.size
57
+ print "\n" + gbc_color("Invalid input. Enter a number from 1 to #{files_changed.size} >") + ' '
58
+ end
59
+
60
+ return files_changed[input-1]
61
+
62
+ end
63
+
64
+ def prompt_for_line(count)
65
+ print "\n" + gbc_color("Which line are you concerned with? (1 to #{count}) >") + ' '
66
+ until (input = $stdin.gets.strip.to_i) >= 1 && input <= count
67
+ print "\n" + gbc_color("Invalid input. Enter a number from 1 to #{count} >") + ' '
68
+ end
69
+ input
70
+ end
71
+
72
+ def run_idempotent_git_command(cmd)
73
+ system cmd
74
+ `#{cmd}`
75
+ end
76
+
77
+ def gbc_color(s)
78
+ s.colorize(:color => :light_white, :background => :magenta)
79
+ end
80
+ end
@@ -0,0 +1,7 @@
1
+ module Git
2
+ module Blame
3
+ module Game
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,2 @@
1
+ # Load nothing - just keep the file here to keep bundler happy.
2
+
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git-blame-game
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Charles Finkel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: aruba
16
+ requirement: &18572720 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *18572720
25
+ - !ruby/object:Gem::Dependency
26
+ name: colorize
27
+ requirement: &18572180 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *18572180
36
+ description: When one `git blame` is not enough
37
+ email:
38
+ - charles.finkel@gmail.com
39
+ executables:
40
+ - git-blame-game
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - .gitignore
45
+ - .rvmrc
46
+ - Gemfile
47
+ - README.md
48
+ - Rakefile
49
+ - bin/git-blame-game
50
+ - features/blaming.feature
51
+ - features/step_definitions/gbc_steps.rb
52
+ - features/support/env.rb
53
+ - git-blame-game.gemspec
54
+ - lib/git-blame-game.rb
55
+ - lib/git-blame-game/git_blame_game.rb
56
+ - lib/git-blame-game/version.rb
57
+ - public/pensive-kanye.png
58
+ - test/fixtures/sample_git_repo.zip
59
+ homepage: https://github.com/charleseff/git-blame-game
60
+ licenses: []
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project: git-blame-game
79
+ rubygems_version: 1.8.10
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: git-blame-game is an interactive command for chaining 'git blame' calls to
83
+ get to the real culprit for the line of code you care about, when one `git blame`
84
+ does not tell the whole story.
85
+ test_files: []