schacon-grit 0.9.4 → 1.1.1
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.
- data/API.txt +101 -0
- data/History.txt +42 -2
- data/LICENSE +22 -0
- data/README.md +210 -0
- data/VERSION.yml +4 -0
- data/lib/grit.rb +17 -5
- data/lib/grit/blame.rb +61 -0
- data/lib/grit/blob.rb +11 -2
- data/lib/grit/commit.rb +44 -31
- data/lib/grit/commit_stats.rb +26 -2
- data/lib/grit/diff.rb +8 -8
- data/lib/grit/git-ruby.rb +87 -6
- data/lib/grit/git-ruby/git_object.rb +29 -6
- data/lib/grit/git-ruby/internal/{mmap.rb → file_window.rb} +2 -2
- data/lib/grit/git-ruby/internal/loose.rb +6 -6
- data/lib/grit/git-ruby/internal/pack.rb +22 -20
- data/lib/grit/git-ruby/object.rb +8 -2
- data/lib/grit/git-ruby/repository.rb +33 -24
- data/lib/grit/git.rb +189 -11
- data/lib/grit/index.rb +15 -14
- data/lib/grit/merge.rb +45 -0
- data/lib/grit/ref.rb +8 -29
- data/lib/grit/repo.rb +144 -21
- data/lib/grit/ruby1.9.rb +7 -0
- data/lib/grit/submodule.rb +5 -1
- data/lib/grit/tag.rb +22 -66
- data/lib/grit/tree.rb +20 -1
- metadata +32 -47
- data/Manifest.txt +0 -71
- data/README.txt +0 -213
- data/Rakefile +0 -29
- data/grit.gemspec +0 -62
- data/lib/grit/head.rb +0 -83
- data/test/test_actor.rb +0 -35
- data/test/test_blob.rb +0 -79
- data/test/test_commit.rb +0 -190
- data/test/test_config.rb +0 -58
- data/test/test_diff.rb +0 -18
- data/test/test_git.rb +0 -64
- data/test/test_grit.rb +0 -32
- data/test/test_head.rb +0 -47
- data/test/test_real.rb +0 -19
- data/test/test_reality.rb +0 -17
- data/test/test_remote.rb +0 -14
- data/test/test_repo.rb +0 -285
- data/test/test_tag.rb +0 -25
- data/test/test_tree.rb +0 -96
@@ -115,7 +115,7 @@ module Grit
|
|
115
115
|
def initialize(mode, filename, sha1o)
|
116
116
|
@mode = 0
|
117
117
|
mode.each_byte do |i|
|
118
|
-
@mode = (@mode << 3) | (i-'0'
|
118
|
+
@mode = (@mode << 3) | (i-'0'.getord(0))
|
119
119
|
end
|
120
120
|
@name = filename
|
121
121
|
@sha1 = sha1o
|
@@ -179,8 +179,14 @@ module Grit
|
|
179
179
|
|
180
180
|
def self.read_bytes_until(io, char)
|
181
181
|
string = ''
|
182
|
-
|
183
|
-
|
182
|
+
if RUBY_VERSION > '1.9'
|
183
|
+
while ((next_char = io.getc) != char) && !io.eof
|
184
|
+
string += next_char
|
185
|
+
end
|
186
|
+
else
|
187
|
+
while ((next_char = io.getc.chr) != char) && !io.eof
|
188
|
+
string += next_char
|
189
|
+
end
|
184
190
|
end
|
185
191
|
string
|
186
192
|
end
|
@@ -219,6 +225,16 @@ module Grit
|
|
219
225
|
@entry.collect { |e| [[e.format_mode, e.format_type, e.sha1].join(' '), e.name].join("\t") }.join("\n")
|
220
226
|
end
|
221
227
|
|
228
|
+
def to_hash
|
229
|
+
hash = {}
|
230
|
+
@entry.each do |e|
|
231
|
+
hash[e.name] = { 'mode' => e.format_mode,
|
232
|
+
'type' => e.format_type,
|
233
|
+
'sha' => e.sha1 }
|
234
|
+
end
|
235
|
+
hash
|
236
|
+
end
|
237
|
+
|
222
238
|
def actual_raw
|
223
239
|
#@entry.collect { |e| e.raw.join(' '), e.name].join("\t") }.join("\n")
|
224
240
|
end
|
@@ -243,9 +259,6 @@ module Grit
|
|
243
259
|
author = UserInfo.new(value)
|
244
260
|
when "committer"
|
245
261
|
committer = UserInfo.new(value)
|
246
|
-
else
|
247
|
-
warn "unknown header '%s' in commit %s" % \
|
248
|
-
[key, rawobject.sha1.unpack("H*")[0]]
|
249
262
|
end
|
250
263
|
end
|
251
264
|
if not tree && author && committer
|
@@ -281,6 +294,16 @@ module Grit
|
|
281
294
|
output += @message.split("\n").map { |l| ' ' + l }.join("\n") + "\n\n"
|
282
295
|
end
|
283
296
|
|
297
|
+
def to_hash
|
298
|
+
h = {}
|
299
|
+
h['tree'] = @tree
|
300
|
+
h['author'] = @author
|
301
|
+
h['committer'] = @committer
|
302
|
+
h['message'] = @message
|
303
|
+
h['parents'] = @parent
|
304
|
+
h
|
305
|
+
end
|
306
|
+
|
284
307
|
end
|
285
308
|
|
286
309
|
class Tag < GitObject
|
@@ -12,7 +12,7 @@
|
|
12
12
|
module Grit
|
13
13
|
module GitRuby
|
14
14
|
module Internal
|
15
|
-
class
|
15
|
+
class FileWindow
|
16
16
|
def initialize(file, version = 1)
|
17
17
|
@file = file
|
18
18
|
@offset = nil
|
@@ -46,7 +46,7 @@ module Grit
|
|
46
46
|
end
|
47
47
|
@offset = offset + len ? len : 1
|
48
48
|
if not len
|
49
|
-
@file.read(1)
|
49
|
+
@file.read(1).getord(0)
|
50
50
|
else
|
51
51
|
@file.read(len)
|
52
52
|
end
|
@@ -29,7 +29,7 @@ module Grit
|
|
29
29
|
begin
|
30
30
|
return nil unless sha1[0...2] && sha1[2..39]
|
31
31
|
path = @directory + '/' + sha1[0...2] + '/' + sha1[2..39]
|
32
|
-
get_raw_object(File.
|
32
|
+
get_raw_object(File.open(path, 'rb').read)
|
33
33
|
rescue Errno::ENOENT
|
34
34
|
nil
|
35
35
|
end
|
@@ -76,7 +76,7 @@ module Grit
|
|
76
76
|
content = Zlib::Deflate.deflate(store)
|
77
77
|
|
78
78
|
FileUtils.mkdir_p(@directory+'/'+sha1[0...2])
|
79
|
-
File.open(path, '
|
79
|
+
File.open(path, 'wb') do |f|
|
80
80
|
f.write content
|
81
81
|
end
|
82
82
|
end
|
@@ -102,7 +102,7 @@ module Grit
|
|
102
102
|
# private
|
103
103
|
def unpack_object_header_gently(buf)
|
104
104
|
used = 0
|
105
|
-
c = buf
|
105
|
+
c = buf.getord(used)
|
106
106
|
used += 1
|
107
107
|
|
108
108
|
type = (c >> 4) & 7;
|
@@ -112,7 +112,7 @@ module Grit
|
|
112
112
|
if buf.length <= used
|
113
113
|
raise LooseObjectError, "object file too short"
|
114
114
|
end
|
115
|
-
c = buf
|
115
|
+
c = buf.getord(used)
|
116
116
|
used += 1
|
117
117
|
|
118
118
|
size += (c & 0x7f) << shift
|
@@ -127,8 +127,8 @@ module Grit
|
|
127
127
|
private :unpack_object_header_gently
|
128
128
|
|
129
129
|
def legacy_loose_object?(buf)
|
130
|
-
word = (buf
|
131
|
-
buf
|
130
|
+
word = (buf.getord(0) << 8) + buf.getord(1)
|
131
|
+
buf.getord(0) == 0x78 && word % 31 == 0
|
132
132
|
end
|
133
133
|
private :legacy_loose_object?
|
134
134
|
end
|
@@ -11,7 +11,7 @@
|
|
11
11
|
|
12
12
|
require 'zlib'
|
13
13
|
require 'grit/git-ruby/internal/raw_object'
|
14
|
-
require 'grit/git-ruby/internal/
|
14
|
+
require 'grit/git-ruby/internal/file_window'
|
15
15
|
|
16
16
|
PACK_SIGNATURE = "PACK"
|
17
17
|
PACK_IDX_SIGNATURE = "\377tOc"
|
@@ -36,6 +36,8 @@ module Grit
|
|
36
36
|
EntrySize = OffsetSize + SHA1Size
|
37
37
|
EntrySizeV2 = SHA1Size + CrcSize + OffsetSize
|
38
38
|
|
39
|
+
attr_reader :size, :name
|
40
|
+
|
39
41
|
def initialize(file)
|
40
42
|
if file =~ /\.idx$/
|
41
43
|
file = file[0...-3] + 'pack'
|
@@ -48,9 +50,9 @@ module Grit
|
|
48
50
|
def with_idx(index_file = nil)
|
49
51
|
if !index_file
|
50
52
|
index_file = @name
|
51
|
-
idxfile = File.open(@name[0...-4]+'idx')
|
53
|
+
idxfile = File.open(@name[0...-4]+'idx', 'rb')
|
52
54
|
else
|
53
|
-
idxfile = File.open(index_file)
|
55
|
+
idxfile = File.open(index_file, 'rb')
|
54
56
|
end
|
55
57
|
|
56
58
|
# read header
|
@@ -66,14 +68,14 @@ module Grit
|
|
66
68
|
@version = 1
|
67
69
|
end
|
68
70
|
|
69
|
-
idx =
|
71
|
+
idx = FileWindow.new(idxfile, @version)
|
70
72
|
yield idx
|
71
73
|
idx.unmap
|
72
74
|
idxfile.close
|
73
75
|
end
|
74
76
|
|
75
77
|
def with_packfile
|
76
|
-
packfile = File.open(@name)
|
78
|
+
packfile = File.open(@name, 'rb')
|
77
79
|
yield packfile
|
78
80
|
packfile.close
|
79
81
|
end
|
@@ -189,7 +191,7 @@ module Grit
|
|
189
191
|
end
|
190
192
|
|
191
193
|
def find_object_in_index(idx, sha1)
|
192
|
-
slot = sha1
|
194
|
+
slot = sha1.getord(0)
|
193
195
|
return nil if !slot
|
194
196
|
first, last = @offsets[slot,2]
|
195
197
|
while first < last
|
@@ -248,13 +250,13 @@ module Grit
|
|
248
250
|
obj_offset = offset
|
249
251
|
packfile.seek(offset)
|
250
252
|
|
251
|
-
c = packfile.read(1)
|
253
|
+
c = packfile.read(1).getord(0)
|
252
254
|
size = c & 0xf
|
253
255
|
type = (c >> 4) & 7
|
254
256
|
shift = 4
|
255
257
|
offset += 1
|
256
258
|
while c & 0x80 != 0
|
257
|
-
c = packfile.read(1)
|
259
|
+
c = packfile.read(1).getord(0)
|
258
260
|
size |= ((c & 0x7f) << shift)
|
259
261
|
shift += 7
|
260
262
|
offset += 1
|
@@ -265,7 +267,7 @@ module Grit
|
|
265
267
|
case type
|
266
268
|
when OBJ_OFS_DELTA, OBJ_REF_DELTA
|
267
269
|
data, type = unpack_deltified(packfile, type, offset, obj_offset, size, options)
|
268
|
-
#puts type
|
270
|
+
#puts "Type: #{type}"
|
269
271
|
when OBJ_COMMIT, OBJ_TREE, OBJ_BLOB, OBJ_TAG
|
270
272
|
data = unpack_compressed(offset, size)
|
271
273
|
else
|
@@ -281,10 +283,10 @@ module Grit
|
|
281
283
|
|
282
284
|
if type == OBJ_OFS_DELTA
|
283
285
|
i = 0
|
284
|
-
c = data
|
286
|
+
c = data.getord(i)
|
285
287
|
base_offset = c & 0x7f
|
286
288
|
while c & 0x80 != 0
|
287
|
-
c = data
|
289
|
+
c = data.getord(i += 1)
|
288
290
|
base_offset += 1
|
289
291
|
base_offset <<= 7
|
290
292
|
base_offset |= c & 0x7f
|
@@ -335,18 +337,18 @@ module Grit
|
|
335
337
|
dest_size, pos = patch_delta_header_size(delta, pos)
|
336
338
|
dest = ""
|
337
339
|
while pos < delta.size
|
338
|
-
c = delta
|
340
|
+
c = delta.getord(pos)
|
339
341
|
pos += 1
|
340
342
|
if c & 0x80 != 0
|
341
343
|
pos -= 1
|
342
344
|
cp_off = cp_size = 0
|
343
|
-
cp_off = delta
|
344
|
-
cp_off |= delta
|
345
|
-
cp_off |= delta
|
346
|
-
cp_off |= delta
|
347
|
-
cp_size = delta
|
348
|
-
cp_size |= delta
|
349
|
-
cp_size |= delta
|
345
|
+
cp_off = delta.getord(pos += 1) if c & 0x01 != 0
|
346
|
+
cp_off |= delta.getord(pos += 1) << 8 if c & 0x02 != 0
|
347
|
+
cp_off |= delta.getord(pos += 1) << 16 if c & 0x04 != 0
|
348
|
+
cp_off |= delta.getord(pos += 1) << 24 if c & 0x08 != 0
|
349
|
+
cp_size = delta.getord(pos += 1) if c & 0x10 != 0
|
350
|
+
cp_size |= delta.getord(pos += 1) << 8 if c & 0x20 != 0
|
351
|
+
cp_size |= delta.getord(pos += 1) << 16 if c & 0x40 != 0
|
350
352
|
cp_size = 0x10000 if cp_size == 0
|
351
353
|
pos += 1
|
352
354
|
dest += base[cp_off,cp_size]
|
@@ -365,7 +367,7 @@ module Grit
|
|
365
367
|
size = 0
|
366
368
|
shift = 0
|
367
369
|
begin
|
368
|
-
c = delta
|
370
|
+
c = delta.getord(pos)
|
369
371
|
if c == nil
|
370
372
|
raise PackFormatError, 'invalid delta header'
|
371
373
|
end
|
data/lib/grit/git-ruby/object.rb
CHANGED
@@ -163,8 +163,14 @@ module Grit
|
|
163
163
|
|
164
164
|
def self.read_bytes_until(io, char)
|
165
165
|
string = ''
|
166
|
-
|
167
|
-
|
166
|
+
if RUBY_VERSION > '1.9'
|
167
|
+
while ((next_char = io.getc) != char) && !io.eof
|
168
|
+
string += next_char
|
169
|
+
end
|
170
|
+
else
|
171
|
+
while ((next_char = io.getc.chr) != char) && !io.eof
|
172
|
+
string += next_char
|
173
|
+
end
|
168
174
|
end
|
169
175
|
string
|
170
176
|
end
|
@@ -37,7 +37,7 @@ module Grit
|
|
37
37
|
def initialize(git_dir, options = {})
|
38
38
|
@git_dir = git_dir
|
39
39
|
@options = options
|
40
|
-
|
40
|
+
#@packs = []
|
41
41
|
end
|
42
42
|
|
43
43
|
# returns the loose objects object lazily
|
@@ -92,7 +92,7 @@ module Grit
|
|
92
92
|
return o if o
|
93
93
|
end
|
94
94
|
|
95
|
-
|
95
|
+
puts "*#{sha1o}*"
|
96
96
|
raise NoSuchShaFound
|
97
97
|
end
|
98
98
|
|
@@ -185,16 +185,15 @@ module Grit
|
|
185
185
|
def get_raw_tree(sha)
|
186
186
|
o = get_raw_object_by_sha1(sha)
|
187
187
|
if o.type == :commit
|
188
|
-
|
188
|
+
cat_file(get_object_by_sha1(sha).tree)
|
189
189
|
elsif o.type == :tag
|
190
190
|
commit_sha = get_object_by_sha1(sha).object
|
191
|
-
|
192
|
-
|
193
|
-
|
191
|
+
cat_file(get_object_by_sha1(commit_sha).tree)
|
192
|
+
elsif o.type == :tree
|
193
|
+
cat_file(sha)
|
194
194
|
end
|
195
|
-
return tree
|
196
195
|
end
|
197
|
-
|
196
|
+
|
198
197
|
# return array of tree entries
|
199
198
|
## TODO : refactor this to remove the fugly
|
200
199
|
def ls_tree_path(sha, path, append = nil)
|
@@ -376,37 +375,41 @@ module Grit
|
|
376
375
|
else
|
377
376
|
tree2 = get_object_by_sha1(commit_obj1.parent.first).tree
|
378
377
|
end
|
379
|
-
|
378
|
+
|
380
379
|
qdiff = quick_diff(tree1, tree2)
|
381
|
-
|
380
|
+
|
382
381
|
qdiff.sort.each do |diff_arr|
|
382
|
+
path, status, treeSHA1, treeSHA2 = *diff_arr
|
383
383
|
format, lines, output = :unified, 3, ''
|
384
384
|
file_length_difference = 0
|
385
|
-
|
386
|
-
fileA =
|
387
|
-
fileB =
|
388
|
-
|
389
|
-
sha1 =
|
390
|
-
sha2 =
|
385
|
+
|
386
|
+
fileA = treeSHA1 ? cat_file(treeSHA1) : ''
|
387
|
+
fileB = treeSHA2 ? cat_file(treeSHA2) : ''
|
388
|
+
|
389
|
+
sha1 = treeSHA1 || '0000000000000000000000000000000000000000'
|
390
|
+
sha2 = treeSHA2 || '0000000000000000000000000000000000000000'
|
391
391
|
|
392
392
|
data_old = fileA.split(/\n/).map! { |e| e.chomp }
|
393
393
|
data_new = fileB.split(/\n/).map! { |e| e.chomp }
|
394
|
-
|
395
|
-
diffs = Difference::LCS.diff(data_old, data_new)
|
394
|
+
|
395
|
+
diffs = Difference::LCS.diff(data_old, data_new)
|
396
396
|
next if diffs.empty?
|
397
397
|
|
398
|
-
|
398
|
+
a_path = "a/#{path.gsub('./', '')}"
|
399
|
+
b_path = "b/#{path.gsub('./', '')}"
|
400
|
+
|
401
|
+
header = "diff --git #{a_path} #{b_path}"
|
399
402
|
if options[:full_index]
|
400
403
|
header << "\n" + 'index ' + sha1 + '..' + sha2
|
401
|
-
header << ' 100644' if
|
404
|
+
header << ' 100644' if treeSHA2 # hard coding this because i don't think we use it
|
402
405
|
else
|
403
406
|
header << "\n" + 'index ' + sha1[0,7] + '..' + sha2[0,7]
|
404
|
-
header << ' 100644' if
|
407
|
+
header << ' 100644' if treeSHA2 # hard coding this because i don't think we use it
|
405
408
|
end
|
406
|
-
header << "\n--- " +
|
407
|
-
header << "\n+++ " +
|
409
|
+
header << "\n--- " + (treeSHA1 ? a_path : '/dev/null')
|
410
|
+
header << "\n+++ " + (treeSHA2 ? b_path : '/dev/null')
|
408
411
|
header += "\n"
|
409
|
-
|
412
|
+
|
410
413
|
oldhunk = hunk = nil
|
411
414
|
|
412
415
|
diffs.each do |piece|
|
@@ -664,6 +667,7 @@ module Grit
|
|
664
667
|
private
|
665
668
|
|
666
669
|
def initloose
|
670
|
+
@loaded = []
|
667
671
|
@loose = []
|
668
672
|
load_loose(git_path('objects'))
|
669
673
|
load_alternate_loose(git_path('objects'))
|
@@ -675,6 +679,7 @@ module Grit
|
|
675
679
|
alt = File.join(path, 'info/alternates')
|
676
680
|
if File.exists?(alt)
|
677
681
|
File.readlines(alt).each do |line|
|
682
|
+
next if @loaded.include?(line.chomp)
|
678
683
|
if line[0, 2] == '..'
|
679
684
|
line = File.expand_path(File.join(@git_dir, line))
|
680
685
|
end
|
@@ -685,12 +690,14 @@ module Grit
|
|
685
690
|
end
|
686
691
|
|
687
692
|
def load_loose(path)
|
693
|
+
@loaded << path
|
688
694
|
return if !File.exists?(path)
|
689
695
|
@loose << Grit::GitRuby::Internal::LooseStorage.new(path)
|
690
696
|
end
|
691
697
|
|
692
698
|
def initpacks
|
693
699
|
close
|
700
|
+
@loaded_packs = []
|
694
701
|
@packs = []
|
695
702
|
load_packs(git_path("objects/pack"))
|
696
703
|
load_alternate_packs(git_path('objects'))
|
@@ -705,6 +712,7 @@ module Grit
|
|
705
712
|
line = File.expand_path(File.join(@git_dir, line))
|
706
713
|
end
|
707
714
|
full_pack = File.join(line.chomp, 'pack')
|
715
|
+
next if @loaded_packs.include?(full_pack)
|
708
716
|
load_packs(full_pack)
|
709
717
|
load_alternate_packs(File.join(line.chomp))
|
710
718
|
end
|
@@ -712,6 +720,7 @@ module Grit
|
|
712
720
|
end
|
713
721
|
|
714
722
|
def load_packs(path)
|
723
|
+
@loaded_packs << path
|
715
724
|
return if !File.exists?(path)
|
716
725
|
Dir.open(path) do |dir|
|
717
726
|
dir.each do |entry|
|
data/lib/grit/git.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'tempfile'
|
1
2
|
module Grit
|
2
3
|
|
3
4
|
class Git
|
@@ -13,13 +14,33 @@ module Grit
|
|
13
14
|
undef_method :clone
|
14
15
|
|
15
16
|
include GitRuby
|
16
|
-
|
17
|
+
|
18
|
+
def exist?
|
19
|
+
File.exist?(self.git_dir)
|
20
|
+
end
|
21
|
+
|
22
|
+
def put_raw_object(content, type)
|
23
|
+
ruby_git.put_raw_object(content, type)
|
24
|
+
end
|
25
|
+
|
26
|
+
def object_exists?(object_id)
|
27
|
+
ruby_git.object_exists?(object_id)
|
28
|
+
end
|
29
|
+
|
17
30
|
class << self
|
18
|
-
attr_accessor :git_binary, :git_timeout
|
31
|
+
attr_accessor :git_binary, :git_timeout, :git_max_size
|
19
32
|
end
|
20
33
|
|
21
|
-
self.git_binary
|
22
|
-
self.git_timeout
|
34
|
+
self.git_binary = "/usr/bin/env git"
|
35
|
+
self.git_timeout = 10
|
36
|
+
self.git_max_size = 5242880 # 5.megabytes
|
37
|
+
|
38
|
+
def self.with_timeout(timeout = 10.seconds)
|
39
|
+
old_timeout = Grit::Git.git_timeout
|
40
|
+
Grit::Git.git_timeout = timeout
|
41
|
+
yield
|
42
|
+
Grit::Git.git_timeout = old_timeout
|
43
|
+
end
|
23
44
|
|
24
45
|
attr_accessor :git_dir, :bytes_read
|
25
46
|
|
@@ -28,6 +49,152 @@ module Grit
|
|
28
49
|
self.bytes_read = 0
|
29
50
|
end
|
30
51
|
|
52
|
+
def shell_escape(str)
|
53
|
+
str.to_s.gsub("'", "\\\\'").gsub(";", '\\;')
|
54
|
+
end
|
55
|
+
alias_method :e, :shell_escape
|
56
|
+
|
57
|
+
# Check if a normal file exists on the filesystem
|
58
|
+
# +file+ is the relative path from the Git dir
|
59
|
+
#
|
60
|
+
# Returns Boolean
|
61
|
+
def fs_exist?(file)
|
62
|
+
File.exist?(File.join(self.git_dir, file))
|
63
|
+
end
|
64
|
+
|
65
|
+
# Read a normal file from the filesystem.
|
66
|
+
# +file+ is the relative path from the Git dir
|
67
|
+
#
|
68
|
+
# Returns the String contents of the file
|
69
|
+
def fs_read(file)
|
70
|
+
File.open(File.join(self.git_dir, file)).read
|
71
|
+
end
|
72
|
+
|
73
|
+
# Write a normal file to the filesystem.
|
74
|
+
# +file+ is the relative path from the Git dir
|
75
|
+
# +contents+ is the String content to be written
|
76
|
+
#
|
77
|
+
# Returns nothing
|
78
|
+
def fs_write(file, contents)
|
79
|
+
path = File.join(self.git_dir, file)
|
80
|
+
FileUtils.mkdir_p(File.dirname(path))
|
81
|
+
File.open(path, 'w') do |f|
|
82
|
+
f.write(contents)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Delete a normal file from the filesystem
|
87
|
+
# +file+ is the relative path from the Git dir
|
88
|
+
#
|
89
|
+
# Returns nothing
|
90
|
+
def fs_delete(file)
|
91
|
+
FileUtils.rm_rf(File.join(self.git_dir, file))
|
92
|
+
end
|
93
|
+
|
94
|
+
# Move a normal file
|
95
|
+
# +from+ is the relative path to the current file
|
96
|
+
# +to+ is the relative path to the destination file
|
97
|
+
#
|
98
|
+
# Returns nothing
|
99
|
+
def fs_move(from, to)
|
100
|
+
FileUtils.mv(File.join(self.git_dir, from), File.join(self.git_dir, to))
|
101
|
+
end
|
102
|
+
|
103
|
+
# Make a directory
|
104
|
+
# +dir+ is the relative path to the directory to create
|
105
|
+
#
|
106
|
+
# Returns nothing
|
107
|
+
def fs_mkdir(dir)
|
108
|
+
FileUtils.mkdir_p(File.join(self.git_dir, dir))
|
109
|
+
end
|
110
|
+
|
111
|
+
# Chmod the the file or dir and everything beneath
|
112
|
+
# +file+ is the relative path from the Git dir
|
113
|
+
#
|
114
|
+
# Returns nothing
|
115
|
+
def fs_chmod(mode, file = '/')
|
116
|
+
FileUtils.chmod_R(mode, File.join(self.git_dir, file))
|
117
|
+
end
|
118
|
+
|
119
|
+
# Create a new directory
|
120
|
+
# +path+ is an absolute path
|
121
|
+
#
|
122
|
+
# Returns nothing
|
123
|
+
def fs_mkdir(path)
|
124
|
+
FileUtils.mkdir_p(path)
|
125
|
+
end
|
126
|
+
|
127
|
+
def fs_exist(path)
|
128
|
+
File.exist?(path)
|
129
|
+
end
|
130
|
+
|
131
|
+
def list_remotes
|
132
|
+
remotes = []
|
133
|
+
Dir.chdir(File.join(self.git_dir, 'refs/remotes')) do
|
134
|
+
remotes = Dir.glob('*')
|
135
|
+
end
|
136
|
+
remotes
|
137
|
+
rescue
|
138
|
+
[]
|
139
|
+
end
|
140
|
+
|
141
|
+
def create_tempfile(seed, unlink = false)
|
142
|
+
path = Tempfile.new(seed).path
|
143
|
+
File.unlink(path) if unlink
|
144
|
+
return path
|
145
|
+
end
|
146
|
+
|
147
|
+
def check_applies(head_sha, applies_sha)
|
148
|
+
git_index = create_tempfile('index', true)
|
149
|
+
(o1, exit1) = raw_git("git read-tree #{head_sha} 2>/dev/null", git_index)
|
150
|
+
(o2, exit2) = raw_git("git diff #{applies_sha}^ #{applies_sha} | git apply --check --cached >/dev/null 2>/dev/null", git_index)
|
151
|
+
return (exit1 + exit2)
|
152
|
+
end
|
153
|
+
|
154
|
+
def get_patch(applies_sha)
|
155
|
+
git_index = create_tempfile('index', true)
|
156
|
+
(patch, exit2) = raw_git("git diff #{applies_sha}^ #{applies_sha}", git_index)
|
157
|
+
patch
|
158
|
+
end
|
159
|
+
|
160
|
+
def apply_patch(head_sha, patch)
|
161
|
+
git_index = create_tempfile('index', true)
|
162
|
+
|
163
|
+
git_patch = create_tempfile('patch')
|
164
|
+
File.open(git_patch, 'w+') { |f| f.print patch }
|
165
|
+
|
166
|
+
raw_git("git read-tree #{head_sha} 2>/dev/null", git_index)
|
167
|
+
(op, exit) = raw_git("git apply --cached < #{git_patch}", git_index)
|
168
|
+
if exit == 0
|
169
|
+
return raw_git("git write-tree", git_index).first.chomp
|
170
|
+
end
|
171
|
+
false
|
172
|
+
end
|
173
|
+
|
174
|
+
# RAW CALLS WITH ENV SETTINGS
|
175
|
+
def raw_git_call(command, index)
|
176
|
+
tmp = ENV['GIT_INDEX_FILE']
|
177
|
+
ENV['GIT_INDEX_FILE'] = index
|
178
|
+
out = `#{command}`
|
179
|
+
after = ENV['GIT_INDEX_FILE'] # someone fucking with us ??
|
180
|
+
ENV['GIT_INDEX_FILE'] = tmp
|
181
|
+
if after != index
|
182
|
+
raise 'environment was changed for the git call'
|
183
|
+
end
|
184
|
+
[out, $?.exitstatus]
|
185
|
+
end
|
186
|
+
|
187
|
+
def raw_git(command, index)
|
188
|
+
output = nil
|
189
|
+
Dir.chdir(self.git_dir) do
|
190
|
+
output = raw_git_call(command, index)
|
191
|
+
end
|
192
|
+
output
|
193
|
+
end
|
194
|
+
# RAW CALLS WITH ENV SETTINGS END
|
195
|
+
|
196
|
+
|
197
|
+
|
31
198
|
# Run the given git command with the specified arguments and return
|
32
199
|
# the result as a String
|
33
200
|
# +cmd+ is the command
|
@@ -42,14 +209,21 @@ module Grit
|
|
42
209
|
run('', cmd, '', options, args)
|
43
210
|
end
|
44
211
|
|
212
|
+
# Bypass any pure Ruby implementations and go straight to the native Git command
|
213
|
+
#
|
214
|
+
# Returns String
|
215
|
+
def native(cmd, options = {}, *args)
|
216
|
+
method_missing(cmd, options, *args)
|
217
|
+
end
|
218
|
+
|
45
219
|
def run(prefix, cmd, postfix, options, args)
|
46
|
-
timeout = options.delete(:timeout)
|
220
|
+
timeout = options.delete(:timeout) rescue nil
|
47
221
|
timeout = true if timeout.nil?
|
48
222
|
|
49
223
|
opt_args = transform_options(options)
|
50
|
-
ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|') ? a : "'#{a}'" }
|
51
|
-
|
52
|
-
call = "#{prefix}#{Git.git_binary} --git-dir='#{self.git_dir}' #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{postfix}"
|
224
|
+
ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|' || Grit.no_quote) ? a : "'#{e(a)}'" }
|
225
|
+
|
226
|
+
call = "#{prefix}#{Git.git_binary} --git-dir='#{self.git_dir}' #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{e(postfix)}"
|
53
227
|
Grit.log(call) if Grit.debug
|
54
228
|
response, err = timeout ? sh(call) : wild_sh(call)
|
55
229
|
Grit.log(response) if Grit.debug
|
@@ -63,7 +237,7 @@ module Grit
|
|
63
237
|
Timeout.timeout(self.class.git_timeout) do
|
64
238
|
while tmp = stdout.read(1024)
|
65
239
|
ret += tmp
|
66
|
-
if (@bytes_read += tmp.size) >
|
240
|
+
if (@bytes_read += tmp.size) > self.class.git_max_size
|
67
241
|
bytes = @bytes_read
|
68
242
|
@bytes_read = 0
|
69
243
|
raise GitTimeout.new(command, bytes)
|
@@ -107,16 +281,20 @@ module Grit
|
|
107
281
|
if opt.to_s.size == 1
|
108
282
|
if options[opt] == true
|
109
283
|
args << "-#{opt}"
|
284
|
+
elsif options[opt] == false
|
285
|
+
# ignore
|
110
286
|
else
|
111
287
|
val = options.delete(opt)
|
112
|
-
args << "-#{opt.to_s} '#{val}'"
|
288
|
+
args << "-#{opt.to_s} '#{e(val)}'"
|
113
289
|
end
|
114
290
|
else
|
115
291
|
if options[opt] == true
|
116
292
|
args << "--#{opt.to_s.gsub(/_/, '-')}"
|
293
|
+
elsif options[opt] == false
|
294
|
+
# ignore
|
117
295
|
else
|
118
296
|
val = options.delete(opt)
|
119
|
-
args << "--#{opt.to_s.gsub(/_/, '-')}='#{val}'"
|
297
|
+
args << "--#{opt.to_s.gsub(/_/, '-')}='#{e(val)}'"
|
120
298
|
end
|
121
299
|
end
|
122
300
|
end
|