emerge 0.2.2 → 0.4.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 +4 -4
- data/README.md +28 -3
- data/lib/commands/global_options.rb +2 -0
- data/lib/commands/order_files/download_order_files.rb +77 -0
- data/lib/commands/order_files/validate_linkmaps.rb +55 -0
- data/lib/commands/reaper/reaper.rb +201 -0
- data/lib/commands/snapshots/validate_app.rb +64 -0
- data/lib/emerge_cli.rb +18 -2
- data/lib/reaper/ast_parser.rb +188 -3
- data/lib/reaper/code_deleter.rb +263 -0
- data/lib/utils/git.rb +13 -1
- data/lib/utils/macho_parser.rb +325 -0
- data/lib/utils/network.rb +20 -13
- data/lib/utils/version_check.rb +32 -0
- data/lib/version.rb +1 -1
- data/parsers/libtree-sitter-java-darwin-arm64.dylib +0 -0
- data/parsers/libtree-sitter-java-linux-x86_64.so +0 -0
- data/parsers/libtree-sitter-kotlin-darwin-arm64.dylib +0 -0
- data/parsers/libtree-sitter-kotlin-linux-x86_64.so +0 -0
- data/parsers/libtree-sitter-swift-darwin-arm64.dylib +0 -0
- data/parsers/libtree-sitter-swift-linux-x86_64.so +0 -0
- metadata +31 -12
@@ -0,0 +1,325 @@
|
|
1
|
+
require 'macho'
|
2
|
+
|
3
|
+
module EmergeCLI
|
4
|
+
class MachOParser
|
5
|
+
TYPE_METADATA_KIND_MASK = 0x7 << 3
|
6
|
+
TYPE_METADATA_KIND_SHIFT = 3
|
7
|
+
|
8
|
+
# Bind Codes
|
9
|
+
BIND_OPCODE_MASK = 0xF0
|
10
|
+
BIND_IMMEDIATE_MASK = 0x0F
|
11
|
+
BIND_OPCODE_DONE = 0x00
|
12
|
+
BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10
|
13
|
+
BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20
|
14
|
+
BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30
|
15
|
+
BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40
|
16
|
+
BIND_OPCODE_SET_TYPE_IMM = 0x50
|
17
|
+
BIND_OPCODE_SET_ADDEND_SLEB = 0x60
|
18
|
+
BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70
|
19
|
+
BIND_OPCODE_ADD_ADDR_ULEB = 0x80
|
20
|
+
BIND_OPCODE_DO_BIND = 0x90
|
21
|
+
BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0
|
22
|
+
BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0
|
23
|
+
BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0
|
24
|
+
|
25
|
+
UINT64_SIZE = 8
|
26
|
+
UINT64_MAX_VALUE = 0xFFFFFFFFFFFFFFFF
|
27
|
+
|
28
|
+
def load_binary(binary_path)
|
29
|
+
@macho_file = MachO::MachOFile.new(binary_path)
|
30
|
+
@binary_data = File.binread(binary_path)
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_linkedit_data_command
|
34
|
+
chained_fixups_command = nil
|
35
|
+
@macho_file.load_commands.each do |lc|
|
36
|
+
chained_fixups_command = lc if lc.type == :LC_DYLD_CHAINED_FIXUPS
|
37
|
+
end
|
38
|
+
|
39
|
+
if chained_fixups_command.nil?
|
40
|
+
Logger.debug 'No LC_DYLD_CHAINED_FIXUPS found'
|
41
|
+
return false, []
|
42
|
+
end
|
43
|
+
|
44
|
+
# linkedit_data_command
|
45
|
+
_, _, dataoff, datasize = @binary_data[chained_fixups_command.offset, 16].unpack('L<L<L<L<')
|
46
|
+
|
47
|
+
header = @binary_data[dataoff, datasize].unpack('L<L<L<L<L<L<L<')
|
48
|
+
# dyld_chained_fixups_header
|
49
|
+
_, _, imports_offset, symbols_offset, imports_count,
|
50
|
+
imports_format, = header
|
51
|
+
|
52
|
+
imports_start = dataoff + imports_offset
|
53
|
+
symbols_start = dataoff + symbols_offset
|
54
|
+
|
55
|
+
imported_symbols = []
|
56
|
+
|
57
|
+
import_size, name_offset_proc =
|
58
|
+
case imports_format
|
59
|
+
when 1, nil # DYLD_CHAINED_IMPORT
|
60
|
+
[4, ->(ptr) { ptr.unpack1('L<') >> 9 }]
|
61
|
+
when 2 # DYLD_CHAINED_IMPORT_ADDEND
|
62
|
+
[8, ->(ptr) { ptr.unpack1('L<') >> 9 }]
|
63
|
+
when 3 # DYLD_CHAINED_IMPORT_ADDEND64
|
64
|
+
[16, ->(ptr) { ptr.unpack1('Q<') >> 32 }]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Extract imported symbol names
|
68
|
+
imports_count.times do |i|
|
69
|
+
import_offset = imports_start + (i * import_size)
|
70
|
+
name_offset = name_offset_proc.call(@binary_data[import_offset, import_size])
|
71
|
+
name_start = symbols_start + name_offset
|
72
|
+
name = read_null_terminated_string(@binary_data[name_start..])
|
73
|
+
imported_symbols << name
|
74
|
+
end
|
75
|
+
|
76
|
+
[true, imported_symbols]
|
77
|
+
end
|
78
|
+
|
79
|
+
def read_dyld_info_only_command
|
80
|
+
dyld_info_only_command = nil
|
81
|
+
@macho_file.load_commands.each do |lc|
|
82
|
+
dyld_info_only_command = lc if lc.type == :LC_DYLD_INFO_ONLY
|
83
|
+
end
|
84
|
+
|
85
|
+
if dyld_info_only_command.nil?
|
86
|
+
Logger.debug 'No LC_DYLD_INFO_ONLY found'
|
87
|
+
return []
|
88
|
+
end
|
89
|
+
|
90
|
+
bound_symbols = []
|
91
|
+
start_address = dyld_info_only_command.bind_off
|
92
|
+
end_address = dyld_info_only_command.bind_off + dyld_info_only_command.bind_size
|
93
|
+
current_address = start_address
|
94
|
+
|
95
|
+
current_symbol = BoundSymbol.new(segment_offset: 0, library: nil, offset: 0, symbol: '')
|
96
|
+
while current_address < end_address
|
97
|
+
results, current_address, current_symbol = read_next_symbol(@binary_data, current_address, end_address,
|
98
|
+
current_symbol)
|
99
|
+
|
100
|
+
# Dup items to avoid pointer issues
|
101
|
+
results.each do |res|
|
102
|
+
bound_symbols << res.dup
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Filter only swift symbols starting with _$s
|
107
|
+
swift_symbols = bound_symbols.select { |bound_symbol| bound_symbol.symbol.start_with?('_$s') }
|
108
|
+
|
109
|
+
load_commands = @macho_file.load_commands.select { |lc| lc.type == :LC_SEGMENT_64 || lc.type == :LC_SEGMENT } # rubocop:disable Naming/VariableNumber
|
110
|
+
|
111
|
+
swift_symbols.each do |swift_symbol|
|
112
|
+
swift_symbol.address = load_commands[swift_symbol.segment_offset].vmaddr + swift_symbol.offset
|
113
|
+
end
|
114
|
+
|
115
|
+
swift_symbols
|
116
|
+
end
|
117
|
+
|
118
|
+
def find_protocols_in_swift_proto(use_chained_fixups, imported_symbols, bound_symbols, search_symbols)
|
119
|
+
found_section = nil
|
120
|
+
@macho_file.segments.each do |segment|
|
121
|
+
segment.sections.each do |section|
|
122
|
+
if section.segname.strip == '__TEXT' && section.sectname.strip == '__swift5_proto'
|
123
|
+
found_section = section
|
124
|
+
break
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
unless found_section
|
130
|
+
Logger.error 'The __swift5_proto section was not found.'
|
131
|
+
return false
|
132
|
+
end
|
133
|
+
|
134
|
+
start = found_section.offset
|
135
|
+
size = found_section.size
|
136
|
+
offsets_list = parse_list(@binary_data, start, size)
|
137
|
+
|
138
|
+
offsets_list.each do |relative_offset, offset_start|
|
139
|
+
type_file_address = offset_start + relative_offset
|
140
|
+
if type_file_address <= 0 || type_file_address >= @binary_data.size
|
141
|
+
Logger.error 'Invalid protocol conformance offset'
|
142
|
+
next
|
143
|
+
end
|
144
|
+
|
145
|
+
# ProtocolConformanceDescriptor -> ProtocolDescriptor
|
146
|
+
protocol_descriptor = read_little_endian_signed_integer(@binary_data, type_file_address)
|
147
|
+
|
148
|
+
# # ProtocolConformanceDescriptor -> ConformanceFlags
|
149
|
+
conformance_flags = read_little_endian_signed_integer(@binary_data, type_file_address + 12)
|
150
|
+
kind = (conformance_flags & TYPE_METADATA_KIND_MASK) >> TYPE_METADATA_KIND_SHIFT
|
151
|
+
|
152
|
+
next unless kind == 0
|
153
|
+
|
154
|
+
indirect_relative_offset = get_indirect_relative_offset(type_file_address, protocol_descriptor)
|
155
|
+
|
156
|
+
bound_symbol = bound_symbols.find { |symbol| symbol.address == indirect_relative_offset }
|
157
|
+
if bound_symbol
|
158
|
+
return true if search_symbols.include?(bound_symbol.symbol)
|
159
|
+
elsif use_chained_fixups
|
160
|
+
descriptor_offset = protocol_descriptor & ~1
|
161
|
+
jump_ptr = type_file_address + descriptor_offset
|
162
|
+
|
163
|
+
address = @binary_data[jump_ptr, 4].unpack1('I<')
|
164
|
+
symbol_name = imported_symbols[address]
|
165
|
+
return true if search_symbols.include?(symbol_name)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
false
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
def read_next_symbol(binary_data, current_address, end_address, current_symbol)
|
174
|
+
while current_address < end_address
|
175
|
+
first_byte = read_byte(binary_data, current_address)
|
176
|
+
current_address += 1
|
177
|
+
immediate = first_byte & BIND_IMMEDIATE_MASK
|
178
|
+
opcode = first_byte & BIND_OPCODE_MASK
|
179
|
+
|
180
|
+
case opcode
|
181
|
+
when BIND_OPCODE_DONE
|
182
|
+
result = current_symbol.dup
|
183
|
+
current_symbol.segment_offset = 0
|
184
|
+
current_symbol.library = 0
|
185
|
+
current_symbol.offset = 0
|
186
|
+
current_symbol.symbol = ''
|
187
|
+
return [result], current_address, current_symbol
|
188
|
+
when BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
|
189
|
+
current_symbol.library = [immediate].pack('L').unpack1('L')
|
190
|
+
when BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
|
191
|
+
current_symbol.symbol = read_null_terminated_string(binary_data[current_address..])
|
192
|
+
# Increase current pointer
|
193
|
+
current_address += current_symbol.symbol.size + 1
|
194
|
+
when BIND_OPCODE_ADD_ADDR_ULEB
|
195
|
+
offset, new_current_address = read_uleb(@binary_data, current_address)
|
196
|
+
current_symbol.offset = (current_symbol.offset + offset) & UINT64_MAX_VALUE
|
197
|
+
current_address = new_current_address
|
198
|
+
when BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
|
199
|
+
offset, new_current_address = read_uleb(@binary_data, current_address)
|
200
|
+
current_symbol.offset = (current_symbol.offset + offset + UINT64_SIZE) & UINT64_MAX_VALUE
|
201
|
+
current_address = new_current_address
|
202
|
+
return [current_symbol], current_address, current_symbol
|
203
|
+
when BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
|
204
|
+
offset, current_address = read_uleb(@binary_data, current_address)
|
205
|
+
current_symbol.segment_offset = immediate
|
206
|
+
current_symbol.offset = offset
|
207
|
+
when BIND_OPCODE_SET_ADDEND_SLEB
|
208
|
+
_, current_address = read_uleb(@binary_data, current_address)
|
209
|
+
when BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
|
210
|
+
result = current_symbol.dup
|
211
|
+
current_symbol.offset = (
|
212
|
+
current_symbol.offset + (immediate * UINT64_SIZE) + UINT64_SIZE
|
213
|
+
) & UINT64_MAX_VALUE
|
214
|
+
return [result], current_address, current_symbol
|
215
|
+
when BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
|
216
|
+
count, current_address = read_uleb(@binary_data, current_address)
|
217
|
+
skipping, current_address = read_uleb(@binary_data, current_address)
|
218
|
+
|
219
|
+
results = []
|
220
|
+
count.times do
|
221
|
+
results << current_symbol.dup
|
222
|
+
current_symbol.offset = (current_symbol.offset + skipping + UINT64_SIZE) & UINT64_MAX_VALUE
|
223
|
+
end
|
224
|
+
|
225
|
+
return results, current_address, current_symbol
|
226
|
+
when BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
|
227
|
+
count, current_address = read_uleb(@binary_data, current_address)
|
228
|
+
current_symbol.library = count
|
229
|
+
when BIND_OPCODE_DO_BIND
|
230
|
+
result = current_symbol.dup
|
231
|
+
current_symbol.offset = (current_symbol.offset + UINT64_SIZE) & UINT64_MAX_VALUE
|
232
|
+
return [result], current_address, current_symbol
|
233
|
+
end
|
234
|
+
end
|
235
|
+
[[], current_address, current_symbol]
|
236
|
+
end
|
237
|
+
|
238
|
+
def read_byte(binary_data, address)
|
239
|
+
binary_data[address, 1].unpack1('C')
|
240
|
+
end
|
241
|
+
|
242
|
+
def read_little_endian_signed_integer(binary_data, address)
|
243
|
+
binary_data[address, 4].unpack1('l<')
|
244
|
+
end
|
245
|
+
|
246
|
+
def read_uleb(binary_data, address)
|
247
|
+
next_byte = 0
|
248
|
+
size = 0
|
249
|
+
result = 0
|
250
|
+
|
251
|
+
loop do
|
252
|
+
next_byte = read_byte(binary_data, address)
|
253
|
+
address += 1
|
254
|
+
bytes = next_byte & 0x7F
|
255
|
+
shifted = bytes << (size * 7)
|
256
|
+
|
257
|
+
size += 1
|
258
|
+
result |= shifted
|
259
|
+
break if next_byte.nobits?(0x80)
|
260
|
+
end
|
261
|
+
|
262
|
+
[result, address]
|
263
|
+
end
|
264
|
+
|
265
|
+
def read_null_terminated_string(data)
|
266
|
+
data.unpack1('Z*')
|
267
|
+
end
|
268
|
+
|
269
|
+
def vm_address(file_offset, macho)
|
270
|
+
load_commands = macho.load_commands.select { |lc| lc.type == :LC_SEGMENT_64 || lc.type == :LC_SEGMENT } # rubocop:disable Naming/VariableNumber
|
271
|
+
load_commands.each do |lc|
|
272
|
+
next unless file_offset >= lc.fileoff && file_offset < (lc.fileoff + lc.filesize)
|
273
|
+
unless lc.respond_to?(:sections)
|
274
|
+
Logger.error 'Load command does not support sections function'
|
275
|
+
next
|
276
|
+
end
|
277
|
+
|
278
|
+
lc.sections.each do |section|
|
279
|
+
if file_offset >= section.offset && file_offset < (section.offset) + section.size
|
280
|
+
return section.addr + (file_offset - section.offset)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
nil
|
285
|
+
end
|
286
|
+
|
287
|
+
def parse_list(bytes, start, size)
|
288
|
+
data_pointer = bytes[start..]
|
289
|
+
file_offset = start
|
290
|
+
pointer_size = 4
|
291
|
+
class_pointers = []
|
292
|
+
|
293
|
+
(size / pointer_size).to_i.times do
|
294
|
+
pointer = data_pointer.unpack1('l<')
|
295
|
+
class_pointers << [pointer, file_offset]
|
296
|
+
data_pointer = data_pointer[pointer_size..]
|
297
|
+
file_offset += pointer_size
|
298
|
+
end
|
299
|
+
|
300
|
+
class_pointers
|
301
|
+
end
|
302
|
+
|
303
|
+
def get_indirect_relative_offset(type_file_address, protocol_descriptor)
|
304
|
+
vm_start = vm_address(type_file_address, @macho_file)
|
305
|
+
return nil if vm_start.nil?
|
306
|
+
if (vm_start + protocol_descriptor).odd?
|
307
|
+
(vm_start + protocol_descriptor) & ~1
|
308
|
+
elsif vm_start + protocol_descriptor > 0
|
309
|
+
vm_start + protocol_descriptor
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
class BoundSymbol
|
315
|
+
attr_accessor :segment_offset, :library, :offset, :symbol, :address
|
316
|
+
|
317
|
+
def initialize(segment_offset:, library:, offset:, symbol:)
|
318
|
+
@segment_offset = segment_offset
|
319
|
+
@library = library
|
320
|
+
@offset = offset
|
321
|
+
@symbol = symbol
|
322
|
+
@address = 0
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
data/lib/utils/network.rb
CHANGED
@@ -11,22 +11,22 @@ module EmergeCLI
|
|
11
11
|
RETRY_DELAY = 5
|
12
12
|
MAX_RETRIES = 3
|
13
13
|
|
14
|
-
def initialize(api_token
|
14
|
+
def initialize(api_token: nil, base_url: EMERGE_API_PROD_URL)
|
15
15
|
@base_url = base_url
|
16
16
|
@api_token = api_token
|
17
17
|
@internet = Async::HTTP::Internet.new
|
18
18
|
end
|
19
19
|
|
20
|
-
def get(path:, headers: {})
|
21
|
-
request(:get, path, nil, headers)
|
20
|
+
def get(path:, headers: {}, max_retries: MAX_RETRIES)
|
21
|
+
request(:get, path, nil, headers, nil, max_retries)
|
22
22
|
end
|
23
23
|
|
24
|
-
def post(path:, body:, headers: {})
|
25
|
-
request(:post, path, body, headers)
|
24
|
+
def post(path:, body:, headers: {}, query: nil, max_retries: MAX_RETRIES)
|
25
|
+
request(:post, path, body, headers, query, max_retries)
|
26
26
|
end
|
27
27
|
|
28
|
-
def put(path:, body:, headers: {})
|
29
|
-
request(:put, path, body, headers)
|
28
|
+
def put(path:, body:, headers: {}, max_retries: MAX_RETRIES)
|
29
|
+
request(:put, path, body, headers, nil, max_retries)
|
30
30
|
end
|
31
31
|
|
32
32
|
def close
|
@@ -35,18 +35,23 @@ module EmergeCLI
|
|
35
35
|
|
36
36
|
private
|
37
37
|
|
38
|
-
def request(method, path, body, custom_headers)
|
38
|
+
def request(method, path, body, custom_headers, query = nil, max_retries = MAX_RETRIES)
|
39
39
|
uri = if path.start_with?('http')
|
40
40
|
URI.parse(path)
|
41
41
|
else
|
42
|
-
URI
|
42
|
+
query_string = query ? URI.encode_www_form(query) : nil
|
43
|
+
URI::HTTPS.build(
|
44
|
+
host: @base_url,
|
45
|
+
path: path,
|
46
|
+
query: query_string
|
47
|
+
)
|
43
48
|
end
|
44
49
|
absolute_uri = uri.to_s
|
45
50
|
|
46
51
|
headers = {
|
47
|
-
'X-API-Token' => @api_token,
|
48
52
|
'User-Agent' => "emerge-cli/#{EmergeCLI::VERSION}"
|
49
53
|
}
|
54
|
+
headers['X-API-Token'] = @api_token if @api_token
|
50
55
|
headers['Content-Type'] = 'application/json' if method == :post && body.is_a?(Hash)
|
51
56
|
headers.merge!(custom_headers)
|
52
57
|
|
@@ -66,10 +71,10 @@ module EmergeCLI
|
|
66
71
|
response
|
67
72
|
rescue StandardError => e
|
68
73
|
retries += 1
|
69
|
-
if retries <=
|
74
|
+
if retries <= max_retries
|
70
75
|
delay = RETRY_DELAY * retries
|
71
76
|
error_message = e.message
|
72
|
-
Logger.warn "Request failed (attempt #{retries}/#{
|
77
|
+
Logger.warn "Request failed (attempt #{retries}/#{max_retries}): #{error_message}"
|
73
78
|
Logger.warn "Retrying in #{delay} seconds..."
|
74
79
|
|
75
80
|
begin
|
@@ -82,7 +87,9 @@ module EmergeCLI
|
|
82
87
|
sleep delay
|
83
88
|
retry
|
84
89
|
else
|
85
|
-
|
90
|
+
unless max_retries == 0
|
91
|
+
Logger.error "Request failed after #{max_retries} attempts: #{absolute_uri} #{e.message}"
|
92
|
+
end
|
86
93
|
raise e
|
87
94
|
end
|
88
95
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module EmergeCLI
|
4
|
+
module Utils
|
5
|
+
class VersionCheck
|
6
|
+
def initialize(network: EmergeCLI::Network.new)
|
7
|
+
@network = network
|
8
|
+
end
|
9
|
+
|
10
|
+
def check_version
|
11
|
+
Sync do
|
12
|
+
response = @network.get(
|
13
|
+
path: 'https://rubygems.org/api/v1/gems/emerge.json',
|
14
|
+
headers: {}
|
15
|
+
)
|
16
|
+
latest_version = JSON.parse(response.read).fetch('version')
|
17
|
+
current_version = EmergeCLI::VERSION
|
18
|
+
|
19
|
+
if Gem::Version.new(latest_version) > Gem::Version.new(current_version)
|
20
|
+
Logger.warn "A new version of emerge-cli is available (#{latest_version})"
|
21
|
+
Logger.warn "You are currently using version #{current_version}"
|
22
|
+
Logger.warn "To update, run: gem update emerge\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
rescue KeyError
|
26
|
+
Logger.error 'Failed to parse version from RubyGems API response'
|
27
|
+
rescue StandardError => e
|
28
|
+
Logger.error "Failed to check for updates: #{e.message}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/version.rb
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
metadata
CHANGED
@@ -1,43 +1,49 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: emerge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emerge Tools
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: async
|
14
|
+
name: async-http
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.86.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.86.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: CFPropertyList
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '2.3'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 2.3.2
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
41
|
- - "~>"
|
39
42
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
43
|
+
version: '2.3'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.3.2
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: chunky_png
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,19 +87,19 @@ dependencies:
|
|
81
87
|
- !ruby/object:Gem::Version
|
82
88
|
version: 0.2.1
|
83
89
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
90
|
+
name: ruby-macho
|
85
91
|
requirement: !ruby/object:Gem::Requirement
|
86
92
|
requirements:
|
87
93
|
- - "~>"
|
88
94
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
95
|
+
version: 4.1.0
|
90
96
|
type: :runtime
|
91
97
|
prerelease: false
|
92
98
|
version_requirements: !ruby/object:Gem::Requirement
|
93
99
|
requirements:
|
94
100
|
- - "~>"
|
95
101
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
102
|
+
version: 4.1.0
|
97
103
|
- !ruby/object:Gem::Dependency
|
98
104
|
name: ruby_tree_sitter
|
99
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -165,6 +171,10 @@ files:
|
|
165
171
|
- lib/commands/config/snapshots/snapshots_ios.rb
|
166
172
|
- lib/commands/global_options.rb
|
167
173
|
- lib/commands/integrate/fastlane.rb
|
174
|
+
- lib/commands/order_files/download_order_files.rb
|
175
|
+
- lib/commands/order_files/validate_linkmaps.rb
|
176
|
+
- lib/commands/reaper/reaper.rb
|
177
|
+
- lib/commands/snapshots/validate_app.rb
|
168
178
|
- lib/commands/upload/snapshots/client_libraries/default.rb
|
169
179
|
- lib/commands/upload/snapshots/client_libraries/paparazzi.rb
|
170
180
|
- lib/commands/upload/snapshots/client_libraries/roborazzi.rb
|
@@ -172,15 +182,24 @@ files:
|
|
172
182
|
- lib/commands/upload/snapshots/snapshots.rb
|
173
183
|
- lib/emerge_cli.rb
|
174
184
|
- lib/reaper/ast_parser.rb
|
185
|
+
- lib/reaper/code_deleter.rb
|
175
186
|
- lib/utils/git.rb
|
176
187
|
- lib/utils/git_info_provider.rb
|
177
188
|
- lib/utils/git_result.rb
|
178
189
|
- lib/utils/github.rb
|
179
190
|
- lib/utils/logger.rb
|
191
|
+
- lib/utils/macho_parser.rb
|
180
192
|
- lib/utils/network.rb
|
181
193
|
- lib/utils/profiler.rb
|
182
194
|
- lib/utils/project_detector.rb
|
195
|
+
- lib/utils/version_check.rb
|
183
196
|
- lib/version.rb
|
197
|
+
- parsers/libtree-sitter-java-darwin-arm64.dylib
|
198
|
+
- parsers/libtree-sitter-java-linux-x86_64.so
|
199
|
+
- parsers/libtree-sitter-kotlin-darwin-arm64.dylib
|
200
|
+
- parsers/libtree-sitter-kotlin-linux-x86_64.so
|
201
|
+
- parsers/libtree-sitter-swift-darwin-arm64.dylib
|
202
|
+
- parsers/libtree-sitter-swift-linux-x86_64.so
|
184
203
|
homepage: https://github.com/EmergeTools/emerge-cli
|
185
204
|
licenses:
|
186
205
|
- MIT
|
@@ -204,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
223
|
- !ruby/object:Gem::Version
|
205
224
|
version: '0'
|
206
225
|
requirements: []
|
207
|
-
rubygems_version: 3.
|
226
|
+
rubygems_version: 3.5.11
|
208
227
|
signing_key:
|
209
228
|
specification_version: 4
|
210
229
|
summary: Emerge CLI
|