deep_blame 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c52613a60cc0b6ffdd9b5e12abc743061f9aeab2
4
+ data.tar.gz: bea17f625b0e37cc4910ec22fbaca95a3cf6e218
5
+ SHA512:
6
+ metadata.gz: 79a3d40b6833cc811fbec76fa94a4c16b4866c41146f361484125ea96acde0fcae977c62dbe9280660232fc8a635439fa393c6be62bcd0d09d447cbb329dac26
7
+ data.tar.gz: d6d44fc2fb07ead97dba95860fcf38254be20371451843f9946ece391e430c4140f30cf9dd8768f4c1335135d98bfa9a00ebe740047e851dadb927bed3036d7b
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in deep_blame.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Sam Schenkman-Moore
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # DeepBlame
2
+
3
+ Look at the blame before the blame (before the blame...).
4
+
5
+ Bit of an experiment. No tests, you might die.
6
+
7
+ ## Installation
8
+
9
+ gem install deep_blame
10
+
11
+ ## Usage
12
+
13
+ deep_blame path line_number
14
+ deep_blame path start_line,end_line
15
+ deep_blame path line_number --display=ids
16
+
17
+ ### Display Options
18
+
19
+ * ids (space separated list of ids)
20
+ * commits (fairly readable list of commits)
21
+ * full (shows whole, multi-line commit message)
22
+ * default (full commit messages, linebreaks removed)
23
+
24
+ ## Contributing
25
+
26
+ 1. Fork it
27
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
28
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
29
+ 4. Push to the branch (`git push origin my-new-feature`)
30
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/deep_blame ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "..")) + "/lib/deep_blame"
4
+
5
+ begin
6
+ start_line, end_line = ARGV[1].split(",")
7
+ rescue
8
+ puts "format: deep_blame <filepath> <startline>,<endline(optional)>"
9
+ exit
10
+ end
11
+
12
+ raw_options = ARGV[2..-1] || Array.new
13
+ options = raw_options.inject({}) do |opts, o|
14
+ k,v = o.split("=")
15
+ opts[k.sub(/\A-+/,'').to_sym] = v || true
16
+ opts
17
+ end
18
+
19
+ DeepBlame.line_history(ARGV.first, start_line, end_line, 'HEAD', options)
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'deep_blame/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "deep_blame"
8
+ spec.version = DeepBlame::VERSION
9
+ spec.authors = ["Sam Schenkman-Moore"]
10
+ spec.email = ["samsm@samsm.com"]
11
+ spec.description = %q{Recursive blame.}
12
+ spec.summary = %q{Recursive blame.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,3 @@
1
+ module DeepBlame
2
+ VERSION = "0.0.1"
3
+ end
data/lib/deep_blame.rb ADDED
@@ -0,0 +1,131 @@
1
+ require 'pry'
2
+ require_relative "deep_blame/version"
3
+
4
+ module DeepBlame
5
+ def self.line_history(path, start_line, end_line = nil, rev = 'HEAD', options)
6
+ blames = Blame.find_recursive_uniq(rev, path, start_line, end_line)
7
+ blames.each do |b|
8
+ case options[:display]
9
+ when "ids"
10
+ display_ids(b)
11
+ when "commits"
12
+ display_commit_messages(b)
13
+ when "full"
14
+ display_full_commit_messages(b)
15
+ else
16
+ display_full_concise(b)
17
+ end
18
+ end
19
+ puts if options[:display] == "ids"
20
+ end
21
+
22
+ def self.display_commit_messages(blame)
23
+ puts "#{blame.short_sha} (#{blame.committed_at.to_date}): #{blame.summary} <#{blame.author}> "
24
+ end
25
+
26
+ def self.display_ids(blame)
27
+ print "#{blame.short_sha} "
28
+ end
29
+
30
+ def self.display_full_commit_messages(blame)
31
+ puts "#{blame.short_sha}: <#{blame.author}>"
32
+ puts commit_message(blame.sha)
33
+ end
34
+
35
+ def self.commit_message(sha)
36
+ result = `git show #{sha}`
37
+ result.sub(/\A[\S\s]+^Date.+/,'').sub(/^diff[\S\s]+\Z/,'')
38
+ end
39
+
40
+ def self.display_full_concise(blame)
41
+ puts "#{blame.short_sha}: <#{blame.author}>"
42
+ message = commit_message(blame.sha)
43
+ puts message.gsub(/\s+/, ' ')
44
+ end
45
+
46
+ class Blame
47
+ def self.find(rev, path, start_line, end_line = nil)
48
+ end_line ||= start_line
49
+ command = "git blame -b --incremental -l -L #{start_line},#{end_line} #{rev} #{path}"
50
+ # puts "Running: #{command}"
51
+ result = `#{command}`
52
+ segments = result.scan(/[\s\S]+?filename.+/)
53
+ segments.collect do |segment|
54
+ new parse_segment(segment)
55
+ end
56
+ end
57
+
58
+ def self.find_recursive_uniq(*args)
59
+ result = find(*args)
60
+ result.collect {|r| r.recursive }.flatten.uniq {|b| b.sha }
61
+ end
62
+
63
+ def self.parse_segment(blame)
64
+ first_line = blame.slice!(/.+/)
65
+ hsh = [:sha, :line_number_original_file, :line_number_final_file,
66
+ :line_number_group].inject({}) do |h, attr|
67
+ h[attr] = first_line.slice!(/\w+/) ; h
68
+ end
69
+ hsh[:line_number_group] = nil if hsh[:line_number_group] == 0
70
+ blame.strip.split("\n").inject(hsh) do |h, line|
71
+ key = line.slice!(/\S+/)
72
+ key = key.gsub("-","_").to_sym
73
+ h[key] = line.strip.empty? ? true : line.strip
74
+ h
75
+ end
76
+ end
77
+
78
+ attr_reader :data
79
+ def initialize(data)
80
+ @data = data
81
+ end
82
+
83
+ [:sha, :line_number_original_file, :line_number_final_file, :line_number_group,
84
+ :author, :author_mail, :author_time, :author_tz, :committer, :committer_mail,
85
+ :committer_time, :committer_tz, :summary, :boundary, :filename,
86
+ :previous].each do |attr|
87
+ define_method attr do
88
+ data[attr]
89
+ end
90
+ end
91
+
92
+ def recursive
93
+ all = [self]
94
+ all += parent.recursive if parent
95
+ all
96
+ end
97
+
98
+ def committed_at
99
+ @committed_at ||= Time.at(committer_time.to_i)
100
+ end
101
+
102
+ def short_sha
103
+ sha[0..6]
104
+ end
105
+
106
+ def previous?
107
+ previous # or !boundary # ?
108
+ end
109
+
110
+ def previous_sha
111
+ previous[/^\S+/]
112
+ end
113
+
114
+ def previous_file
115
+ previous.sub(/^\S+\s+/,'')
116
+ end
117
+
118
+ def previous_line_number
119
+ line_number_original_file
120
+ end
121
+
122
+ # rev, path, start_line, end_line = nil
123
+ def parent
124
+ if previous?
125
+ @parent_results = self.class.find(previous_sha, previous_file, previous_line_number)
126
+ puts "#{@parent_result.length} results for #{previous_sha}. Interesting." if @parent_results.length > 1
127
+ @parent_results.first
128
+ end
129
+ end
130
+ end
131
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: deep_blame
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sam Schenkman-Moore
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Recursive blame.
42
+ email:
43
+ - samsm@samsm.com
44
+ executables:
45
+ - deep_blame
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - .gitignore
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - bin/deep_blame
55
+ - deep_blame.gemspec
56
+ - lib/deep_blame.rb
57
+ - lib/deep_blame/version.rb
58
+ homepage: ''
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.1.11
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Recursive blame.
82
+ test_files: []