git-object-browser 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/README.md +17 -0
  2. data/htdocs/{css → common/css}/angular-ui.min.css +0 -0
  3. data/htdocs/{css → common/css}/bootstrap-responsive.css +0 -0
  4. data/htdocs/{css → common/css}/bootstrap-responsive.min.css +0 -0
  5. data/htdocs/{css → common/css}/bootstrap.css +0 -0
  6. data/htdocs/{css → common/css}/bootstrap.min.css +0 -0
  7. data/htdocs/{css → common/css}/font-awesome-ie7.css +0 -0
  8. data/htdocs/{css → common/css}/font-awesome.css +0 -0
  9. data/htdocs/{css → common/css}/main.css +0 -0
  10. data/htdocs/{font → common/font}/fontawesome-webfont.eot +0 -0
  11. data/htdocs/{font → common/font}/fontawesome-webfont.svg +0 -0
  12. data/htdocs/{font → common/font}/fontawesome-webfont.ttf +0 -0
  13. data/htdocs/{font → common/font}/fontawesome-webfont.woff +0 -0
  14. data/htdocs/{img → common/img}/glyphicons-halflings-white.png +0 -0
  15. data/htdocs/{img → common/img}/glyphicons-halflings.png +0 -0
  16. data/htdocs/common/js/main.js +495 -0
  17. data/htdocs/{js → common/js}/vendor/angular-bootstrap-prettify.min.js +0 -0
  18. data/htdocs/{js → common/js}/vendor/angular-bootstrap.min.js +0 -0
  19. data/htdocs/{js → common/js}/vendor/angular-cookies.min.js +0 -0
  20. data/htdocs/{js → common/js}/vendor/angular-loader.min.js +0 -0
  21. data/htdocs/{js → common/js}/vendor/angular-resource.min.js +0 -0
  22. data/htdocs/{js → common/js}/vendor/angular-sanitize.min.js +0 -0
  23. data/htdocs/{js → common/js}/vendor/angular-ui-ieshiv.min.js +0 -0
  24. data/htdocs/{js → common/js}/vendor/angular-ui.min.js +0 -0
  25. data/htdocs/{js → common/js}/vendor/angular.js +0 -0
  26. data/htdocs/{js → common/js}/vendor/angular.min.js +0 -0
  27. data/htdocs/{js → common/js}/vendor/bootstrap.js +0 -0
  28. data/htdocs/{js → common/js}/vendor/bootstrap.min.js +0 -0
  29. data/htdocs/{js → common/js}/vendor/html5shiv.js +0 -0
  30. data/htdocs/{js → common/js}/vendor/jquery-1.8.2.min.js +0 -0
  31. data/htdocs/{templates → common/templates}/directory.html +2 -2
  32. data/htdocs/common/templates/error.html +6 -0
  33. data/htdocs/{templates → common/templates}/file.html +0 -0
  34. data/htdocs/{templates → common/templates}/git.html +0 -0
  35. data/htdocs/{templates → common/templates}/index.html +1 -1
  36. data/htdocs/{templates → common/templates}/index_entry.html +0 -0
  37. data/htdocs/{templates → common/templates}/info_refs.html +2 -2
  38. data/htdocs/{templates → common/templates}/loading.html +0 -0
  39. data/htdocs/{templates → common/templates}/notfound.html +1 -2
  40. data/htdocs/{templates → common/templates}/object.html +1 -1
  41. data/htdocs/{templates → common/templates}/objects.html +3 -3
  42. data/htdocs/{templates → common/templates}/pack_file.html +1 -1
  43. data/htdocs/common/templates/pack_index.html +39 -0
  44. data/htdocs/{templates → common/templates}/packed_object.html +4 -4
  45. data/htdocs/{templates → common/templates}/packed_refs.html +2 -2
  46. data/htdocs/{templates → common/templates}/ref.html +0 -0
  47. data/htdocs/common/templates/reflog.html +29 -0
  48. data/htdocs/config.js +6 -0
  49. data/htdocs/default.js +7 -0
  50. data/htdocs/index.html +52 -20
  51. data/lib/git-object-browser.rb +12 -4
  52. data/lib/git-object-browser/dumper/directories_dumper.rb +42 -0
  53. data/lib/git-object-browser/dumper/index_dumper.rb +20 -7
  54. data/lib/git-object-browser/dumper/info_refs_dumper.rb +37 -0
  55. data/lib/git-object-browser/dumper/main.rb +188 -81
  56. data/lib/git-object-browser/dumper/objects_dumper.rb +46 -0
  57. data/lib/git-object-browser/dumper/pack_indexes_dumper.rb +85 -0
  58. data/lib/git-object-browser/dumper/packed_objects_dumper.rb +36 -0
  59. data/lib/git-object-browser/dumper/packed_refs_dumper.rb +37 -0
  60. data/lib/git-object-browser/dumper/plain_files_dumper.rb +74 -0
  61. data/lib/git-object-browser/dumper/refs_dumper.rb +46 -0
  62. data/lib/git-object-browser/main.rb +22 -6
  63. data/lib/git-object-browser/models/directory.rb +5 -3
  64. data/lib/git-object-browser/models/git_date.rb +26 -0
  65. data/lib/git-object-browser/models/git_object.rb +1 -1
  66. data/lib/git-object-browser/models/pack_file.rb +1 -1
  67. data/lib/git-object-browser/models/pack_index.rb +139 -25
  68. data/lib/git-object-browser/models/packed_object.rb +1 -1
  69. data/lib/git-object-browser/models/reflog.rb +54 -0
  70. data/lib/git-object-browser/models/wrapped_object.rb +40 -0
  71. data/lib/git-object-browser/server/git_servlet.rb +130 -100
  72. data/lib/git-object-browser/server/main.rb +1 -1
  73. data/lib/git-object-browser/version.rb +1 -1
  74. metadata +62 -50
  75. data/htdocs/js/main.js +0 -285
  76. data/htdocs/templates/pack_index.html +0 -37
  77. data/lib/git-object-browser/dumper/object_dumper.rb +0 -20
  78. data/lib/git-object-browser/dumper/pack_index_dumper.rb +0 -21
  79. data/lib/git-object-browser/dumper/packed_object_dumper.rb +0 -19
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module GitObjectBrowser
4
+
5
+ module Dumper
6
+
7
+ class PackedObjectsDumper
8
+
9
+ def initialize(root, outdir)
10
+ @root = root
11
+ @outdir = outdir
12
+ end
13
+
14
+ def dump(path, index)
15
+ File.open(File.join(@root, path)) do |input|
16
+ index.entries.each do |entry|
17
+ dump_packed_object(index, input, entry[:offset], path)
18
+ end
19
+ end
20
+ end
21
+
22
+ def dump_packed_object(index, input, offset, path)
23
+ obj = GitObjectBrowser::Models::PackedObject.new(index, input).parse(offset)
24
+ wrapped = GitObjectBrowser::Models::WrappedObject.new(nil, path, obj)
25
+
26
+ ostr = "0000#{ offset }"
27
+ outfile = File.join(@outdir, path, ostr[-2,2], ostr[-4,2], "#{ offset }.json")
28
+ FileUtils.mkdir_p(File.dirname(outfile))
29
+
30
+ File.open(outfile, 'w') do |output|
31
+ output << JSON.pretty_generate(wrapped.to_hash)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module GitObjectBrowser
4
+
5
+ module Dumper
6
+
7
+ class PackedRefsDumper
8
+
9
+ def initialize(root, outdir)
10
+ @root = root
11
+ @outdir = outdir
12
+ end
13
+
14
+ def dump
15
+ src_file = File.join(@root, "packed-refs")
16
+ dst_file = File.join(@outdir, "packed-refs.json")
17
+
18
+ return unless File.exist?(src_file)
19
+
20
+ puts "Write: packed-refs\n"
21
+ File.open(src_file) do |input|
22
+ File.open(dst_file, "w") do |output|
23
+ dump_object(input, output)
24
+ end
25
+ end
26
+ end
27
+
28
+ def dump_object(input, output)
29
+ obj = GitObjectBrowser::Models::PackedRefs.new(input)
30
+ wrapped = GitObjectBrowser::Models::WrappedObject.new(nil, 'packed-refs', obj)
31
+ output << JSON.pretty_generate(wrapped.to_hash)
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,74 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module GitObjectBrowser
4
+
5
+ module Dumper
6
+
7
+ class PlainFilesDumper
8
+
9
+ def initialize(root, outdir)
10
+ @root = root
11
+ @outdir = outdir
12
+ end
13
+
14
+ def dump
15
+ obj_files = []
16
+
17
+ # ! info/refs
18
+ # info
19
+ # logs
20
+ # objects/info
21
+
22
+ plain_files = []
23
+ subdirs = []
24
+
25
+ Dir.chdir(@root) do
26
+ Dir.glob('*') do |path|
27
+ next if %w{HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD CHERRY_PICK_HEAD}.include?(path)
28
+ next if %w{dump index objects refs packed-refs}.include?(path)
29
+
30
+ if File.directory?(path)
31
+ subdirs << path
32
+ else
33
+ plain_files << path
34
+ end
35
+ end
36
+ end
37
+ subdirs << 'objects/info'
38
+
39
+ subdirs.each do |dir|
40
+ next unless File.directory?(File.join(@root, dir))
41
+ Dir.chdir(File.join(@root, dir)) do
42
+ Dir.glob('**/*') do |path|
43
+ # skip info/refs (InfoRefs)
44
+ next if dir == 'info' && path == 'refs'
45
+ if File.file?(path)
46
+ plain_files << File.join(dir, path)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ plain_files.each do |path|
53
+ outfile = File.join(@outdir, "#{ path }.json")
54
+ FileUtils.mkdir_p(File.dirname(outfile))
55
+
56
+ puts "Write: #{path}\n"
57
+ file = File.join(@root, path)
58
+ File.open(file) do |input|
59
+ File.open(outfile, "w") do |output|
60
+ dump_object(input, output, path)
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ def dump_object(input, output, path)
67
+ obj = GitObjectBrowser::Models::PlainFile.new(input).parse
68
+ wrapped = GitObjectBrowser::Models::WrappedObject.new(nil, path, obj)
69
+ output << JSON.pretty_generate(wrapped.to_hash)
70
+ end
71
+ end
72
+ end
73
+ end
74
+
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module GitObjectBrowser
4
+
5
+ module Dumper
6
+
7
+ class RefsDumper
8
+
9
+ def initialize(root, outdir)
10
+ @root = root
11
+ @outdir = outdir
12
+ end
13
+
14
+ def dump
15
+ ref_files = %w{HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD CHERRY_PICK_HEAD}
16
+ Dir.chdir(@root) do
17
+ Dir.glob("refs/**/*") do |path|
18
+ ref_files << path if File.file?(path)
19
+ end
20
+ end
21
+ return if ref_files.empty?
22
+
23
+ ref_files.each do |path|
24
+ next unless File.exist?(File.join(@root, path))
25
+ outfile = File.join(@outdir, "#{ path }.json")
26
+ FileUtils.mkdir_p(File.dirname(outfile))
27
+
28
+ puts "Write: #{path}\n"
29
+ ref_file = File.join(@root, path)
30
+ File.open(ref_file) do |input|
31
+ File.open(outfile, "w") do |output|
32
+ dump_object(input, output, path)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def dump_object(input, output, path)
39
+ obj = GitObjectBrowser::Models::Ref.new(input)
40
+ wrapped = GitObjectBrowser::Models::WrappedObject.new(nil, path, obj)
41
+ output << JSON.pretty_generate(wrapped.to_hash)
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -4,7 +4,10 @@ module GitObjectBrowser
4
4
  def execute
