From 0791356e3e92b72d43a09f58b57dabfacfcdc689 Mon Sep 17 00:00:00 2001 From: Ajeet D'Souza <98ajeet@gmail.com> Date: Tue, 12 Oct 2021 01:35:24 +0530 Subject: [PATCH] Use workspace for xtask (#276) --- .cargo/config.toml | 2 +- .github/workflows/ci.yml | 2 +- Cargo.lock | 157 +++++++++++++++++++-- Cargo.toml | 16 ++- shell.nix | 11 +- src/shell.rs | 13 +- templates/fish.txt | 2 +- tests/{completion.rs => completions.rs} | 4 +- tests/man.rs | 28 ---- xtask/Cargo.lock | 170 ----------------------- xtask/Cargo.toml | 11 +- xtask/src/main.rs | 174 ++++++++++++++++++------ 12 files changed, 309 insertions(+), 281 deletions(-) rename tests/{completion.rs => completions.rs} (94%) delete mode 100644 tests/man.rs delete mode 100644 xtask/Cargo.lock diff --git a/.cargo/config.toml b/.cargo/config.toml index d8c2032b..35049cbc 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,2 @@ [alias] -xtask = "run --manifest-path ./xtask/Cargo.toml --" +xtask = "run --package xtask --" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aed25a25..52ac2a20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,4 +21,4 @@ jobs: if: ${{ matrix.os != 'windows-latest' }} with: nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/20.09.tar.gz - - run: cargo xtask --nix=${{ matrix.os != 'windows-latest' }} ci + - run: cargo xtask ci diff --git a/Cargo.lock b/Cargo.lock index 399d20e6..a9f3a1cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.44" @@ -57,9 +66,9 @@ dependencies = [ [[package]] name = "assert_cmd" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b800c4403e8105d959595e1f88119e78bc12bc874c4336973658b648a746ba93" +checksum = "e996dc7940838b7ef1096b882e29ec30a3149a3a443cdc8dba19ed382eca1fe2" dependencies = [ "bstr", "doc-comment", @@ -170,6 +179,16 @@ dependencies = [ "clap", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +dependencies = [ + "cfg-if", + "lazy_static", +] + [[package]] name = "difflib" version = "0.4.0" @@ -215,6 +234,12 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "funty" version = "1.1.0" @@ -238,6 +263,19 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "globset" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -262,6 +300,24 @@ dependencies = [ "libc", ] +[[package]] +name = "ignore" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" +dependencies = [ + "crossbeam-utils", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "1.7.0" @@ -306,6 +362,15 @@ version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.4.1" @@ -334,6 +399,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + [[package]] name = "ordered-float" version = "2.8.0" @@ -357,9 +428,9 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "predicates" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c143348f141cc87aab5b950021bac6145d0e5ae754b0591de23244cee42c9308" +checksum = "5c6ce811d0b2e103743eec01db1c50612221f173084ce2f7941053e94b6bb474" dependencies = [ "difflib", "itertools", @@ -374,12 +445,12 @@ checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" [[package]] name = "predicates-tree" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7dd0fd014130206c9352efbdc92be592751b2b9274dff685348341082c6ea3d" +checksum = "338c7be2905b732ae3984a2f40032b5e94fd8f52505b186c7d4d68d193445df7" dependencies = [ "predicates-core", - "treeline", + "termtree", ] [[package]] @@ -489,12 +560,29 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + [[package]] name = "regex-automata" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -532,6 +620,15 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "semver" version = "1.0.4" @@ -558,6 +655,12 @@ dependencies = [ "syn", ] +[[package]] +name = "shell-words" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074" + [[package]] name = "static_assertions" version = "1.1.0" @@ -572,9 +675,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.78" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4eac2e6c19f5c3abc0c229bea31ff0b9b091c7b14990e8924b92902a303a0c0" +checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" dependencies = [ "proc-macro2", "quote", @@ -610,6 +713,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termtree" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78fbf2dd23e79c28ccfa2472d3e6b3b189866ffef1aeb91f17c2d968b6586378" + [[package]] name = "textwrap" version = "0.14.2" @@ -620,10 +729,13 @@ dependencies = [ ] [[package]] -name = "treeline" -version = "0.1.0" +name = "thread_local" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +dependencies = [ + "once_cell", +] [[package]] name = "unicode-segmentation" @@ -664,6 +776,17 @@ dependencies = [ "libc", ] +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -707,6 +830,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "ignore", + "shell-words", +] + [[package]] name = "zoxide" version = "0.7.5" diff --git a/Cargo.toml b/Cargo.toml index 281f5d7f..08b2d477 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,12 @@ license = "MIT" keywords = ["cli"] categories = ["command-line-utilities", "filesystem"] +[badges] +maintenance = { status = "actively-developed" } + +[workspace] +members = ["xtask/"] + [dependencies] anyhow = "1.0.32" askama = { version = "0.10.3", default-features = false } @@ -27,17 +33,17 @@ rand = { version = "0.8.4", features = [ "small_rng", ], default-features = false } -[dev-dependencies] -assert_cmd = "2.0.0" -rstest = "0.11.0" - [build-dependencies] clap = "=3.0.0-beta.4" clap_generate = "=3.0.0-beta.4" +[dev-dependencies] +assert_cmd = "2.0.0" +rstest = "0.11.0" + [features] default = [] -nix_tests = [] +nix = [] [profile.release] codegen-units = 1 diff --git a/shell.nix b/shell.nix index dcee1a30..2b081fc2 100644 --- a/shell.nix +++ b/shell.nix @@ -1,9 +1,11 @@ let - rust = import (builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/ad311f5bb5c5ef475985f1e0f264e831470a8510.tar.gz"); + rust = import (builtins.fetchTarball + "https://github.com/oxalica/rust-overlay/archive/ad311f5bb5c5ef475985f1e0f264e831470a8510.tar.gz"); pkgs = import { overlays = [ rust ]; }; - pkgs-latest = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/b4692e4197869c42c46d77e31af7e687e1892f55.tar.gz") {}; -in -pkgs.mkShell { + pkgs-latest = import (fetchTarball + "https://github.com/NixOS/nixpkgs/archive/b4692e4197869c42c46d77e31af7e687e1892f55.tar.gz") + { }; +in pkgs.mkShell { buildInputs = [ # Rust pkgs.rust-bin.stable.latest.default @@ -21,6 +23,7 @@ pkgs.mkShell { # Tools pkgs-latest.cargo-audit pkgs-latest.mandoc + pkgs-latest.nixfmt pkgs-latest.nodePackages.markdownlint-cli pkgs-latest.python3Packages.black pkgs-latest.python3Packages.mypy diff --git a/src/shell.rs b/src/shell.rs index 2b857990..6199a049 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -41,7 +41,7 @@ make_template!(Powershell, "powershell.txt"); make_template!(Xonsh, "xonsh.txt"); make_template!(Zsh, "zsh.txt"); -#[cfg(feature = "nix_tests")] +#[cfg(feature = "nix")] #[cfg(test)] mod tests { use askama::Template; @@ -321,16 +321,7 @@ mod tests { let mut source = Xonsh(&opts).render().unwrap(); source.push('\n'); - let tempdir = tempfile::tempdir().unwrap(); - let tempdir = tempdir.path().to_str().unwrap(); - - Command::new("pylint") - .args(&["--from-stdin", "zoxide"]) - .env("HOME", tempdir) - .write_stdin(source) - .assert() - .success() - .stderr(""); + Command::new("pylint").args(&["--from-stdin", "zoxide"]).write_stdin(source).assert().success().stderr(""); } #[rstest] diff --git a/templates/fish.txt b/templates/fish.txt index 573f71c9..47bceba2 100644 --- a/templates/fish.txt +++ b/templates/fish.txt @@ -30,7 +30,6 @@ function __zoxide_cd {%- if echo %} and __zoxide_pwd {%- endif %} - and builtin commandline -f repaint end {{ section }} @@ -124,6 +123,7 @@ end __zoxide_unset {{cmd}} alias {{cmd}}=__zoxide_z +complete -e {{cmd}} complete -c {{cmd}} -f -a '(__zoxide_z_complete)' __zoxide_unset {{cmd}}i diff --git a/tests/completion.rs b/tests/completions.rs similarity index 94% rename from tests/completion.rs rename to tests/completions.rs index 9887096d..56975d8e 100644 --- a/tests/completion.rs +++ b/tests/completions.rs @@ -1,5 +1,5 @@ -//! Syntax checking for auto-generated shell completions. -#![cfg(feature = "nix_tests")] +//! Test clap generated completions. +#![cfg(feature = "nix")] use assert_cmd::Command; diff --git a/tests/man.rs b/tests/man.rs deleted file mode 100644 index 6792fa1d..00000000 --- a/tests/man.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! Syntax checking for manpages. -#![cfg(feature = "nix_tests")] - -use assert_cmd::Command; - -use std::fs; - -#[test] -fn mandoc_lint() { - let paths = fs::read_dir("man") - .unwrap() - .filter_map(|entry| { - let path = entry.unwrap().path(); - if path.is_file() && path.extension() == Some("1".as_ref()) { - Some(path.to_str().unwrap().to_string()) - } else { - None - } - }) - .collect::>(); - Command::new("mandoc") - .args(&["-man", "-Wall", "-Tlint", "--"]) - .args(&paths) - .assert() - .success() - .stdout("") - .stderr(""); -} diff --git a/xtask/Cargo.lock b/xtask/Cargo.lock deleted file mode 100644 index c026cf82..00000000 --- a/xtask/Cargo.lock +++ /dev/null @@ -1,170 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "clap" -version = "3.0.0-beta.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcd70aa5597dbc42f7217a543f9ef2768b2ef823ba29036072d30e1d88e98406" -dependencies = [ - "bitflags", - "clap_derive", - "indexmap", - "lazy_static", - "os_str_bytes", - "textwrap", - "vec_map", -] - -[[package]] -name = "clap_derive" -version = "3.0.0-beta.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5bb0d655624a0b8770d1c178fb8ffcb1f91cc722cb08f451e3dc72465421ac" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "indexmap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "os_str_bytes" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6acbef58a60fe69ab50510a55bc8cdd4d6cf2283d27ad338f54cb52747a9cf2d" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "syn" -version = "1.0.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "textwrap" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" - -[[package]] -name = "unicode-segmentation" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "xtask" -version = "0.1.0" -dependencies = [ - "clap", -] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 5926f49f..68523405 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -2,11 +2,10 @@ name = "xtask" version = "0.1.0" edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +publish = false [dependencies] -clap = { version = "=3.0.0-beta.4", default-features = false, features = [ - "derive", - "std", -] } +anyhow = "1.0.32" +clap = "=3.0.0-beta.4" +ignore = "0.4.18" +shell-words = "1.0.0" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index bc150314..6de70d47 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,56 +1,150 @@ -use std::process::Command; - +use anyhow::{bail, Context, Result}; use clap::Clap; +use ignore::Walk; + +use std::env; +use std::ffi::OsStr; +use std::path::PathBuf; +use std::process::{self, Command}; + +fn main() -> Result<()> { + let nix_enabled = enable_nix(); -#[derive(Clap, Debug)] -struct App { - #[clap(subcommand)] - task: Task, - #[clap(long)] - nix: Option, + let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let dir = dir.parent().with_context(|| format!("could not find workspace root: {}", dir.display()))?; + env::set_current_dir(dir).with_context(|| format!("could not set current directory: {}", dir.display()))?; + + let app = App::parse(); + match app { + App::CI => run_ci(nix_enabled)?, + App::Fmt { check } => run_fmt(nix_enabled, check)?, + App::Lint => run_lint(nix_enabled)?, + App::Test { name } => run_tests(nix_enabled, &name)?, + } + + Ok(()) } -#[derive(Clap, Debug)] -enum Task { +#[derive(Clap)] +enum App { CI, - Test { keywords: Vec }, + Fmt { + #[clap(long)] + check: bool, + }, + Lint, + Test { + #[clap(default_value = "")] + name: String, + }, } -fn run(args: &[&str], nix: bool) { - let args_str = args.join(" "); - println!(">>> {}", args_str); +trait CommandExt { + fn _run(self) -> Result<()>; +} - let status = if nix { - Command::new("nix-shell").args(&["--pure", "--run", &args_str]).status() - } else { - let (cmd, args) = args.split_first().unwrap(); - Command::new(cmd).args(args).status() - }; - if !status.unwrap().success() { - panic!("command exited with an error"); +impl CommandExt for &mut Command { + fn _run(self) -> Result<()> { + println!(">>> {:?}", self); + let status = self.status().with_context(|| format!("command failed to start: {:?}", self))?; + if !status.success() { + bail!("command failed: {:?} with status: {:?}", self, status); + } + Ok(()) } } -fn main() { - let app = App::parse(); - let nix = app.nix.unwrap_or_else(|| Command::new("nix-shell").arg("--version").output().is_ok()); - let run = |args: &[&str]| run(args, nix); - match app.task { - Task::CI => { - let color = if std::env::var_os("CI").is_some() { "--color=always" } else { "" }; - run(&["cargo", "fmt", "--", "--check", color, "--files-with-diff"]); - run(&["cargo", "check", "--all-features", color]); - run(&["cargo", "clippy", "--all-features", color, "--", "--deny=clippy::all", "--deny=warnings"]); - run(&["cargo", "test", if nix { "--all-features" } else { "" }, color, "--no-fail-fast"]); - run(&["cargo", "audit", color, "--deny=warnings"]); - if nix { - run(&["markdownlint", "--ignore-path=.gitignore", "."]); +fn run_ci(nix_enabled: bool) -> Result<()> { + let color: &[&str] = if is_ci() { &["--color=always"] } else { &[] }; + Command::new("cargo").args(&["check", "--all-features"]).args(color)._run()?; + + run_fmt(nix_enabled, true)?; + run_lint(nix_enabled)?; + run_tests(nix_enabled, "") +} + +fn run_fmt(nix_enabled: bool, check: bool) -> Result<()> { + // Run cargo-fmt. + let color: &[&str] = if is_ci() { &["--color=always"] } else { &[] }; + let check_args: &[&str] = if check { &["--check", "--files-with-diff"] } else { &[] }; + Command::new("cargo").args(&["fmt", "--all", "--"]).args(color).args(check_args)._run()?; + + // Run nixfmt. + if nix_enabled { + for result in Walk::new("./") { + let entry = result.unwrap(); + let path = entry.path(); + if path.is_file() && path.extension() == Some(OsStr::new("nix")) { + let check_args: &[&str] = if check { &["--check"] } else { &[] }; + Command::new("nixfmt").args(check_args).arg("--").arg(path)._run()?; } } - Task::Test { keywords } => { - let mut args = vec!["cargo", "test", if nix { "--all-features" } else { "" }, "--no-fail-fast", "--"]; - args.extend(keywords.iter().map(String::as_str)); - run(&args); + } + + Ok(()) +} + +fn run_lint(nix_enabled: bool) -> Result<()> { + // Run cargo-clippy. + let color: &[&str] = if is_ci() { &["--color=always"] } else { &[] }; + Command::new("cargo").args(&["clippy", "--all-features", "--all-targets"]).args(color)._run()?; + + if nix_enabled { + // Run cargo-audit. + let color: &[&str] = if is_ci() { &["--color=always"] } else { &[] }; + Command::new("cargo").args(&["audit", "--deny=warnings"]).args(color)._run()?; + + // Run markdownlint. + for result in Walk::new("./") { + let entry = result.unwrap(); + let path = entry.path(); + if path.is_file() && path.extension() == Some(OsStr::new("md")) { + Command::new("markdownlint").arg(path)._run()?; + } + } + + // Run mandoc with linting enabled. + for result in Walk::new("./man/") { + let entry = result.unwrap(); + let path = entry.path(); + if path.is_file() && path.extension() == Some(OsStr::new("1")) { + Command::new("mandoc").args(&["-man", "-Wall", "-Tlint", "--"]).arg(path)._run()?; + } } } + + Ok(()) +} + +fn run_tests(nix_enabled: bool, name: &str) -> Result<()> { + let color: &[&str] = if is_ci() { &["--color=always"] } else { &[] }; + let features: &[&str] = if nix_enabled { &["--all-features"] } else { &[] }; + Command::new("cargo").args(&["test", "--no-fail-fast", "--workspace"]).args(color).args(features).arg(name)._run() +} + +fn is_ci() -> bool { + env::var_os("CI").is_some() +} + +fn enable_nix() -> bool { + let nix_supported = cfg!(any(target_os = "linux", target_os = "macos")); + if !nix_supported { + return false; + } + let nix_enabled = env::var_os("IN_NIX_SHELL").unwrap_or_default() == "pure"; + if nix_enabled { + return true; + } + let nix_detected = Command::new("nix-shell").arg("--version").status().map(|s| s.success()).unwrap_or(false); + if !nix_detected { + return false; + } + + println!("Detected Nix in environment, re-running in Nix."); + let args = env::args(); + let cmd = shell_words::join(args); + let mut nix_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + nix_path.push("../shell.nix"); + let status = Command::new("nix-shell").args(&["--pure", "--run", &cmd, "--"]).arg(nix_path).status().unwrap(); + process::exit(status.code().unwrap_or(1)); }