From 72bf299f9c7cb48e5a6d59bd06bdddbb4419bbb1 Mon Sep 17 00:00:00 2001 From: Patrick Nordahl Date: Wed, 20 Nov 2024 09:10:59 -0600 Subject: [PATCH] Fix checkpoint update noargs (#33) * remove autohelp when checkpoint update is run without args * various fixes * add cargo.lock * clippy ci issue * rustflags ci issues --- .github/workflows/branch.yml | 8 +- .gitignore | 5 - CHANGELOG.md | 20 +- Cargo.lock | 1044 ++++++++++++++++++++++++++++++++++ Cargo.toml | 7 +- README.md | 2 +- TUTORIAL.md | 40 +- src/api/cli.rs | 7 +- src/app/analyze.rs | 13 +- src/app/checkpoint.rs | 21 +- src/app/log.rs | 33 +- src/app/run.rs | 32 +- src/core/error.rs | 11 +- src/core/file.rs | 3 +- src/core/git.rs | 132 ++--- src/core/testing.rs | 2 +- 16 files changed, 1227 insertions(+), 153 deletions(-) create mode 100644 Cargo.lock diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 0b6ad77..0203393 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -20,11 +20,13 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + rustflags: "" - run: | sudo chown -R $USER:$USER ${{ github.workspace }} mkdir -p "$MONORAIL_TEST_DIR" git config --global user.name "FIRST_NAME LAST_NAME" git config --global user.email "MY_NAME@example.com" - - run: cargo clippy -- -D warnings - - run: cargo build --verbose --all - - run: cargo test -- --nocapture + - run: cargo clippy --locked -- -D warnings + - run: cargo build --locked --verbose --all + - run: cargo test --locked -- --nocapture diff --git a/.gitignore b/.gitignore index 5a6d384..465d0b9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,14 +2,9 @@ # will have compiled files and executables /target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - # These are backup files generated by rustfmt **/*.rs.bk - #Added by cargo # #already existing elements are commented out diff --git a/CHANGELOG.md b/CHANGELOG.md index 3563eb6..7c1143b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,24 @@ # Change Log -## [3.5.3] - 2024-11-17 +## [3.5.4] - 2024-11-20 + +### Added +- `checkpointed` boolean on `run` and `analyze` output, indicating if the checkpoint was used + +### Fixed +- `checkpoint update` run without args always forced a help message + +### Changed +- `analyze` and `run` no longer query the change provider when a checkpoint does not exist +- `--changes` and `--change-targets` flags on `analyze` are disabled if no checkpoint is available to guide change detection +- (internal) `Cargo.lock` to git +- (internal) Removed `hex` dependency +- (internal) Removed `flume` dependency +- (internal) Changed resolver to "2" +- (internal) Update CI to use locked cargo commands + + +## [3.5.3] - 2024-11-19 ### Added - `config generate` API for generating a configuration file that is synchronized with its source file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7b743d4 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1044 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "cc" +version = "1.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e804ac3194a48bb129643eb1d62fcc20d18c6b8c181704489353d13120bcd1" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "num-traits", +] + +[[package]] +name = "clap" +version = "4.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fid-rs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6956a1e60e2d1412b44b4169d44a03dae518f8583d3e10090c912c105e48447" +dependencies = [ + "rayon", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "louds-rs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936de6c22f08e7135a921f8ada907acd0d88880c4f42b5591f634b9f1dd8e07f" +dependencies = [ + "fid-rs", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "monorail" +version = "3.5.4" +dependencies = [ + "chrono", + "clap", + "once_cell", + "serde", + "serde_json", + "sha2", + "tempfile", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", + "tracing-subscriber", + "trie-rs", + "zstd", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.209" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.209" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "time", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "trie-rs" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f88f4b0a1ebd6c3d16be3e45eb0e8089372ccadd88849b7ca162ba64b5e6f6" +dependencies = [ + "louds-rs", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 3b34ee1..c89558a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,10 +4,11 @@ description = "A tool for effective polyglot, multi-project monorepo development license = "MIT" homepage = "https://github.com/pnordahl/monorail" repository = "https://github.com/pnordahl/monorail" -version = "3.5.3" +version = "3.5.4" authors = ["Patrick Nordahl "] edition = "2021" keywords = ["monorail", "monorepo", "build", "cli", "build-tool"] +resolver = "2" [dependencies] clap = "4.5" @@ -18,13 +19,11 @@ tokio = { version = "1.40", features = ["net", "fs", "io-std", "io-util", "proce tokio-util = { version = "0.7" } tokio-stream = "0.1.16" sha2 = "0.10" -hex = "0.4" zstd = "0.13.2" -flume = "0.11.1" tracing = { version = "0.1.40", features = ["attributes"] } tracing-subscriber = { version = "0.3.18", features = ["time", "fmt", "std", "registry", "json", "env-filter"] } once_cell = "1.20.2" chrono = { version = "0.4.38", default-features = false, features = ["alloc", "now", "std"] } [dev-dependencies] -tempfile = "3.13" \ No newline at end of file +tempfile = "3.13" diff --git a/README.md b/README.md index c4316c6..c7580b1 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ At this time, Windows is unsupported. However, there are no technical limitation ## Overview -`monorail` blends features of build systems like `bazel` and `buck` with the simplicity and flexibility of command runners like `make` and `just`. It manages dependencies and target mapping with `bazel`-like change tracking, enabling selective rebuilds and efficient parallel execution. Additionally, `monorail` provides a CLI-driven workflow for running custom code in any language across any subset of your monorepo. +`monorail` blends features of build systems like `bazel` and `buck` with the simplicity and flexibility of command runners like `make` and `just` to create a lightweight monorepo development system. It combines a graph representation of your repository with incremental change tracking, enabling guided and efficient parallel execution across any subset of your monorepo. `monorail` is internally driven by two things: diff --git a/TUTORIAL.md b/TUTORIAL.md index d9d6bbc..eac6ca0 100644 --- a/TUTORIAL.md +++ b/TUTORIAL.md @@ -209,7 +209,8 @@ monorail run -c hello -t rust | jq } ] } - ] + ], + "checkpointed": true } ``` @@ -243,11 +244,12 @@ monorail analyze | jq "proto", "python/app3", "rust" - ] + ], + "checkpointed": true } ``` -This indicates that based on our current changeset and graph, all three targets have changed. Display more information about the specific changes causing these targets to appear by adding `--change-targets`: +This indicates that based on our current changeset and graph, all three targets have changed. The `checkpointed` field indicates if a checkpoint (explained in a later section) was used to obtain changes from the change provider. If the checkpoint is not present, this will be `false`. Display more information about the specific changes causing these targets to appear by adding `--change-targets`: ```sh monorail analyze --changes | jq ``` @@ -259,7 +261,8 @@ monorail analyze --changes | jq "proto", "python/app3", "rust" - ] + ], + "checkpointed": true } ``` @@ -319,7 +322,9 @@ monorail analyze --changes | jq "proto", "python/app3", "rust" - + ], + "checkpointed": true +} ``` ### Ignoring with 'ignores' @@ -356,7 +361,8 @@ monorail analyze --target-groups | jq "rust", "python/app3" ] - ] + ], + "checkpointed": true } ``` @@ -400,7 +406,8 @@ monorail analyze --target-groups | jq "rust", "python/app3" ] - ] + ], + "checkpointed": true } ``` @@ -450,7 +457,8 @@ monorail result show | jq } ] } - ] + ], + "checkpointed": true } ``` @@ -536,7 +544,7 @@ As this command executes, you'll see internal progress due to the inclusion of t {"timestamp":"2024-11-10T11:16:48.802646+00:00","level":"INFO","message":"processing targets","num":1,"command":"hello"} {"timestamp":"2024-11-10T11:16:48.802652+00:00","level":"INFO","message":"task","status":"scheduled","command":"hello","target":"rust"} {"timestamp":"2024-11-10T11:16:49.372712+00:00","level":"INFO","message":"task","status":"success","command":"hello","target":"rust"} -{"timestamp":"2024-11-10T11:16:49.373482+00:00","failed":false,"invocation":"-v run -c hello -t rust","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/3","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{"rust":"521fe5c9ece1aa1f8b66228171598263574aefc6fa4ba06a61747ec81ee9f5a3"}}},"results":[{"command":"hello","target_groups":[{"rust":{"status":"success","code":0,"runtime_secs":0.57000625}}]}] +{"timestamp":"2024-11-10T11:16:49.373482+00:00","checkpointed":false,"failed":false,"invocation":"-v run -c hello -t rust","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/3","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{"rust":"521fe5c9ece1aa1f8b66228171598263574aefc6fa4ba06a61747ec81ee9f5a3"}}},"results":[{"command":"hello","target_groups":[{"rust":{"status":"success","code":0,"runtime_secs":0.57000625}}]}] ``` ... as well as log statements from the command itself in your log tailing window: @@ -651,7 +659,8 @@ monorail analyze --target-groups | jq "rust", "python/app3" ] - ] + ], + "checkpointed": true } ``` @@ -677,7 +686,7 @@ monorail -v run -c hello {"timestamp":"2024-11-10T11:21:10.121846+00:00","level":"INFO","message":"task","status":"scheduled","command":"hello","target":"python/app3"} {"timestamp":"2024-11-10T11:21:10.144093+00:00","level":"INFO","message":"task","status":"success","command":"hello","target":"python/app3"} {"timestamp":"2024-11-10T11:21:10.685876+00:00","level":"INFO","message":"task","status":"success","command":"hello","target":"rust"} -{"timestamp":"2024-11-10T11:21:10.687816+00:00","failed":false,"invocation":"-v run -c hello","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/6","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{"python/app3":"585b3a9bcac009158d3e5df009aab9e31ab98ee466a2e818a8753736aefdfda7","proto":"1cafa6d851c65817d04c841673d025dcf4ed498435407058d3a36608d17e32b6","rust":"521fe5c9ece1aa1f8b66228171598263574aefc6fa4ba06a61747ec81ee9f5a3"}}},"results":[{"command":"hello","target_groups":[{"proto":{"status":"success","code":0,"runtime_secs":0.001930458}},{"python/app3":{"status":"success","code":0,"runtime_secs":0.02222046},"rust":{"status":"success","code":0,"runtime_secs":0.56421417}}]}]} +{"timestamp":"2024-11-10T11:21:10.687816+00:00","checkpointed":true,"failed":false,"invocation":"-v run -c hello","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/6","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{"python/app3":"585b3a9bcac009158d3e5df009aab9e31ab98ee466a2e818a8753736aefdfda7","proto":"1cafa6d851c65817d04c841673d025dcf4ed498435407058d3a36608d17e32b6","rust":"521fe5c9ece1aa1f8b66228171598263574aefc6fa4ba06a61747ec81ee9f5a3"}}},"results":[{"command":"hello","target_groups":[{"proto":{"status":"success","code":0,"runtime_secs":0.001930458}},{"python/app3":{"status":"success","code":0,"runtime_secs":0.02222046},"rust":{"status":"success","code":0,"runtime_secs":0.56421417}}]}]} ``` In this sequence of events: the `hello` command is scheduled and executed to completion for `proto` prior to the same for `python/app3` and `rust`. This is because both of the latter depend on `proto`. A practical scenario where this is relevant is building protobuf files for use by both `python/app3` and `rust`. By encoding this dependency in `Monorail.json`, we have ensured that when protobuf files in `proto` change, we have definitely compiled them by the time we execute commands for `python/app3` and `rust`. @@ -706,7 +715,7 @@ monorail -v run -c hello build {"timestamp":"2024-11-10T11:21:41.345703+00:00","level":"INFO","message":"processing targets","num":2,"command":"build"} {"timestamp":"2024-11-10T11:21:41.345719+00:00","level":"INFO","message":"task","status":"undefined","command":"build","target":"rust"} {"timestamp":"2024-11-10T11:21:41.345729+00:00","level":"INFO","message":"task","status":"undefined","command":"build","target":"python/app3"} -{"timestamp":"2024-11-10T11:21:41.347199+00:00","failed":false,"invocation":"-v run -c hello build","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/7","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{"rust":"521fe5c9ece1aa1f8b66228171598263574aefc6fa4ba06a61747ec81ee9f5a3","python/app3":"585b3a9bcac009158d3e5df009aab9e31ab98ee466a2e818a8753736aefdfda7","proto":"1cafa6d851c65817d04c841673d025dcf4ed498435407058d3a36608d17e32b6"}}},"results":[{"command":"hello","target_groups":[{"proto":{"status":"success","code":0,"runtime_secs":0.001693833}},{"python/app3":{"status":"success","code":0,"runtime_secs":0.02183325},"rust":{"status":"success","code":0,"runtime_secs":0.5603645}}]},{"command":"build","target_groups":[{"proto":{"status":"undefined"}},{"python/app3":{"status":"undefined"},"rust":{"status":"undefined"}}]}]} +{"timestamp":"2024-11-10T11:21:41.347199+00:00","checkpointed":true,"failed":false,"invocation":"-v run -c hello build","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/7","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{"rust":"521fe5c9ece1aa1f8b66228171598263574aefc6fa4ba06a61747ec81ee9f5a3","python/app3":"585b3a9bcac009158d3e5df009aab9e31ab98ee466a2e818a8753736aefdfda7","proto":"1cafa6d851c65817d04c841673d025dcf4ed498435407058d3a36608d17e32b6"}}},"results":[{"command":"hello","target_groups":[{"proto":{"status":"success","code":0,"runtime_secs":0.001693833}},{"python/app3":{"status":"success","code":0,"runtime_secs":0.02183325},"rust":{"status":"success","code":0,"runtime_secs":0.5603645}}]},{"command":"build","target_groups":[{"proto":{"status":"undefined"}},{"python/app3":{"status":"undefined"},"rust":{"status":"undefined"}}]}]} ``` You might notice the exit code of 0 and `"failed":false`, and that's because by default it is not required for a target to define a command. You can override this behavior with `--fail-on-undefined`, but in general this allows targets to define only the commands they need and eliminates the need for "stubs" that may never be implemented. @@ -750,7 +759,7 @@ monorail -v run -s dev {"timestamp":"2024-11-10T11:23:31.231144+00:00","level":"INFO","message":"processing targets","num":2,"command":"build"} {"timestamp":"2024-11-10T11:23:31.231158+00:00","level":"INFO","message":"task","status":"undefined","command":"build","target":"rust"} {"timestamp":"2024-11-10T11:23:31.231171+00:00","level":"INFO","message":"task","status":"undefined","command":"build","target":"python/app3"} -{"timestamp":"2024-11-10T11:23:31.232863+00:00","failed":false,"invocation":"-v run -s dev","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/8","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{"proto":"1cafa6d851c65817d04c841673d025dcf4ed498435407058d3a36608d17e32b6","rust":"521fe5c9ece1aa1f8b66228171598263574aefc6fa4ba06a61747ec81ee9f5a3","python/app3":"585b3a9bcac009158d3e5df009aab9e31ab98ee466a2e818a8753736aefdfda7"}}},"results":[{"command":"hello","target_groups":[{"proto":{"status":"success","code":0,"runtime_secs":0.00200725}},{"python/app3":{"status":"success","code":0,"runtime_secs":0.023067666},"rust":{"status":"success","code":0,"runtime_secs":0.56926215}}]},{"command":"build","target_groups":[{"proto":{"status":"undefined"}},{"rust":{"status":"undefined"},"python/app3":{"status":"undefined"}}]}]} +{"timestamp":"2024-11-10T11:23:31.232863+00:00","checkpointed":true,"failed":false,"invocation":"-v run -s dev","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/8","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{"proto":"1cafa6d851c65817d04c841673d025dcf4ed498435407058d3a36608d17e32b6","rust":"521fe5c9ece1aa1f8b66228171598263574aefc6fa4ba06a61747ec81ee9f5a3","python/app3":"585b3a9bcac009158d3e5df009aab9e31ab98ee466a2e818a8753736aefdfda7"}}},"results":[{"command":"hello","target_groups":[{"proto":{"status":"success","code":0,"runtime_secs":0.00200725}},{"python/app3":{"status":"success","code":0,"runtime_secs":0.023067666},"rust":{"status":"success","code":0,"runtime_secs":0.56926215}}]},{"command":"build","target_groups":[{"proto":{"status":"undefined"}},{"rust":{"status":"undefined"},"python/app3":{"status":"undefined"}}]}]} ``` When you run a sequence, it is first expanded into the commands it maps to. Then, any commands provided with `--commands` or `-c` are added to this list. For example, `monorail run -s dev -c foo bar` is equivalent to `monorail run -c hello build foo bar`. Sequences are useful for defining commands for use in specific contexts, such as setting up a repository for a new user, general development, and CI/CD. @@ -874,7 +883,8 @@ monorail analyze | jq ```json { "timestamp": "2024-11-10T11:24:30.349076+00:00", - "targets": [] + "targets": [], + "checkpointed": true } ``` @@ -889,7 +899,7 @@ monorail -v run -c hello build {"timestamp":"2024-11-10T11:25:21.766272+00:00","level":"INFO","message":"processing commands","num":2} {"timestamp":"2024-11-10T11:25:21.766282+00:00","level":"INFO","message":"processing target groups","num":0,"command":"hello"} {"timestamp":"2024-11-10T11:25:21.766285+00:00","level":"INFO","message":"processing target groups","num":0,"command":"build"} -{"timestamp":"2024-11-10T11:25:21.766730+00:00","failed":false,"invocation":"-v run -c hello build","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/9","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{}}},"results":[{"command":"hello","target_groups":[]},{"command":"build","target_groups":[]}]} +{"timestamp":"2024-11-10T11:25:21.766730+00:00","checkpointed":true,"failed":false,"invocation":"-v run -c hello build","out":{"run":{"path":"/private/tmp/monorail-tutorial/monorail-out/run/9","files":{"result":"result.json.zst","stdout":"stdout.zst","stderr":"stderr.zst"},"targets":{}}},"results":[{"command":"hello","target_groups":[]},{"command":"build","target_groups":[]}]} ``` You can also freely `monorail checkpoint delete` and essentially bypass change detection entirely, causing all targets will be considered changed. You can also manually set the checkpoint with `monorail checkpoint update -i `, where `` is a change provider reference (e.g. for git, this is usually a commit SHA). diff --git a/src/api/cli.rs b/src/api/cli.rs index 0cbc961..16c6cdc 100644 --- a/src/api/cli.rs +++ b/src/api/cli.rs @@ -169,7 +169,6 @@ pub fn build() -> clap::Command { Command::new(CMD_UPDATE) .about("Update the tracking checkpoint") .after_help(r#"This command updates the tracking checkpoint with data appropriate for the configured vcs."#) - .arg_required_else_help(true) .arg(arg_git_path.clone()) .arg( Arg::new(ARG_PENDING) @@ -412,7 +411,7 @@ See `monorail run -h` for information on how this interacts with other arg-relat .arg( Arg::new(ARG_CHANGES) .long(ARG_CHANGES) - .help("Display changes") + .help("Displays detailed information about changes. If no checkpoint is available to guide change detection, this flag is ignored.") .action(ArgAction::SetTrue) .default_value_if(ARG_CHANGE_TARGETS, ArgPredicate::IsPresent, Some("true")) .default_value_if(ARG_ALL, ArgPredicate::IsPresent, Some("true")), @@ -420,14 +419,14 @@ See `monorail run -h` for information on how this interacts with other arg-relat .arg( Arg::new(ARG_CHANGE_TARGETS) .long(ARG_CHANGE_TARGETS) - .help("Display targets for each change") + .help("For each change, display the targets affected. If no checkpoint is available to guide change detection, this flag is ignored.") .action(ArgAction::SetTrue) .default_value_if(ARG_ALL, ArgPredicate::IsPresent, Some("true")), ) .arg( Arg::new(ARG_TARGET_GROUPS) .long(ARG_TARGET_GROUPS) - .help("Display targets grouped according to the dependency graph.") + .help("Display targets grouped according to the dependency graph. If no checkpoint is available to guide change detection, all targets are returned.") .action(ArgAction::SetTrue) .default_value_if(ARG_ALL, ArgPredicate::IsPresent, Some("true")), ) diff --git a/src/app/analyze.rs b/src/app/analyze.rs index dad2d12..5853e69 100644 --- a/src/app/analyze.rs +++ b/src/app/analyze.rs @@ -42,6 +42,7 @@ pub(crate) struct AnalyzeOutput { pub(crate) targets: Vec, #[serde(skip_serializing_if = "Option::is_none")] pub(crate) target_groups: Option>>, + pub(crate) checkpointed: bool, } #[derive(Serialize, Debug, Eq, PartialEq)] @@ -97,7 +98,13 @@ pub(crate) async fn handle_analyze<'a>( return Err(e); } }; - git::get_git_all_changes(&input.git_opts, &checkpoint, work_path).await? + // Only check the change provider if a checkpoint is informing us + match checkpoint { + Some(checkpoint) => Some( + git::get_git_all_changes(&input.git_opts, &checkpoint, work_path).await?, + ), + None => None, + } } }, }; @@ -214,7 +221,8 @@ pub(crate) fn analyze( index: &mut core::Index<'_>, changes: Option>, ) -> Result { - let mut analyzed_changes = if input.show_changes { + let checkpointed = changes.is_some(); + let mut analyzed_changes = if input.show_changes && changes.is_some() { Some(vec![]) } else { None @@ -377,6 +385,7 @@ pub(crate) fn analyze( changes: analyzed_changes, targets, target_groups, + checkpointed, }) } diff --git a/src/app/checkpoint.rs b/src/app/checkpoint.rs index e56d0e9..8091e70 100644 --- a/src/app/checkpoint.rs +++ b/src/app/checkpoint.rs @@ -83,18 +83,17 @@ async fn checkpoint_update_git<'a>( }; if input.pending { - // get all changes with no checkpoint, so diff will return [HEAD, staging area] - let pending_changes = git::get_git_all_changes(&input.git_opts, &None, work_path).await?; - if let Some(pending_changes) = pending_changes { - if !pending_changes.is_empty() { - let mut pending = HashMap::new(); - for change in pending_changes.iter() { - let p = work_path.join(&change.name); - - pending.insert(change.name.clone(), file::get_file_checksum(&p).await?); - } - checkpoint.pending = Some(pending); + // get all changes with default checkpoint, i.e. [HEAD, staging area] + let pending_changes = + git::get_git_all_changes(&input.git_opts, &Default::default(), work_path).await?; + if !pending_changes.is_empty() { + let mut pending = HashMap::new(); + for change in pending_changes.iter() { + let p = work_path.join(&change.name); + + pending.insert(change.name.clone(), file::get_file_checksum(&p).await?); } + checkpoint.pending = Some(pending); } } checkpoint.save()?; diff --git a/src/app/log.rs b/src/app/log.rs index ecfb721..d68469c 100644 --- a/src/app/log.rs +++ b/src/app/log.rs @@ -8,6 +8,7 @@ use sha2::Digest; use std::io::BufRead; use tokio::io::{AsyncBufReadExt, AsyncWriteExt}; +use tokio::sync::mpsc; use tracing::{debug, info, instrument, trace}; use crate::core::{self, error::MonorailError, tracking}; @@ -354,8 +355,8 @@ pub(crate) struct Compressor { index: usize, num_threads: usize, req_channels: Vec<( - flume::Sender, - Option>, + mpsc::Sender, + Option>, )>, registrations: Vec>, shutdown: sync::Arc, @@ -364,24 +365,25 @@ pub(crate) struct Compressor { pub(crate) struct CompressorClient { pub(crate) file_name: String, pub(crate) encoder_index: usize, - pub(crate) req_tx: flume::Sender, + pub(crate) req_tx: mpsc::Sender, } impl CompressorClient { pub(crate) async fn data(&self, data: sync::Arc>>) -> Result<(), MonorailError> { self.req_tx - .send_async(CompressRequest::Data(self.encoder_index, data)) + .send(CompressRequest::Data(self.encoder_index, data)) .await .map_err(MonorailError::from) } pub(crate) async fn end(&self) -> Result<(), MonorailError> { self.req_tx - .send_async(CompressRequest::End(self.encoder_index)) + .send(CompressRequest::End(self.encoder_index)) .await .map_err(MonorailError::from) } - pub(crate) fn shutdown(&self) -> Result<(), MonorailError> { + pub(crate) async fn shutdown(&self) -> Result<(), MonorailError> { self.req_tx .send(CompressRequest::Shutdown) + .await .map_err(MonorailError::from) } } @@ -391,7 +393,7 @@ impl Compressor { let mut req_channels = vec![]; let mut registrations = vec![]; for _ in 0..num_threads { - let (req_tx, req_rx) = flume::bounded(1000); + let (req_tx, req_rx) = mpsc::channel(1000); req_channels.push((req_tx, Some(req_rx))); registrations.push(vec![]); } @@ -425,7 +427,7 @@ impl Compressor { std::thread::scope(|s| { for x in 0..self.num_threads { let regs = &self.registrations[x]; - let req_rx = + let mut req_rx = self.req_channels[x] .1 .take() @@ -450,7 +452,7 @@ impl Compressor { if shutdown.load(sync::atomic::Ordering::Relaxed) { break; }; - match req_rx.recv()? { + match req_rx.blocking_recv().ok_or(MonorailError::ChannelRecv("CompressorClient unexpectedly closed its channel before sending shutdown".to_string()))? { CompressRequest::End(encoder_index) => { trace!( encoder_index = encoder_index, @@ -545,8 +547,8 @@ mod tests { assert_eq!(client_2.encoder_index, 0); } - #[test] - fn test_run_compressor_with_data_requests() { + #[tokio::test] + async fn test_run_compressor_with_data_requests() { let shutdown = Arc::new(AtomicBool::new(false)); let mut compressor = Compressor::new(1, shutdown.clone()); let temp_dir = new_testdir().unwrap(); @@ -564,10 +566,11 @@ mod tests { client .req_tx .send(CompressRequest::Data(client.encoder_index, data.clone())) + .await .expect("Failed to send data"); // Finalize the encoder and shut down the thread - client.shutdown().unwrap(); + client.shutdown().await.unwrap(); // Wait for the compressor thread to end compressor_handle.join().unwrap().unwrap(); @@ -580,8 +583,8 @@ mod tests { assert!(metadata.len() > 0, "Compressed file should not be empty"); } - #[test] - fn test_shutdown_compressor() { + #[tokio::test] + async fn test_shutdown_compressor() { let shutdown = Arc::new(AtomicBool::new(false)); let mut compressor = Compressor::new(2, shutdown.clone()); let temp_dir = new_testdir().unwrap(); @@ -603,10 +606,12 @@ mod tests { client_1 .req_tx .send(CompressRequest::Shutdown) + .await .expect("Failed to send shutdown request"); client_2 .req_tx .send(CompressRequest::Shutdown) + .await .expect("Failed to send shutdown request"); // Wait for the compressor threads to end diff --git a/src/app/run.rs b/src/app/run.rs index 233f98b..22eca74 100644 --- a/src/app/run.rs +++ b/src/app/run.rs @@ -131,6 +131,7 @@ pub(crate) struct RunOutput { invocation: String, out: Out, results: Vec, + checkpointed: bool, } #[derive(Debug, Deserialize, Default)] @@ -250,6 +251,7 @@ pub(crate) async fn handle_run<'a>( let run_path = setup_run_path(cfg, tracking_run.id, work_path)?; let commands = get_all_commands(cfg, &input.commands, &input.sequences)?; let mut argmap = ArgMap::new(); + let mut checkpointed = false; let (index, target_groups) = match input.targets.len() { 0 => { @@ -263,11 +265,18 @@ pub(crate) async fn handle_run<'a>( } }; - let changes = match cfg.change_provider.r#use { - ChangeProviderKind::Git => { - git::get_git_all_changes(&input.git_opts, &checkpoint, work_path).await? - } + // Fetch changes from the change provider if a checkpoint exists + let changes = match checkpoint { + Some(checkpoint) => match cfg.change_provider.r#use { + ChangeProviderKind::Git => Some( + git::get_git_all_changes(&input.git_opts, &checkpoint, work_path).await?, + ), + }, + None => None, }; + + checkpointed = changes.is_some(); + let ai = analyze::AnalyzeInput::new(false, false, true); let ao = analyze::analyze(&ai, &mut index, changes)?; let target_groups = ao @@ -338,12 +347,15 @@ pub(crate) async fn handle_run<'a>( cfg, plan, &commands, - &run_path, input.fail_on_undefined, invocation, + checkpointed, ) .await?; + // Store the run output record + store_run_output(&run_output, &run_path)?; + // Update the run counter tracking_run.save()?; Ok(run_output) @@ -990,8 +1002,8 @@ async fn process_plan( crr.target_groups.push(result_target_group); for client in compressor_clients { - client.0.shutdown()?; - client.1.shutdown()?; + client.0.shutdown().await?; + client.1.shutdown().await?; } // Unwrap for thread dyn Any panic contents, which isn't easily mapped to a MonorailError // because it doesn't impl Error; however, the internals of this handle do, so they @@ -1010,9 +1022,9 @@ async fn run_internal<'a>( cfg: &'a core::Config, plan: Plan, commands: &'a [&'a String], - run_path: &path::Path, fail_on_undefined: bool, invocation: &'a str, + checkpointed: bool, ) -> Result { info!("Processing plan"); let (results, failed) = process_plan(cfg, &plan, commands, fail_on_undefined).await?; @@ -1021,10 +1033,9 @@ async fn run_internal<'a>( invocation: invocation.to_owned(), out: plan.out, results, + checkpointed, }; - store_run_output(&o, run_path)?; - Ok(o) } @@ -1513,6 +1524,7 @@ mod tests { )])], }, ], + checkpointed: true, }; let result = store_run_output(&run_output, run_path); diff --git a/src/core/error.rs b/src/core/error.rs index 7755162..3d704a5 100644 --- a/src/core/error.rs +++ b/src/core/error.rs @@ -50,7 +50,7 @@ pub enum MonorailError { MissingArg(String), TaskCancelled, ChannelSend(String), - ChannelRecv(flume::RecvError), + ChannelRecv(String), Server(server::ServerError), } impl From for MonorailError { @@ -58,13 +58,8 @@ impl From for MonorailError { MonorailError::Server(error) } } -impl From for MonorailError { - fn from(error: flume::RecvError) -> Self { - MonorailError::ChannelRecv(error) - } -} -impl From> for MonorailError { - fn from(error: flume::SendError) -> Self { +impl From> for MonorailError { + fn from(error: tokio::sync::mpsc::error::SendError) -> Self { MonorailError::ChannelSend(error.to_string()) } } diff --git a/src/core/file.rs b/src/core/file.rs index b2d8b4d..8df8a95 100644 --- a/src/core/file.rs +++ b/src/core/file.rs @@ -74,8 +74,7 @@ pub(crate) async fn get_file_checksum(p: &path::Path) -> Result( git_opts: &'a GitOptions<'a>, - checkpoint: &'a Option, + checkpoint: &'a tracking::Checkpoint, work_path: &path::Path, ) -> Result, MonorailError> { let begin = git_opts.begin.or_else(|| { // otherwise, check checkpoint.id; if provided, use that - if let Some(checkpoint) = checkpoint { - if checkpoint.id.is_empty() { - None - } else { - Some(&checkpoint.id) - } - } else { - // if not then there's nowhere to begin from, and we're done + if checkpoint.id.is_empty() { None + } else { + Some(&checkpoint.id) } }); @@ -73,37 +68,29 @@ pub(crate) async fn get_git_diff_changes<'a>( pub(crate) async fn get_git_all_changes<'a>( git_opts: &'a GitOptions<'a>, - checkpoint: &'a Option, + checkpoint: &'a tracking::Checkpoint, work_path: &path::Path, -) -> Result>, MonorailError> { +) -> Result, MonorailError> { let (diff_changes, mut other_changes) = tokio::try_join!( get_git_diff_changes(git_opts, checkpoint, work_path), git_cmd_other_changes(git_opts.git_path, work_path) )?; other_changes.extend(diff_changes); - let mut filtered_changes = match checkpoint { - Some(checkpoint) => { - if let Some(pending) = &checkpoint.pending { + let mut filtered_changes = { + match &checkpoint.pending { + Some(pending) => { if !pending.is_empty() { get_filtered_changes(other_changes, pending, work_path).await } else { other_changes } - } else { - other_changes - } - } - None => { - // no changes and no checkpoint means change detection is not possible - if other_changes.is_empty() { - return Ok(None); } - other_changes + None => other_changes, } }; filtered_changes.sort(); - Ok(Some(filtered_changes)) + Ok(filtered_changes) } pub(crate) async fn get_git_cmd_child( @@ -251,7 +238,7 @@ mod tests { // no begin/end without a checkpoint or pending changes is ok(none) assert_eq!( - get_git_diff_changes(&git_opts, &None, repo_path) + get_git_diff_changes(&git_opts, &Default::default(), repo_path) .await .unwrap(), vec![] @@ -261,7 +248,7 @@ mod tests { git_opts.begin = Some(&begin); git_opts.end = Some(&begin); assert_eq!( - get_git_diff_changes(&git_opts, &None, repo_path) + get_git_diff_changes(&git_opts, &Default::default(), repo_path) .await .unwrap(), vec![] @@ -276,7 +263,7 @@ mod tests { git_opts.begin = Some(&begin); git_opts.end = Some(&end); assert_eq!( - get_git_diff_changes(&git_opts, &None, repo_path) + get_git_diff_changes(&git_opts, &Default::default(), repo_path) .await .unwrap(), vec![Change { @@ -288,7 +275,7 @@ mod tests { git_opts.begin = Some(&end); git_opts.end = Some(&begin); assert_eq!( - get_git_diff_changes(&git_opts, &None, repo_path) + get_git_diff_changes(&git_opts, &Default::default(), repo_path) .await .unwrap(), vec![Change { @@ -317,11 +304,11 @@ mod tests { assert_eq!( get_git_diff_changes( &git_opts, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: "".to_string(), pending: None, - }), + }, repo_path ) .await @@ -337,11 +324,11 @@ mod tests { assert_eq!( get_git_diff_changes( &git_opts, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: first_head.clone(), pending: None, - }), + }, repo_path ) .await @@ -360,11 +347,11 @@ mod tests { assert_eq!( get_git_diff_changes( &git_opts, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: first_head.clone(), pending: None, - }), + }, repo_path ) .await @@ -377,11 +364,11 @@ mod tests { assert_eq!( get_git_diff_changes( &git_opts, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: second_head.clone(), pending: None, - }), + }, repo_path ) .await @@ -396,11 +383,11 @@ mod tests { end: None, git_path: "git", }, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: second_head.clone(), pending: None, - }), + }, repo_path ) .await @@ -430,14 +417,14 @@ mod tests { // no begin/end, with invalid checkpoint commit is err assert!(get_git_diff_changes( &git_opts, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: "test".to_string(), pending: Some(HashMap::from([( "foo.txt".to_string(), "blarp".to_string() )])), - }), + }, repo_path ) .await @@ -445,16 +432,20 @@ mod tests { // bad begin is err git_opts.begin = Some("foo"); - assert!(get_git_diff_changes(&git_opts, &None, repo_path) - .await - .is_err()); + assert!( + get_git_diff_changes(&git_opts, &Default::default(), repo_path) + .await + .is_err() + ); // bad end is err git_opts.begin = Some(&begin); git_opts.end = Some("foo"); - assert!(get_git_diff_changes(&git_opts, &None, repo_path) - .await - .is_err()); + assert!( + get_git_diff_changes(&git_opts, &Default::default(), repo_path) + .await + .is_err() + ); git_opts.begin = None; git_opts.end = None; @@ -470,18 +461,20 @@ mod tests { commit(repo_path).await; // no changes, no checkpoint is ok - assert!(get_git_all_changes( - &GitOptions { - begin: None, - end: None, - git_path: "git", - }, - &None, - repo_path - ) - .await - .unwrap() - .is_none()); + assert_eq!( + get_git_all_changes( + &GitOptions { + begin: None, + end: None, + git_path: "git", + }, + &Default::default(), + repo_path + ) + .await + .unwrap(), + vec![] + ); } #[tokio::test] @@ -503,19 +496,18 @@ mod tests { assert_eq!( get_git_all_changes( &git_opts, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: begin.clone(), pending: Some(HashMap::from([( "foo.txt".to_string(), "dsfksl".to_string() )])), - }), + }, repo_path ) .await .unwrap() - .unwrap() .len(), 0 ); @@ -543,10 +535,9 @@ mod tests { commit(repo_path).await; assert_eq!( - get_git_all_changes(&git_opts, &None, repo_path) + get_git_all_changes(&git_opts, &Default::default(), repo_path) .await .unwrap() - .unwrap() .len(), 1 ); @@ -556,19 +547,18 @@ mod tests { assert_eq!( get_git_all_changes( &git_opts, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: begin.clone(), pending: Some(HashMap::from([( "foo.txt".to_string(), foo_checksum.clone() )])), - }), + }, repo_path ) .await .unwrap() - .unwrap() .len(), 0 ); @@ -583,19 +573,18 @@ mod tests { assert_eq!( get_git_all_changes( &git_opts, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: end.clone(), pending: Some(HashMap::from([( "foo.txt".to_string(), foo_checksum.clone() )])), - }), + }, repo_path ) .await .unwrap() - .unwrap() .len(), 1 ); @@ -604,19 +593,18 @@ mod tests { assert_eq!( get_git_all_changes( &git_opts, - &Some(tracking::Checkpoint { + &tracking::Checkpoint { path: path::Path::new("x").to_path_buf(), id: end.clone(), pending: Some(HashMap::from([ ("foo.txt".to_string(), foo_checksum), ("bar.txt".to_string(), bar_checksum) ])), - }), + }, repo_path ) .await .unwrap() - .unwrap() .len(), 0 ); diff --git a/src/core/testing.rs b/src/core/testing.rs index 68e5bc4..7eb8d82 100644 --- a/src/core/testing.rs +++ b/src/core/testing.rs @@ -165,7 +165,7 @@ pub(crate) async fn write_with_checksum( let mut hasher = sha2::Sha256::new(); hasher.update(data); tokio::fs::write(path, &data).await?; - Ok(hex::encode(hasher.finalize()).to_string()) + Ok(format!("{:x}", hasher.finalize())) } pub(crate) fn get_pair_map(pairs: &[(&str, String)]) -> HashMap {