5
5
  host = '127.0.0.1'
6
6
  port = 8080
7
- dump = false
7
+ dump = nil
8
+ step = nil
9
+ diff_dir = nil
10
+ nextstep = false
8
11
  opts = OptionParser.new do |opts|
9
12
  opts.on('-p', '--port PORT', 'port number') do |value|
10
13
  port = value.to_i if 0 < value.to_i
@@ -12,8 +15,17 @@ module GitObjectBrowser
12
15
  opts.on('-b', '--bind HOST', 'address to bind') do |value|
13
16
  host = value
14
17
  end
15
- opts.on('-d', '--dump', 'dump objects') do |value|
16
- dump = true
18
+ opts.on('-d', '--dump PATH', 'dump .git as JSON and HTMLs') do |value|
19
+ dump = value
20
+ end
21
+ opts.on('--step STEP', 'dump JSONs into sub directory') do |value|
22
+ step = value
23
+ end
24
+ opts.on('--diff OLD_JSON_DIR', 'dump JSONs with diff data') do |value|
25
+ diff_dir = value
26
+ end
27
+ opts.on('--next', 'same with --step step${N} --diff step${N-1}') do |value|
28
+ nextstep = true
17
29
  end
18
30
  opts.on_tail("-h", "--help", "show this help.") do
