Skip to content

Commit 779f21b

Browse files
author
scott Chacon
committed
Merge branches 'master' and 'internals'
2 parents 55c3c13 + 6a9db96 commit 779f21b

17 files changed

+1088
-19
lines changed

bin/gitr

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env ruby
2+
3+
# This is a command line client that can do a number of read operations
4+
# on a git repository in pure ruby. This may be helpful if you have access
5+
# to a computer that has no C compiler but you want to do some git stuff
6+
# on it. It's also helpful for me to test Git stuff with.
7+
#
8+
# author : Scott Chacon (schacon@gmail.com)
9+
#
10+
# todo:
11+
# add --git-dir
12+
# add --log-file
13+
# add --help
14+
15+
#require 'lib/git'
16+
require 'rubygems'
17+
require 'git'
18+
require 'logger'
19+
20+
command = ARGV[0]
21+
22+
if !command
23+
puts 'You have to provide a command'
24+
puts 'usage: gitr (command) [args]'
25+
puts
26+
puts 'commands: log'
27+
puts ' log-shas'
28+
puts ' cat-file'
29+
puts ' rev-parse'
30+
puts ' branches'
31+
puts ' config'
32+
exit
33+
end
34+
35+
git_dir = ENV['GIT_DIR'] || '.git'
36+
@git = Git.bare(git_dir, :log => Logger.new(STDOUT))
37+
38+
case command
39+
when 'log'
40+
# gitr log
41+
@git.log.each do |l|
42+
puts 'commit ' + l.sha
43+
puts l.contents
44+
puts
45+
end
46+
when 'log-shas'
47+
# gitr log-shas
48+
puts @git.log
49+
when 'cat-file'
50+
# gitr cat-file
51+
puts @git.cat_file(ARGV[1])
52+
when 'rev-parse'
53+
# gitr rev-parse
54+
puts @git.revparse(ARGV[1])
55+
when 'branches'
56+
# gitr branches
57+
puts @git.branches
58+
when 'config'
59+
# gitr config
60+
@git.config.sort.each do |k,v|
61+
puts "#{k} : #{v}"
62+
end
63+
end
64+
65+
# gitr ls-tree
66+
# gitr pack-browse
67+
68+
# gitr diff / stats ?
69+
# output in yaml?

camping/gitweb.rb

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# todo
1414
# - diff/patch between any two objects
1515
# - expand patch to entire file
16+
# - set title properly
1617
# - grep / search function
1718
# - prettify : http://projects.wh.techno-weenie.net/changesets/3030
1819
# - add user model (add/remove repos)
@@ -90,10 +91,7 @@ def get repo_id
9091
class View < R '/view/(\d+)'
9192
def get repo_id
9293
@repo = Repository.find repo_id
93-
logger = Logger.new('/tmp/git.log')
94-
logger.level = Logger::INFO
95-
96-
@git = Git.bare(@repo.path, :log => logger)
94+
@git = Git.bare(@repo.path)
9795
render :view
9896
end
9997
end
@@ -109,7 +107,7 @@ def get repo_id, path
109107
class Commit < R '/commit/(\d+)/(\w+)'
110108
def get repo_id, sha
111109
@repo = Repository.find repo_id
112-
@git = Git.bare(@repo.path)
110+
@git = Git.bare(@repo.path)
113111
@commit = @git.gcommit(sha)
114112
render :commit
115113
end
@@ -118,7 +116,7 @@ def get repo_id, sha
118116
class Tree < R '/tree/(\d+)/(\w+)'
119117
def get repo_id, sha
120118
@repo = Repository.find repo_id
121-
@git = Git.bare(@repo.path)
119+
@git = Git.bare(@repo.path)
122120
@tree = @git.gtree(sha)
123121
render :tree
124122
end
@@ -127,7 +125,10 @@ def get repo_id, sha
127125
class Blob < R '/blob/(\d+)/(.*?)/(\w+)'
128126
def get repo_id, file, sha
129127
@repo = Repository.find repo_id
130-
@git = Git.bare(@repo.path)
128+
logger = Logger.new('/tmp/git.log')
129+
logger.level = Logger::INFO
130+
131+
@git = Git.bare(@repo.path, :log => logger)
131132
@blob = @git.gblob(sha)
132133
@file = file
133134
render :blob
@@ -212,7 +213,7 @@ def layout
212213
body :onload => "sh_highlightDocument();" do
213214
before = Time.now().usec
214215
self << yield
215-
self << ((Time.now().usec - before).to_f / 60).to_s + ' sec'
216+
self << '<br/>' + ((Time.now().usec - before).to_f / 60).to_s + ' sec'
216217
end
217218
end
218219
end

