Show More
This diff has been collapsed as it changes many lines, (560 lines changed) Show them Hide them | |||
@@ -0,0 +1,560 b'' | |||
|
1 | # This file is automatically @generated by Cargo. | |
|
2 | # It is not intended for manual editing. | |
|
3 | version = 3 | |
|
4 | ||
|
5 | [[package]] | |
|
6 | name = "aho-corasick" | |
|
7 | version = "0.7.18" | |
|
8 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
9 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" | |
|
10 | dependencies = [ | |
|
11 | "memchr", | |
|
12 | ] | |
|
13 | ||
|
14 | [[package]] | |
|
15 | name = "assert_cmd" | |
|
16 | version = "2.0.4" | |
|
17 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
18 | checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e" | |
|
19 | dependencies = [ | |
|
20 | "bstr", | |
|
21 | "doc-comment", | |
|
22 | "predicates", | |
|
23 | "predicates-core", | |
|
24 | "predicates-tree", | |
|
25 | "wait-timeout", | |
|
26 | ] | |
|
27 | ||
|
28 | [[package]] | |
|
29 | name = "atty" | |
|
30 | version = "0.2.14" | |
|
31 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
32 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" | |
|
33 | dependencies = [ | |
|
34 | "hermit-abi", | |
|
35 | "libc", | |
|
36 | "winapi", | |
|
37 | ] | |
|
38 | ||
|
39 | [[package]] | |
|
40 | name = "autocfg" | |
|
41 | version = "1.1.0" | |
|
42 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
43 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" | |
|
44 | ||
|
45 | [[package]] | |
|
46 | name = "bitflags" | |
|
47 | version = "1.3.2" | |
|
48 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
49 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | |
|
50 | ||
|
51 | [[package]] | |
|
52 | name = "bstr" | |
|
53 | version = "0.2.17" | |
|
54 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
55 | checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" | |
|
56 | dependencies = [ | |
|
57 | "lazy_static", | |
|
58 | "memchr", | |
|
59 | "regex-automata", | |
|
60 | ] | |
|
61 | ||
|
62 | [[package]] | |
|
63 | name = "clap" | |
|
64 | version = "3.1.6" | |
|
65 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
66 | checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" | |
|
67 | dependencies = [ | |
|
68 | "atty", | |
|
69 | "bitflags", | |
|
70 | "clap_derive", | |
|
71 | "indexmap", | |
|
72 | "lazy_static", | |
|
73 | "os_str_bytes", | |
|
74 | "strsim", | |
|
75 | "termcolor", | |
|
76 | "textwrap", | |
|
77 | ] | |
|
78 | ||
|
79 | [[package]] | |
|
80 | name = "clap_derive" | |
|
81 | version = "3.1.4" | |
|
82 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
83 | checksum = "da95d038ede1a964ce99f49cbe27a7fb538d1da595e4b4f70b8c8f338d17bf16" | |
|
84 | dependencies = [ | |
|
85 | "heck", | |
|
86 | "proc-macro-error", | |
|
87 | "proc-macro2", | |
|
88 | "quote", | |
|
89 | "syn", | |
|
90 | ] | |
|
91 | ||
|
92 | [[package]] | |
|
93 | name = "console" | |
|
94 | version = "0.15.0" | |
|
95 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
96 | checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" | |
|
97 | dependencies = [ | |
|
98 | "encode_unicode", | |
|
99 | "libc", | |
|
100 | "once_cell", | |
|
101 | "terminal_size", | |
|
102 | "winapi", | |
|
103 | ] | |
|
104 | ||
|
105 | [[package]] | |
|
106 | name = "difflib" | |
|
107 | version = "0.4.0" | |
|
108 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
109 | checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" | |
|
110 | ||
|
111 | [[package]] | |
|
112 | name = "doc-comment" | |
|
113 | version = "0.3.3" | |
|
114 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
115 | checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" | |
|
116 | ||
|
117 | [[package]] | |
|
118 | name = "either" | |
|
119 | version = "1.6.1" | |
|
120 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
121 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" | |
|
122 | ||
|
123 | [[package]] | |
|
124 | name = "encode_unicode" | |
|
125 | version = "0.3.6" | |
|
126 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
127 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" | |
|
128 | ||
|
129 | [[package]] | |
|
130 | name = "fuchsia-cprng" | |
|
131 | version = "0.1.1" | |
|
132 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
133 | checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" | |
|
134 | ||
|
135 | [[package]] | |
|
136 | name = "hashbrown" | |
|
137 | version = "0.11.2" | |
|
138 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
139 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" | |
|
140 | ||
|
141 | [[package]] | |
|
142 | name = "heck" | |
|
143 | version = "0.4.0" | |
|
144 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
145 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" | |
|
146 | ||
|
147 | [[package]] | |
|
148 | name = "hermit-abi" | |
|
149 | version = "0.1.19" | |
|
150 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
151 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" | |
|
152 | dependencies = [ | |
|
153 | "libc", | |
|
154 | ] | |
|
155 | ||
|
156 | [[package]] | |
|
157 | name = "indexmap" | |
|
158 | version = "1.8.0" | |
|
159 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
160 | checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" | |
|
161 | dependencies = [ | |
|
162 | "autocfg", | |
|
163 | "hashbrown", | |
|
164 | ] | |
|
165 | ||
|
166 | [[package]] | |
|
167 | name = "insta" | |
|
168 | version = "1.13.0" | |
|
169 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
170 | checksum = "30a7e1911532a662f6b08b68f884080850f2fd9544963c3ab23a5af42bda1eac" | |
|
171 | dependencies = [ | |
|
172 | "console", | |
|
173 | "once_cell", | |
|
174 | "serde", | |
|
175 | "serde_json", | |
|
176 | "serde_yaml", | |
|
177 | "similar", | |
|
178 | ] | |
|
179 | ||
|
180 | [[package]] | |
|
181 | name = "itertools" | |
|
182 | version = "0.10.3" | |
|
183 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
184 | checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" | |
|
185 | dependencies = [ | |
|
186 | "either", | |
|
187 | ] | |
|
188 | ||
|
189 | [[package]] | |
|
190 | name = "itoa" | |
|
191 | version = "1.0.1" | |
|
192 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
193 | checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" | |
|
194 | ||
|
195 | [[package]] | |
|
196 | name = "lazy_static" | |
|
197 | version = "1.4.0" | |
|
198 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
199 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |
|
200 | ||
|
201 | [[package]] | |
|
202 | name = "libc" | |
|
203 | version = "0.2.119" | |
|
204 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
205 | checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" | |
|
206 | ||
|
207 | [[package]] | |
|
208 | name = "linked-hash-map" | |
|
209 | version = "0.5.4" | |
|
210 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
211 | checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" | |
|
212 | ||
|
213 | [[package]] | |
|
214 | name = "memchr" | |
|
215 | version = "2.4.1" | |
|
216 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
217 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" | |
|
218 | ||
|
219 | [[package]] | |
|
220 | name = "merge-lists" | |
|
221 | version = "0.1.0" | |
|
222 | dependencies = [ | |
|
223 | "assert_cmd", | |
|
224 | "clap", | |
|
225 | "insta", | |
|
226 | "itertools", | |
|
227 | "regex", | |
|
228 | "similar", | |
|
229 | "tempdir", | |
|
230 | ] | |
|
231 | ||
|
232 | [[package]] | |
|
233 | name = "once_cell" | |
|
234 | version = "1.10.0" | |
|
235 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
236 | checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" | |
|
237 | ||
|
238 | [[package]] | |
|
239 | name = "os_str_bytes" | |
|
240 | version = "6.0.0" | |
|
241 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
242 | checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" | |
|
243 | dependencies = [ | |
|
244 | "memchr", | |
|
245 | ] | |
|
246 | ||
|
247 | [[package]] | |
|
248 | name = "predicates" | |
|
249 | version = "2.1.1" | |
|
250 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
251 | checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c" | |
|
252 | dependencies = [ | |
|
253 | "difflib", | |
|
254 | "itertools", | |
|
255 | "predicates-core", | |
|
256 | ] | |
|
257 | ||
|
258 | [[package]] | |
|
259 | name = "predicates-core" | |
|
260 | version = "1.0.3" | |
|
261 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
262 | checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" | |
|
263 | ||
|
264 | [[package]] | |
|
265 | name = "predicates-tree" | |
|
266 | version = "1.0.5" | |
|
267 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
268 | checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" | |
|
269 | dependencies = [ | |
|
270 | "predicates-core", | |
|
271 | "termtree", | |
|
272 | ] | |
|
273 | ||
|
274 | [[package]] | |
|
275 | name = "proc-macro-error" | |
|
276 | version = "1.0.4" | |
|
277 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
278 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" | |
|
279 | dependencies = [ | |
|
280 | "proc-macro-error-attr", | |
|
281 | "proc-macro2", | |
|
282 | "quote", | |
|
283 | "syn", | |
|
284 | "version_check", | |
|
285 | ] | |
|
286 | ||
|
287 | [[package]] | |
|
288 | name = "proc-macro-error-attr" | |
|
289 | version = "1.0.4" | |
|
290 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
291 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" | |
|
292 | dependencies = [ | |
|
293 | "proc-macro2", | |
|
294 | "quote", | |
|
295 | "version_check", | |
|
296 | ] | |
|
297 | ||
|
298 | [[package]] | |
|
299 | name = "proc-macro2" | |
|
300 | version = "1.0.36" | |
|
301 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
302 | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" | |
|
303 | dependencies = [ | |
|
304 | "unicode-xid", | |
|
305 | ] | |
|
306 | ||
|
307 | [[package]] | |
|
308 | name = "quote" | |
|
309 | version = "1.0.15" | |
|
310 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
311 | checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" | |
|
312 | dependencies = [ | |
|
313 | "proc-macro2", | |
|
314 | ] | |
|
315 | ||
|
316 | [[package]] | |
|
317 | name = "rand" | |
|
318 | version = "0.4.6" | |
|
319 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
320 | checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" | |
|
321 | dependencies = [ | |
|
322 | "fuchsia-cprng", | |
|
323 | "libc", | |
|
324 | "rand_core 0.3.1", | |
|
325 | "rdrand", | |
|
326 | "winapi", | |
|
327 | ] | |
|
328 | ||
|
329 | [[package]] | |
|
330 | name = "rand_core" | |
|
331 | version = "0.3.1" | |
|
332 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
333 | checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" | |
|
334 | dependencies = [ | |
|
335 | "rand_core 0.4.2", | |
|
336 | ] | |
|
337 | ||
|
338 | [[package]] | |
|
339 | name = "rand_core" | |
|
340 | version = "0.4.2" | |
|
341 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
342 | checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" | |
|
343 | ||
|
344 | [[package]] | |
|
345 | name = "rdrand" | |
|
346 | version = "0.4.0" | |
|
347 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
348 | checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" | |
|
349 | dependencies = [ | |
|
350 | "rand_core 0.3.1", | |
|
351 | ] | |
|
352 | ||
|
353 | [[package]] | |
|
354 | name = "regex" | |
|
355 | version = "1.5.5" | |
|
356 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
357 | checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" | |
|
358 | dependencies = [ | |
|
359 | "aho-corasick", | |
|
360 | "memchr", | |
|
361 | "regex-syntax", | |
|
362 | ] | |
|
363 | ||
|
364 | [[package]] | |
|
365 | name = "regex-automata" | |
|
366 | version = "0.1.10" | |
|
367 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
368 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" | |
|
369 | ||
|
370 | [[package]] | |
|
371 | name = "regex-syntax" | |
|
372 | version = "0.6.25" | |
|
373 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
374 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" | |
|
375 | ||
|
376 | [[package]] | |
|
377 | name = "remove_dir_all" | |
|
378 | version = "0.5.3" | |
|
379 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
380 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" | |
|
381 | dependencies = [ | |
|
382 | "winapi", | |
|
383 | ] | |
|
384 | ||
|
385 | [[package]] | |
|
386 | name = "ryu" | |
|
387 | version = "1.0.9" | |
|
388 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
389 | checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" | |
|
390 | ||
|
391 | [[package]] | |
|
392 | name = "serde" | |
|
393 | version = "1.0.136" | |
|
394 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
395 | checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" | |
|
396 | dependencies = [ | |
|
397 | "serde_derive", | |
|
398 | ] | |
|
399 | ||
|
400 | [[package]] | |
|
401 | name = "serde_derive" | |
|
402 | version = "1.0.136" | |
|
403 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
404 | checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" | |
|
405 | dependencies = [ | |
|
406 | "proc-macro2", | |
|
407 | "quote", | |
|
408 | "syn", | |
|
409 | ] | |
|
410 | ||
|
411 | [[package]] | |
|
412 | name = "serde_json" | |
|
413 | version = "1.0.79" | |
|
414 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
415 | checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" | |
|
416 | dependencies = [ | |
|
417 | "itoa", | |
|
418 | "ryu", | |
|
419 | "serde", | |
|
420 | ] | |
|
421 | ||
|
422 | [[package]] | |
|
423 | name = "serde_yaml" | |
|
424 | version = "0.8.23" | |
|
425 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
426 | checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" | |
|
427 | dependencies = [ | |
|
428 | "indexmap", | |
|
429 | "ryu", | |
|
430 | "serde", | |
|
431 | "yaml-rust", | |
|
432 | ] | |
|
433 | ||
|
434 | [[package]] | |
|
435 | name = "similar" | |
|
436 | version = "2.1.0" | |
|
437 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
438 | checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3" | |
|
439 | dependencies = [ | |
|
440 | "bstr", | |
|
441 | ] | |
|
442 | ||
|
443 | [[package]] | |
|
444 | name = "strsim" | |
|
445 | version = "0.10.0" | |
|
446 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
447 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | |
|
448 | ||
|
449 | [[package]] | |
|
450 | name = "syn" | |
|
451 | version = "1.0.87" | |
|
452 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
453 | checksum = "1e59d925cf59d8151f25a3bedf97c9c157597c9df7324d32d68991cc399ed08b" | |
|
454 | dependencies = [ | |
|
455 | "proc-macro2", | |
|
456 | "quote", | |
|
457 | "unicode-xid", | |
|
458 | ] | |
|
459 | ||
|
460 | [[package]] | |
|
461 | name = "tempdir" | |
|
462 | version = "0.3.7" | |
|
463 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
464 | checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" | |
|
465 | dependencies = [ | |
|
466 | "rand", | |
|
467 | "remove_dir_all", | |
|
468 | ] | |
|
469 | ||
|
470 | [[package]] | |
|
471 | name = "termcolor" | |
|
472 | version = "1.1.3" | |
|
473 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
474 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" | |
|
475 | dependencies = [ | |
|
476 | "winapi-util", | |
|
477 | ] | |
|
478 | ||
|
479 | [[package]] | |
|
480 | name = "terminal_size" | |
|
481 | version = "0.1.17" | |
|
482 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
483 | checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" | |
|
484 | dependencies = [ | |
|
485 | "libc", | |
|
486 | "winapi", | |
|
487 | ] | |
|
488 | ||
|
489 | [[package]] | |
|
490 | name = "termtree" | |
|
491 | version = "0.2.4" | |
|
492 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
493 | checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" | |
|
494 | ||
|
495 | [[package]] | |
|
496 | name = "textwrap" | |
|
497 | version = "0.15.0" | |
|
498 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
499 | checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" | |
|
500 | ||
|
501 | [[package]] | |
|
502 | name = "unicode-xid" | |
|
503 | version = "0.2.2" | |
|
504 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
505 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" | |
|
506 | ||
|
507 | [[package]] | |
|
508 | name = "version_check" | |
|
509 | version = "0.9.4" | |
|
510 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
511 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" | |
|
512 | ||
|
513 | [[package]] | |
|
514 | name = "wait-timeout" | |
|
515 | version = "0.2.0" | |
|
516 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
517 | checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" | |
|
518 | dependencies = [ | |
|
519 | "libc", | |
|
520 | ] | |
|
521 | ||
|
522 | [[package]] | |
|
523 | name = "winapi" | |
|
524 | version = "0.3.9" | |
|
525 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
526 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | |
|
527 | dependencies = [ | |
|
528 | "winapi-i686-pc-windows-gnu", | |
|
529 | "winapi-x86_64-pc-windows-gnu", | |
|
530 | ] | |
|
531 | ||
|
532 | [[package]] | |
|
533 | name = "winapi-i686-pc-windows-gnu" | |
|
534 | version = "0.4.0" | |
|
535 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
536 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | |
|
537 | ||
|
538 | [[package]] | |
|
539 | name = "winapi-util" | |
|
540 | version = "0.1.5" | |
|
541 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
542 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" | |
|
543 | dependencies = [ | |
|
544 | "winapi", | |
|
545 | ] | |
|
546 | ||
|
547 | [[package]] | |
|
548 | name = "winapi-x86_64-pc-windows-gnu" | |
|
549 | version = "0.4.0" | |
|
550 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
551 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | |
|
552 | ||
|
553 | [[package]] | |
|
554 | name = "yaml-rust" | |
|
555 | version = "0.4.5" | |
|
556 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
557 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" | |
|
558 | dependencies = [ | |
|
559 | "linked-hash-map", | |
|
560 | ] |
@@ -0,0 +1,21 b'' | |||
|
1 | # A tool that performs a 3-way merge, resolving conflicts in sorted lists and | |
|
2 | # leaving other conflicts unchanged. This is useful with Mercurial's support | |
|
3 | # for partial merge tools (configured in `[partial-merge-tools]`). | |
|
4 | ||
|
5 | [package] | |
|
6 | name = "merge-lists" | |
|
7 | version = "0.1.0" | |
|
8 | edition = "2021" | |
|
9 | # We need https://github.com/rust-lang/rust/pull/89825 | |
|
10 | rust-version = "1.59" | |
|
11 | ||
|
12 | [dependencies] | |
|
13 | clap = { version = "3.1.6", features = ["derive"] } | |
|
14 | itertools = "0.10.3" | |
|
15 | regex = "1.5.5" | |
|
16 | similar = { version="2.1.0", features = ["bytes"] } | |
|
17 | ||
|
18 | [dev-dependencies] | |
|
19 | assert_cmd = "2.0.4" | |
|
20 | insta = "1.13.0" | |
|
21 | tempdir = "0.3.7" |
@@ -0,0 +1,280 b'' | |||
|
1 | use clap::Parser; | |
|
2 | use itertools::Itertools; | |
|
3 | use regex::bytes::Regex; | |
|
4 | use similar::ChangeTag; | |
|
5 | use std::cmp::{max, min, Ordering}; | |
|
6 | use std::collections::HashSet; | |
|
7 | use std::ffi::OsString; | |
|
8 | use std::ops::Range; | |
|
9 | use std::path::PathBuf; | |
|
10 | ||
|
11 | fn find_unchanged_ranges( | |
|
12 | old_bytes: &[u8], | |
|
13 | new_bytes: &[u8], | |
|
14 | ) -> Vec<(Range<usize>, Range<usize>)> { | |
|
15 | let diff = similar::TextDiff::configure() | |
|
16 | .algorithm(similar::Algorithm::Patience) | |
|
17 | .diff_lines(old_bytes, new_bytes); | |
|
18 | let mut new_unchanged_ranges = vec![]; | |
|
19 | let mut old_index = 0; | |
|
20 | let mut new_index = 0; | |
|
21 | for diff in diff.iter_all_changes() { | |
|
22 | match diff.tag() { | |
|
23 | ChangeTag::Equal => { | |
|
24 | new_unchanged_ranges.push(( | |
|
25 | old_index..old_index + diff.value().len(), | |
|
26 | new_index..new_index + diff.value().len(), | |
|
27 | )); | |
|
28 | old_index += diff.value().len(); | |
|
29 | new_index += diff.value().len(); | |
|
30 | } | |
|
31 | ChangeTag::Delete => { | |
|
32 | old_index += diff.value().len(); | |
|
33 | } | |
|
34 | ChangeTag::Insert => { | |
|
35 | new_index += diff.value().len(); | |
|
36 | } | |
|
37 | } | |
|
38 | } | |
|
39 | new_unchanged_ranges | |
|
40 | } | |
|
41 | ||
|
42 | /// Returns a list of all the lines in the input (including trailing newlines), | |
|
43 | /// but only if they all match the regex and they are sorted. | |
|
44 | fn get_lines<'input>( | |
|
45 | input: &'input [u8], | |
|
46 | regex: &Regex, | |
|
47 | ) -> Option<Vec<&'input [u8]>> { | |
|
48 | let lines = input.split_inclusive(|x| *x == b'\n').collect_vec(); | |
|
49 | let mut previous_line = "".as_bytes(); | |
|
50 | for line in &lines { | |
|
51 | if *line < previous_line { | |
|
52 | return None; | |
|
53 | } | |
|
54 | if !regex.is_match(line) { | |
|
55 | return None; | |
|
56 | } | |
|
57 | previous_line = line; | |
|
58 | } | |
|
59 | Some(lines) | |
|
60 | } | |
|
61 | ||
|
62 | fn resolve_conflict( | |
|
63 | base_slice: &[u8], | |
|
64 | local_slice: &[u8], | |
|
65 | other_slice: &[u8], | |
|
66 | regex: &Regex, | |
|
67 | ) -> Option<Vec<u8>> { | |
|
68 | let base_lines = get_lines(base_slice, regex)?; | |
|
69 | let local_lines = get_lines(local_slice, regex)?; | |
|
70 | let other_lines = get_lines(other_slice, regex)?; | |
|
71 | let base_lines_set: HashSet<_> = base_lines.iter().copied().collect(); | |
|
72 | let local_lines_set: HashSet<_> = local_lines.iter().copied().collect(); | |
|
73 | let other_lines_set: HashSet<_> = other_lines.iter().copied().collect(); | |
|
74 | let mut result = local_lines_set; | |
|
75 | for to_add in other_lines_set.difference(&base_lines_set) { | |
|
76 | result.insert(to_add); | |
|
77 | } | |
|
78 | for to_remove in base_lines_set.difference(&other_lines_set) { | |
|
79 | result.remove(to_remove); | |
|
80 | } | |
|
81 | Some(result.into_iter().sorted().collect_vec().concat()) | |
|
82 | } | |
|
83 | ||
|
84 | fn resolve( | |
|
85 | base_bytes: &[u8], | |
|
86 | local_bytes: &[u8], | |
|
87 | other_bytes: &[u8], | |
|
88 | regex: &Regex, | |
|
89 | ) -> (Vec<u8>, Vec<u8>, Vec<u8>) { | |
|
90 | // Find unchanged ranges between the base and the two sides. We do that by | |
|
91 | // initially considering the whole base unchanged. Then we compare each | |
|
92 | // side with the base and intersect the unchanged ranges we find with | |
|
93 | // what we had before. | |
|
94 | let unchanged_ranges = vec![UnchangedRange { | |
|
95 | base_range: 0..base_bytes.len(), | |
|
96 | offsets: vec![], | |
|
97 | }]; | |
|
98 | let unchanged_ranges = intersect_regions( | |
|
99 | unchanged_ranges, | |
|
100 | &find_unchanged_ranges(base_bytes, local_bytes), | |
|
101 | ); | |
|
102 | let mut unchanged_ranges = intersect_regions( | |
|
103 | unchanged_ranges, | |
|
104 | &find_unchanged_ranges(base_bytes, other_bytes), | |
|
105 | ); | |
|
106 | // Add an empty UnchangedRange at the end to make it easier to find change | |
|
107 | // ranges. That way there's a changed range before each UnchangedRange. | |
|
108 | unchanged_ranges.push(UnchangedRange { | |
|
109 | base_range: base_bytes.len()..base_bytes.len(), | |
|
110 | offsets: vec![ | |
|
111 | local_bytes.len().wrapping_sub(base_bytes.len()) as isize, | |
|
112 | other_bytes.len().wrapping_sub(base_bytes.len()) as isize, | |
|
113 | ], | |
|
114 | }); | |
|
115 | ||
|
116 | let mut new_base_bytes: Vec<u8> = vec![]; | |
|
117 | let mut new_local_bytes: Vec<u8> = vec![]; | |
|
118 | let mut new_other_bytes: Vec<u8> = vec![]; | |
|
119 | let mut previous = UnchangedRange { | |
|
120 | base_range: 0..0, | |
|
121 | offsets: vec![0, 0], | |
|
122 | }; | |
|
123 | for current in unchanged_ranges { | |
|
124 | let base_slice = | |
|
125 | &base_bytes[previous.base_range.end..current.base_range.start]; | |
|
126 | let local_slice = &local_bytes[previous.end(0)..current.start(0)]; | |
|
127 | let other_slice = &other_bytes[previous.end(1)..current.start(1)]; | |
|
128 | if let Some(resolution) = | |
|
129 | resolve_conflict(base_slice, local_slice, other_slice, regex) | |
|
130 | { | |
|
131 | new_base_bytes.extend(&resolution); | |
|
132 | new_local_bytes.extend(&resolution); | |
|
133 | new_other_bytes.extend(&resolution); | |
|
134 | } else { | |
|
135 | new_base_bytes.extend(base_slice); | |
|
136 | new_local_bytes.extend(local_slice); | |
|
137 | new_other_bytes.extend(other_slice); | |
|
138 | } | |
|
139 | new_base_bytes.extend(&base_bytes[current.base_range.clone()]); | |
|
140 | new_local_bytes.extend(&local_bytes[current.start(0)..current.end(0)]); | |
|
141 | new_other_bytes.extend(&other_bytes[current.start(1)..current.end(1)]); | |
|
142 | previous = current; | |
|
143 | } | |
|
144 | ||
|
145 | (new_base_bytes, new_local_bytes, new_other_bytes) | |
|
146 | } | |
|
147 | ||
|
148 | /// A tool that performs a 3-way merge, resolving conflicts in sorted lists and | |
|
149 | /// leaving other conflicts unchanged. This is useful with Mercurial's support | |
|
150 | /// for partial merge tools (configured in `[partial-merge-tools]`). | |
|
151 | #[derive(Parser, Debug)] | |
|
152 | #[clap(version, about, long_about = None)] | |
|
153 | struct Args { | |
|
154 | /// Path to the file's content in the "local" side | |
|
155 | local: OsString, | |
|
156 | ||
|
157 | /// Path to the file's content in the base | |
|
158 | base: OsString, | |
|
159 | ||
|
160 | /// Path to the file's content in the "other" side | |
|
161 | other: OsString, | |
|
162 | } | |
|
163 | ||
|
164 | fn main() { | |
|
165 | let args: Args = Args::parse(); | |
|
166 | ||
|
167 | let base_path = PathBuf::from(&args.base); | |
|
168 | let local_path = PathBuf::from(&args.local); | |
|
169 | let other_path = PathBuf::from(&args.other); | |
|
170 | ||
|
171 | let base_bytes = std::fs::read(&base_path).unwrap(); | |
|
172 | let local_bytes = std::fs::read(&local_path).unwrap(); | |
|
173 | let other_bytes = std::fs::read(&other_path).unwrap(); | |
|
174 | ||
|
175 | let regex = | |
|
176 | regex::bytes::Regex::new(r"import \w+(\.\w+)*( +#.*)?\n|from (\w+(\.\w+)* import \w+( as \w+)?(, \w+( as \w+)?)*( +#.*)?)\r?\n?").unwrap(); | |
|
177 | let (new_base_bytes, new_local_bytes, new_other_bytes) = | |
|
178 | resolve(&base_bytes, &local_bytes, &other_bytes, ®ex); | |
|
179 | ||
|
180 | // Write out the result if anything changed | |
|
181 | if new_base_bytes != base_bytes { | |
|
182 | std::fs::write(&base_path, new_base_bytes).unwrap(); | |
|
183 | } | |
|
184 | if new_local_bytes != local_bytes { | |
|
185 | std::fs::write(&local_path, new_local_bytes).unwrap(); | |
|
186 | } | |
|
187 | if new_other_bytes != other_bytes { | |
|
188 | std::fs::write(&other_path, new_other_bytes).unwrap(); | |
|
189 | } | |
|
190 | } | |
|
191 | ||
|
192 | fn checked_add(base: usize, offset: isize) -> usize { | |
|
193 | if offset < 0 { | |
|
194 | base.checked_sub(offset.checked_abs().unwrap() as usize) | |
|
195 | .unwrap() | |
|
196 | } else { | |
|
197 | base.checked_add(offset as usize).unwrap() | |
|
198 | } | |
|
199 | } | |
|
200 | ||
|
201 | // The remainder of the file is copied from | |
|
202 | // https://github.com/martinvonz/jj/blob/main/lib/src/diff.rs | |
|
203 | ||
|
204 | #[derive(Clone, PartialEq, Eq, Debug)] | |
|
205 | struct UnchangedRange { | |
|
206 | base_range: Range<usize>, | |
|
207 | offsets: Vec<isize>, | |
|
208 | } | |
|
209 | ||
|
210 | impl UnchangedRange { | |
|
211 | fn start(&self, side: usize) -> usize { | |
|
212 | checked_add(self.base_range.start, self.offsets[side]) | |
|
213 | } | |
|
214 | ||
|
215 | fn end(&self, side: usize) -> usize { | |
|
216 | checked_add(self.base_range.end, self.offsets[side]) | |
|
217 | } | |
|
218 | } | |
|
219 | ||
|
220 | impl PartialOrd for UnchangedRange { | |
|
221 | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | |
|
222 | Some(self.cmp(other)) | |
|
223 | } | |
|
224 | } | |
|
225 | ||
|
226 | impl Ord for UnchangedRange { | |
|
227 | fn cmp(&self, other: &Self) -> Ordering { | |
|
228 | self.base_range | |
|
229 | .start | |
|
230 | .cmp(&other.base_range.start) | |
|
231 | .then_with(|| self.base_range.end.cmp(&other.base_range.end)) | |
|
232 | } | |
|
233 | } | |
|
234 | ||
|
235 | /// Takes the current regions and intersects it with the new unchanged ranges | |
|
236 | /// from a 2-way diff. The result is a map of unchanged regions with one more | |
|
237 | /// offset in the map's values. | |
|
238 | fn intersect_regions( | |
|
239 | current_ranges: Vec<UnchangedRange>, | |
|
240 | new_unchanged_ranges: &[(Range<usize>, Range<usize>)], | |
|
241 | ) -> Vec<UnchangedRange> { | |
|
242 | let mut result = vec![]; | |
|
243 | let mut current_ranges_iter = current_ranges.into_iter().peekable(); | |
|
244 | for (new_base_range, other_range) in new_unchanged_ranges.iter() { | |
|
245 | assert_eq!(new_base_range.len(), other_range.len()); | |
|
246 | while let Some(UnchangedRange { | |
|
247 | base_range, | |
|
248 | offsets, | |
|
249 | }) = current_ranges_iter.peek() | |
|
250 | { | |
|
251 | // No need to look further if we're past the new range. | |
|
252 | if base_range.start >= new_base_range.end { | |
|
253 | break; | |
|
254 | } | |
|
255 | // Discard any current unchanged regions that don't match between | |
|
256 | // the base and the new input. | |
|
257 | if base_range.end <= new_base_range.start { | |
|
258 | current_ranges_iter.next(); | |
|
259 | continue; | |
|
260 | } | |
|
261 | let new_start = max(base_range.start, new_base_range.start); | |
|
262 | let new_end = min(base_range.end, new_base_range.end); | |
|
263 | let mut new_offsets = offsets.clone(); | |
|
264 | new_offsets | |
|
265 | .push(other_range.start.wrapping_sub(new_base_range.start) | |
|
266 | as isize); | |
|
267 | result.push(UnchangedRange { | |
|
268 | base_range: new_start..new_end, | |
|
269 | offsets: new_offsets, | |
|
270 | }); | |
|
271 | if base_range.end >= new_base_range.end { | |
|
272 | // Break without consuming the item; there may be other new | |
|
273 | // ranges that overlap with it. | |
|
274 | break; | |
|
275 | } | |
|
276 | current_ranges_iter.next(); | |
|
277 | } | |
|
278 | } | |
|
279 | result | |
|
280 | } |
@@ -0,0 +1,156 b'' | |||
|
1 | use similar::DiffableStr; | |
|
2 | use tempdir::TempDir; | |
|
3 | ||
|
4 | fn run_test(input: &str) -> String { | |
|
5 | let mut cmd = assert_cmd::Command::cargo_bin("merge-lists").unwrap(); | |
|
6 | let temp_dir = TempDir::new("test").unwrap(); | |
|
7 | let base_path = temp_dir.path().join("base"); | |
|
8 | let local_path = temp_dir.path().join("local"); | |
|
9 | let other_path = temp_dir.path().join("other"); | |
|
10 | ||
|
11 | let rest = input.strip_prefix("\nbase:\n").unwrap(); | |
|
12 | let mut split = rest.split("\nlocal:\n"); | |
|
13 | std::fs::write(&base_path, split.next().unwrap()).unwrap(); | |
|
14 | let rest = split.next().unwrap(); | |
|
15 | let mut split = rest.split("\nother:\n"); | |
|
16 | std::fs::write(&local_path, split.next().unwrap()).unwrap(); | |
|
17 | std::fs::write(&other_path, split.next().unwrap()).unwrap(); | |
|
18 | cmd.args(&[ | |
|
19 | local_path.as_os_str(), | |
|
20 | base_path.as_os_str(), | |
|
21 | other_path.as_os_str(), | |
|
22 | ]) | |
|
23 | .assert() | |
|
24 | .success(); | |
|
25 | ||
|
26 | let new_base_bytes = std::fs::read(&base_path).unwrap(); | |
|
27 | let new_local_bytes = std::fs::read(&local_path).unwrap(); | |
|
28 | let new_other_bytes = std::fs::read(&other_path).unwrap(); | |
|
29 | // No newline before "base:" because of https://github.com/mitsuhiko/insta/issues/117 | |
|
30 | format!( | |
|
31 | "base:\n{}\nlocal:\n{}\nother:\n{}", | |
|
32 | new_base_bytes.as_str().unwrap(), | |
|
33 | new_local_bytes.as_str().unwrap(), | |
|
34 | new_other_bytes.as_str().unwrap() | |
|
35 | ) | |
|
36 | } | |
|
37 | ||
|
38 | #[test] | |
|
39 | fn test_merge_lists_basic() { | |
|
40 | let output = run_test( | |
|
41 | r" | |
|
42 | base: | |
|
43 | import lib1 | |
|
44 | import lib2 | |
|
45 | ||
|
46 | local: | |
|
47 | import lib2 | |
|
48 | import lib3 | |
|
49 | ||
|
50 | other: | |
|
51 | import lib3 | |
|
52 | import lib4 | |
|
53 | ", | |
|
54 | ); | |
|
55 | insta::assert_snapshot!(output, @r###" | |
|
56 | base: | |
|
57 | import lib3 | |
|
58 | import lib4 | |
|
59 | ||
|
60 | local: | |
|
61 | import lib3 | |
|
62 | import lib4 | |
|
63 | ||
|
64 | other: | |
|
65 | import lib3 | |
|
66 | import lib4 | |
|
67 | "###); | |
|
68 | } | |
|
69 | ||
|
70 | #[test] | |
|
71 | fn test_merge_lists_from() { | |
|
72 | // Test some "from x import y" statements and some non-import conflicts | |
|
73 | // (unresolvable) | |
|
74 | let output = run_test( | |
|
75 | r" | |
|
76 | base: | |
|
77 | from . import x | |
|
78 | ||
|
79 | 1+1 | |
|
80 | ||
|
81 | local: | |
|
82 | from . import x | |
|
83 | from a import b | |
|
84 | ||
|
85 | 2+2 | |
|
86 | ||
|
87 | other: | |
|
88 | from a import c | |
|
89 | ||
|
90 | 3+3 | |
|
91 | ", | |
|
92 | ); | |
|
93 | insta::assert_snapshot!(output, @r###" | |
|
94 | base: | |
|
95 | from a import b | |
|
96 | from a import c | |
|
97 | ||
|
98 | 1+1 | |
|
99 | ||
|
100 | local: | |
|
101 | from a import b | |
|
102 | from a import c | |
|
103 | ||
|
104 | 2+2 | |
|
105 | ||
|
106 | other: | |
|
107 | from a import b | |
|
108 | from a import c | |
|
109 | ||
|
110 | 3+3 | |
|
111 | "###); | |
|
112 | } | |
|
113 | ||
|
114 | #[test] | |
|
115 | fn test_merge_lists_not_sorted() { | |
|
116 | // Test that nothing is done if the elements in the conflicting hunks are | |
|
117 | // not sorted | |
|
118 | let output = run_test( | |
|
119 | r" | |
|
120 | base: | |
|
121 | import x | |
|
122 | ||
|
123 | 1+1 | |
|
124 | ||
|
125 | local: | |
|
126 | import a | |
|
127 | import x | |
|
128 | ||
|
129 | 2+2 | |
|
130 | ||
|
131 | other: | |
|
132 | import z | |
|
133 | import y | |
|
134 | ||
|
135 | 3+3 | |
|
136 | ", | |
|
137 | ); | |
|
138 | insta::assert_snapshot!(output, @r###" | |
|
139 | base: | |
|
140 | import x | |
|
141 | ||
|
142 | 1+1 | |
|
143 | ||
|
144 | local: | |
|
145 | import a | |
|
146 | import x | |
|
147 | ||
|
148 | 2+2 | |
|
149 | ||
|
150 | other: | |
|
151 | import z | |
|
152 | import y | |
|
153 | ||
|
154 | 3+3 | |
|
155 | "###); | |
|
156 | } |
General Comments 0
You need to be logged in to leave comments.
Login now