git_spelunk 0.4.1 → 0.5.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1b01cdc9019c68eea06ac6c29c082825ca79fe38
4
- data.tar.gz: 3b735af021fb4cc09e22ee3f27658094bf87c70f
2
+ SHA256:
3
+ metadata.gz: ee9a524ce1012243516ff781bc7ab085710b9201b1fa0781745a97727a5c4a13
4
+ data.tar.gz: ce58f6b2738fa29f294e2c7ef0ee59ced41c642be2ea5f538eb91a4864feec50
5
5
  SHA512:
6
- metadata.gz: 977b086900391210e36e91eda889a68c9327ca0e84cab598dcc51ca071658f30163ac797f650e096fbd2e410e25f767d5a9b2cf13d24b53a912b9f1ccffc5a8a
7
- data.tar.gz: 30d809b6d384b71491be31d48501f435ad2de9f8dd61cbdba87ca4ac80c7e016a7e5f832cd565316ae7d99724d289d01aa593293d99ac47683322612bbb38421
6
+ metadata.gz: ffb7863801c8fcadc0ded69633bc09f5da9f5859bab2a935aa9b80dba7721720e4549d09737f62b203c6e256dd20b801303f45fdb2fc8ea976625972af24b13c
7
+ data.tar.gz: c81a7be76968ed1830a9cbe17918daae13d2ac6105d0c694014da575276aeae996eb33ce68d8ed22d04539c8178d6f31fe9b9891f6256258184990dc46ab4310
data/bin/git-spelunk CHANGED
@@ -25,8 +25,8 @@ end
25
25
 
26
26
  options = parse_options(ARGV)
27
27
 
28
- raise "No filename specified. You must provide a file to blame-on." if ARGV.size == 0
29
- raise "Too many arguments" if ARGV.size > 1
28
+ abort "No filename specified. You must provide a file to blame-on." if ARGV.size == 0
29
+ abort "Too many arguments" if ARGV.size > 1
30
30
 
31
31
  file = ARGV[0]
32
32
 
@@ -1,7 +1,23 @@
1
+ require 'open3'
2
+
1
3
  module GitSpelunk
2
4
  BlameLine = Struct.new(:line_number, :old_line_number, :sha, :commit, :filename, :content)
3
5
  class EmptyBlame < StandardError ; end
4
- class Blame < Grit::Blame
6
+ class Blame
7
+ def initialize(repo, file, sha)
8
+ @lines = nil
9
+ @repo = repo
10
+ @file = file
11
+ @sha = sha
12
+ end
13
+
14
+ def lines
15
+ return @lines if @lines
16
+ cmd = ["git", "--git-dir", @repo.path, "blame", "--porcelain", @sha, "--", @file]
17
+ output, err, status = Open3.capture3(*cmd)
18
+ @lines ||= process_raw_blame(output)
19
+ end
20
+
5
21
  def process_raw_blame(output)
6
22
  lines = []
7
23
  commits = {}
@@ -17,8 +33,7 @@ module GitSpelunk
17
33
 
18
34
  sha, old_lineno, lineno = sha_split[0], sha_split[1].to_i, sha_split[2].to_i
19
35
 
20
- # indicate we need to fetch this sha in the bulk-fetch
21
- commits[sha] = nil
36
+ commits[sha] ||= @repo.lookup(sha)
22
37
 
23
38
  if rest =~ /^filename (.*)$/
24
39
  commit_file_map[sha] = $1
@@ -28,16 +43,9 @@ module GitSpelunk
28
43
  { :data => data, :sha => sha, :filename => commit_file_map[sha], :old_line_number => old_lineno, :line_number => lineno }
29
44
  end
30
45
 
31
-
32
- # load all commits in single call
33
- @repo.batch(*commits.keys).each do |commit|
34
- commits[commit.id] = commit
35
- end
36
-
37
- @lines = lines.map do |hash|
46
+ lines.map do |hash|
38
47
  GitSpelunk::BlameLine.new(hash[:line_number], hash[:old_line_number], hash[:sha], commits[hash[:sha]], hash[:filename], hash[:data])
39
48
  end
40
49
  end
41
50
  end
42
51
  end
43
-
@@ -1,4 +1,4 @@
1
- require 'grit'
1
+ require 'rugged'
2
2
  require 'fileutils'
3
3
  require 'git_spelunk/blame'
4
4
 
@@ -12,12 +12,10 @@ module GitSpelunk
12
12
  @line_number = options[:line_number] || 1
13
13
 
14
14
  @repo = options.fetch(:repo) do