19
31
  puts opts
@@ -26,10 +38,14 @@ module GitObjectBrowser
26
38
  opts.parse!(ARGV)
27
39
  end
28
40
  target = find_target(ARGV[0])
29
- if dump
30
- GitObjectBrowser::Dumper::Main.execute(target)
31
- else
41
+ if dump.nil?
32
42
  GitObjectBrowser::Server::Main.execute(target, host, port)
43
+ else
44
+ if nextstep
45
+ step = :next
46
+ diff_dir = nil
47
+ end
48
+ GitObjectBrowser::Dumper::Main.execute(target, dump, step, diff_dir)
33
49
  end
34
50
  end
35
51
 
@@ -18,11 +18,13 @@ module GitObjectBrowser
18
18
  relpath = File.join(@path, file).gsub(%r{\A/}, '')
19
19
  entry = {}
20
20
  if File.directory?(file)
21
- entry[:type] = "directory"
21
+ entry[:type] = 'directory'
22
22
  elsif File.symlink?(file)
23
- entry[:type] = "symlink"
23
+ entry[:type] = 'symlink'
24
24
  elsif Ref::path?(relpath)
25
25
  entry[:type] = 'ref'
26
+ elsif Reflog::path?(relpath)
27
+ entry[:type] = 'reflog'
26
28
  elsif InfoRefs::path?(relpath)