lib/git.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
require 'git/status'
2424
require 'git/author'
2525

26+
require 'git/raw/repository'
27+
28+
2629
# Git/Ruby Library
2730
#
2831
# This provides bindings for working with git in complex

lib/git/base.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,10 @@ def revparse(objectish)
429429
self.lib.revparse(objectish)
430430
end
431431

432+
def cat_file(objectish)
433+
self.lib.object_contents(objectish)
434+
end
435+
432436
# returns the name of the branch the working directory is currently on
433437
def current_branch
434438
self.lib.branch_current

lib/git/branches.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,17 @@ def [](symbol)
4141
@branches[symbol.to_s]
4242
end
4343

44+
def to_s
45+
out = ''
46+
@branches.each do |k, b|
47+
if b.current
48+
out += "* " + b.to_s + "\n"
49+
else
50+
out += " " + b.to_s + "\n"
51+
end
52+
end
53+
out
54+
end
55+
4456
end
4557
end

lib/git/lib.rb

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class Lib
1313
@path = nil
1414

1515
@logger = nil
16+
@raw_repo = nil
1617

1718
def initialize(base = nil, logger = nil)
1819
if base.is_a?(Git::Base)
@@ -75,6 +76,17 @@ def log_commits(opts = {})
7576
end
7677

7778
def full_log_commits(opts = {})
79+
if !(opts[:since] || opts[:between] || opts[:path_limiter])
80+
# can do this in pure ruby
81+
sha = revparse(opts[:object] || branch_current || 'master')
82+
count = opts[:count] || 30
83+
84+
if /\w{40}/.match(sha) # valid sha
85+
repo = get_raw_repo
86+
return process_commit_data(repo.log(sha, count))
87+
end
88+
end
89+
7890
arr_opts = ['--pretty=raw']
7991
arr_opts << "-#{opts[:count]}" if opts[:count]
8092
arr_opts << "--since=\"#{opts[:since]}\"" if opts[:since].is_a? String
@@ -92,10 +104,13 @@ def revparse(string)
92104
end
93105

94106
head = File.join(@git_dir, 'refs', 'heads', string)
95-
return File.read(head) if File.file?(head)
107+
return File.read(head).chomp if File.file?(head)
96108

97109
head = File.join(@git_dir, 'refs', 'remotes', string)
98-
return File.read(head) if File.file?(head)
110+
return File.read(head).chomp if File.file?(head)
111+
112+
head = File.join(@git_dir, 'refs', 'tags', string)
113+
return File.read(head).chomp if File.file?(head)
99114

100115
command('rev-parse', string)
101116
end
@@ -111,24 +126,30 @@ def object_type(sha)
111126
def object_size(sha)
112127
command('cat-file', ['-s', sha]).to_i
113128
end
129+
130+
def get_raw_repo
131+
@raw_repo ||= Git::Raw::Repository.new(@git_dir)
132+
end
114133

115134
# returns useful array of raw commit object data
116135
def commit_data(sha)
117136
sha = sha.to_s
118-
cdata = command_lines('cat-file', ['commit', sha])
137+
cdata = get_raw_repo.cat_file(revparse(sha))
138+
#cdata = command_lines('cat-file', ['commit', sha])
119139
process_commit_data(cdata, sha)
120140
end
121141

122142
def process_commit_data(data, sha = nil)
123143
in_message = false
124-
144+
125145
if sha
126146
hsh = {'sha' => sha, 'message' => '', 'parent' => []}
127147
else
128148
hsh_array = []
129149
end
130150

131151
data.each do |line|
152+
line = line.chomp
132153
if in_message && line != ''
133154
hsh['message'] += line + "\n"
134155
end
@@ -163,16 +184,23 @@ def process_commit_data(data, sha = nil)
163184
end
164185

165186
def object_contents(sha)
166-
command('cat-file', ['-p', sha])
187+
#command('cat-file', ['-p', sha])
188+
get_raw_repo.cat_file(revparse(sha)).chomp
167189
end
168190

