├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── lib.rs ├── list.rs ├── main.rs ├── record.rs └── replay.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 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.19" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "android_system_properties" 16 | version = "0.1.5" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 19 | dependencies = [ 20 | "libc", 21 | ] 22 | 23 | [[package]] 24 | name = "ansi_term" 25 | version = "0.12.1" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 28 | dependencies = [ 29 | "winapi", 30 | ] 31 | 32 | [[package]] 33 | name = "anyhow" 34 | version = "1.0.65" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" 37 | 38 | [[package]] 39 | name = "arrayvec" 40 | version = "0.5.2" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 43 | 44 | [[package]] 45 | name = "atty" 46 | version = "0.2.14" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 49 | dependencies = [ 50 | "hermit-abi", 51 | "libc", 52 | "winapi", 53 | ] 54 | 55 | [[package]] 56 | name = "autocfg" 57 | version = "1.1.0" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 60 | 61 | [[package]] 62 | name = "base-x" 63 | version = "0.2.11" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" 66 | 67 | [[package]] 68 | name = "beef" 69 | version = "0.5.2" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" 72 | 73 | [[package]] 74 | name = "bitflags" 75 | version = "1.3.2" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 78 | 79 | [[package]] 80 | name = "bumpalo" 81 | version = "3.11.0" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" 84 | 85 | [[package]] 86 | name = "camino" 87 | version = "1.1.1" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e" 90 | dependencies = [ 91 | "serde", 92 | ] 93 | 94 | [[package]] 95 | name = "cargo-platform" 96 | version = "0.1.2" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" 99 | dependencies = [ 100 | "serde", 101 | ] 102 | 103 | [[package]] 104 | name = "cargo-rr" 105 | version = "0.3.0" 106 | dependencies = [ 107 | "anyhow", 108 | "camino", 109 | "cargo_metadata 0.15.0", 110 | "clap 3.2.22", 111 | "ctrlc", 112 | "seacan", 113 | "skim", 114 | "tracing", 115 | "tracing-subscriber", 116 | ] 117 | 118 | [[package]] 119 | name = "cargo_metadata" 120 | version = "0.13.1" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "081e3f0755c1f380c2d010481b6fa2e02973586d5f2b24eebb7a2a1d98b143d8" 123 | dependencies = [ 124 | "camino", 125 | "cargo-platform", 126 | "semver 0.11.0", 127 | "semver-parser 0.10.2", 128 | "serde", 129 | "serde_json", 130 | ] 131 | 132 | [[package]] 133 | name = "cargo_metadata" 134 | version = "0.15.0" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "3abb7553d5b9b8421c6de7cb02606ff15e0c6eea7d8eadd75ef013fd636bec36" 137 | dependencies = [ 138 | "camino", 139 | "cargo-platform", 140 | "semver 1.0.14", 141 | "serde", 142 | "serde_json", 143 | ] 144 | 145 | [[package]] 146 | name = "cc" 147 | version = "1.0.73" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" 150 | 151 | [[package]] 152 | name = "cfg-if" 153 | version = "0.1.10" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 156 | 157 | [[package]] 158 | name = "cfg-if" 159 | version = "1.0.0" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 162 | 163 | [[package]] 164 | name = "chrono" 165 | version = "0.4.22" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" 168 | dependencies = [ 169 | "iana-time-zone", 170 | "js-sys", 171 | "num-integer", 172 | "num-traits", 173 | "time 0.1.44", 174 | "wasm-bindgen", 175 | "winapi", 176 | ] 177 | 178 | [[package]] 179 | name = "clap" 180 | version = "2.34.0" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" 183 | dependencies = [ 184 | "ansi_term", 185 | "atty", 186 | "bitflags", 187 | "strsim 0.8.0", 188 | "textwrap 0.11.0", 189 | "unicode-width", 190 | "vec_map", 191 | ] 192 | 193 | [[package]] 194 | name = "clap" 195 | version = "3.2.22" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" 198 | dependencies = [ 199 | "atty", 200 | "bitflags", 201 | "clap_derive", 202 | "clap_lex", 203 | "indexmap", 204 | "once_cell", 205 | "strsim 0.10.0", 206 | "termcolor", 207 | "textwrap 0.15.1", 208 | ] 209 | 210 | [[package]] 211 | name = "clap_derive" 212 | version = "3.2.18" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" 215 | dependencies = [ 216 | "heck", 217 | "proc-macro-error", 218 | "proc-macro2", 219 | "quote", 220 | "syn", 221 | ] 222 | 223 | [[package]] 224 | name = "clap_lex" 225 | version = "0.2.4" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" 228 | dependencies = [ 229 | "os_str_bytes", 230 | ] 231 | 232 | [[package]] 233 | name = "const_fn" 234 | version = "0.4.9" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" 237 | 238 | [[package]] 239 | name = "core-foundation-sys" 240 | version = "0.8.3" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 243 | 244 | [[package]] 245 | name = "crossbeam" 246 | version = "0.8.2" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" 249 | dependencies = [ 250 | "cfg-if 1.0.0", 251 | "crossbeam-channel 0.5.6", 252 | "crossbeam-deque", 253 | "crossbeam-epoch", 254 | "crossbeam-queue", 255 | "crossbeam-utils 0.8.11", 256 | ] 257 | 258 | [[package]] 259 | name = "crossbeam-channel" 260 | version = "0.4.4" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" 263 | dependencies = [ 264 | "crossbeam-utils 0.7.2", 265 | "maybe-uninit", 266 | ] 267 | 268 | [[package]] 269 | name = "crossbeam-channel" 270 | version = "0.5.6" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" 273 | dependencies = [ 274 | "cfg-if 1.0.0", 275 | "crossbeam-utils 0.8.11", 276 | ] 277 | 278 | [[package]] 279 | name = "crossbeam-deque" 280 | version = "0.8.2" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" 283 | dependencies = [ 284 | "cfg-if 1.0.0", 285 | "crossbeam-epoch", 286 | "crossbeam-utils 0.8.11", 287 | ] 288 | 289 | [[package]] 290 | name = "crossbeam-epoch" 291 | version = "0.9.10" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" 294 | dependencies = [ 295 | "autocfg", 296 | "cfg-if 1.0.0", 297 | "crossbeam-utils 0.8.11", 298 | "memoffset", 299 | "once_cell", 300 | "scopeguard", 301 | ] 302 | 303 | [[package]] 304 | name = "crossbeam-queue" 305 | version = "0.3.6" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" 308 | dependencies = [ 309 | "cfg-if 1.0.0", 310 | "crossbeam-utils 0.8.11", 311 | ] 312 | 313 | [[package]] 314 | name = "crossbeam-utils" 315 | version = "0.7.2" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" 318 | dependencies = [ 319 | "autocfg", 320 | "cfg-if 0.1.10", 321 | "lazy_static", 322 | ] 323 | 324 | [[package]] 325 | name = "crossbeam-utils" 326 | version = "0.8.11" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" 329 | dependencies = [ 330 | "cfg-if 1.0.0", 331 | "once_cell", 332 | ] 333 | 334 | [[package]] 335 | name = "ctrlc" 336 | version = "3.2.3" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "1d91974fbbe88ec1df0c24a4f00f99583667a7e2e6272b2b92d294d81e462173" 339 | dependencies = [ 340 | "nix 0.25.0", 341 | "winapi", 342 | ] 343 | 344 | [[package]] 345 | name = "darling" 346 | version = "0.10.2" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" 349 | dependencies = [ 350 | "darling_core", 351 | "darling_macro", 352 | ] 353 | 354 | [[package]] 355 | name = "darling_core" 356 | version = "0.10.2" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" 359 | dependencies = [ 360 | "fnv", 361 | "ident_case", 362 | "proc-macro2", 363 | "quote", 364 | "strsim 0.9.3", 365 | "syn", 366 | ] 367 | 368 | [[package]] 369 | name = "darling_macro" 370 | version = "0.10.2" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" 373 | dependencies = [ 374 | "darling_core", 375 | "quote", 376 | "syn", 377 | ] 378 | 379 | [[package]] 380 | name = "defer-drop" 381 | version = "1.2.0" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "828aca0e5e4341b0320a319209cbc6255b8b06254849ce8a5f33d33f7f2fa0f0" 384 | dependencies = [ 385 | "crossbeam-channel 0.4.4", 386 | "once_cell", 387 | ] 388 | 389 | [[package]] 390 | name = "derivative" 391 | version = "2.2.0" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" 394 | dependencies = [ 395 | "proc-macro2", 396 | "quote", 397 | "syn", 398 | ] 399 | 400 | [[package]] 401 | name = "derive_builder" 402 | version = "0.9.0" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" 405 | dependencies = [ 406 | "darling", 407 | "derive_builder_core", 408 | "proc-macro2", 409 | "quote", 410 | "syn", 411 | ] 412 | 413 | [[package]] 414 | name = "derive_builder_core" 415 | version = "0.9.0" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" 418 | dependencies = [ 419 | "darling", 420 | "proc-macro2", 421 | "quote", 422 | "syn", 423 | ] 424 | 425 | [[package]] 426 | name = "dirs-next" 427 | version = "2.0.0" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 430 | dependencies = [ 431 | "cfg-if 1.0.0", 432 | "dirs-sys-next", 433 | ] 434 | 435 | [[package]] 436 | name = "dirs-sys-next" 437 | version = "0.1.2" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 440 | dependencies = [ 441 | "libc", 442 | "redox_users", 443 | "winapi", 444 | ] 445 | 446 | [[package]] 447 | name = "discard" 448 | version = "1.0.4" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" 451 | 452 | [[package]] 453 | name = "displaydoc" 454 | version = "0.2.3" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" 457 | dependencies = [ 458 | "proc-macro2", 459 | "quote", 460 | "syn", 461 | ] 462 | 463 | [[package]] 464 | name = "either" 465 | version = "1.8.0" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" 468 | 469 | [[package]] 470 | name = "env_logger" 471 | version = "0.8.4" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" 474 | dependencies = [ 475 | "atty", 476 | "humantime", 477 | "log", 478 | "regex", 479 | "termcolor", 480 | ] 481 | 482 | [[package]] 483 | name = "fnv" 484 | version = "1.0.7" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 487 | 488 | [[package]] 489 | name = "fuzzy-matcher" 490 | version = "0.3.7" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" 493 | dependencies = [ 494 | "thread_local", 495 | ] 496 | 497 | [[package]] 498 | name = "getrandom" 499 | version = "0.2.7" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" 502 | dependencies = [ 503 | "cfg-if 1.0.0", 504 | "libc", 505 | "wasi 0.11.0+wasi-snapshot-preview1", 506 | ] 507 | 508 | [[package]] 509 | name = "hashbrown" 510 | version = "0.12.3" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 513 | 514 | [[package]] 515 | name = "heck" 516 | version = "0.4.0" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 519 | 520 | [[package]] 521 | name = "hermit-abi" 522 | version = "0.1.19" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 525 | dependencies = [ 526 | "libc", 527 | ] 528 | 529 | [[package]] 530 | name = "humantime" 531 | version = "2.1.0" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 534 | 535 | [[package]] 536 | name = "iana-time-zone" 537 | version = "0.1.48" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" 540 | dependencies = [ 541 | "android_system_properties", 542 | "core-foundation-sys", 543 | "js-sys", 544 | "once_cell", 545 | "wasm-bindgen", 546 | "winapi", 547 | ] 548 | 549 | [[package]] 550 | name = "ident_case" 551 | version = "1.0.1" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 554 | 555 | [[package]] 556 | name = "indexmap" 557 | version = "1.9.1" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" 560 | dependencies = [ 561 | "autocfg", 562 | "hashbrown", 563 | ] 564 | 565 | [[package]] 566 | name = "itoa" 567 | version = "1.0.3" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" 570 | 571 | [[package]] 572 | name = "js-sys" 573 | version = "0.3.60" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" 576 | dependencies = [ 577 | "wasm-bindgen", 578 | ] 579 | 580 | [[package]] 581 | name = "lazy_static" 582 | version = "1.4.0" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 585 | 586 | [[package]] 587 | name = "libc" 588 | version = "0.2.132" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" 591 | 592 | [[package]] 593 | name = "log" 594 | version = "0.4.17" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 597 | dependencies = [ 598 | "cfg-if 1.0.0", 599 | ] 600 | 601 | [[package]] 602 | name = "matchers" 603 | version = "0.1.0" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 606 | dependencies = [ 607 | "regex-automata", 608 | ] 609 | 610 | [[package]] 611 | name = "maybe-uninit" 612 | version = "2.0.0" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" 615 | 616 | [[package]] 617 | name = "memchr" 618 | version = "2.5.0" 619 | source = "registry+https://github.com/rust-lang/crates.io-index" 620 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 621 | 622 | [[package]] 623 | name = "memoffset" 624 | version = "0.6.5" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 627 | dependencies = [ 628 | "autocfg", 629 | ] 630 | 631 | [[package]] 632 | name = "nix" 633 | version = "0.19.1" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" 636 | dependencies = [ 637 | "bitflags", 638 | "cc", 639 | "cfg-if 1.0.0", 640 | "libc", 641 | ] 642 | 643 | [[package]] 644 | name = "nix" 645 | version = "0.24.2" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" 648 | dependencies = [ 649 | "bitflags", 650 | "cfg-if 1.0.0", 651 | "libc", 652 | "memoffset", 653 | ] 654 | 655 | [[package]] 656 | name = "nix" 657 | version = "0.25.0" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" 660 | dependencies = [ 661 | "autocfg", 662 | "bitflags", 663 | "cfg-if 1.0.0", 664 | "libc", 665 | ] 666 | 667 | [[package]] 668 | name = "num-integer" 669 | version = "0.1.45" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 672 | dependencies = [ 673 | "autocfg", 674 | "num-traits", 675 | ] 676 | 677 | [[package]] 678 | name = "num-traits" 679 | version = "0.2.15" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 682 | dependencies = [ 683 | "autocfg", 684 | ] 685 | 686 | [[package]] 687 | name = "num_cpus" 688 | version = "1.13.1" 689 | source = "registry+https://github.com/rust-lang/crates.io-index" 690 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 691 | dependencies = [ 692 | "hermit-abi", 693 | "libc", 694 | ] 695 | 696 | [[package]] 697 | name = "once_cell" 698 | version = "1.14.0" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" 701 | 702 | [[package]] 703 | name = "os_str_bytes" 704 | version = "6.3.0" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" 707 | 708 | [[package]] 709 | name = "pest" 710 | version = "2.3.1" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" 713 | dependencies = [ 714 | "thiserror", 715 | "ucd-trie", 716 | ] 717 | 718 | [[package]] 719 | name = "pin-project-lite" 720 | version = "0.2.9" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 723 | 724 | [[package]] 725 | name = "proc-macro-error" 726 | version = "1.0.4" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 729 | dependencies = [ 730 | "proc-macro-error-attr", 731 | "proc-macro2", 732 | "quote", 733 | "syn", 734 | "version_check", 735 | ] 736 | 737 | [[package]] 738 | name = "proc-macro-error-attr" 739 | version = "1.0.4" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 742 | dependencies = [ 743 | "proc-macro2", 744 | "quote", 745 | "version_check", 746 | ] 747 | 748 | [[package]] 749 | name = "proc-macro-hack" 750 | version = "0.5.19" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 753 | 754 | [[package]] 755 | name = "proc-macro2" 756 | version = "1.0.43" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" 759 | dependencies = [ 760 | "unicode-ident", 761 | ] 762 | 763 | [[package]] 764 | name = "quote" 765 | version = "1.0.21" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" 768 | dependencies = [ 769 | "proc-macro2", 770 | ] 771 | 772 | [[package]] 773 | name = "rayon" 774 | version = "1.5.3" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" 777 | dependencies = [ 778 | "autocfg", 779 | "crossbeam-deque", 780 | "either", 781 | "rayon-core", 782 | ] 783 | 784 | [[package]] 785 | name = "rayon-core" 786 | version = "1.9.3" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" 789 | dependencies = [ 790 | "crossbeam-channel 0.5.6", 791 | "crossbeam-deque", 792 | "crossbeam-utils 0.8.11", 793 | "num_cpus", 794 | ] 795 | 796 | [[package]] 797 | name = "redox_syscall" 798 | version = "0.2.16" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 801 | dependencies = [ 802 | "bitflags", 803 | ] 804 | 805 | [[package]] 806 | name = "redox_users" 807 | version = "0.4.3" 808 | source = "registry+https://github.com/rust-lang/crates.io-index" 809 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 810 | dependencies = [ 811 | "getrandom", 812 | "redox_syscall", 813 | "thiserror", 814 | ] 815 | 816 | [[package]] 817 | name = "regex" 818 | version = "1.6.0" 819 | source = "registry+https://github.com/rust-lang/crates.io-index" 820 | checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" 821 | dependencies = [ 822 | "aho-corasick", 823 | "memchr", 824 | "regex-syntax", 825 | ] 826 | 827 | [[package]] 828 | name = "regex-automata" 829 | version = "0.1.10" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 832 | dependencies = [ 833 | "regex-syntax", 834 | ] 835 | 836 | [[package]] 837 | name = "regex-syntax" 838 | version = "0.6.27" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 841 | 842 | [[package]] 843 | name = "rustc_version" 844 | version = "0.2.3" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 847 | dependencies = [ 848 | "semver 0.9.0", 849 | ] 850 | 851 | [[package]] 852 | name = "rustversion" 853 | version = "1.0.9" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" 856 | 857 | [[package]] 858 | name = "ryu" 859 | version = "1.0.11" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" 862 | 863 | [[package]] 864 | name = "scopeguard" 865 | version = "1.1.0" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 868 | 869 | [[package]] 870 | name = "seacan" 871 | version = "0.1.0" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | checksum = "546b59e4ea599b3188772c66bd7351000d935555a77064701a43a03a907db8b3" 874 | dependencies = [ 875 | "camino", 876 | "cargo_metadata 0.13.1", 877 | "derivative", 878 | "displaydoc", 879 | "lazy_static", 880 | "regex", 881 | "thiserror", 882 | "tracing", 883 | ] 884 | 885 | [[package]] 886 | name = "semver" 887 | version = "0.9.0" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 890 | dependencies = [ 891 | "semver-parser 0.7.0", 892 | ] 893 | 894 | [[package]] 895 | name = "semver" 896 | version = "0.11.0" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" 899 | dependencies = [ 900 | "semver-parser 0.10.2", 901 | "serde", 902 | ] 903 | 904 | [[package]] 905 | name = "semver" 906 | version = "1.0.14" 907 | source = "registry+https://github.com/rust-lang/crates.io-index" 908 | checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" 909 | dependencies = [ 910 | "serde", 911 | ] 912 | 913 | [[package]] 914 | name = "semver-parser" 915 | version = "0.7.0" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 918 | 919 | [[package]] 920 | name = "semver-parser" 921 | version = "0.10.2" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" 924 | dependencies = [ 925 | "pest", 926 | ] 927 | 928 | [[package]] 929 | name = "serde" 930 | version = "1.0.144" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" 933 | dependencies = [ 934 | "serde_derive", 935 | ] 936 | 937 | [[package]] 938 | name = "serde_derive" 939 | version = "1.0.144" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" 942 | dependencies = [ 943 | "proc-macro2", 944 | "quote", 945 | "syn", 946 | ] 947 | 948 | [[package]] 949 | name = "serde_json" 950 | version = "1.0.85" 951 | source = "registry+https://github.com/rust-lang/crates.io-index" 952 | checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" 953 | dependencies = [ 954 | "itoa", 955 | "ryu", 956 | "serde", 957 | ] 958 | 959 | [[package]] 960 | name = "sha1" 961 | version = "0.6.1" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" 964 | dependencies = [ 965 | "sha1_smol", 966 | ] 967 | 968 | [[package]] 969 | name = "sha1_smol" 970 | version = "1.0.0" 971 | source = "registry+https://github.com/rust-lang/crates.io-index" 972 | checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" 973 | 974 | [[package]] 975 | name = "sharded-slab" 976 | version = "0.1.4" 977 | source = "registry+https://github.com/rust-lang/crates.io-index" 978 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 979 | dependencies = [ 980 | "lazy_static", 981 | ] 982 | 983 | [[package]] 984 | name = "shlex" 985 | version = "0.1.1" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" 988 | 989 | [[package]] 990 | name = "skim" 991 | version = "0.9.4" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "4b9d19f904221fab15163486d2ce116cb86e60296470bb4e956d6687f04ebbb4" 994 | dependencies = [ 995 | "atty", 996 | "beef", 997 | "bitflags", 998 | "chrono", 999 | "clap 2.34.0", 1000 | "crossbeam", 1001 | "defer-drop", 1002 | "derive_builder", 1003 | "env_logger", 1004 | "fuzzy-matcher", 1005 | "lazy_static", 1006 | "log", 1007 | "nix 0.19.1", 1008 | "rayon", 1009 | "regex", 1010 | "shlex", 1011 | "time 0.2.27", 1012 | "timer", 1013 | "tuikit", 1014 | "unicode-width", 1015 | "vte", 1016 | ] 1017 | 1018 | [[package]] 1019 | name = "smallvec" 1020 | version = "1.9.0" 1021 | source = "registry+https://github.com/rust-lang/crates.io-index" 1022 | checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" 1023 | 1024 | [[package]] 1025 | name = "standback" 1026 | version = "0.2.17" 1027 | source = "registry+https://github.com/rust-lang/crates.io-index" 1028 | checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" 1029 | dependencies = [ 1030 | "version_check", 1031 | ] 1032 | 1033 | [[package]] 1034 | name = "stdweb" 1035 | version = "0.4.20" 1036 | source = "registry+https://github.com/rust-lang/crates.io-index" 1037 | checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" 1038 | dependencies = [ 1039 | "discard", 1040 | "rustc_version", 1041 | "stdweb-derive", 1042 | "stdweb-internal-macros", 1043 | "stdweb-internal-runtime", 1044 | "wasm-bindgen", 1045 | ] 1046 | 1047 | [[package]] 1048 | name = "stdweb-derive" 1049 | version = "0.5.3" 1050 | source = "registry+https://github.com/rust-lang/crates.io-index" 1051 | checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" 1052 | dependencies = [ 1053 | "proc-macro2", 1054 | "quote", 1055 | "serde", 1056 | "serde_derive", 1057 | "syn", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "stdweb-internal-macros" 1062 | version = "0.2.9" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" 1065 | dependencies = [ 1066 | "base-x", 1067 | "proc-macro2", 1068 | "quote", 1069 | "serde", 1070 | "serde_derive", 1071 | "serde_json", 1072 | "sha1", 1073 | "syn", 1074 | ] 1075 | 1076 | [[package]] 1077 | name = "stdweb-internal-runtime" 1078 | version = "0.1.5" 1079 | source = "registry+https://github.com/rust-lang/crates.io-index" 1080 | checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" 1081 | 1082 | [[package]] 1083 | name = "strsim" 1084 | version = "0.8.0" 1085 | source = "registry+https://github.com/rust-lang/crates.io-index" 1086 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 1087 | 1088 | [[package]] 1089 | name = "strsim" 1090 | version = "0.9.3" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" 1093 | 1094 | [[package]] 1095 | name = "strsim" 1096 | version = "0.10.0" 1097 | source = "registry+https://github.com/rust-lang/crates.io-index" 1098 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1099 | 1100 | [[package]] 1101 | name = "syn" 1102 | version = "1.0.99" 1103 | source = "registry+https://github.com/rust-lang/crates.io-index" 1104 | checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" 1105 | dependencies = [ 1106 | "proc-macro2", 1107 | "quote", 1108 | "unicode-ident", 1109 | ] 1110 | 1111 | [[package]] 1112 | name = "term" 1113 | version = "0.7.0" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" 1116 | dependencies = [ 1117 | "dirs-next", 1118 | "rustversion", 1119 | "winapi", 1120 | ] 1121 | 1122 | [[package]] 1123 | name = "termcolor" 1124 | version = "1.1.3" 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" 1126 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" 1127 | dependencies = [ 1128 | "winapi-util", 1129 | ] 1130 | 1131 | [[package]] 1132 | name = "textwrap" 1133 | version = "0.11.0" 1134 | source = "registry+https://github.com/rust-lang/crates.io-index" 1135 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 1136 | dependencies = [ 1137 | "unicode-width", 1138 | ] 1139 | 1140 | [[package]] 1141 | name = "textwrap" 1142 | version = "0.15.1" 1143 | source = "registry+https://github.com/rust-lang/crates.io-index" 1144 | checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" 1145 | 1146 | [[package]] 1147 | name = "thiserror" 1148 | version = "1.0.35" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" 1151 | dependencies = [ 1152 | "thiserror-impl", 1153 | ] 1154 | 1155 | [[package]] 1156 | name = "thiserror-impl" 1157 | version = "1.0.35" 1158 | source = "registry+https://github.com/rust-lang/crates.io-index" 1159 | checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" 1160 | dependencies = [ 1161 | "proc-macro2", 1162 | "quote", 1163 | "syn", 1164 | ] 1165 | 1166 | [[package]] 1167 | name = "thread_local" 1168 | version = "1.1.4" 1169 | source = "registry+https://github.com/rust-lang/crates.io-index" 1170 | checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" 1171 | dependencies = [ 1172 | "once_cell", 1173 | ] 1174 | 1175 | [[package]] 1176 | name = "time" 1177 | version = "0.1.44" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 1180 | dependencies = [ 1181 | "libc", 1182 | "wasi 0.10.0+wasi-snapshot-preview1", 1183 | "winapi", 1184 | ] 1185 | 1186 | [[package]] 1187 | name = "time" 1188 | version = "0.2.27" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" 1191 | dependencies = [ 1192 | "const_fn", 1193 | "libc", 1194 | "standback", 1195 | "stdweb", 1196 | "time-macros", 1197 | "version_check", 1198 | "winapi", 1199 | ] 1200 | 1201 | [[package]] 1202 | name = "time-macros" 1203 | version = "0.1.1" 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" 1205 | checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" 1206 | dependencies = [ 1207 | "proc-macro-hack", 1208 | "time-macros-impl", 1209 | ] 1210 | 1211 | [[package]] 1212 | name = "time-macros-impl" 1213 | version = "0.1.2" 1214 | source = "registry+https://github.com/rust-lang/crates.io-index" 1215 | checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" 1216 | dependencies = [ 1217 | "proc-macro-hack", 1218 | "proc-macro2", 1219 | "quote", 1220 | "standback", 1221 | "syn", 1222 | ] 1223 | 1224 | [[package]] 1225 | name = "timer" 1226 | version = "0.2.0" 1227 | source = "registry+https://github.com/rust-lang/crates.io-index" 1228 | checksum = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" 1229 | dependencies = [ 1230 | "chrono", 1231 | ] 1232 | 1233 | [[package]] 1234 | name = "tracing" 1235 | version = "0.1.36" 1236 | source = "registry+https://github.com/rust-lang/crates.io-index" 1237 | checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" 1238 | dependencies = [ 1239 | "cfg-if 1.0.0", 1240 | "pin-project-lite", 1241 | "tracing-attributes", 1242 | "tracing-core", 1243 | ] 1244 | 1245 | [[package]] 1246 | name = "tracing-attributes" 1247 | version = "0.1.22" 1248 | source = "registry+https://github.com/rust-lang/crates.io-index" 1249 | checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" 1250 | dependencies = [ 1251 | "proc-macro2", 1252 | "quote", 1253 | "syn", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "tracing-core" 1258 | version = "0.1.29" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" 1261 | dependencies = [ 1262 | "once_cell", 1263 | "valuable", 1264 | ] 1265 | 1266 | [[package]] 1267 | name = "tracing-log" 1268 | version = "0.1.3" 1269 | source = "registry+https://github.com/rust-lang/crates.io-index" 1270 | checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" 1271 | dependencies = [ 1272 | "lazy_static", 1273 | "log", 1274 | "tracing-core", 1275 | ] 1276 | 1277 | [[package]] 1278 | name = "tracing-subscriber" 1279 | version = "0.3.15" 1280 | source = "registry+https://github.com/rust-lang/crates.io-index" 1281 | checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" 1282 | dependencies = [ 1283 | "ansi_term", 1284 | "matchers", 1285 | "once_cell", 1286 | "regex", 1287 | "sharded-slab", 1288 | "smallvec", 1289 | "thread_local", 1290 | "tracing", 1291 | "tracing-core", 1292 | "tracing-log", 1293 | ] 1294 | 1295 | [[package]] 1296 | name = "tuikit" 1297 | version = "0.4.6" 1298 | source = "registry+https://github.com/rust-lang/crates.io-index" 1299 | checksum = "667c8e002675e76d98358d8869021793a472d28e3a50fbd750284a1d211abd09" 1300 | dependencies = [ 1301 | "bitflags", 1302 | "lazy_static", 1303 | "log", 1304 | "nix 0.24.2", 1305 | "term", 1306 | "unicode-width", 1307 | ] 1308 | 1309 | [[package]] 1310 | name = "ucd-trie" 1311 | version = "0.1.5" 1312 | source = "registry+https://github.com/rust-lang/crates.io-index" 1313 | checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" 1314 | 1315 | [[package]] 1316 | name = "unicode-ident" 1317 | version = "1.0.4" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" 1320 | 1321 | [[package]] 1322 | name = "unicode-width" 1323 | version = "0.1.10" 1324 | source = "registry+https://github.com/rust-lang/crates.io-index" 1325 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 1326 | 1327 | [[package]] 1328 | name = "utf8parse" 1329 | version = "0.2.0" 1330 | source = "registry+https://github.com/rust-lang/crates.io-index" 1331 | checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" 1332 | 1333 | [[package]] 1334 | name = "valuable" 1335 | version = "0.1.0" 1336 | source = "registry+https://github.com/rust-lang/crates.io-index" 1337 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 1338 | 1339 | [[package]] 1340 | name = "vec_map" 1341 | version = "0.8.2" 1342 | source = "registry+https://github.com/rust-lang/crates.io-index" 1343 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 1344 | 1345 | [[package]] 1346 | name = "version_check" 1347 | version = "0.9.4" 1348 | source = "registry+https://github.com/rust-lang/crates.io-index" 1349 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1350 | 1351 | [[package]] 1352 | name = "vte" 1353 | version = "0.9.0" 1354 | source = "registry+https://github.com/rust-lang/crates.io-index" 1355 | checksum = "6e7745610024d50ab1ebfa41f8f8ee361c567f7ab51032f93cc1cc4cbf0c547a" 1356 | dependencies = [ 1357 | "arrayvec", 1358 | "utf8parse", 1359 | "vte_generate_state_changes", 1360 | ] 1361 | 1362 | [[package]] 1363 | name = "vte_generate_state_changes" 1364 | version = "0.1.1" 1365 | source = "registry+https://github.com/rust-lang/crates.io-index" 1366 | checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" 1367 | dependencies = [ 1368 | "proc-macro2", 1369 | "quote", 1370 | ] 1371 | 1372 | [[package]] 1373 | name = "wasi" 1374 | version = "0.10.0+wasi-snapshot-preview1" 1375 | source = "registry+https://github.com/rust-lang/crates.io-index" 1376 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 1377 | 1378 | [[package]] 1379 | name = "wasi" 1380 | version = "0.11.0+wasi-snapshot-preview1" 1381 | source = "registry+https://github.com/rust-lang/crates.io-index" 1382 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1383 | 1384 | [[package]] 1385 | name = "wasm-bindgen" 1386 | version = "0.2.83" 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" 1388 | checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" 1389 | dependencies = [ 1390 | "cfg-if 1.0.0", 1391 | "wasm-bindgen-macro", 1392 | ] 1393 | 1394 | [[package]] 1395 | name = "wasm-bindgen-backend" 1396 | version = "0.2.83" 1397 | source = "registry+https://github.com/rust-lang/crates.io-index" 1398 | checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" 1399 | dependencies = [ 1400 | "bumpalo", 1401 | "log", 1402 | "once_cell", 1403 | "proc-macro2", 1404 | "quote", 1405 | "syn", 1406 | "wasm-bindgen-shared", 1407 | ] 1408 | 1409 | [[package]] 1410 | name = "wasm-bindgen-macro" 1411 | version = "0.2.83" 1412 | source = "registry+https://github.com/rust-lang/crates.io-index" 1413 | checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" 1414 | dependencies = [ 1415 | "quote", 1416 | "wasm-bindgen-macro-support", 1417 | ] 1418 | 1419 | [[package]] 1420 | name = "wasm-bindgen-macro-support" 1421 | version = "0.2.83" 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" 1423 | checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" 1424 | dependencies = [ 1425 | "proc-macro2", 1426 | "quote", 1427 | "syn", 1428 | "wasm-bindgen-backend", 1429 | "wasm-bindgen-shared", 1430 | ] 1431 | 1432 | [[package]] 1433 | name = "wasm-bindgen-shared" 1434 | version = "0.2.83" 1435 | source = "registry+https://github.com/rust-lang/crates.io-index" 1436 | checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" 1437 | 1438 | [[package]] 1439 | name = "winapi" 1440 | version = "0.3.9" 1441 | source = "registry+https://github.com/rust-lang/crates.io-index" 1442 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1443 | dependencies = [ 1444 | "winapi-i686-pc-windows-gnu", 1445 | "winapi-x86_64-pc-windows-gnu", 1446 | ] 1447 | 1448 | [[package]] 1449 | name = "winapi-i686-pc-windows-gnu" 1450 | version = "0.4.0" 1451 | source = "registry+https://github.com/rust-lang/crates.io-index" 1452 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1453 | 1454 | [[package]] 1455 | name = "winapi-util" 1456 | version = "0.1.5" 1457 | source = "registry+https://github.com/rust-lang/crates.io-index" 1458 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1459 | dependencies = [ 1460 | "winapi", 1461 | ] 1462 | 1463 | [[package]] 1464 | name = "winapi-x86_64-pc-windows-gnu" 1465 | version = "0.4.0" 1466 | source = "registry+https://github.com/rust-lang/crates.io-index" 1467 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1468 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cargo-rr" 3 | version = "0.3.0" 4 | authors = ["Daniel Franklin "] 5 | edition = "2018" 6 | description = "A light wrapper around rr, the time-travelling debugger" 7 | license = "MIT" 8 | keywords = ["rr", "debug", "debugger", "test"] 9 | categories = ["development-tools"] 10 | repository = "https://github.com/danielzfranklin/cargo-rr" 11 | 12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 13 | [dependencies] 14 | anyhow = "1.0.65" 15 | clap = { version = "3.2.22", features = ["derive"] } 16 | cargo_metadata = "0.15.0" 17 | camino = "1.1.1" 18 | ctrlc = "3.2.3" 19 | tracing = "0.1.36" 20 | tracing-subscriber = { version = "0.3.15", features = ["env-filter"] } 21 | seacan = "0.1.0" 22 | skim = "0.9.4" 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Daniel Franklin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cargo-rr 2 | 3 | ![Crates.io](https://img.shields.io/crates/v/cargo-rr) 4 | ![MIT Licensed](https://img.shields.io/crates/l/cargo-rr) 5 | 6 | A light wrapper around [`rr`](https://rr-project.org/), the time-travelling debugger. 7 | 8 | > Do you find yourself running the same test over and over in the debugger, 9 | > trying to figure out how the code got in a bad state? We have a tool for you! 10 | > Easy to install and setup, it will record an execution trace, and that gives 11 | > magical new powers to gdb. Step backwards, run backwards, see where variables 12 | > changed their value or when a function was last called on an object (using 13 | > conditional breakpoints). [(source)][about-quote-source] 14 | 15 | 16 | ## Example 17 | Suppose we ran a test `my_test` and got a failure. We first re-run the test under `rr` 18 | to record the entire execution (including everything else on your system the test 19 | interacts with). 20 | 21 | ```bash 22 | > cargo rr test my_test 23 | 24 | thread 'main' panicked at 'assertion failed: `(left == right)` 25 | left: `1`, 26 | right: `2`', tests/tests.rs:100 27 | 28 | test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.06s 29 | ``` 30 | 31 | Let's replay the recording. 32 | 33 | ```bash 34 | > cargo rr replay 35 | 36 | (rr) continue 37 | 38 | thread 'main' panicked at 'assertion failed: `(left == right)` 39 | left: `1`, 40 | right: `42`', tests/tests.rs:100 41 | 42 | test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.06s 43 | ``` 44 | 45 | We'll go backwards until we return to the failed assertion so we can have a look at `a` and `b`. 46 | 47 | ```bash 48 | (rr) break tests/tests.rs:100 49 | (rr) reverse-continue 50 | Continuing. 51 | 52 | Breakpoint 1, tests::main () at tests/tests.rs:100 53 | 100 assert_eq!(a, b); 54 | 55 | (rr) print a 56 | $1 = 1 57 | 58 | (rr) print b 59 | $2 = 42 60 | ``` 61 | 62 | I wonder where `a` is set to `1`? 63 | 64 | ```bash 65 | (rr) watch -l a 66 | (rr) reverse-continue 67 | 68 | Old value = 1 69 | New value = -1992923200 70 | 0x000055dcac485ed9 in tests::main () at tests/tests.rs:30 71 | 30 let a = some_calculation(); 72 | 73 | ``` 74 | 75 | Note that since we're going in reverse the old and new values are backwards. 76 | `-1992923200` is whatever used to be at the address `0x000055dcac485ed9` 77 | before it was used for `a`. 78 | 79 | ## Installation 80 | 81 | `cargo-rr` is a [custom cargo subcommand](custom-cargo-subcommands). It can be installed 82 | by installing the `cargo-rr` package from `crates.io`: just run 83 | ```bash 84 | cargo install cargo-rr 85 | ``` 86 | in a terminal. After installing you can run `cargo rr` in the terminal to access `cargo-rr`. 87 | ## Usage 88 | 89 | Run `cargo rr test` or `cargo rr run` with any options you'd normally give to `cargo test` or `cargo run`. For example, you might run `cargo rr test --test my_integration_test some_filter`. 90 | 91 | Once you've made a recording you can replay the last recording in a debugger with `cargo rr replay`. 92 | 93 | ### Advanced 94 | 95 | Use the options `--rr-opts=".."` and `--gdb-opts="..."` to pass custom options to rr and gdb, respectively. You are responsible for ensuring the options you pass don't conflict with the options we pass. You can see the options we pass in the source code. We don't promise any stability here, but you probably won't run into issues. 96 | 97 | Run `cargo rr help` to see the full usage. 98 | 99 | [about-quote-source]: https://developer.chrome.com/blog/chromium-chronicle-13/ 100 | [crates-io]: https://crates.io/crates/cargo-rr 101 | [custom-cargo-subcommands]: https://doc.rust-lang.org/stable/book/ch14-05-extending-cargo.html 102 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use camino::{Utf8Path, Utf8PathBuf}; 2 | use std::{ 3 | fs::{self, File}, 4 | io::{self, Read}, 5 | }; 6 | 7 | use anyhow::anyhow; 8 | 9 | mod list; 10 | mod record; 11 | mod replay; 12 | 13 | pub use list::list; 14 | pub use record::record; 15 | pub use replay::replay; 16 | 17 | pub struct Trace(Utf8PathBuf); 18 | 19 | impl Trace { 20 | pub fn new(name: &str) -> anyhow::Result { 21 | let root = traces_dir()?; 22 | let dir = root.join(name); 23 | if !dir.exists() { 24 | return Err(anyhow!("Trace `{}` does not exist in `{}`", name, root)); 25 | } 26 | Ok(Self(dir)) 27 | } 28 | 29 | fn name_for_bin(bin: &Utf8Path) -> anyhow::Result { 30 | let root = traces_dir()?; 31 | let bin_name = bin 32 | .file_name() 33 | .ok_or_else(|| anyhow!("Can't get file name of bin"))?; 34 | let mut dir = root.join(bin_name); 35 | 36 | let mut suffix = 0; 37 | loop { 38 | if !dir.exists() { 39 | break Ok(Self(dir)); 40 | } 41 | suffix += 1; 42 | dir.set_file_name(format!("{}-{}", bin_name, suffix)); 43 | } 44 | } 45 | 46 | pub fn name(&self) -> &str { 47 | &self.0.file_name().expect("Trace dir shouldn't end in ..") 48 | } 49 | 50 | pub fn dir(&self) -> &Utf8Path { 51 | self.0.as_path() 52 | } 53 | 54 | pub fn set_latest(&self) -> anyhow::Result<()> { 55 | let root = self.0.parent().expect("Trace has parent"); 56 | fs::write(root.join("latest"), self.name())?; 57 | Ok(()) 58 | } 59 | 60 | pub fn latest() -> anyhow::Result { 61 | let root = traces_dir()?; 62 | let mut file = match File::open(root.join("latest")) { 63 | Ok(f) => f, 64 | Err(err) if err.kind() == io::ErrorKind::NotFound => { 65 | return Err(anyhow!("No trace in `{}`", root)); 66 | } 67 | Err(err) => return Err(err.into()), 68 | }; 69 | let mut latest = String::new(); 70 | file.read_to_string(&mut latest)?; 71 | let latest = latest.trim(); 72 | let latest = fs::canonicalize(root.join(latest))?; 73 | let latest = Utf8PathBuf::from_path_buf(latest) 74 | .map_err(|_| anyhow!("Path to target dir must be utf-8"))?; 75 | Ok(Self(latest)) 76 | } 77 | } 78 | 79 | pub fn traces_dir() -> anyhow::Result { 80 | let meta = cargo_metadata::MetadataCommand::new().no_deps().exec()?; 81 | let dir = meta.target_directory.join("rr"); 82 | fs::create_dir_all(&dir)?; 83 | Ok(dir) 84 | } 85 | 86 | pub fn split_opts(opts: Option<&str>) -> Vec<&str> { 87 | opts.map_or_else(Vec::new, |s| s.split(' ').collect()) 88 | } 89 | -------------------------------------------------------------------------------- /src/list.rs: -------------------------------------------------------------------------------- 1 | use anyhow::anyhow; 2 | use std::fs; 3 | 4 | use crate::traces_dir; 5 | 6 | pub fn list() -> anyhow::Result<()> { 7 | let root = traces_dir()?; 8 | let mut items = Vec::new(); 9 | 10 | for entry in fs::read_dir(root)? { 11 | let entry = entry?; 12 | if entry.file_type()?.is_dir() { 13 | let name = entry.file_name(); 14 | let name = name 15 | .to_str() 16 | .ok_or_else(|| anyhow!("Trace name not valid unicode"))?; 17 | let created = entry.metadata()?.created()?; 18 | items.push((created, name.to_owned())); 19 | } 20 | } 21 | 22 | items.sort_by(|(a, _), (b, _)| a.cmp(&b)); 23 | 24 | for (_, name) in items { 25 | println!("{}", name); 26 | } 27 | 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![warn(clippy::all, clippy::pedantic, clippy::cargo)] 2 | 3 | use std::{borrow::Cow, sync::Arc}; 4 | 5 | use anyhow::anyhow; 6 | use clap::{AppSettings, Parser, Subcommand}; 7 | use seacan::{bin, test, CompilerMessage, ExecutableArtifact, FeatureSpec, PackageSpec}; 8 | #[allow(unused)] 9 | use tracing::{debug, error, info, warn}; 10 | 11 | use cargo_rr::{list, record, replay, Trace}; 12 | 13 | #[derive(Parser, Debug)] 14 | #[clap(bin_name = "cargo", about, author)] 15 | enum OptWrapper { 16 | #[clap(subcommand, name = "rr")] 17 | Opt(Opt), 18 | } 19 | 20 | #[derive(Subcommand, Debug)] 21 | #[clap(about, author)] 22 | enum Opt { 23 | #[clap(about = "Record a binary or example")] 24 | Run(RunOpt), 25 | #[clap(about = "Record a test")] 26 | Test(TestOpt), 27 | #[clap(about = "Replay a trace")] 28 | Replay(ReplayOpt), 29 | #[clap(about = "List traces")] 30 | Ls, 31 | } 32 | 33 | #[derive(Parser, Debug)] 34 | #[clap(setting(AppSettings::TrailingVarArg))] 35 | #[clap(setting(AppSettings::AllowHyphenValues))] 36 | struct RunOpt { 37 | #[clap(long)] 38 | bin: Option, 39 | #[clap(long)] 40 | example: Option, 41 | #[clap(long)] 42 | all_features: bool, 43 | #[clap(long)] 44 | no_default_features: bool, 45 | #[clap(long)] 46 | features: Vec, 47 | #[clap(long)] 48 | release: bool, 49 | #[clap(long)] 50 | package: Option, 51 | #[clap( 52 | long, 53 | require_equals(true), 54 | help = r#"Space-separated options to pass to `rr record` (e.g `--rr-opts="--chaos -M"`). See `rr record -h`"# 55 | )] 56 | rr_opts: Option, 57 | #[clap(last = true)] 58 | args: Vec, 59 | } 60 | 61 | #[allow(clippy::struct_excessive_bools)] 62 | #[derive(Parser, Debug)] 63 | #[clap(setting(AppSettings::AllowHyphenValues))] 64 | struct TestOpt { 65 | name: Option, 66 | #[clap(long, help = "Match name exactly")] 67 | exact: bool, 68 | #[clap(long)] 69 | lib: bool, 70 | #[clap(long)] 71 | bin: Option, 72 | #[clap(long)] 73 | bins: bool, 74 | #[clap( 75 | long, 76 | help = "Test only the specified integration test (i.e. file in tests/)" 77 | )] 78 | test: Option, 79 | #[clap(long)] 80 | tests: bool, 81 | #[clap(long)] 82 | example: Option, 83 | #[clap(long)] 84 | examples: bool, 85 | #[clap(long)] 86 | doc: bool, 87 | #[clap(long)] 88 | all_features: bool, 89 | #[clap(long)] 90 | no_default_features: bool, 91 | #[clap(long)] 92 | features: Vec, 93 | #[clap(long)] 94 | release: bool, 95 | #[clap(long)] 96 | package: Option, 97 | #[clap( 98 | long, 99 | require_equals(true), 100 | help = r#"Space-separated options to pass to `rr record` (e.g `--rr-opts="--chaos -M"`). See `rr record -h`"# 101 | )] 102 | rr_opts: Option, 103 | } 104 | 105 | #[derive(Parser, Debug)] 106 | #[clap(setting(AppSettings::AllowHyphenValues))] 107 | struct ReplayOpt { 108 | #[clap(help = "Leave blank to replay the last trace recorded")] 109 | trace: Option, 110 | #[clap( 111 | long, 112 | require_equals(true), 113 | help = "Space-separated options to pass to `rr replay`. See `rr replay -h`" 114 | )] 115 | rr_opts: Option, 116 | #[clap(long, require_equals(true), help = "Options to pass to rust-gdb")] 117 | gdb_opts: Option, 118 | } 119 | 120 | fn main() -> anyhow::Result<()> { 121 | if let Err(err) = handle_opts() { 122 | println!(); // to separate is_test_artifactour output from anything cargo outputs 123 | return Err(err); 124 | } 125 | Ok(()) 126 | } 127 | 128 | fn handle_opts() -> anyhow::Result<()> { 129 | tracing_subscriber::fmt() 130 | .with_env_filter(tracing_subscriber::EnvFilter::from_env("CARGO_RR_LOG")) 131 | .init(); 132 | 133 | let OptWrapper::Opt(opt) = OptWrapper::from_args(); 134 | 135 | debug!(?opt, "Parsed options"); 136 | 137 | match opt { 138 | Opt::Run(opt) => { 139 | handle_run(opt)?; 140 | } 141 | Opt::Test(opt) => { 142 | handle_test(opt)?; 143 | } 144 | Opt::Replay(opt) => { 145 | handle_replay(opt)?; 146 | } 147 | Opt::Ls => list()?, 148 | } 149 | 150 | Ok(()) 151 | } 152 | 153 | fn handle_run(opt: RunOpt) -> anyhow::Result<()> { 154 | let package = opt.package.map_or(PackageSpec::Any, PackageSpec::Name); 155 | 156 | let features = parse_features(opt.all_features, opt.no_default_features, opt.features)?; 157 | 158 | let mut compiler = match (opt.bin, opt.example) { 159 | (Some(bin), None) => bin::Compiler::bin(bin), 160 | (None, Some(example)) => bin::Compiler::example(example), 161 | (None, None) => todo!("Run default bin"), 162 | (Some(_), Some(_)) => return Err(anyhow!("You cannot specify both --bin and --example")), 163 | }; 164 | 165 | eprintln!("Compiling..."); 166 | let artifact = compiler 167 | .package(package) 168 | .release(opt.release) 169 | .features(features) 170 | .on_compiler_msg(on_compiler_msg) 171 | .compile()?; 172 | 173 | let trace = record(artifact.executable, opt.rr_opts.as_deref(), &opt.args)?; 174 | print_replay_howto(&trace); 175 | Ok(()) 176 | } 177 | 178 | fn handle_test(opt: TestOpt) -> anyhow::Result<()> { 179 | let (rr_opts, mut compiler) = configure_test_compiler(opt)?; 180 | eprintln!("Compiling..."); 181 | let artifacts = compiler.on_compiler_msg(on_compiler_msg).compile()?; 182 | 183 | let mut specs = Vec::new(); 184 | for artifact in artifacts { 185 | let tests = artifact.tests; 186 | let artifact = Arc::new(artifact.artifact); 187 | for test in tests { 188 | let spec = TestSpec { 189 | test, 190 | artifact: artifact.clone(), 191 | }; 192 | specs.push(spec); 193 | } 194 | } 195 | 196 | let selected = select_test_spec(specs)?; 197 | 198 | let trace = record( 199 | selected.artifact.executable.clone(), 200 | rr_opts.as_deref(), 201 | &selected.test.run_args(), 202 | )?; 203 | print_replay_howto(&trace); 204 | Ok(()) 205 | } 206 | 207 | #[derive(Clone, Debug)] 208 | struct TestSpec { 209 | test: test::TestFn, 210 | artifact: Arc, 211 | } 212 | 213 | impl skim::SkimItem for TestSpec { 214 | fn text(&self) -> Cow { 215 | Cow::Owned(format!( 216 | "{}::{} ({})", 217 | self.artifact.target.name, self.test.name, self.test.test_type 218 | )) 219 | } 220 | } 221 | 222 | fn select_test_spec(mut specs: Vec) -> anyhow::Result { 223 | use skim::prelude::*; 224 | 225 | if specs.is_empty() { 226 | return Err(anyhow!("No matching test or benchmark functions")); 227 | } 228 | if specs.len() == 1 { 229 | return Ok(specs.pop().unwrap()); 230 | } 231 | 232 | let skim_opts = SkimOptionsBuilder::default() 233 | .height(Some("50%")) 234 | .build() 235 | .map_err(|e| anyhow!("skim: {}", e))?; 236 | 237 | let (tx, rx): (SkimItemSender, SkimItemReceiver) = unbounded(); 238 | for spec in specs { 239 | tx.send(Arc::new(spec))?; 240 | } 241 | drop(tx); 242 | 243 | let mut selected = Skim::run_with(&skim_opts, Some(rx)) 244 | .map(|o| { 245 | if o.is_abort { 246 | Vec::new() 247 | } else { 248 | o.selected_items 249 | } 250 | }) 251 | .unwrap_or_default(); 252 | if selected.is_empty() { 253 | return Err(anyhow!("No test selected")); 254 | } 255 | if selected.len() > 1 { 256 | panic!("Should have been impossible to select more than one test"); 257 | } 258 | let selected = &*selected.pop().unwrap(); 259 | if let Some(selected) = selected.as_any().downcast_ref::() { 260 | Ok(selected.clone()) 261 | } else { 262 | Err(anyhow!("No test selected")) 263 | } 264 | } 265 | 266 | fn configure_test_compiler(opt: TestOpt) -> anyhow::Result<(Option, test::Compiler)> { 267 | use test::{NameSpec, TypeSpec}; 268 | 269 | let name = match (opt.name, opt.exact) { 270 | (Some(name), true) => NameSpec::Exact(name), 271 | (Some(name), false) => NameSpec::Substring(name), 272 | (None, true) => return Err(anyhow!("Cannot specify --exact without specifying a name")), 273 | (None, false) => NameSpec::Any, 274 | }; 275 | 276 | let mut test_type = None; 277 | let require_tt_unset = |tt: &Option| { 278 | if tt.is_some() { 279 | Err(anyhow!( 280 | "Only one type of test can be specified (--lib, --bins, etc)" 281 | )) 282 | } else { 283 | Ok(()) 284 | } 285 | }; 286 | if opt.lib { 287 | require_tt_unset(&test_type)?; 288 | test_type = Some(TypeSpec::Lib); 289 | } 290 | if let Some(name) = opt.bin { 291 | require_tt_unset(&test_type)?; 292 | test_type = Some(TypeSpec::Bin(name)); 293 | } 294 | if opt.bins { 295 | require_tt_unset(&test_type)?; 296 | test_type = Some(TypeSpec::Bins); 297 | } 298 | if let Some(name) = opt.test { 299 | require_tt_unset(&test_type)?; 300 | test_type = Some(TypeSpec::Integration(name)); 301 | } 302 | if opt.tests { 303 | require_tt_unset(&test_type)?; 304 | test_type = Some(TypeSpec::Integrations); 305 | } 306 | if let Some(name) = opt.example { 307 | require_tt_unset(&test_type)?; 308 | test_type = Some(TypeSpec::Example(name)); 309 | } 310 | if opt.examples { 311 | require_tt_unset(&test_type)?; 312 | test_type = Some(TypeSpec::Examples); 313 | } 314 | if opt.doc { 315 | require_tt_unset(&test_type)?; 316 | test_type = Some(TypeSpec::Doc); 317 | } 318 | let test_type = test_type.unwrap_or(TypeSpec::Unspecified); 319 | 320 | let package = opt.package.map_or(PackageSpec::Any, PackageSpec::Name); 321 | let features = parse_features(opt.all_features, opt.no_default_features, opt.features)?; 322 | 323 | let mut compiler = test::Compiler::new(name, test_type); 324 | compiler 325 | .package(package) 326 | .release(opt.release) 327 | .features(features); 328 | Ok((opt.rr_opts, compiler)) 329 | } 330 | 331 | fn parse_features( 332 | all: bool, 333 | no_default: bool, 334 | features: Vec, 335 | ) -> anyhow::Result { 336 | match (all, no_default) { 337 | (true, false) => { 338 | if features.is_empty() { 339 | Ok(FeatureSpec::all()) 340 | } else { 341 | Err(anyhow!( 342 | "You cannot specify both --all-features and --features" 343 | )) 344 | } 345 | } 346 | (true, true) => Err(anyhow!( 347 | "You cannot specify both --all-features and --no-default-features" 348 | )), 349 | (false, true) => Ok(FeatureSpec::new_no_default(features)), 350 | (false, false) => Ok(FeatureSpec::new(features)), 351 | } 352 | } 353 | 354 | fn on_compiler_msg(msg: CompilerMessage) { 355 | if let Some(rendered) = msg.message.rendered { 356 | eprintln!("{}", rendered); 357 | } 358 | } 359 | 360 | fn handle_replay(opt: ReplayOpt) -> anyhow::Result<()> { 361 | let trace = opt.trace.map_or_else(Trace::latest, |s| Trace::new(&s))?; 362 | replay(trace, opt.rr_opts.as_deref(), opt.gdb_opts.as_deref())?; 363 | Ok(()) 364 | } 365 | 366 | fn print_replay_howto(trace: &Trace) { 367 | eprintln!( 368 | "\nTrace {} recorded.\nRun `cargo rr replay` to debug the latest trace", 369 | trace.name() 370 | ); 371 | } 372 | -------------------------------------------------------------------------------- /src/record.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | use anyhow::Context; 4 | use camino::Utf8PathBuf; 5 | use tracing::debug; 6 | 7 | use crate::{split_opts, Trace}; 8 | 9 | pub fn record(bin: Utf8PathBuf, rr_opts: Option<&str>, args: &[String]) -> anyhow::Result { 10 | debug!(?bin, ?args, "Recording"); 11 | 12 | let trace = Trace::name_for_bin(&bin)?; 13 | 14 | let mut cmd = Command::new("rr") 15 | .arg("record") 16 | .args(&split_opts(rr_opts)) 17 | .args(&["--output-trace-dir", trace.0.as_str()]) 18 | .arg(bin) 19 | .args(args) 20 | .spawn() 21 | .context("Failed to run rr")?; 22 | 23 | trace.set_latest()?; 24 | 25 | let status = cmd.wait()?; 26 | if !status.success() { 27 | // Not an error as this might just mean the recorded program failed 28 | println!("cargo-rr: `rr record` exited with status {}", status); 29 | } 30 | 31 | Ok(trace) 32 | } 33 | -------------------------------------------------------------------------------- /src/replay.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | use anyhow::{anyhow, Context}; 4 | 5 | use crate::{split_opts, Trace}; 6 | 7 | pub fn replay(trace: Trace, rr_opts: Option<&str>, gdb_opts: Option<&str>) -> anyhow::Result<()> { 8 | // Ignore, as gdb handles 9 | ctrlc::set_handler(|| {})?; 10 | 11 | let mut gdb_opts = split_opts(gdb_opts); 12 | gdb_opts.push("--quiet"); 13 | 14 | let mut cmd = Command::new("rr") 15 | .arg("replay") 16 | .args(split_opts(rr_opts)) 17 | .args(&["-d", "rust-gdb"]) 18 | .arg(trace.dir()) 19 | .arg("--") 20 | .args(gdb_opts) 21 | .spawn() 22 | .context("Failed to run rr")?; 23 | 24 | let status = cmd.wait()?; 25 | if !status.success() { 26 | return Err(anyhow!( 27 | "cargo-rr: `rr replay` exited with status {}", 28 | status 29 | )); 30 | } 31 | 32 | Ok(()) 33 | } 34 | --------------------------------------------------------------------------------