27
29
  entry[:type] = 'info_refs'
28
30
  elsif PackedRefs::path?(relpath)
@@ -40,7 +42,7 @@ module GitObjectBrowser
40
42
  entries << entry
41
43
  end
42
44
  end
43
- order = %w{directory ref info_refs packed_refs index object file symlink}
45
+ order = %w{directory ref reflog info_refs packed_refs index object file symlink}
44
46
  entries.sort do |a,b|
45
47
  (order.index(a[:type]) <=> order.index(b[:type])).nonzero? ||
46
48
  a[:basename] <=> b[:basename]
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+ module GitObjectBrowser
3
+
4
+ module Models
5
+
6
+ class GitDate
7
+ attr_reader :unixtime, :timezone, :date
8
+
9
+ def initialize(unixtime, timezone)
10
+ @unixtime = unixtime
11
+ @timezone = timezone
12
+ @date = DateTime.strptime(unixtime.to_s, '%s').new_offset(parse_timezone(timezone))
13
+ end
14
+
15
+ def parse_timezone(timezone)
16
+ timezone = '+00:00' if timezone == 'Z'
17
+ return Rational(0, 24) unless timezone =~ /(\+|-)?(\d\d):?(\d\d)/
18
+ Rational($2.to_i, 24) + Rational($3, 60) * (($1 == '-') ? -1 : 1)
19
+ end
20
+
21
+ def to_s
22
+ @date.iso8601
23
+ end
24
+ end
25
+ end
26
+ end
@@ -98,7 +98,7 @@ module GitObjectBrowser
98
98
  prop[:email] = force_utf8($2)
99
99
  prop[:unixtime] = $3
100
100
  prop[:timezone] = $4
101
- prop[:date] = epoch($3.to_i, $4).iso8601
101
+ prop[:date] = GitDate.new($3, $4).to_s
102
102
 
103
103
  prop[:value] = force_utf8(prop[:value])
104
104
  else
@@ -17,7 +17,7 @@ module GitObjectBrowser
17
17
  end
18
18
 
19
19
  def self.path?(relpath)
20
- return relpath =~ %r{\Aobjects/pack/pack-[0-9a-f]{40}.pack\z}
20
+ return relpath =~ %r{\Aobjects/pack/pack-[0-9a-f]{40}\.pack\z}
21
21
  end
22
22
 
23
23
  def parse
@@ -4,46 +4,142 @@ module GitObjectBrowser
4
4
  module Models
