jugyo-grit 2.4.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.
@@ -0,0 +1,128 @@
1
+ module Grit
2
+
3
+ class CommitStats
4
+
5
+ attr_reader :id, :files, :additions, :deletions, :total
6
+
7
+ # Instantiate a new CommitStats
8
+ # +id+ is the id of the commit
9
+ # +files+ is an array of :
10
+ # [ [filename, adds, deletes, total],
11
+ # [filename, adds, deletes, total],
12
+ # [filename, adds, deletes, total] ]
13
+ #
14
+ # Returns Grit::CommitStats (baked)
15
+ def initialize(repo, id, files)
16
+ @repo = repo
17
+ @id = id
18
+ @files = files
19
+ @additions = files.inject(0) { |total, a| total += a[1] }
20
+ @deletions = files.inject(0) { |total, a| total += a[2] }
21
+ @total = files.inject(0) { |total, a| total += a[3] }
22
+ end
23
+
24
+ # Find all commit stats matching the given criteria.
25
+ # +repo+ is the Repo
26
+ # +ref+ is the ref from which to begin (SHA1 or name) or nil for --all
27
+ # +options+ is a Hash of optional arguments to git
28
+ # :max_count is the maximum number of commits to fetch
29
+ # :skip is the number of commits to skip
30
+ #
31
+ # Returns assoc array [sha, Grit::Commit[] (baked)]
32
+ def self.find_all(repo, ref, options = {})
33
+ allowed_options = [:max_count, :skip, :since]
34
+
35
+ default_options = {:numstat => true}
36
+ actual_options = default_options.merge(options)
37
+
38
+ if ref
39
+ output = repo.git.log(actual_options, ref)
40
+ else
41
+ output = repo.git.log(actual_options.merge(:all => true))
42
+ end
43
+
44
+ self.list_from_string(repo, output)
45
+ end
46
+
47
+ # Parse out commit information into an array of baked Commit objects
48
+ # +repo+ is the Repo
49
+ # +text+ is the text output from the git command (raw format)
50
+ #
51
+ # Returns assoc array [sha, Grit::Commit[] (baked)]
52
+ def self.list_from_string(repo, text)
53
+ lines = text.split("\n")
54
+
55
+ commits = []
56
+
57
+ while !lines.empty?
58
+ id = lines.shift.split.last
59
+
60
+ lines.shift
61
+ lines.shift
62
+ lines.shift
63
+
64
+ message_lines = []
65
+ message_lines << lines.shift[4..-1] while lines.first =~ /^ {4}/ || lines.first == ''
66
+
67
+ lines.shift while lines.first && lines.first.empty?
68
+
69
+ files = []
70
+ while lines.first =~ /^([-\d]+)\s+([-\d]+)\s+(.+)/
71
+ (additions, deletions, filename) = lines.shift.split
72
+ additions = additions.to_i
73
+ deletions = deletions.to_i
74
+ total = additions + deletions
75
+ files << [filename, additions, deletions, total]
76
+ end
77
+
78
+ lines.shift while lines.first && lines.first.empty?
79
+
80
+ commits << [id, CommitStats.new(repo, id, files)]
81
+ end
82
+
83
+ commits
84
+ end
85
+
86
+ # Pretty object inspection
87
+ def inspect
88
+ %Q{#<Grit::CommitStats "#{@id}">}
89
+ end
90
+
91
+ # Convert to an easy-to-traverse structure
92
+ def to_diffstat
93
+ files.map do |metadata|
94
+ DiffStat.new(*metadata)
95
+ end
96
+ end
97
+
98
+ # private
99
+
100
+ def to_hash
101
+ {
102
+ 'id' => id,
103
+ 'files' => files,
104
+ 'additions' => additions,
105
+ 'deletions' => deletions,
106
+ 'total' => total
107
+ }
108
+ end
109
+
110
+ end # CommitStats
111
+
112
+ class DiffStat
113
+ attr_reader :filename, :additions, :deletions
114
+
115
+ def initialize(filename, additions, deletions, total=nil)
116
+ @filename, @additions, @deletions = filename, additions, deletions
117
+ end
118
+
119
+ def net
120
+ additions - deletions
121
+ end
122
+
123
+ def inspect
124
+ "#{filename}: +#{additions} -#{deletions}"
125
+ end
126
+ end
127
+
128
+ end # Grit
@@ -0,0 +1,44 @@
1
+ module Grit
2
+
3
+ class Config
4
+ def initialize(repo)
5
+ @repo = repo
6
+ end
7
+
8
+ def []=(key, value)
9
+ @repo.git.config({}, key, value)
10
+ @data = nil
11
+ end
12
+
13
+ def [](key)
14
+ data[key]
15
+ end
16
+
17
+ def fetch(key, default = nil)
18
+ data[key] || default || raise(IndexError.new("key not found"))
19
+ end
20
+
21
+ def keys
22
+ data.keys
23
+ end
24
+
25
+ protected
26
+ def data
27
+ @data ||= load_config
28
+ end
29
+
30
+ def load_config
31
+ hash = {}
32
+ config_lines.map do |line|
33
+ key, value = line.split(/=/, 2)
34
+ hash[key] = value
35
+ end
36
+ hash
37
+ end
38
+
39
+ def config_lines
40
+ @repo.git.config(:list => true).split(/\n/)
41
+ end
42
+ end # Config
43
+
44
+ end # Grit
@@ -0,0 +1,79 @@
1
+ module Grit
2
+
3
+ class Diff
4
+ attr_reader :a_path, :b_path
5
+ attr_reader :a_blob, :b_blob
6
+ attr_reader :a_mode, :b_mode
7
+ attr_reader :new_file, :deleted_file, :renamed_file
8
+ attr_reader :similarity_index
9
+ attr_accessor :diff
10
+
11
+ def initialize(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff, renamed_file = false, similarity_index = 0)
12
+ @repo = repo
13
+ @a_path = a_path
14
+ @b_path = b_path
15
+ @a_blob = a_blob =~ /^0{40}$/ ? nil : Blob.create(repo, :id => a_blob)
16
+ @b_blob = b_blob =~ /^0{40}$/ ? nil : Blob.create(repo, :id => b_blob)
17
+ @a_mode = a_mode
18
+ @b_mode = b_mode
19
+ @new_file = new_file || @a_blob.nil?
20
+ @deleted_file = deleted_file || @b_blob.nil?
21
+ @renamed_file = renamed_file
22
+ @similarity_index = similarity_index.to_i
23
+ @diff = diff
24
+ end
25
+
26
+ def self.list_from_string(repo, text)
27
+ lines = text.split("\n")
28
+
29
+ diffs = []
30
+
31
+ while !lines.empty?
32
+ m, a_path, b_path = *lines.shift.match(%r{^diff --git a/(.+?) b/(.+)$})
33
+
34
+ if lines.first =~ /^old mode/
35
+ m, a_mode = *lines.shift.match(/^old mode (\d+)/)
36
+ m, b_mode = *lines.shift.match(/^new mode (\d+)/)
37
+ end
38
+
39
+ if lines.empty? || lines.first =~ /^diff --git/
40
+ diffs << Diff.new(repo, a_path, b_path, nil, nil, a_mode, b_mode, false, false, nil)
41
+ next
42
+ end
43
+
44
+ sim_index = 0
45
+ new_file = false
46
+ deleted_file = false
47
+ renamed_file = false
48
+
49
+ if lines.first =~ /^new file/
50
+ m, b_mode = lines.shift.match(/^new file mode (.+)$/)
51
+ a_mode = nil
52
+ new_file = true
53
+ elsif lines.first =~ /^deleted file/
54
+ m, a_mode = lines.shift.match(/^deleted file mode (.+)$/)
55
+ b_mode = nil
56
+ deleted_file = true
57
+ elsif lines.first =~ /^similarity index (\d+)\%/
58
+ sim_index = $1.to_i
59
+ renamed_file = true
60
+ 2.times { lines.shift } # shift away the 2 `rename from/to ...` lines
61
+ end
62
+
63
+ m, a_blob, b_blob, b_mode = *lines.shift.match(%r{^index ([0-9A-Fa-f]+)\.\.([0-9A-Fa-f]+) ?(.+)?$})
64
+ b_mode.strip! if b_mode
65
+
66
+ diff_lines = []
67
+ while lines.first && lines.first !~ /^diff/
68
+ diff_lines << lines.shift
69
+ end
70
+ diff = diff_lines.join("\n")
71
+
72
+ diffs << Diff.new(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff, renamed_file, sim_index)
73
+ end
74
+
75
+ diffs
76
+ end
77
+ end # Diff
78
+
79
+ end # Grit
@@ -0,0 +1,10 @@
1
+ module Grit
2
+ class InvalidGitRepositoryError < StandardError
3
+ end
4
+
5
+ class NoSuchPathError < StandardError
6
+ end
7
+
8
+ class InvalidObjectType < StandardError
9
+ end
10
+ end
@@ -0,0 +1,259 @@
1
+ require 'grit/git-ruby/repository'
2
+
3
+ module Grit
4
+
5
+ # the functions in this module intercept the calls to git binary
6
+ # made buy the grit objects and attempts to run them in pure ruby
7
+ # if it will be faster, or if the git binary is not available (!!TODO!!)
8
+ module GitRuby
9
+
10
+ attr_accessor :ruby_git_repo, :git_file_index
11
+
12
+ def init(options, *args)
13
+ if options.size == 0
14
+ Grit::GitRuby::Repository.init(@git_dir)
15
+ else
16
+ method_missing('init', options, *args)
17
+ end
18
+ end
19
+
20
+ def cat_file(options, sha)
21
+ if options[:t]
22
+ file_type(sha)
23
+ elsif options[:s]
24
+ file_size(sha)
25
+ elsif options[:p]
26
+ try_run { ruby_git.cat_file(sha) }
27
+ end
28
+ rescue Grit::GitRuby::Repository::NoSuchShaFound
29
+ ''
30
+ end
31
+
32
+ def cat_ref(options, ref)
33
+ sha = rev_parse({}, ref)
34
+ cat_file(options, sha)
35
+ end
36
+
37
+ # lib/grit/tree.rb:16: output = repo.git.ls_tree({}, treeish, *paths)
38
+ def ls_tree(options, treeish, *paths)
39
+ sha = rev_parse({}, treeish)
40
+ ruby_git.ls_tree(sha, paths.flatten, options.delete(:r))
41
+ rescue Grit::GitRuby::Repository::NoSuchShaFound
42
+ ''
43
+ end
44
+
45
+ # git diff --full-index 'ec037431382e83c3e95d4f2b3d145afbac8ea55d' 'f1ec1aea10986159456846b8a05615b87828d6c6'
46
+ def diff(options, sha1, sha2 = nil)
47
+ try_run { ruby_git.diff(sha1, sha2, options) }
48
+ end
49
+
50
+ def rev_list(options, *refs)
51
+ refs = ['master'] if refs.empty?
52
+ options.delete(:skip) if options[:skip].to_i == 0
53
+ allowed_options = [:max_count, :since, :until, :pretty] # this is all I can do right now
54
+ if ((options.keys - allowed_options).size > 0) || refs.size > 1
55
+ method_missing('rev-list', options, *refs)
56
+ elsif (options.size == 0)
57
+ # pure rev-list
58
+ ref = refs.first
59
+ begin
60
+ file_index.commits_from(rev_parse({}, ref)).join("\n") + "\n"
61
+ rescue
62
+ method_missing('rev-list', options, *refs)
63
+ end
64
+ else
65
+ ref = refs.first
66
+ aref = rev_parse({:verify => true}, ref)
67
+ if aref.is_a? Array
68
+ method_missing('rev-list', options, *refs)
69
+ else
70
+ try_run { ruby_git.rev_list(aref, options) }
71
+ end
72
+ end
73
+ end
74
+
75
+ def rev_parse(options, string)
76
+ raise RuntimeError, "invalid string: #{string.inspect}" unless string.is_a?(String)
77
+
78
+ if string =~ /\.\./
79
+ (sha1, sha2) = string.split('..')
80
+ return [rev_parse({}, sha1), rev_parse({}, sha2)]
81
+ end
82
+
83
+ if /^[0-9a-f]{40}$/.match(string) # passing in a sha - just no-op it
84
+ return string.chomp
85
+ end
86
+
87
+ head = File.join(@git_dir, 'refs', 'heads', string)
88
+ return File.read(head).chomp if File.file?(head)
89
+
90
+ head = File.join(@git_dir, 'refs', 'remotes', string)
91
+ return File.read(head).chomp if File.file?(head)
92
+
93
+ head = File.join(@git_dir, 'refs', 'tags', string)
94
+ return File.read(head).chomp if File.file?(head)
95
+
96
+ ## check packed-refs file, too
97
+ packref = File.join(@git_dir, 'packed-refs')
98
+ if File.file?(packref)
99
+ File.readlines(packref).each do |line|
100
+ if m = /^(\w{40}) refs\/.+?\/(.*?)$/.match(line)
101
+ next if !Regexp.new(Regexp.escape(string) + '$').match(m[3])
102
+ return m[1].chomp
103
+ end
104
+ end
105
+ end
106
+
107
+ ## !! more - partials and such !!
108
+
109
+ # revert to calling git - grr
110
+ return method_missing('rev-parse', options, string).chomp
111
+ end
112
+
113
+ def refs(options, prefix)
114
+ refs = []
115
+ already = {}
116
+ Dir.chdir(@git_dir) do
117
+ files = Dir.glob(prefix + '/**/*')
118
+ files.each do |ref|
119
+ next if !File.file?(ref)
120
+ id = File.read(ref).chomp
121
+ name = ref.sub("#{prefix}/", '')
122
+ if !already[name]
123
+ refs << "#{name} #{id}"
124
+ already[name] = true
125
+ end
126
+ end
127
+
128
+ if File.file?('packed-refs')
129
+ File.readlines('packed-refs').each do |line|
130
+ if m = /^(\w{40}) (.*?)$/.match(line)
131
+ next if !Regexp.new('^' + prefix).match(m[2])
132
+ name = m[2].sub("#{prefix}/", '')
133
+ if !already[name]
134
+ refs << "#{name} #{m[1]}"
135
+ already[name] = true
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ refs.join("\n")
143
+ end
144
+
145
+ def tags(options, prefix)
146
+ refs = []
147
+ already = {}
148
+
149
+ Dir.chdir(repo.path) do
150
+ files = Dir.glob(prefix + '/**/*')
151
+
152
+ files.each do |ref|
153
+ next if !File.file?(ref)
154
+
155
+ id = File.read(ref).chomp
156
+ name = ref.sub("#{prefix}/", '')
157
+
158
+ if !already[name]
159
+ refs << "#{name} #{id}"
160
+ already[name] = true
161
+ end
162
+ end
163
+
164
+ if File.file?('packed-refs')
165
+ lines = File.readlines('packed-refs')
166
+ lines.each_with_index do |line, i|
167
+ if m = /^(\w{40}) (.*?)$/.match(line)
168
+ next if !Regexp.new('^' + prefix).match(m[2])
169
+ name = m[2].sub("#{prefix}/", '')
170
+
171
+ # Annotated tags in packed-refs include a reference
172
+ # to the commit object on the following line.
173
+ next_line = lines[i + 1]
174
+
175
+ id =
176
+ if next_line && next_line[0] == ?^
177
+ next_line[1..-1].chomp
178
+ else
179
+ m[1]
180
+ end
181
+
182
+ if !already[name]
183
+ refs << "#{name} #{id}"
184
+ already[name] = true
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ refs.join("\n")
192
+ end
193
+
194
+ def file_size(ref)
195
+ try_run { ruby_git.cat_file_size(ref).to_s }
196
+ end
197
+
198
+ def file_type(ref)
199
+ try_run { ruby_git.cat_file_type(ref).to_s }
200
+ end
201
+
202
+ def ruby_git
203
+ @ruby_git_repo ||= Repository.new(@git_dir)
204
+ end
205
+
206
+ private
207
+
208
+ def try_run
209
+ ret = ''
210
+ Timeout.timeout(self.class.git_timeout) do
211
+ ret = yield
212
+ end
213
+ @bytes_read += ret.size
214
+
215
+ #if @bytes_read > 5242880 # 5.megabytes
216
+ # bytes = @bytes_read
217
+ # @bytes_read = 0
218
+ # raise Grit::Git::GitTimeout.new(command, bytes)
219
+ #end
220
+
221
+ ret
222
+ rescue Timeout::Error => e
223
+ bytes = @bytes_read
224
+ @bytes_read = 0
225
+ raise Grit::Git::GitTimeout.new(command, bytes)
226
+ end
227
+
228
+ def looking_for(commit, path = nil)
229
+ tree_sha = ruby_git.get_subtree(rev_parse({}, commit), path)
230
+
231
+ looking_for = []
232
+ ruby_git.get_object_by_sha1(tree_sha).entry.each do |e|
233
+ if path && !(path == '' || path == '.' || path == './')
234
+ file = File.join(path, e.name)
235
+ else
236
+ file = e.name
237
+ end
238
+ file += '/' if e.type == :directory
239
+ looking_for << file
240
+ end
241
+ looking_for
242
+ end
243
+
244
+ def clean_paths(commit_array)
245
+ new_commits = {}
246
+ commit_array.each do |file, sha|
247
+ file = file.chop if file[file.size - 1 , 1] == '/'
248
+ new_commits[file] = sha
249
+ end
250
+ new_commits
251
+ end
252
+
253
+ # TODO
254
+ # git grep -n 'foo' 'master'
255
+ # git log --pretty='raw' --max-count='1' 'master' -- 'LICENSE'
256
+ # git log --pretty='raw' --max-count='1' 'master' -- 'test'
257
+
258
+ end
259
+ end