-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchandy.rb
113 lines (96 loc) · 3.37 KB
/
chandy.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
require 'grit'
Grit::Git.git_timeout = 60
Grit::Git.git_max_size = 104857600
module Chandy
class Repo
attr_accessor :repo
attr_accessor :trees_hash
def initialize(repo_dir)
begin
@repo = File.basename(repo_dir)
@grit = Grit::Repo.new(repo_dir)
rescue => e
raise Chandy::Error, e.message
end
@trees_hash = {}
end
def index(ref)
root = root_tree_of(ref)
@trees_hash['.'] = root.id
root.trees.each { |tree| build_path(tree, []) }
return @trees_hash
end
def file(args)
blob = nil
if args.has_key? :blob_id
blob = @grit.blob(args[:blob_id])
raise Chandy::NotFound, "#{@repo} / blob: #{args[:blob_id]} not found" if blob.nil?
elsif args.has_key? :tree_id and args.has_key? :filename
blob = @grit.tree(args[:tree_id]) / args[:filename]
raise Chandy::NotFound, "#{@repo} / #{args[:tree_id]}/#{args[:filename]} not found" if blob.nil?
elsif args.has_key? :tag and args.has_key? :path
blob = root_tree_of(args[:tag]) / args[:path]
raise Chandy::NotFound, "#{@repo} / #{args[:path]}@#{args[:tag]} not found" if blob.nil?
else
raise Chandy::NotFound, "invalid args"
end
{ 'bytes' => blob.size, 'mime_type' => blob.mime_type, 'data' => blob.data }
end
def diff(tag1, tag2)
[tag1, tag2].each do |ref|
head = @grit.commits(ref, 1)
raise Chandy::NotFound, "#{@repo} / ref: #{ref} not found" if head.size == 0
end
diffs = []
native_diff(tag1, tag2).each do |diff|
next if diff.b_path.nil? or diff.b_blob.nil? or diff.b_blob.id.nil?
diffs << [diff.b_path, diff.b_blob.id]
end
return diffs
end
def all_blobs(ref)
blobs = {}
index(ref).each do |dir, tid|
@grit.tree(tid).blobs.each { |b| blobs["#{dir}/#{b.basename}"] = b.id }
end
return blobs
end
def grit
@grit
end
private
def root_tree_of(ref)
head = @grit.commits(ref, 1)
raise Chandy::NotFound, "#{@repo} / ref: #{ref} not found" if head.size == 0
return head.first.tree
end
# 构建 path
def build_path(tree, parents)
paths = parents << tree.basename
@trees_hash[paths.join('/')] = tree.id
# 继续构建子目录
tree.trees.each { |t| build_path(t, paths.clone) }
end
def native_diff(a, b, *paths)
diff = @grit.git.native('diff', {}, a, b, '--full-index', *paths)
if diff =~ /diff --git a/
diff = diff.sub(/.*?(diff --git a)/m, '\1')
else
diff = ''
end
Grit::Diff.list_from_string(@grit, diff)
end
end
class Error < StandardError
attr_reader :reason
def initialize(reason)
@reason = reason
end
end
class NotFound < StandardError
attr_reader :reason
def initialize(reason)
@reason = reason
end
end
end