5
5
 
6
6
  # v2
7
- # signature 4bytes
8
- # version 4bytes
9
- # fanout 4bytes * 256
10
- # sha1 20bytes * fanout[255]
11
- # crc 4bytes * fanout[255]
12
- # offset 4bytes * fanout[255]
7
+ # signature 4bytes
8
+ # version 4bytes
9
+ # fanout 4bytes * 256
10
+ # sha1 20bytes * fanout[255]
11
+ # crc32 4bytes * fanout[255]
12
+ # offset 4bytes * fanout[255]
13
+ # pack sha1 20bytes
14
+ # index sha1 20bytes
13
15
  class PackIndex < Bindata
16
+ attr_reader :entries
17
+
18
+ PER_PAGE = 200
14
19
 
15
20
  def initialize(input)
16
21
  super(input)
17
22
  end
18
23
 
19
- def parse
24
+ def parse(order, page)
20
25
  parse_fanout
26
+ @page = page
27
+ @order = order
28
+
29
+ if order == 'digest'
30
+ parse_digest
31
+ elsif order == 'sha1'
32
+ parse_sha1_page
33
+ set_fanouts
34
+ else
35
+ @order = 'offset'
36
+ parse_offset_page
37
+ set_fanouts
38
+ end
39
+
40
+ # XXX Doesn't support packfile >= 2 GiB
41
+ # x.times do |i|
42
+ # puts "offset[#{ i }] = #{ hex(8) }"
43
+ # end
44
+
45
+ seek(4 + 4 + 4 * 256 + (20 + 4 + 4) * @fanout[255])
46
+ @packfile_sha1 = hex(20)
47
+ @index_sha1 = hex(20)
48
+
49
+ self
50
+ end
21
51
 
52
+ def empty?
53
+ @entries.empty?
54
+ end
55
+
56
+ def set_fanouts
57
+ @fanout.each_with_index do |fo, i|
58
+ entry = @entries.select { |entry| entry[:index] == fo }
59
+ next if entry.empty?
60
+ entry = entry.first
61
+ entry[:fanout_min] = entry[:fanout_min] ? [entry[:fanout_min], i].min : i
62
+ entry[:fanout_max] = entry[:fanout_max] ? [entry[:fanout_max], i].max : i
63
+ end
64
+
65
+ @entries.each do |entry|
66
+ next unless entry[:fanout_min]
67
+ entry[:fanout_min] = '%02x' % entry[:fanout_min]
68
+ entry[:fanout_max] = '%02x' % entry[:fanout_max]
69
+ entry.delete(:fanout_max) if entry[:fanout_min] == entry[:fanout_max]
70
+ end
71
+ end
72
+ private :set_fanouts
73
+
74
+ def parse_digest
75
+ index = 0
22
76
  @entries = []
23
- @fanout[255].times do |i|
24
- entry = {}
25
- entry[:sha1] = hex(20)
77
+ while index <= @fanout[255] - 1
78
+ @entries << hex(20)
79
+ index += PER_PAGE
80
+ skip(20 * (PER_PAGE - 1)) if index <= @fanout[255] - 1
81
+ end
82
+ end
83
+ private :parse_digest
84
+
85
+ def parse_sha1_page
86
+ @entries = []
87
+
88
+ index_start = PER_PAGE * (@page - 1)
89
+ index_end = PER_PAGE * @page - 1
90
+ index_last = @fanout[255] - 1
91
+ return if index_last < index_start
92
+ index_end = index_last if index_last <= index_end
93
+ entry_count = index_end - index_start + 1
94
+
95
+ skip(20 * index_start)
96
+ entry_count.times do |i|
97
+ entry = { :index => index_start + i, :sha1 => hex(20) }
26
98
  @entries << entry
27
99
  end
100
+ skip(20 * (index_last - index_end))
28
101
 
29
- @fanout[255].times do |i|
102
+ skip(4 * index_start)
103
+ entry_count.times do |i|
30
104
  @entries[i][:crc32] = hex(4)
31
105
  end
106
+ skip(4 * (index_last - index_end))
32
107
 
33
- @fanout[255].times do |i|
108
+ skip(4 * index_start)
109
+ entry_count.times do |i|
34
110
  @entries[i][:offset] = int