15
- repo_directory = find_repo_from_file(file)
16
- @file = File.expand_path(file).sub(%r{^#{repo_directory}/}, '')
17
- Grit::Repo.new(repo_directory)
15
+ find_repo_from_file(file)
18
16
  end
19
17
 
20
- @file ||= options.fetch(:file)
18
+ @file = File.expand_path(file).sub(@repo.workdir, '')
21
19
  @commit_cache = {}
22
20
  end
23
21
 
@@ -32,18 +30,7 @@ module GitSpelunk
32
30
  end
33
31
 
34
32
  def find_repo_from_file(file)
35
- file = './' + file unless file.start_with?('/')
36
- targets = File.expand_path(file).split('/')
37
- targets.pop
38
- while !File.directory?(targets.join("/") + "/.git")
39
- targets.pop
40
- end
41
-
42
- if targets.empty?
43
- nil
44
- else
45
- targets.join("/")
46
- end
33
+ Rugged::Repository.discover(file)
47
34
  end
48
35
 
49
36
  def get_blame
@@ -58,15 +45,17 @@ module GitSpelunk
58
45
  get_blame
59
46
  commit = blame_line.commit
60
47
  return nil unless commit
61
-
62
- author_info = commit.author_string.split(" ")
63
- tz = author_info.pop
64
- utc = Time.at(author_info.pop.to_i)
65
- [
66
- "commit " + commit.id,
67
- "Author: " + author_info.join(" "),
68
- "Date: " + utc.to_s
69
- ].join("\n") + "\n\n" + " " + commit.short_message
48
+ author = commit.author
49
+
50
+ author_info = "%s %s" % [author[:name], author[:email]]
51
+ short_message = commit.message.split("\n").find { |x| !x.strip.empty? } || ''
52
+ utc = author[:time]
53
+ {
54
+ commit: commit.oid,
55
+ author: author_info,
56
+ date: author[:time].to_s,
57
+ message: commit.message
58
+ }
70
59
  end
71
60
  end
72
61
  end
@@ -33,17 +33,16 @@
33
33
 
34
34
 
35
35
  module GitSpelunk
36
- require 'grit'
37
-
38
36
  class Offset
39
- attr_reader :repo, :file_name, :sha, :chunks
37
+ attr_reader :repo, :file_name, :sha, :hunks
40
38
 
41
39
  def initialize(repo, file_name, sha, line_number)
42
40
  @repo = repo
43
41
  @file_name = file_name
44
42
  @sha = sha
45
43
  @line_number = line_number
46
- @parent = @repo.commits(@sha)[0].parents[0]
44
+ @commit = @repo.lookup(@sha)
45
+ @parent = @commit.parents[0]
47
46
  true
48
47
  end
49
48
 
@@ -51,9 +50,13 @@ module GitSpelunk
51
50
  class Chunk
52
51
  attr_reader :minus_offset, :minus_length, :plus_offset, :plus_length, :lines
53
52
 
54
- def initialize(data)
55
- @minus_offset, @minus_length, @plus_offset, @plus_length = *extract_stats(data[0])
56
- @lines = data[1..-1]
53
+ def initialize(hunk)
54
+ @minus_offset = hunk.old_start
55
+ @minus_length = hunk.old_lines
56
+ @plus_offset = hunk.new_start
57
+ @plus_length = hunk.new_lines
58
+
59
+ @lines = hunk.lines
57
60
  end
58
61
 
59
62
  def has_line?(line_number)
@@ -66,7 +69,7 @@ module GitSpelunk
66
69
  end
67
70
 
68
71
  def type
69
- data.first[0]
72
+ data.first.line_origin
70
73
  end
71
74
 
72
75
  def size
@@ -79,6 +82,7 @@ module GitSpelunk
79
82
  end
80
83
 
81
84
  def find_parent_line_number(target)
85
+ return 1 if target == 1
82
86
  # separate in blocks of lines with the same prefix
83
87
 
84
88
  old_line_number = minus_offset
@@ -86,16 +90,15 @@ module GitSpelunk
86
90
 
87
91
  blocks = []
88
92
  lines.each do |l|
89
- next if l =~ /\/
90
93
  last_block = blocks.last
91
94
 
92
- if last_block.nil? || last_block.type != l[0]
95
+ if last_block.nil? || last_block.type != l.line_origin
93
96
  blocks << LineBlock.new(old_line_number, l)
94
97
  else
95
98
  last_block << l
96
99
  end
97
100
 
98
- if l[0] == "+" || l[0] == " "
101
+ if l.line_origin == :context || l.line_origin == :addition
99
102
  if new_line_number == target
100
103
  # important: we don't finish building the structure.
101
104
  break
@@ -104,7 +107,7 @@ module GitSpelunk
104
107
  new_line_number += 1
105
108
  end
106
109
 
107
- if l[0] == "-" || l[0] == " "
110
+ if l.line_origin == :deletion || l.line_origin == :context
108
111
  old_line_number += 1
109
112
  end
110
113
  end
@@ -112,7 +115,7 @@ module GitSpelunk
112
115
  addition_block = blocks.pop
113
116
  last_old_block = blocks.last
114
117
 
115
- if last_old_block.type == " "
118
+ if last_old_block.type == :context
116
119
  # if the previous context existed in both, just go to the end of that.
117
120
  last_old_block.offset + (last_old_block.size - 1)
118
121
  else
@@ -120,37 +123,14 @@ module GitSpelunk
120
123
  last_old_block.offset + [addition_block.size - 1, last_old_block.size].min
121
124
  end
122
125
  end
123
-
124
- private
125
-
126
- def extract_stats(l)
127
- #@@ -1,355 +1,355 @@
128
- l.scan(STATS_PATTERN).first.map(&:to_i)
129
- end
130
-
131
- def old_has?(line)
132
- # Src line will either have a "+" or will be an unchanged line
133
- line[0] == '-' || line[0] == " "
134
- end
135
-
136
- def new_has?(line)
137
- # Src line will either have a "-" or will be an unchanged line
138
- line[0] == '+' || line[0] == " "
139
- end
140
126
  end
141
127
 
142
- def chunks
143
- @chunks ||= begin
144
- diffs = @repo.diff(@parent.id, @sha, @file_name)
145
- return nil if diffs.empty?
146
-
147
- chunks = diffs[0].diff.split(/\n/).inject([[]]) do |arr, line|
148
- arr.push([]) if line =~ STATS_PATTERN
149
- arr.last << line
150
- arr
151
- end
128
+ def hunks
129
+ @hunks ||= begin
130
+ diff = @parent.diff(@commit, paths: [@file_name])
131
+ return nil unless diff
152
132
 
153
- chunks[1..-1].map { |c| Chunk.new(c) } # slice off first chunk -- it's just the filename
133
+ diff.patches[0].hunks.map { |h| Chunk.new(h) }
154
134
  end
155
135
  end
156
136
 
@@ -159,11 +139,11 @@ module GitSpelunk
159
139
  end
160
140
 
161
141
  def unable_to_trace_lineage?
162
- @parent && (@chunks.nil? || target_chunk.nil?)
142
+ @parent && (@hunks.nil? || target_chunk.nil?)
163
143
  end
164
144
 
165
145
  def line_number_to_parent
166
- return :at_beginning_of_time unless @parent && chunks
146
+ return :at_beginning_of_time unless @parent && hunks
167
147
  chunk = target_chunk(@line_number)
168
148
  return :unable_to_trace unless chunk
169
149
 
@@ -175,7 +155,7 @@ module GitSpelunk
175
155
  private
176
156
 
177
157
  def target_chunk(line_number)
178
- chunks.find { |c| c.has_line?(line_number) }
158
+ hunks.find { |c| c.has_line?(line_number) }
179
159
  end
180
160
  end
181
161
  end
@@ -13,7 +13,7 @@ module GitSpelunk
13
13
  @highlight_sha = true
14
14
  end
15
15
 
16
- attr_accessor :data, :highlight_sha, :search_term
16
+ attr_accessor :data, :highlight_sha, :search_term, :height
17
17
  attr_reader :cursor, :top, :data
18
18
 
19
19
  def blame_line
@@ -1,7 +1,7 @@
1
1
  module GitSpelunk
2
2
  class UI
3
3
  class RepoWindow
4
- attr_accessor :content, :command_mode, :command_buffer
4
+ attr_accessor :content, :command_mode, :command_buffer, :height
5
5
 
6
6
  def initialize(height)
7
7
  @height = height
@@ -18,7 +18,6 @@ module GitSpelunk
18
18
 
19
19
  private
20
20
 
21
- #with_highlighting do
22
21
  def status_line
23
22
  [
24
23
  "navigation: j k CTRL-D CTRL-U",
@@ -6,22 +6,23 @@ module GitSpelunk
6
6
  class UI
7
7
  def initialize(file_context)
8
8
  Dispel::Screen.open(:colors => true) do |screen|
9
- calculate_heights!
10
9
  @file_context = file_context
11
10
  @history = [file_context]
12
11
 
13
- @pager = PagerWindow.new(@pager_height)
12
+ @pager = PagerWindow.new(0)
14
13
  @pager.data = @file_context.get_blame
15
14
 
16
- @repo = RepoWindow.new(@repo_height)
15
+ @repo = RepoWindow.new(0)
17
16
  set_repo_content
18
17
 
19
18
  @status = StatusWindow.new
20
19
  set_status_message
21
20
 
21
+ calculate_heights!(screen)
22
22
  screen.draw *draw
23
- Dispel::Keyboard.output :timeout => 0.30 do |key|
23
+ Dispel::Keyboard.output(timeout: 0.5) do |key|
24
24
  handle_key(key)
25
+ calculate_heights!(screen)
25
26
  screen.draw *draw
26
27
  end
27
28
  end
@@ -33,7 +34,7 @@ module GitSpelunk
33
34
  view3, style3 = @status.draw
34
35
 
35
36
  cursor = if typing?
36
- [@pager_height + @repo_height, @status.command_buffer.size + 1]
37
+ [@pager.height + @repo.height, @status.command_buffer.size + 1]
37
38
  else
38
39
  [Curses.lines-1, Curses.cols]
39
40
  end
@@ -45,10 +46,10 @@ module GitSpelunk
45
46
  ]
46
47
  end
47
48
 
48
- def calculate_heights!
49
- @status_height = 1
50
- @repo_height = [(Curses.lines.to_f * 0.20).to_i, 6].max
51
- @pager_height = Curses.lines - @repo_height - @status_height
49
+ def calculate_heights!(screen)
50
+ status_height = 1
51
+ @repo.height = [(screen.lines.to_f * 0.20).to_i, 6].max
52
+ @pager.height = screen.lines - @repo.height - status_height
52
53
  end
53
54
 
54
55
  def set_status_message
@@ -56,7 +57,16 @@ module GitSpelunk
56
57
  end
57
58
 
58
59
  def set_repo_content
59
- @repo.content = @file_context.get_line_commit_info(@pager.blame_line)
60
+ info = @file_context.get_line_commit_info(@pager.blame_line)
61
+ content = <<-EOL
62
+ commit: #{info[:commit]}
63
+ Author: #{info[:author]}
64
+ Date: #{info[:date]}
65
+
66
+ EOL
67
+ message_lines = info[:message].split(/\r?\n/)
68
+ content += message_lines[0..(@repo.height - 6)].join("\n")
69
+ @repo.content = content
60
70
  @repo.draw
61
71
  end
62
72
 
@@ -1,3 +1,3 @@
1
1
  module GitSpelunk
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.2"
3
3
  end
data/lib/git_spelunk.rb CHANGED
@@ -2,5 +2,4 @@ require 'git_spelunk/version'
2
2
  require 'git_spelunk/ui'
3
3
  require 'git_spelunk/file_context'
4
4
  require 'git_spelunk/offset'
5
- require 'git_spelunk/grit_patches'
6
5
 
metadata CHANGED
@@ -1,18 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git_spelunk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Osheroff
8
8
  - Saroj Yadav
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-10-10 00:00:00.000000000 Z
12
+ date: 2023-01-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: grit
15
+ name: rugged
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
18
  - - ">="
@@ -68,7 +68,6 @@ files:
68
68
  - lib/git_spelunk.rb
69
69
  - lib/git_spelunk/blame.rb
70
70
  - lib/git_spelunk/file_context.rb
71
- - lib/git_spelunk/grit_patches.rb
72
71
  - lib/git_spelunk/offset.rb
73
72
  - lib/git_spelunk/ui.rb
74
73
  - lib/git_spelunk/ui/pager.rb
@@ -79,7 +78,7 @@ homepage: https://github.com/osheroff/git-spelunk
79
78
  licenses:
80
79
  - MIT
81
80
  metadata: {}
82
- post_install_message:
81
+ post_install_message:
83
82
  rdoc_options: []
84
83
  require_paths:
85
84
  - lib
@@ -94,9 +93,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
93
  - !ruby/object:Gem::Version
95
94
  version: '0'
96
95
  requirements: []
97
- rubyforge_project:
98
- rubygems_version: 2.4.5.1
99
- signing_key:
96
+ rubygems_version: 3.4.2
97
+ signing_key:
100
98
  specification_version: 4
101
99
  summary: A git tool for exploring history and blame
102
100
  test_files: []
@@ -1,14 +0,0 @@
1
- require 'grit'
2
-
3
- if RUBY_VERSION >= "2.0.0"
4
- class String
5
- def getord(offset); self[offset].ord; end
6
- end
7
-
8
- begin
9
- old, $VERBOSE = $VERBOSE, nil
10
- PACK_IDX_SIGNATURE = "\377tOc".force_encoding(Encoding::ASCII_8BIT)
11
- ensure
12
- $VERBOSE = old
13
- end
14
- end