jit 0.0.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE.txt +674 -0
- data/bin/jit +21 -0
- data/lib/color.rb +32 -0
- data/lib/command.rb +62 -0
- data/lib/command/add.rb +65 -0
- data/lib/command/base.rb +92 -0
- data/lib/command/branch.rb +199 -0
- data/lib/command/checkout.rb +104 -0
- data/lib/command/cherry_pick.rb +51 -0
- data/lib/command/commit.rb +86 -0
- data/lib/command/config.rb +126 -0
- data/lib/command/diff.rb +114 -0
- data/lib/command/fetch.rb +116 -0
- data/lib/command/init.rb +41 -0
- data/lib/command/log.rb +188 -0
- data/lib/command/merge.rb +148 -0
- data/lib/command/push.rb +172 -0
- data/lib/command/receive_pack.rb +92 -0
- data/lib/command/remote.rb +55 -0
- data/lib/command/reset.rb +64 -0
- data/lib/command/rev_list.rb +33 -0
- data/lib/command/revert.rb +69 -0
- data/lib/command/rm.rb +105 -0
- data/lib/command/shared/fast_forward.rb +19 -0
- data/lib/command/shared/print_diff.rb +116 -0
- data/lib/command/shared/receive_objects.rb +37 -0
- data/lib/command/shared/remote_agent.rb +44 -0
- data/lib/command/shared/remote_client.rb +82 -0
- data/lib/command/shared/send_objects.rb +24 -0
- data/lib/command/shared/sequencing.rb +146 -0
- data/lib/command/shared/write_commit.rb +167 -0
- data/lib/command/status.rb +210 -0
- data/lib/command/upload_pack.rb +54 -0
- data/lib/config.rb +240 -0
- data/lib/config/stack.rb +42 -0
- data/lib/database.rb +112 -0
- data/lib/database/author.rb +27 -0
- data/lib/database/backends.rb +57 -0
- data/lib/database/blob.rb +24 -0
- data/lib/database/commit.rb +70 -0
- data/lib/database/entry.rb +7 -0
- data/lib/database/loose.rb +70 -0
- data/lib/database/packed.rb +75 -0
- data/lib/database/tree.rb +77 -0
- data/lib/database/tree_diff.rb +88 -0
- data/lib/diff.rb +46 -0
- data/lib/diff/combined.rb +72 -0
- data/lib/diff/hunk.rb +64 -0
- data/lib/diff/myers.rb +90 -0
- data/lib/editor.rb +59 -0
- data/lib/index.rb +212 -0
- data/lib/index/checksum.rb +44 -0
- data/lib/index/entry.rb +91 -0
- data/lib/lockfile.rb +55 -0
- data/lib/merge/bases.rb +38 -0
- data/lib/merge/common_ancestors.rb +77 -0
- data/lib/merge/diff3.rb +156 -0
- data/lib/merge/inputs.rb +42 -0
- data/lib/merge/resolve.rb +178 -0
- data/lib/pack.rb +45 -0
- data/lib/pack/compressor.rb +83 -0
- data/lib/pack/delta.rb +58 -0
- data/lib/pack/entry.rb +54 -0
- data/lib/pack/expander.rb +54 -0
- data/lib/pack/index.rb +100 -0
- data/lib/pack/indexer.rb +200 -0
- data/lib/pack/numbers.rb +79 -0
- data/lib/pack/reader.rb +98 -0
- data/lib/pack/stream.rb +80 -0
- data/lib/pack/unpacker.rb +62 -0
- data/lib/pack/window.rb +47 -0
- data/lib/pack/writer.rb +92 -0
- data/lib/pack/xdelta.rb +118 -0
- data/lib/pager.rb +24 -0
- data/lib/progress.rb +78 -0
- data/lib/refs.rb +260 -0
- data/lib/remotes.rb +82 -0
- data/lib/remotes/protocol.rb +82 -0
- data/lib/remotes/refspec.rb +70 -0
- data/lib/remotes/remote.rb +57 -0
- data/lib/repository.rb +64 -0
- data/lib/repository/divergence.rb +21 -0
- data/lib/repository/hard_reset.rb +35 -0
- data/lib/repository/inspector.rb +49 -0
- data/lib/repository/migration.rb +168 -0
- data/lib/repository/pending_commit.rb +60 -0
- data/lib/repository/sequencer.rb +118 -0
- data/lib/repository/status.rb +98 -0
- data/lib/rev_list.rb +244 -0
- data/lib/revision.rb +155 -0
- data/lib/sorted_hash.rb +17 -0
- data/lib/temp_file.rb +34 -0
- data/lib/workspace.rb +107 -0
- metadata +103 -9
data/lib/pack/numbers.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
module Pack
|
2
|
+
module Numbers
|
3
|
+
|
4
|
+
module VarIntLE
|
5
|
+
def self.write(value, shift)
|
6
|
+
bytes = []
|
7
|
+
mask = 2 ** shift - 1
|
8
|
+
|
9
|
+
until value <= mask
|
10
|
+
bytes.push(0x80 | value & mask)
|
11
|
+
value >>= shift
|
12
|
+
|
13
|
+
mask, shift = 0x7f, 7
|
14
|
+
end
|
15
|
+
|
16
|
+
bytes + [value]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.read(input, shift)
|
20
|
+
first = input.readbyte
|
21
|
+
value = first & (2 ** shift - 1)
|
22
|
+
|
23
|
+
byte = first
|
24
|
+
|
25
|
+
until byte < 0x80
|
26
|
+
byte = input.readbyte
|
27
|
+
value |= (byte & 0x7f) << shift
|
28
|
+
shift += 7
|
29
|
+
end
|
30
|
+
|
31
|
+
[first, value]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module VarIntBE
|
36
|
+
def self.write(value)
|
37
|
+
bytes = [value & 0x7f]
|
38
|
+
|
39
|
+
until (value >>= 7) == 0
|
40
|
+
value -= 1
|
41
|
+
bytes.push(0x80 | value & 0x7f)
|
42
|
+
end
|
43
|
+
|
44
|
+
bytes.reverse.pack("C*")
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.read(input)
|
48
|
+
byte = input.readbyte
|
49
|
+
value = byte & 0x7f
|
50
|
+
|
51
|
+
until byte < 0x80
|
52
|
+
byte = input.readbyte
|
53
|
+
value = ((value + 1) << 7) | (byte & 0x7f)
|
54
|
+
end
|
55
|
+
|
56
|
+
value
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module PackedInt56LE
|
61
|
+
def self.write(value)
|
62
|
+
bytes = (0..6).map { |i| (value >> (8 * i)) & 0xff }
|
63
|
+
|
64
|
+
flags = bytes.map.with_index { |b, i| b == 0 ? 0 : 1 << i }
|
65
|
+
header = flags.reduce(0) { |a, b| a | b }
|
66
|
+
|
67
|
+
[header] + bytes.reject { |b| b == 0 }
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.read(input, header)
|
71
|
+
flags = (0..6).reject { |i| header & (1 << i) == 0 }
|
72
|
+
bytes = flags.map { |i| input.readbyte << (8 * i) }
|
73
|
+
|
74
|
+
bytes.reduce(0) { |a, b| a | b }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
data/lib/pack/reader.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require "zlib"
|
2
|
+
|
3
|
+
require_relative "./expander"
|
4
|
+
require_relative "./numbers"
|
5
|
+
|
6
|
+
module Pack
|
7
|
+
class Reader
|
8
|
+
|
9
|
+
attr_reader :count
|
10
|
+
|
11
|
+
def initialize(input)
|
12
|
+
@input = input
|
13
|
+
end
|
14
|
+
|
15
|
+
def read_header
|
16
|
+
data = @input.read(HEADER_SIZE)
|
17
|
+
signature, version, @count = data.unpack(HEADER_FORMAT)
|
18
|
+
|
19
|
+
unless signature == SIGNATURE
|
20
|
+
raise InvalidPack, "bad pack signature: #{ signature }"
|
21
|
+
end
|
22
|
+
|
23
|
+
unless version == VERSION
|
24
|
+
raise InvalidPack, "unsupported pack version: #{ version }"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_record
|
29
|
+
type, _ = read_record_header
|
30
|
+
|
31
|
+
case type
|
32
|
+
when COMMIT, TREE, BLOB
|
33
|
+
Record.new(TYPE_CODES.key(type), read_zlib_stream)
|
34
|
+
when OFS_DELTA
|
35
|
+
read_ofs_delta
|
36
|
+
when REF_DELTA
|
37
|
+
read_ref_delta
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def read_info
|
42
|
+
type, size = read_record_header
|
43
|
+
|
44
|
+
case type
|
45
|
+
when COMMIT, TREE, BLOB
|
46
|
+
Record.new(TYPE_CODES.key(type), size)
|
47
|
+
|
48
|
+
when OFS_DELTA
|
49
|
+
delta = read_ofs_delta
|
50
|
+
size = Expander.new(delta.delta_data).target_size
|
51
|
+
|
52
|
+
OfsDelta.new(delta.base_ofs, size)
|
53
|
+
|
54
|
+
when REF_DELTA
|
55
|
+
delta = read_ref_delta
|
56
|
+
size = Expander.new(delta.delta_data).target_size
|
57
|
+
|
58
|
+
RefDelta.new(delta.base_oid, size)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def read_record_header
|
65
|
+
byte, size = Numbers::VarIntLE.read(@input, 4)
|
66
|
+
type = (byte >> 4) & 0x7
|
67
|
+
|
68
|
+
[type, size]
|
69
|
+
end
|
70
|
+
|
71
|
+
def read_ofs_delta
|
72
|
+
offset = Numbers::VarIntBE.read(@input)
|
73
|
+
OfsDelta.new(offset, read_zlib_stream)
|
74
|
+
end
|
75
|
+
|
76
|
+
def read_ref_delta
|
77
|
+
base_oid = @input.read(20).unpack("H40").first
|
78
|
+
RefDelta.new(base_oid, read_zlib_stream)
|
79
|
+
end
|
80
|
+
|
81
|
+
def read_zlib_stream
|
82
|
+
stream = Zlib::Inflate.new
|
83
|
+
string = ""
|
84
|
+
total = 0
|
85
|
+
|
86
|
+
until stream.finished?
|
87
|
+
data = @input.read_nonblock(256)
|
88
|
+
total += data.bytesize
|
89
|
+
|
90
|
+
string.concat(stream.inflate(data))
|
91
|
+
end
|
92
|
+
@input.seek(stream.total_in - total, IO::SEEK_CUR)
|
93
|
+
|
94
|
+
string
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
data/lib/pack/stream.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require "digest/sha1"
|
2
|
+
|
3
|
+
module Pack
|
4
|
+
class Stream
|
5
|
+
|
6
|
+
attr_reader :digest, :offset
|
7
|
+
|
8
|
+
def initialize(input, buffer = "")
|
9
|
+
@input = input
|
10
|
+
@digest = Digest::SHA1.new
|
11
|
+
@offset = 0
|
12
|
+
@buffer = new_byte_string.concat(buffer)
|
13
|
+
@capture = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def capture
|
17
|
+
@capture = new_byte_string
|
18
|
+
result = [yield, @capture]
|
19
|
+
|
20
|
+
@digest.update(@capture)
|
21
|
+
@capture = nil
|
22
|
+
|
23
|
+
result
|
24
|
+
end
|
25
|
+
|
26
|
+
def verify_checksum
|
27
|
+
unless read_buffered(20) == @digest.digest
|
28
|
+
raise InvalidPack, "Checksum does not match value read from pack"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def read(size)
|
33
|
+
data = read_buffered(size)
|
34
|
+
update_state(data)
|
35
|
+
data
|
36
|
+
end
|
37
|
+
|
38
|
+
def read_nonblock(size)
|
39
|
+
data = read_buffered(size, false)
|
40
|
+
update_state(data)
|
41
|
+
data
|
42
|
+
end
|
43
|
+
|
44
|
+
def readbyte
|
45
|
+
read(1).bytes.first
|
46
|
+
end
|
47
|
+
|
48
|
+
def seek(amount, whence = IO::SEEK_SET)
|
49
|
+
return unless amount < 0
|
50
|
+
|
51
|
+
data = @capture.slice!(amount .. -1)
|
52
|
+
@buffer.prepend(data)
|
53
|
+
@offset += amount
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def new_byte_string
|
59
|
+
String.new("", :encoding => Encoding::ASCII_8BIT)
|
60
|
+
end
|
61
|
+
|
62
|
+
def read_buffered(size, block = true)
|
63
|
+
from_buf = @buffer.slice!(0, size)
|
64
|
+
needed = size - from_buf.bytesize
|
65
|
+
from_io = block ? @input.read(needed) : @input.read_nonblock(needed)
|
66
|
+
|
67
|
+
from_buf.concat(from_io.to_s)
|
68
|
+
|
69
|
+
rescue EOFError, Errno::EWOULDBLOCK
|
70
|
+
from_buf
|
71
|
+
end
|
72
|
+
|
73
|
+
def update_state(data)
|
74
|
+
@digest.update(data) unless @capture
|
75
|
+
@offset += data.bytesize
|
76
|
+
@capture&.concat(data)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require_relative "./expander"
|
2
|
+
|
3
|
+
module Pack
|
4
|
+
class Unpacker
|
5
|
+
|
6
|
+
def initialize(database, reader, stream, progress)
|
7
|
+
@database = database
|
8
|
+
@reader = reader
|
9
|
+
@stream = stream
|
10
|
+
@progress = progress
|
11
|
+
@offsets = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def process_pack
|
15
|
+
@progress&.start("Unpacking objects", @reader.count)
|
16
|
+
|
17
|
+
@reader.count.times do
|
18
|
+
process_record
|
19
|
+
@progress&.tick(@stream.offset)
|
20
|
+
end
|
21
|
+
@progress&.stop
|
22
|
+
|
23
|
+
@stream.verify_checksum
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def process_record
|
29
|
+
offset = @stream.offset
|
30
|
+
record, _ = @stream.capture { @reader.read_record }
|
31
|
+
|
32
|
+
record = resolve(record, offset)
|
33
|
+
@database.store(record)
|
34
|
+
@offsets[offset] = record.oid
|
35
|
+
end
|
36
|
+
|
37
|
+
def resolve(record, offset)
|
38
|
+
case record
|
39
|
+
when Record then record
|
40
|
+
when OfsDelta then resolve_ofs_delta(record, offset)
|
41
|
+
when RefDelta then resolve_ref_delta(record)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def resolve_ofs_delta(delta, offset)
|
46
|
+
oid = @offsets[offset - delta.base_ofs]
|
47
|
+
resolve_delta(oid, delta.delta_data)
|
48
|
+
end
|
49
|
+
|
50
|
+
def resolve_ref_delta(delta)
|
51
|
+
resolve_delta(delta.base_oid, delta.delta_data)
|
52
|
+
end
|
53
|
+
|
54
|
+
def resolve_delta(oid, delta_data)
|
55
|
+
base = @database.load_raw(oid)
|
56
|
+
data = Expander.expand(base.data, delta_data)
|
57
|
+
|
58
|
+
Record.new(base.type, data)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/lib/pack/window.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module Pack
|
4
|
+
class Window
|
5
|
+
|
6
|
+
Unpacked = Struct.new(:entry, :data) do
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :entry, :type, :size, :delta, :depth
|
9
|
+
|
10
|
+
attr_accessor :delta_index
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(size)
|
14
|
+
@objects = Array.new(size)
|
15
|
+
@offset = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(entry, data)
|
19
|
+
unpacked = Unpacked.new(entry, data)
|
20
|
+
@objects[@offset] = unpacked
|
21
|
+
@offset = wrap(@offset + 1)
|
22
|
+
|
23
|
+
unpacked
|
24
|
+
end
|
25
|
+
|
26
|
+
def each
|
27
|
+
cursor = wrap(@offset - 2)
|
28
|
+
limit = wrap(@offset - 1)
|
29
|
+
|
30
|
+
loop do
|
31
|
+
break if cursor == limit
|
32
|
+
|
33
|
+
unpacked = @objects[cursor]
|
34
|
+
yield unpacked if unpacked
|
35
|
+
|
36
|
+
cursor = wrap(cursor - 1)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def wrap(offset)
|
43
|
+
offset % @objects.size
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
data/lib/pack/writer.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require "digest/sha1"
|
2
|
+
require "zlib"
|
3
|
+
|
4
|
+
require_relative "./compressor"
|
5
|
+
require_relative "./entry"
|
6
|
+
require_relative "./numbers"
|
7
|
+
|
8
|
+
module Pack
|
9
|
+
class Writer
|
10
|
+
|
11
|
+
def initialize(output, database, options = {})
|
12
|
+
@output = output
|
13
|
+
@database = database
|
14
|
+
@digest = Digest::SHA1.new
|
15
|
+
@offset = 0
|
16
|
+
|
17
|
+
@compression = options.fetch(:compression, Zlib::DEFAULT_COMPRESSION)
|
18
|
+
@allow_ofs = options[:allow_ofs]
|
19
|
+
@progress = options[:progress]
|
20
|
+
end
|
21
|
+
|
22
|
+
def write_objects(rev_list)
|
23
|
+
prepare_pack_list(rev_list)
|
24
|
+
compress_objects
|
25
|
+
write_header
|
26
|
+
write_entries
|
27
|
+
@output.write(@digest.digest)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def write(data)
|
33
|
+
@output.write(data)
|
34
|
+
@digest.update(data)
|
35
|
+
@offset += data.bytesize
|
36
|
+
end
|
37
|
+
|
38
|
+
def prepare_pack_list(rev_list)
|
39
|
+
@pack_list = []
|
40
|
+
@progress&.start("Counting objects")
|
41
|
+
|
42
|
+
rev_list.each do |object, path|
|
43
|
+
add_to_pack_list(object, path)
|
44
|
+
@progress&.tick
|
45
|
+
end
|
46
|
+
@progress&.stop
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_to_pack_list(object, path)
|
50
|
+
info = @database.load_info(object.oid)
|
51
|
+
@pack_list.push(Entry.new(object.oid, info, path, @allow_ofs))
|
52
|
+
end
|
53
|
+
|
54
|
+
def compress_objects
|
55
|
+
compressor = Compressor.new(@database, @progress)
|
56
|
+
@pack_list.each { |entry| compressor.add(entry) }
|
57
|
+
compressor.build_deltas
|
58
|
+
end
|
59
|
+
|
60
|
+
def write_header
|
61
|
+
header = [SIGNATURE, VERSION, @pack_list.size].pack(HEADER_FORMAT)
|
62
|
+
write(header)
|
63
|
+
end
|
64
|
+
|
65
|
+
def write_entries
|
66
|
+
count = @pack_list.size
|
67
|
+
@progress&.start("Writing objects", count) unless @output == STDOUT
|
68
|
+
|
69
|
+
@pack_list.each { |entry| write_entry(entry) }
|
70
|
+
@progress&.stop
|
71
|
+
end
|
72
|
+
|
73
|
+
def write_entry(entry)
|
74
|
+
write_entry(entry.delta.base) if entry.delta
|
75
|
+
|
76
|
+
return if entry.offset
|
77
|
+
entry.offset = @offset
|
78
|
+
|
79
|
+
object = entry.delta || @database.load_raw(entry.oid)
|
80
|
+
|
81
|
+
header = Numbers::VarIntLE.write(entry.packed_size, 4)
|
82
|
+
header[0] |= entry.packed_type << 4
|
83
|
+
|
84
|
+
write(header.pack("C*"))
|
85
|
+
write(entry.delta_prefix)
|
86
|
+
write(Zlib::Deflate.deflate(object.data, @compression))
|
87
|
+
|
88
|
+
@progress&.tick(@offset)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|