35
111
  end
112
+ end
113
+ private :parse_sha1_page
36
114
 
37
- # XXX Doesn't support packfile >= 2 GiB
38
- # x.times do |i|
39
- # puts "offset[#{ i }] = #{ hex(8) }"
40
- # end
115
+ def parse_offset_page
116
+ @entries = []
41
117
 
42
- @packfile_sha1 = hex(20)
43
- @index_sha1 = hex(20)
118
+ index_start = PER_PAGE * (@page - 1)
119
+ index_end = PER_PAGE * @page - 1
120
+ index_last = @fanout[255] - 1
121
+ return if index_last < index_start
122
+ index_end = index_last if index_last <= index_end
123
+ entry_count = index_end - index_start + 1
44
124
 
45
- self
125
+ # load all offsets
126
+ skip((20 + 4) * @fanout[255])
127
+ offsets = []
128
+ @fanout[255].times do |i|
129
+ offsets << [i, int]
130
+ end
131
+
132
+ offsets = offsets.sort { |a,b| a[1] <=> b[1] }[index_start, entry_count]
133
+ offsets.each do |offset|
134
+ @entries << { :index => offset[0], :offset => offset[1] }
135
+ end
136
+
137
+ @entries.each do |entry|
138
+ entry[:sha1] = get_sha1_hex(entry[:index])
139
+ entry[:crc32] = get_crc32_hex(entry[:index])
140
+ end
46
141
  end
142
+ private :parse_offset_page
47
143
 
48
144
  def parse_fanout
49
145
  return if @fanout
@@ -72,11 +168,11 @@ module GitObjectBrowser
72
168
 
73
169
  while lo < hi
74
170
  mid = (lo + hi) / 2
75
- mid_sha1 = get_sha1(mid)
171
+ mid_sha1 = get_sha1_raw(mid)
76
172
  if mid_sha1 == sha1
77
173
  return {
78
174
  :sha1 => sha1_hex,
79
- :crc => get_crc_hex(mid),
175
+ :crc32 => get_crc32_hex(mid),
80
176
  :offset => get_offset(mid)
81
177
  }
82
178
  elsif sha1 < mid_sha1
@@ -88,7 +184,7 @@ module GitObjectBrowser
88
184
  nil
89
185
  end
90
186
 
91
- def get_sha1(pos)
187
+ def get_sha1_raw(pos)
92
188
  if @version == 2
93
189
  seek(4 + 4 + 4 * 256 + 20 * pos)
94
190
  else
@@ -97,7 +193,16 @@ module GitObjectBrowser
97
193
  raw(20)
98
194
  end
99
195
 
100
- def get_crc_hex(pos)
196
+ def get_sha1_hex(pos)
197
+ if @version == 2
198
+ seek(4 + 4 + 4 * 256 + 20 * pos)
199
+ else
200
+ raise "FIXME version 1"
201
+ end
202
+ hex(20)
203
+ end
204
+
205
+ def get_crc32_hex(pos)
101
206
  if @version == 2
102
207
  seek(4 + 4 + 4 * 256 + 20 * @fanout[255] + 4 * pos)
103
208
  else
@@ -116,18 +221,27 @@ module GitObjectBrowser
116
221
  end
117
222
 
118
223
  def self.path?(relpath)
119
- return relpath =~ %r{\Aobjects/pack/pack-[0-9a-f]{40}.idx\z}
224
+ return relpath =~ %r{\Aobjects/pack/pack-[0-9a-f]{40}\.idx\z}
120
225
  end
121
226
 
122
227
  def to_hash
123
228
  return {
124
- :fanout => @fanout,
125
229
  :entries => @entries,
126
230
  :packfile_sha1 => @packfile_sha1,
127
231
  :index_sha1 => @index_sha1,
128
232
  }
129
233
  end
130
234
 
235
+ # Extended pagenation data for Git Object Browser.
236
+ def page_data
237
+ return {
238
+ :per_page => PER_PAGE,
239
+ :entry_count => @fanout[255],
240
+ :page => @page,
241
+ :order => @order
242
+ }
243
+ end
244
+
131
245
  def load_object_types(input)
132
246
  obj = PackedObject.new(self, input)
133
247
  @entries.each do |entry|