jit 0.0.0 → 1.0.0
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.
- 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/merge/diff3.rb
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
require_relative "../diff"
|
2
|
+
|
3
|
+
module Merge
|
4
|
+
class Diff3
|
5
|
+
|
6
|
+
Clean = Struct.new(:lines) do
|
7
|
+
def to_s(*)
|
8
|
+
lines.join("")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Conflict = Struct.new(:o_lines, :a_lines, :b_lines) do
|
13
|
+
def to_s(a_name = nil, b_name = nil)
|
14
|
+
text = ""
|
15
|
+
separator(text, "<", a_name)
|
16
|
+
a_lines.each { |line| text.concat(line) }
|
17
|
+
separator(text, "=")
|
18
|
+
b_lines.each { |line| text.concat(line) }
|
19
|
+
separator(text, ">", b_name)
|
20
|
+
text
|
21
|
+
end
|
22
|
+
|
23
|
+
def separator(text, char, name = nil)
|
24
|
+
text.concat(char * 7)
|
25
|
+
text.concat(" #{ name }") if name
|
26
|
+
text.concat("\n")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Result = Struct.new(:chunks) do
|
31
|
+
def clean?
|
32
|
+
chunks.none? { |chunk| chunk.is_a?(Conflict) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s(a_name = nil, b_name = nil)
|
36
|
+
chunks.map { |chunk| chunk.to_s(a_name, b_name) }.join("")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.merge(o, a, b)
|
41
|
+
o = o.lines if o.is_a?(String)
|
42
|
+
a = a.lines if a.is_a?(String)
|
43
|
+
b = b.lines if b.is_a?(String)
|
44
|
+
|
45
|
+
new(o, a, b).merge
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(o, a, b)
|
49
|
+
@o, @a, @b = o, a, b
|
50
|
+
end
|
51
|
+
|
52
|
+
def merge
|
53
|
+
setup
|
54
|
+
generate_chunks
|
55
|
+
Result.new(@chunks)
|
56
|
+
end
|
57
|
+
|
58
|
+
def setup
|
59
|
+
@chunks = []
|
60
|
+
@line_o = @line_a = @line_b = 0
|
61
|
+
|
62
|
+
@match_a = match_set(@a)
|
63
|
+
@match_b = match_set(@b)
|
64
|
+
end
|
65
|
+
|
66
|
+
def match_set(file)
|
67
|
+
matches = {}
|
68
|
+
|
69
|
+
Diff.diff(@o, file).each do |edit|
|
70
|
+
next unless edit.type == :eql
|
71
|
+
matches[edit.a_line.number] = edit.b_line.number
|
72
|
+
end
|
73
|
+
|
74
|
+
matches
|
75
|
+
end
|
76
|
+
|
77
|
+
def generate_chunks
|
78
|
+
loop do
|
79
|
+
i = find_next_mismatch
|
80
|
+
|
81
|
+
if i == 1
|
82
|
+
o, a, b = find_next_match
|
83
|
+
|
84
|
+
if a and b
|
85
|
+
emit_chunk(o, a, b)
|
86
|
+
else
|
87
|
+
emit_final_chunk
|
88
|
+
return
|
89
|
+
end
|
90
|
+
|
91
|
+
elsif i
|
92
|
+
emit_chunk(@line_o + i, @line_a + i, @line_b + i)
|
93
|
+
|
94
|
+
else
|
95
|
+
emit_final_chunk
|
96
|
+
return
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def find_next_mismatch
|
102
|
+
i = 1
|
103
|
+
while in_bounds?(i) and
|
104
|
+
match?(@match_a, @line_a, i) and
|
105
|
+
match?(@match_b, @line_b, i)
|
106
|
+
i += 1
|
107
|
+
end
|
108
|
+
in_bounds?(i) ? i : nil
|
109
|
+
end
|
110
|
+
|
111
|
+
def in_bounds?(i)
|
112
|
+
@line_o + i <= @o.size or
|
113
|
+
@line_a + i <= @a.size or
|
114
|
+
@line_b + i <= @b.size
|
115
|
+
end
|
116
|
+
|
117
|
+
def match?(matches, offset, i)
|
118
|
+
matches[@line_o + i] == offset + i
|
119
|
+
end
|
120
|
+
|
121
|
+
def find_next_match
|
122
|
+
o = @line_o + 1
|
123
|
+
until o > @o.size or (@match_a.has_key?(o) and @match_b.has_key?(o))
|
124
|
+
o += 1
|
125
|
+
end
|
126
|
+
[o, @match_a[o], @match_b[o]]
|
127
|
+
end
|
128
|
+
|
129
|
+
def emit_chunk(o, a, b)
|
130
|
+
write_chunk(
|
131
|
+
@o[@line_o ... o - 1],
|
132
|
+
@a[@line_a ... a - 1],
|
133
|
+
@b[@line_b ... b - 1])
|
134
|
+
|
135
|
+
@line_o, @line_a, @line_b = o - 1, a - 1, b - 1
|
136
|
+
end
|
137
|
+
|
138
|
+
def emit_final_chunk
|
139
|
+
write_chunk(
|
140
|
+
@o[@line_o .. -1],
|
141
|
+
@a[@line_a .. -1],
|
142
|
+
@b[@line_b .. -1])
|
143
|
+
end
|
144
|
+
|
145
|
+
def write_chunk(o, a, b)
|
146
|
+
if a == o or a == b
|
147
|
+
@chunks.push(Clean.new(b))
|
148
|
+
elsif b == o
|
149
|
+
@chunks.push(Clean.new(a))
|
150
|
+
else
|
151
|
+
@chunks.push(Conflict.new(o, a, b))
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
data/lib/merge/inputs.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative "./bases"
|
2
|
+
require_relative "../revision"
|
3
|
+
|
4
|
+
module Merge
|
5
|
+
class Inputs
|
6
|
+
|
7
|
+
ATTRS = [ :left_name, :right_name,
|
8
|
+
:left_oid, :right_oid,
|
9
|
+
:base_oids ]
|
10
|
+
|
11
|
+
attr_reader(*ATTRS)
|
12
|
+
|
13
|
+
def initialize(repository, left_name, right_name)
|
14
|
+
@repo = repository
|
15
|
+
@left_name = left_name
|
16
|
+
@right_name = right_name
|
17
|
+
|
18
|
+
@left_oid = resolve_rev(@left_name)
|
19
|
+
@right_oid = resolve_rev(@right_name)
|
20
|
+
|
21
|
+
common = Bases.new(@repo.database, @left_oid, @right_oid)
|
22
|
+
@base_oids = common.find
|
23
|
+
end
|
24
|
+
|
25
|
+
def already_merged?
|
26
|
+
@base_oids == [@right_oid]
|
27
|
+
end
|
28
|
+
|
29
|
+
def fast_forward?
|
30
|
+
@base_oids == [@left_oid]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def resolve_rev(rev)
|
36
|
+
Revision.new(@repo, rev).resolve(Revision::COMMIT)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
CherryPick = Struct.new(*Inputs::ATTRS)
|
42
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require_relative "./diff3"
|
2
|
+
|
3
|
+
module Merge
|
4
|
+
class Resolve
|
5
|
+
|
6
|
+
def initialize(repository, inputs)
|
7
|
+
@repo = repository
|
8
|
+
@inputs = inputs
|
9
|
+
|
10
|
+
@on_progress = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_progress(&block)
|
14
|
+
@on_progress = block
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute
|
18
|
+
prepare_tree_diffs
|
19
|
+
|
20
|
+
migration = @repo.migration(@clean_diff)
|
21
|
+
migration.apply_changes
|
22
|
+
|
23
|
+
add_conflicts_to_index
|
24
|
+
write_untracked_files
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def prepare_tree_diffs
|
30
|
+
base_oid = @inputs.base_oids.first
|
31
|
+
@left_diff = @repo.database.tree_diff(base_oid, @inputs.left_oid)
|
32
|
+
@right_diff = @repo.database.tree_diff(base_oid, @inputs.right_oid)
|
33
|
+
@clean_diff = {}
|
34
|
+
@conflicts = {}
|
35
|
+
@untracked = {}
|
36
|
+
|
37
|
+
@right_diff.each do |path, (old_item, new_item)|
|
38
|
+
file_dir_conflict(path, @left_diff, @inputs.left_name) if new_item
|
39
|
+
same_path_conflict(path, old_item, new_item)
|
40
|
+
end
|
41
|
+
|
42
|
+
@left_diff.each do |path, (_, new_item)|
|
43
|
+
file_dir_conflict(path, @right_diff, @inputs.right_name) if new_item
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def same_path_conflict(path, base, right)
|
48
|
+
return if @conflicts[path]
|
49
|
+
|
50
|
+
unless @left_diff.has_key?(path)
|
51
|
+
@clean_diff[path] = [base, right]
|
52
|
+
return
|
53
|
+
end
|
54
|
+
|
55
|
+
left = @left_diff[path][1]
|
56
|
+
return if left == right
|
57
|
+
|
58
|
+
log "Auto-merging #{ path }" if left and right
|
59
|
+
|
60
|
+
oid_ok, oid = merge_blobs(base&.oid, left&.oid, right&.oid)
|
61
|
+
mode_ok, mode = merge_modes(base&.mode, left&.mode, right&.mode)
|
62
|
+
|
63
|
+
@clean_diff[path] = [left, Database::Entry.new(oid, mode)]
|
64
|
+
return if oid_ok and mode_ok
|
65
|
+
|
66
|
+
@conflicts[path] = [base, left, right]
|
67
|
+
log_conflict(path)
|
68
|
+
end
|
69
|
+
|
70
|
+
def merge_blobs(base_oid, left_oid, right_oid)
|
71
|
+
result = merge3(base_oid, left_oid, right_oid)
|
72
|
+
return result if result
|
73
|
+
|
74
|
+
oids = [base_oid, left_oid, right_oid]
|
75
|
+
blobs = oids.map { |oid| oid ? @repo.database.load(oid).data : "" }
|
76
|
+
merge = Diff3.merge(*blobs)
|
77
|
+
|
78
|
+
data = merge.to_s(@inputs.left_name, @inputs.right_name)
|
79
|
+
blob = Database::Blob.new(data)
|
80
|
+
@repo.database.store(blob)
|
81
|
+
|
82
|
+
[merge.clean?, blob.oid]
|
83
|
+
end
|
84
|
+
|
85
|
+
def merge_modes(base_mode, left_mode, right_mode)
|
86
|
+
merge3(base_mode, left_mode, right_mode) || [false, left_mode]
|
87
|
+
end
|
88
|
+
|
89
|
+
def merge3(base, left, right)
|
90
|
+
return [false, right] unless left
|
91
|
+
return [false, left] unless right
|
92
|
+
|
93
|
+
if left == base or left == right
|
94
|
+
[true, right]
|
95
|
+
elsif right == base
|
96
|
+
[true, left]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def file_dir_conflict(path, diff, name)
|
101
|
+
path.dirname.ascend do |parent|
|
102
|
+
old_item, new_item = diff[parent]
|
103
|
+
next unless new_item
|
104
|
+
|
105
|
+
@conflicts[parent] = case name
|
106
|
+
when @inputs.left_name then [old_item, new_item, nil]
|
107
|
+
when @inputs.right_name then [old_item, nil, new_item]
|
108
|
+
end
|
109
|
+
|
110
|
+
@clean_diff.delete(parent)
|
111
|
+
rename = "#{ parent }~#{ name }"
|
112
|
+
@untracked[rename] = new_item
|
113
|
+
|
114
|
+
log "Adding #{ path }" unless diff[path]
|
115
|
+
log_conflict(parent, rename)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def add_conflicts_to_index
|
120
|
+
@conflicts.each do |path, items|
|
121
|
+
@repo.index.add_conflict_set(path, items)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def write_untracked_files
|
126
|
+
@untracked.each do |path, item|
|
127
|
+
blob = @repo.database.load(item.oid)
|
128
|
+
@repo.workspace.write_file(path, blob.data)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def log(message)
|
133
|
+
@on_progress&.call(message)
|
134
|
+
end
|
135
|
+
|
136
|
+
def log_conflict(path, rename = nil)
|
137
|
+
base, left, right = @conflicts[path]
|
138
|
+
|
139
|
+
if left and right
|
140
|
+
log_left_right_conflict(path)
|
141
|
+
elsif base and (left or right)
|
142
|
+
log_modify_delete_conflict(path, rename)
|
143
|
+
else
|
144
|
+
log_file_directory_conflict(path, rename)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def log_left_right_conflict(path)
|
149
|
+
type = @conflicts[path][0] ? "content" : "add/add"
|
150
|
+
log "CONFLICT (#{ type }): Merge conflict in #{ path }"
|
151
|
+
end
|
152
|
+
|
153
|
+
def log_modify_delete_conflict(path, rename)
|
154
|
+
deleted, modified = log_branch_names(path)
|
155
|
+
|
156
|
+
rename = rename ? " at #{ rename }" : ""
|
157
|
+
|
158
|
+
log "CONFLICT (modify/delete): #{ path } " +
|
159
|
+
"deleted in #{ deleted } and modified in #{ modified }. " +
|
160
|
+
"Version #{ modified } of #{ path } left in tree#{ rename }."
|
161
|
+
end
|
162
|
+
|
163
|
+
def log_file_directory_conflict(path, rename)
|
164
|
+
type = @conflicts[path][1] ? "file/directory" : "directory/file"
|
165
|
+
branch, _ = log_branch_names(path)
|
166
|
+
|
167
|
+
log "CONFLICT (#{ type }): There is a directory " +
|
168
|
+
"with name #{ path } in #{ branch }. " +
|
169
|
+
"Adding #{ path } as #{ rename }"
|
170
|
+
end
|
171
|
+
|
172
|
+
def log_branch_names(path)
|
173
|
+
a, b = @inputs.left_name, @inputs.right_name
|
174
|
+
@conflicts[path][1] ? [b, a] : [a, b]
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
end
|
data/lib/pack.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative "./pack/reader"
|
2
|
+
require_relative "./pack/writer"
|
3
|
+
require_relative "./pack/stream"
|
4
|
+
require_relative "./pack/indexer"
|
5
|
+
require_relative "./pack/unpacker"
|
6
|
+
|
7
|
+
module Pack
|
8
|
+
HEADER_SIZE = 12
|
9
|
+
HEADER_FORMAT = "a4N2"
|
10
|
+
SIGNATURE = "PACK"
|
11
|
+
VERSION = 2
|
12
|
+
|
13
|
+
GIT_MAX_COPY = 0x10000
|
14
|
+
MAX_COPY_SIZE = 0xffffff
|
15
|
+
MAX_INSERT_SIZE = 0x7f
|
16
|
+
|
17
|
+
IDX_SIGNATURE = 0xff744f63
|
18
|
+
IDX_MAX_OFFSET = 0x80000000
|
19
|
+
|
20
|
+
COMMIT = 1
|
21
|
+
TREE = 2
|
22
|
+
BLOB = 3
|
23
|
+
|
24
|
+
OFS_DELTA = 6
|
25
|
+
REF_DELTA = 7
|
26
|
+
|
27
|
+
TYPE_CODES = {
|
28
|
+
"commit" => COMMIT,
|
29
|
+
"tree" => TREE,
|
30
|
+
"blob" => BLOB
|
31
|
+
}
|
32
|
+
|
33
|
+
InvalidPack = Class.new(StandardError)
|
34
|
+
|
35
|
+
Record = Struct.new(:type, :data) do
|
36
|
+
attr_accessor :oid
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
data
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
OfsDelta = Struct.new(:base_ofs, :delta_data)
|
44
|
+
RefDelta = Struct.new(:base_oid, :delta_data)
|
45
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require_relative "./delta"
|
2
|
+
require_relative "./window"
|
3
|
+
|
4
|
+
module Pack
|
5
|
+
class Compressor
|
6
|
+
|
7
|
+
OBJECT_SIZE = 50..0x20000000
|
8
|
+
MAX_DEPTH = 50
|
9
|
+
WINDOW_SIZE = 8
|
10
|
+
|
11
|
+
def initialize(database, progress)
|
12
|
+
@database = database
|
13
|
+
@window = Window.new(WINDOW_SIZE)
|
14
|
+
@progress = progress
|
15
|
+
@objects = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(entry)
|
19
|
+
return unless OBJECT_SIZE.include?(entry.size)
|
20
|
+
@objects.push(entry)
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_deltas
|
24
|
+
@progress&.start("Compressing objects", @objects.size)
|
25
|
+
|
26
|
+
@objects.sort! { |a, b| b.sort_key <=> a.sort_key }
|
27
|
+
|
28
|
+
@objects.each do |entry|
|
29
|
+
build_delta(entry)
|
30
|
+
@progress&.tick
|
31
|
+
end
|
32
|
+
@progress&.stop
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def build_delta(entry)
|
38
|
+
object = @database.load_raw(entry.oid)
|
39
|
+
target = @window.add(entry, object.data)
|
40
|
+
|
41
|
+
@window.each { |source| try_delta(source, target) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def try_delta(source, target)
|
45
|
+
return unless source.type == target.type
|
46
|
+
return unless source.depth < MAX_DEPTH
|
47
|
+
|
48
|
+
max_size = max_size_heuristic(source, target)
|
49
|
+
return unless compatible_sizes?(source, target, max_size)
|
50
|
+
|
51
|
+
delta = Delta.new(source, target)
|
52
|
+
size = target.entry.packed_size
|
53
|
+
|
54
|
+
return if delta.size > max_size
|
55
|
+
return if delta.size == size and delta.base.depth + 1 >= target.depth
|
56
|
+
|
57
|
+
target.entry.assign_delta(delta)
|
58
|
+
end
|
59
|
+
|
60
|
+
def max_size_heuristic(source, target)
|
61
|
+
if target.delta
|
62
|
+
max_size = target.delta.size
|
63
|
+
ref_depth = target.depth
|
64
|
+
else
|
65
|
+
max_size = target.size / 2 - 20
|
66
|
+
ref_depth = 1
|
67
|
+
end
|
68
|
+
|
69
|
+
max_size * (MAX_DEPTH - source.depth) / (MAX_DEPTH + 1 - ref_depth)
|
70
|
+
end
|
71
|
+
|
72
|
+
def compatible_sizes?(source, target, max_size)
|
73
|
+
size_diff = [target.size - source.size, 0].max
|
74
|
+
|
75
|
+
return false if max_size == 0
|
76
|
+
return false if size_diff >= max_size
|
77
|
+
return false if target.size < source.size / 32
|
78
|
+
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|