169191
def ls_tree(sha)
170192
data = {'blob' => {}, 'tree' => {}}
171-
command_lines('ls-tree', sha.to_s).each do |line|
172-
(info, filenm) = line.split("\t")
173-
(mode, type, sha) = info.split
174-
data[type][filenm] = {:mode => mode, :sha => sha}
193+
194+
get_raw_repo.object(revparse(sha)).entry.each do |e|
195+
data[e.format_type][e.name] = {:mode => e.format_mode, :sha => e.sha1}
175196
end
197+
198+
#command_lines('ls-tree', sha.to_s).each do |line|
199+
# (info, filenm) = line.split("\t")
200+
# (mode, type, sha) = info.split
201+
# data[type][filenm] = {:mode => mode, :sha => sha}
202+
#end
203+
176204
data
177205
end
178206

lib/git/raw/internal/loose.rb

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#
2+
# converted from the gitrb project
3+
#
4+
# authors:
5+
# Matthias Lederhofer <matled@gmx.net>
6+
# Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
7+
#
8+
# provides native ruby access to git objects and pack files
9+
#
10+
11+
require 'zlib'
12+
require 'digest/sha1'
13+
14+
require 'git/raw/internal/object'
15+
16+
module Git
17+
module Raw
18+
module Internal
19+
class LooseObjectError < StandardError
20+
end
21+
22+
class LooseStorage
23+
def initialize(directory)
24+
@directory = directory
25+
end
26+
27+
def [](sha1)
28+
sha1 = sha1.unpack("H*")[0]
29+
30+
path = @directory+'/'+sha1[0...2]+'/'+sha1[2..40]
31+
begin
32+
get_raw_object(File.read(path))
33+
rescue Errno::ENOENT
34+
nil
35+
end
36+
end
37+
38+
def get_raw_object(buf)
39+
if buf.length < 2
40+
raise LooseObjectError, "object file too small"
41+
end
42+
43+
if legacy_loose_object?(buf)
44+
content = Zlib::Inflate.inflate(buf)
45+
header, content = content.split(/\0/, 2)
46+
if !header || !content
47+
raise LooseObjectError, "invalid object header"
48+
end
49+
type, size = header.split(/ /, 2)
50+
if !%w(blob tree commit tag).include?(type) || size !~ /^\d+$/
51+
raise LooseObjectError, "invalid object header"
52+
end
53+
type = type.to_sym
54+
size = size.to_i
55+
else
56+
type, size, used = unpack_object_header_gently(buf)
57+
content = Zlib::Inflate.inflate(buf[used..-1])
58+
end
59+
raise LooseObjectError, "size mismatch" if content.length != size
60+
return RawObject.new(type, content)
61+
end
62+
63+
# private
64+
def unpack_object_header_gently(buf)
65+
used = 0
66+
c = buf[used]
67+
used += 1
68+
69+
type = (c >> 4) & 7;
70+
size = c & 15;
71+
shift = 4;
72+
while c & 0x80 != 0
73+
if buf.length <= used
74+
raise LooseObjectError, "object file too short"
75+
end
76+
c = buf[used]
77+
used += 1
78+
79+
size += (c & 0x7f) << shift
80+
shift += 7
81+
end
82+
type = OBJ_TYPES[type]
83+
if ![:blob, :tree, :commit, :tag].include?(type)
84+
raise LooseObjectError, "invalid loose object type"
85+
end
86+
return [type, size, used]
87+
end
88+
private :unpack_object_header_gently
89+
90+
def legacy_loose_object?(buf)
91+
word = (buf[0] << 8) + buf[1]
92+
buf[0] == 0x78 && word % 31 == 0
93+
end
94+
private :legacy_loose_object?
95+
end
96+
end
97+
end
98+
end
99+
100+
if $0 == __FILE__
101+
require 'find'
102+
ARGV.each do |path|
103+
storage = Git::Internal::LooseStorage.new(path)
104+
Find.find(path) do |p|
105+
next if !/\/([0-9a-f]{2})\/([0-9a-f]{38})$/.match(p)
106+
obj = storage[[$1+$2].pack("H*")]
107+
puts "%s %s" % [obj.sha1.unpack("H*")[0], obj.type]
108+
end
109+
end
110+
end

0 commit comments

Comments
 (0)