diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6950de6..04db4ec 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,11 +11,12 @@ jobs: steps: - uses: actions/checkout@v4.1.3 - uses: DeterminateSystems/nix-installer-action@v10 - - uses: DeterminateSystems/magic-nix-cache-action@v4 - name: Build run: nix-build - name: Run pre-commit hooks run: nix-shell --run "pre-commit run --all" + - name: Cargo test + run: nix-shell --run "cargo test" - name: Test dev shell # Simple check that the pins in the current repository are still working. # Importantly, this will fail on any version mismatch, indicating that versions need to be upgraded. diff --git a/Cargo.lock b/Cargo.lock index a397cbb..9b2f95c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,15 +26,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anstream" version = "0.6.14" @@ -98,25 +89,14 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "syn", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" @@ -139,12 +119,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.8.0" @@ -177,19 +151,44 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "2.34.0" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + [[package]] name = "colorchoice" version = "1.0.1" @@ -202,8 +201,8 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.8.0", - "parking_lot 0.12.3", + "bitflags", + "parking_lot", "rustix", ] @@ -215,7 +214,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] @@ -240,16 +239,6 @@ dependencies = [ "log", ] -[[package]] -name = "envtestkit" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea14546e99a5b0e76a883df8ff5531ae2e5f1cd484c88531142ac9bfb11542f" -dependencies = [ - "lazy_static", - "parking_lot 0.11.2", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -337,7 +326,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] @@ -395,21 +384,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -628,7 +605,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] @@ -653,15 +630,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "ipnet" version = "2.9.0" @@ -689,12 +657,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "lenient_semver_parser" version = "0.4.2" @@ -792,9 +754,9 @@ version = "0.2.4" dependencies = [ "anyhow", "async-trait", + "clap", "crossterm", "env_logger", - "envtestkit", "futures", "lenient_semver_parser", "lenient_version", @@ -802,7 +764,6 @@ dependencies = [ "reqwest", "serde", "serde_json", - "structopt", "tokio", "url", ] @@ -813,7 +774,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", ] @@ -832,17 +793,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - [[package]] name = "parking_lot" version = "0.12.3" @@ -850,21 +800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -875,7 +811,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.8", + "redox_syscall", "smallvec", "windows-targets 0.52.5", ] @@ -903,7 +839,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] @@ -918,30 +854,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[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 1.0.109", - "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.85" @@ -960,22 +872,13 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.8.0", + "bitflags", ] [[package]] @@ -1075,7 +978,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -1152,7 +1055,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] @@ -1227,33 +1130,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" @@ -1261,17 +1140,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.66" @@ -1297,16 +1165,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", + "syn", ] [[package]] @@ -1345,7 +1204,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] @@ -1417,18 +1276,6 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-segmentation" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" - -[[package]] -name = "unicode-width" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" - [[package]] name = "untrusted" version = "0.9.0" @@ -1465,18 +1312,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "want" version = "0.3.1" @@ -1513,7 +1348,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn", "wasm-bindgen-shared", ] @@ -1547,7 +1382,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1577,28 +1412,6 @@ dependencies = [ "rustls-pki-types", ] -[[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.48.0" @@ -1780,7 +1593,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", "synstructure", ] @@ -1801,7 +1614,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", "synstructure", ] @@ -1830,5 +1643,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index b71a578..73479e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ license = "EUPL-1.2" serde = { version = "^1.0", features = [ "derive" ] } serde_json = { version = "^1.0", features = ["preserve_order"] } url = { version = "^2.2.2", features = [ "serde" ] } -structopt = "^0.3" +clap = { version = "4.5", features = [ "derive", "env" ] } anyhow = "^1.0" tokio = { version = "^1.0", features = ["macros", "rt-multi-thread", "process"] } env_logger = { version = "^0.11.0", features = ["color", "auto-color", "regex"], default-features = false } @@ -21,6 +21,3 @@ lenient_semver_parser = { version = "0.4.2", default-features = false } lenient_version = { version = "0.4.2" } futures = "0.3.31" crossterm = { version = "0.28.1", default-features = false } - -[dev-dependencies] -envtestkit = "1.1.2" diff --git a/README.md b/README.md index b03ae3d..a48889d 100644 --- a/README.md +++ b/README.md @@ -100,31 +100,24 @@ You may also use attributes from the JSON file, they are exposed 1:1. For exampl ```console $ npins help -npins 0.2.4 - -USAGE: - npins [OPTIONS] - -FLAGS: - -h, --help Prints help information - -V, --version Prints version information - -OPTIONS: - -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] - [default: npins] - -SUBCOMMANDS: - add Adds a new pin entry - help Prints this message or the help of the given subcommand(s) - import-flake Try to import entries from flake.lock - import-niv Try to import entries from Niv - init Intializes the npins directory. Running this multiple times will restore/upgrade the - `default.nix` and never touch your sources.json - remove Removes one pin entry - show Lists the current pin entries - update Updates all or the given pins to the latest version - upgrade Upgrade the sources.json and default.nix to the latest format version. This may occasionally - break Nix evaluation! +Usage: npins [OPTIONS] + +Commands: + init Intializes the npins directory. Running this multiple times will restore/upgrade the `default.nix` and never touch your sources.json + add Adds a new pin entry + show Lists the current pin entries + update Updates all or the given pins to the latest version + upgrade Upgrade the sources.json and default.nix to the latest format version. This may occasionally break Nix evaluation! + remove Removes one pin entry + import-niv Try to import entries from Niv + import-flake Try to import entries from flake.lock + help Print this message or the help of the given subcommand(s) + +Options: + -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] + -v, --verbose Print debug messages + -h, --help Print help + -V, --version Print version ``` ### Initialization @@ -139,20 +132,15 @@ This will create an `npins` folder with a `default.nix` and `sources.json` withi ```console $ npins help init -npins-init 0.2.4 -Intializes the npins directory. Running this multiple times will restore/upgrade the `default.nix` and never touch your -sources.json +Intializes the npins directory. Running this multiple times will restore/upgrade the `default.nix` and never touch your sources.json -USAGE: - npins init [FLAGS] [OPTIONS] +Usage: npins init [OPTIONS] -FLAGS: - --bare Don't add an initial `nixpkgs` entry - -h, --help Prints help information - -OPTIONS: - -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] - [default: npins] +Options: + --bare Don't add an initial `nixpkgs` entry + -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] + -v, --verbose Print debug messages + -h, --help Print help ``` ### Migrate from Niv @@ -170,22 +158,18 @@ Note that the import functionality is minimal and only preserves the necessary i ```console $ npins help import-niv -npins-import-niv 0.2.4 Try to import entries from Niv -USAGE: - npins import-niv [OPTIONS] [path] - -FLAGS: - -h, --help Prints help information +Usage: npins import-niv [OPTIONS] [PATH] -OPTIONS: - -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] - [default: npins] - -n, --name Only import one entry from Niv +Arguments: + [PATH] [default: nix/sources.json] -ARGS: - [default: nix/sources.json] +Options: + -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] + -n, --name Only import one entry from Niv + -v, --verbose Print debug messages + -h, --help Print help ``` ### Adding dependencies @@ -210,81 +194,76 @@ Depending on what kind of dependency you are adding, different arguments must be ```console $ npins help add -npins-add 0.2.4 Adds a new pin entry -USAGE: - npins add [FLAGS] [OPTIONS] - -FLAGS: - -n, --dry-run Don't actually apply the changes - -h, --help Prints help information - -OPTIONS: - -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] - [default: npins] - --name Add the pin with a custom name. If a pin with that name already exists, it willl be - overwritten - -SUBCOMMANDS: - channel Track a Nix channel - forgejo Track a Forgejo repository - git Track a git repository - github Track a GitHub repository - gitlab Track a GitLab repository - help Prints this message or the help of the given subcommand(s) - pypi Track a package on PyPi +Usage: npins add [OPTIONS] + +Commands: + channel Track a Nix channel + github Track a GitHub repository + forgejo Track a Forgejo repository + gitlab Track a GitLab repository + git Track a git repository + pypi Track a package on PyPi + help Print this message or the help of the given subcommand(s) + +Options: + -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] + --name Add the pin with a custom name. If a pin with that name already exists, it will be overwritten + -n, --dry-run Don't actually apply the changes + -v, --verbose Print debug messages + -h, --help Print help ``` There are several options for tracking git branches, releases and tags: ```console $ npins help add git -npins-add-git 0.2.4 Track a git repository -USAGE: - npins add git [FLAGS] [OPTIONS] - -FLAGS: - -h, --help Prints help information - --pre-releases Also track pre-releases. Conflicts with the --branch option - --submodules Also fetch submodules - -OPTIONS: - --at Use a specific commit/release instead of the latest. This may be a tag - name, or a git revision when --branch is set - -b, --branch Track a branch instead of a release - -d, --directory Base folder for sources.json and the boilerplate default.nix [env: - NPINS_DIRECTORY=] [default: npins] - --release-prefix Optional prefix required for each release name / tag. For example, setting - this to "release/" will only consider those that start with that string - --upper-bound Bound the version resolution. For example, setting this to "2" will - restrict updates to 1.X versions. Conflicts with the --branch option - -ARGS: - The git remote URL. For example +Usage: npins add git [OPTIONS] + +Arguments: + The git remote URL. For example + +Options: + -b, --branch + Track a branch instead of a release + -d, --directory + Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] + --name + Add the pin with a custom name. If a pin with that name already exists, it will be overwritten + --at + Use a specific commit/release instead of the latest. This may be a tag name, or a git revision when --branch is set + -v, --verbose + Print debug messages + --pre-releases + Also track pre-releases. Conflicts with the --branch option + --upper-bound + Bound the version resolution. For example, setting this to "2" will restrict updates to 1.X versions. Conflicts with the --branch option + --release-prefix + Optional prefix required for each release name / tag. For example, setting this to "release/" will only consider those that start with that string + --submodules + Also fetch submodules + -h, --help + Print help ``` ### Removing dependencies ```console $ npins help remove -npins-remove 0.2.4 Removes one pin entry -USAGE: - npins remove [OPTIONS] - -FLAGS: - -h, --help Prints help information +Usage: npins remove [OPTIONS] -OPTIONS: - -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] - [default: npins] +Arguments: + -ARGS: - +Options: + -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] + -v, --verbose Print debug messages + -h, --help Print help ``` ### Show current entries @@ -293,18 +272,14 @@ This will print the currently pinned dependencies in a human readable format. Th ```console $ npins help show -npins-show 0.2.4 Lists the current pin entries -USAGE: - npins show [OPTIONS] +Usage: npins show [OPTIONS] -FLAGS: - -h, --help Prints help information - -OPTIONS: - -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] - [default: npins] +Options: + -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] + -v, --verbose Print debug messages + -h, --help Print help ``` ### Updating dependencies @@ -313,27 +288,28 @@ You can decide to update only selected dependencies, or all at once. For some pi ```console $ npins help update -npins-update 0.2.4 Updates all or the given pins to the latest version -USAGE: - npins update [FLAGS] [OPTIONS] [names]... - -FLAGS: - -n, --dry-run Print the diff, but don't write back the changes - -f, --full Re-fetch hashes even if the version hasn't changed. Useful to make sure the derivations are in the - Nix store - -h, --help Prints help information - -p, --partial Don't update versions, only re-fetch hashes - -OPTIONS: - -d, --directory - Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] - - --max-concurrent-downloads Maximum number of simultaneous downloads [default: 5] - -ARGS: - ... Updates only the specified pins +Usage: npins update [OPTIONS] [NAMES]... + +Arguments: + [NAMES]... Updates only the specified pins + +Options: + -d, --directory + Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] + -p, --partial + Don't update versions, only re-fetch hashes + -f, --full + Re-fetch hashes even if the version hasn't changed. Useful to make sure the derivations are in the Nix store + -v, --verbose + Print debug messages + -n, --dry-run + Print the diff, but don't write back the changes + --max-concurrent-downloads + Maximum number of simultaneous downloads [default: 5] + -h, --help + Print help ``` ### Upgrading the pins file @@ -342,18 +318,14 @@ To ensure compatibility across releases, the `npins/sources.json` and `npins/def ```console $ npins help upgrade -npins-upgrade 0.2.4 Upgrade the sources.json and default.nix to the latest format version. This may occasionally break Nix evaluation! -USAGE: - npins upgrade [OPTIONS] - -FLAGS: - -h, --help Prints help information +Usage: npins upgrade [OPTIONS] -OPTIONS: - -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] - [default: npins] +Options: + -d, --directory Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins] + -v, --verbose Print debug messages + -h, --help Print help ``` ### Using private GitLab repositories diff --git a/npins.nix b/npins.nix index eb2b09e..b51871f 100644 --- a/npins.nix +++ b/npins.nix @@ -9,7 +9,7 @@ darwin, # runtime dependencies - nix, # for nix-prefetch-url + lix, # for nix-prefetch-url nix-prefetch-git, git, # for git ls-remote }: @@ -42,7 +42,7 @@ let cargoToml = builtins.fromTOML (builtins.readFile (src + "/Cargo.toml")); runtimePath = lib.makeBinPath [ - nix + lix nix-prefetch-git git ]; diff --git a/npins/sources.json b/npins/sources.json index e674de4..3256cac 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -1,17 +1,5 @@ { "pins": { - "nixfmt": { - "type": "Git", - "repository": { - "type": "GitHub", - "owner": "piegamesde", - "repo": "nixfmt" - }, - "branch": "rfc101-style", - "revision": "8d13b593fa8d8d6e5075f541f3231222a08e84df", - "url": "https://github.com/piegamesde/nixfmt/archive/8d13b593fa8d8d6e5075f541f3231222a08e84df.tar.gz", - "hash": "1blpqs2ifw10xvfpfk77p1bq35gzgssng2m8wqw0kqydcz7fzm8y" - }, "nixpkgs": { "type": "Git", "repository": { @@ -20,9 +8,9 @@ "repo": "nixpkgs" }, "branch": "nixpkgs-unstable", - "revision": "a9858885e197f984d92d7fe64e9fff6b2e488d40", - "url": "https://github.com/nixos/nixpkgs/archive/a9858885e197f984d92d7fe64e9fff6b2e488d40.tar.gz", - "hash": "0a55lp827bfx102czy0bp5d6pbp5lh6l0ysp3zs0m1gyniy2jck9" + "revision": "d9b69c3ec2a2e2e971c534065bdd53374bd68b97", + "url": "https://github.com/nixos/nixpkgs/archive/d9b69c3ec2a2e2e971c534065bdd53374bd68b97.tar.gz", + "hash": "111spkgprzsqd32mwzsjksk1hdzv10gyf04lh956vc1pp0g0fcq1" }, "pre-commit-hooks.nix": { "type": "Git", @@ -32,9 +20,9 @@ "repo": "pre-commit-hooks.nix" }, "branch": "master", - "revision": "cc4d466cb1254af050ff7bdf47f6d404a7c646d1", - "url": "https://github.com/cachix/pre-commit-hooks.nix/archive/cc4d466cb1254af050ff7bdf47f6d404a7c646d1.tar.gz", - "hash": "1gl1bdnv533jyvj12dfyg8q5haprapswnn7hbpikb2qbnnwc2xzd" + "revision": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17", + "url": "https://github.com/cachix/pre-commit-hooks.nix/archive/9364dc02281ce2d37a1f55b6e51f7c0f65a75f17.tar.gz", + "hash": "1n2qlj5l8c4g7gm5v6rvc4hff3ka8ljv7y62inybli093bd2ypa7" } }, "version": 3 diff --git a/shell.nix b/shell.nix index 0514281..f7e4207 100644 --- a/shell.nix +++ b/shell.nix @@ -3,23 +3,13 @@ }: let pins = import ./npins; - pkgs = import pins.nixpkgs { - inherit system; - overlays = [ - (self: super: { - nixfmt = super.nixfmt-classic.overrideAttrs (old: { - src = pins.nixfmt; - }); - }) - ]; - }; + pkgs = import pins.nixpkgs { inherit system; }; inherit (pkgs) stdenv lib; pre-commit = (import pins."pre-commit-hooks.nix").run { src = ./.; - tools.nixfmt = pkgs.nixfmt; # Why don't they just take it from our pkgs? hooks = { - nixfmt = { + nixfmt-rfc-style = { enable = true; settings.width = 100; }; @@ -47,8 +37,8 @@ pkgs.mkShell { rustc rust-analyzer rustfmt - nixfmt - nix_2_3 + nixfmt-rfc-style + lix nix-prefetch-git git npins diff --git a/src/cli.rs b/src/cli.rs index e59b485..5810a44 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -9,6 +9,7 @@ use std::{ }; use anyhow::{Context, Result}; +use clap::{Parser, Subcommand}; use crossterm::{ cursor, execute, style::{ContentStyle, Print, StyledContent, Stylize}, @@ -19,7 +20,6 @@ use futures::{ stream::{self, StreamExt}, TryStreamExt, }; -use structopt::StructOpt; use url::{ParseError, Url}; @@ -56,7 +56,7 @@ impl UpdateStrategy { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ChannelAddOpts { name: String, } @@ -73,25 +73,25 @@ impl ChannelAddOpts { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct GenericGitAddOpts { /// Track a branch instead of a release - #[structopt(short, long)] + #[arg(short, long)] pub branch: Option, /// Use a specific commit/release instead of the latest. /// This may be a tag name, or a git revision when --branch is set. - #[structopt(long, value_name = "tag or rev")] + #[arg(long, value_name = "tag or rev")] pub at: Option, /// Also track pre-releases. /// Conflicts with the --branch option. - #[structopt(long, conflicts_with = "branch")] + #[arg(long, conflicts_with = "branch")] pub pre_releases: bool, /// Bound the version resolution. For example, setting this to "2" will /// restrict updates to 1.X versions. Conflicts with the --branch option. - #[structopt( + #[arg( long = "upper-bound", value_name = "version", conflicts_with_all = &["branch", "at"] @@ -101,20 +101,20 @@ pub struct GenericGitAddOpts { /// Optional prefix required for each release name / tag. For /// example, setting this to "release/" will only consider those /// that start with that string. - #[structopt(long = "release-prefix")] + #[arg(long = "release-prefix")] pub release_prefix: Option, /// Also fetch submodules - #[structopt(long)] + #[arg(long)] pub submodules: bool, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct GitHubAddOpts { pub owner: String, pub repository: String, - #[structopt(flatten)] + #[command(flatten)] pub more: GenericGitAddOpts, } @@ -154,13 +154,13 @@ impl GitHubAddOpts { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ForgejoAddOpts { pub server: String, pub owner: String, pub repository: String, - #[structopt(flatten)] + #[command(flatten)] pub more: GenericGitAddOpts, } impl ForgejoAddOpts { @@ -208,13 +208,13 @@ impl ForgejoAddOpts { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct GitLabAddOpts { /// Usually just `"owner" "repository"`, but GitLab allows arbitrary folder-like structures. - #[structopt(required = true, min_values = 2)] + #[arg(required = true)] // TODO set min number of values to 2 again pub repo_path: Vec, - #[structopt( + #[arg( long, default_value = "https://gitlab.com/", help = "Use a self-hosted GitLab instance instead", @@ -222,14 +222,14 @@ pub struct GitLabAddOpts { )] pub server: url::Url, - #[structopt( + #[arg( long, help = "Use a private token to access the repository.", value_name = "token" )] pub private_token: Option, - #[structopt(flatten)] + #[command(flatten)] pub more: GenericGitAddOpts, } @@ -275,12 +275,12 @@ impl GitLabAddOpts { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct GitAddOpts { /// The git remote URL. For example pub url: String, - #[structopt(flatten)] + #[command(flatten)] pub more: GenericGitAddOpts, } @@ -338,18 +338,18 @@ impl GitAddOpts { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct PyPiAddOpts { /// Name of the package at PyPi.org pub name: String, /// Use a specific release instead of the latest. - #[structopt(long, value_name = "version")] + #[arg(long, value_name = "version")] pub at: Option, /// Bound the version resolution. For example, setting this to "2" will /// restrict updates to 1.X versions. Conflicts with the --branch option. - #[structopt(long = "upper-bound", value_name = "version", conflicts_with = "at")] + #[arg(long = "upper-bound", value_name = "version", conflicts_with = "at")] pub version_upper_bound: Option, } @@ -368,38 +368,38 @@ impl PyPiAddOpts { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum AddCommands { /// Track a Nix channel - #[structopt(name = "channel")] + #[command(name = "channel")] Channel(ChannelAddOpts), /// Track a GitHub repository - #[structopt(name = "github")] + #[command(name = "github")] GitHub(GitHubAddOpts), /// Track a Forgejo repository - #[structopt(name = "forgejo")] + #[command(name = "forgejo")] Forgejo(ForgejoAddOpts), /// Track a GitLab repository - #[structopt(name = "gitlab")] + #[command(name = "gitlab")] GitLab(GitLabAddOpts), /// Track a git repository - #[structopt(name = "git")] + #[command(name = "git")] Git(GitAddOpts), /// Track a package on PyPi - #[structopt(name = "pypi")] + #[command(name = "pypi")] PyPi(PyPiAddOpts), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct AddOpts { /// Add the pin with a custom name. - /// If a pin with that name already exists, it willl be overwritten - #[structopt(long)] + /// If a pin with that name already exists, it will be overwritten + #[arg(long, global = true)] pub name: Option, /// Don't actually apply the changes - #[structopt(short = "n", long)] + #[arg(short = 'n', long)] pub dry_run: bool, - #[structopt(subcommand)] + #[command(subcommand)] command: AddCommands, } @@ -428,56 +428,56 @@ impl AddOpts { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct RemoveOpts { pub name: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct UpdateOpts { /// Updates only the specified pins. pub names: Vec, /// Don't update versions, only re-fetch hashes - #[structopt(short, long, conflicts_with = "full")] + #[arg(short, long, conflicts_with = "full")] pub partial: bool, /// Re-fetch hashes even if the version hasn't changed. /// Useful to make sure the derivations are in the Nix store. - #[structopt(short, long, conflicts_with = "partial")] + #[arg(short, long, conflicts_with = "partial")] pub full: bool, /// Print the diff, but don't write back the changes - #[structopt(short = "n", long, global = true)] + #[arg(short = 'n', long, global = true)] pub dry_run: bool, /// Maximum number of simultaneous downloads #[structopt(default_value = "5", long)] pub max_concurrent_downloads: usize, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct InitOpts { /// Don't add an initial `nixpkgs` entry - #[structopt(long)] + #[arg(long)] pub bare: bool, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ImportOpts { - #[structopt(default_value = "nix/sources.json", parse(from_os_str))] + #[arg(default_value = "nix/sources.json")] pub path: PathBuf, /// Only import one entry from Niv - #[structopt(short, long)] + #[arg(short, long)] pub name: Option, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ImportFlakeOpts { - #[structopt(default_value = "flake.lock", parse(from_os_str))] + #[arg(default_value = "flake.lock")] pub path: PathBuf, /// Only import one entry from the flake - #[structopt(short, long)] + #[arg(short, long)] pub name: Option, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum Command { /// Intializes the npins directory. Running this multiple times will restore/upgrade the /// `default.nix` and never touch your sources.json. @@ -521,27 +521,32 @@ fn print_diff(name: &str, diff: impl AsRef<[diff::DiffEntry]>) { } } -use structopt::clap::AppSettings; - -#[derive(Debug, StructOpt)] -#[structopt( - setting(AppSettings::ArgRequiredElseHelp), - global_setting(AppSettings::VersionlessSubcommands), - global_setting(AppSettings::ColoredHelp), - global_setting(AppSettings::ColorAuto) +#[derive(Debug, Parser)] +#[command( + version, + about, + arg_required_else_help = true, + // Confirm clap defaults + propagate_version = false, + disable_colored_help = false, + color = clap::ColorChoice::Auto )] pub struct Opts { /// Base folder for sources.json and the boilerplate default.nix - #[structopt( + #[arg( global = true, - short = "d", + short = 'd', long = "directory", default_value = "npins", env = "NPINS_DIRECTORY" )] folder: std::path::PathBuf, - #[structopt(subcommand)] + /// Print debug messages. + #[arg(global = true, short = 'v', long = "verbose")] + pub verbose: bool, + + #[command(subcommand)] command: Command, } @@ -701,7 +706,7 @@ impl Opts { } let pin_writer = |mut name: StyledContent<&str>, status: &str, index: usize| { - if stderr().is_terminal() { + if stderr().is_terminal() && !self.verbose { let seek_distance = (length - index) as u16; execute!( diff --git a/src/default.nix b/src/default.nix index 7f295e2..735f48a 100644 --- a/src/default.nix +++ b/src/default.nix @@ -1,3 +1,12 @@ +/* + This file is provided under the MIT licence: + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ # Generated by npins. Do not modify; will be overwritten regularly let data = builtins.fromJSON (builtins.readFile ./sources.json); diff --git a/src/git.rs b/src/git.rs index 090cd5a..2ac5ac1 100644 --- a/src/git.rs +++ b/src/git.rs @@ -616,7 +616,10 @@ impl RemoteInfo { /// Convenience wrapper around calling `git ls-remote` async fn fetch_remote(args: &[&str]) -> Result> { + log::debug!("Executing `git ls-remote {}`", args.join(" ")); let process = Command::new("git") + // Disable any interactive login attempts, failing gracefully instead + .env("GIT_TERMINAL_PROMPT", "0") .arg("ls-remote") .args(args) .output() @@ -636,6 +639,10 @@ async fn fetch_remote(args: &[&str]) -> Result> { .unwrap_or_else(|| "None".into()) ); } + log::debug!("git ls-remote stdout:"); + String::from_utf8_lossy(&process.stdout) + .split('\n') + .for_each(|line| log::debug!("> {}", line)); String::from_utf8_lossy(&process.stdout) .split('\n') @@ -648,6 +655,7 @@ async fn fetch_remote(args: &[&str]) -> Result> { !ref_.contains('\t'), "Output line contains more than one '\\t'" ); + log::debug!("Found remote: {}, {}", revision, ref_); Ok(RemoteInfo { revision: revision.into(), ref_: ref_.into(), @@ -776,9 +784,6 @@ fn latest_release<'a>( #[cfg(test)] mod test { use super::*; - use envtestkit::lock::lock_test; - use envtestkit::set_env; - use std::ffi::OsString; #[tokio::test] async fn test_latest_release() { @@ -1204,177 +1209,4 @@ mod test { ); Ok(()) } - - #[tokio::test] - async fn test_gitlab_private_update() -> Result<()> { - let _lock = lock_test(); - let _test = set_env(OsString::from("GITLAB_TOKEN"), "some-invalid-value"); - let pin = GitPin { - repository: Repository::GitLab { - repo_path: "npins-test/npins-private-test".into(), - server: "https://gitlab.com/".parse().unwrap(), - private_token: Some("glpat-MSsRZG1SNdJU1MzBNosV".into()), - }, - branch: "main".into(), - submodules: false, - }; - let version = pin.update(None).await?; - assert_eq!( - version, - git::GitRevision { - revision: "122f7072f026644fbed6abc17c5c2ab3ae107046".into(), - } - ); - assert_eq!( - pin.fetch(&version).await?, - OptionalUrlHashes { - url: Some("https://gitlab.com/api/v4/projects/npins-test%2Fnpins-private-test/repository/archive.tar.gz?private_token=glpat-MSsRZG1SNdJU1MzBNosV".parse().unwrap()), - hash: "0vdhx429r1w6yffh8gqhyj5g7zkp5dab2jgc630wllplziyfqg7z".into(), - } - ); - Ok(()) - } - - #[tokio::test] - async fn test_gitlab_private_release_update() -> Result<()> { - let _lock = lock_test(); - let _test = set_env(OsString::from("GITLAB_TOKEN"), "some-invalid-value"); - let mut pin = GitReleasePin { - repository: Repository::GitLab { - repo_path: "npins-test/npins-private-test".into(), - server: "https://gitlab.com/".parse().unwrap(), - private_token: Some("glpat-MSsRZG1SNdJU1MzBNosV".into()), - }, - pre_releases: false, - version_upper_bound: Some("1.0.1".into()), - release_prefix: None, - submodules: false, - }; - let version = pin.update(None).await?; - assert_eq!( - version, - GenericVersion { - version: "v1.0.0".into(), - } - ); - // Test whether updating works - pin.version_upper_bound = None; - let version = pin.update(None).await?; - assert_eq!( - version, - GenericVersion { - version: "v1.0.1".into(), - } - ); - // Test fetching - assert_eq!( - pin.fetch(&version).await?, - ReleasePinHashes { - revision: "122f7072f026644fbed6abc17c5c2ab3ae107046".into(), - url: Some("https://gitlab.com/api/v4/projects/npins-test%2Fnpins-private-test/repository/archive.tar.gz?private_token=glpat-MSsRZG1SNdJU1MzBNosV".parse().unwrap()), - hash: "0vdhx429r1w6yffh8gqhyj5g7zkp5dab2jgc630wllplziyfqg7z".into(), - } - ); - Ok(()) - } - - #[tokio::test] - async fn test_gitlab_selfhosted_private_update() -> Result<()> { - let _lock = lock_test(); - let _test = set_env(OsString::from("GITLAB_TOKEN"), "some-invalid-value"); - let pin = GitPin { - repository: Repository::GitLab { - repo_path: "npins-test/npins-private-test".into(), - server: "https://git.helsinki.tools/".parse().unwrap(), - private_token: Some("xqgHNxVNdzvMy6cDvreJ".into()), - }, - branch: "main".into(), - submodules: false, - }; - let version = pin.update(None).await?; - assert_eq!( - version, - git::GitRevision { - revision: "122f7072f026644fbed6abc17c5c2ab3ae107046".into(), - } - ); - assert_eq!( - pin.fetch(&version).await?, - OptionalUrlHashes { - url: Some("https://git.helsinki.tools/api/v4/projects/npins-test%2Fnpins-private-test/repository/archive.tar.gz?private_token=xqgHNxVNdzvMy6cDvreJ".parse().unwrap()), - hash: "0vdhx429r1w6yffh8gqhyj5g7zkp5dab2jgc630wllplziyfqg7z".into(), - } - ); - Ok(()) - } - - #[tokio::test] - async fn test_gitlab_selfhosted_private_release_update() -> Result<()> { - let _lock = lock_test(); - let _test = set_env(OsString::from("GITLAB_TOKEN"), "some-invalid-value"); - let mut pin = GitReleasePin { - repository: Repository::GitLab { - repo_path: "npins-test/npins-private-test".into(), - server: "https://git.helsinki.tools/".parse().unwrap(), - private_token: Some("xqgHNxVNdzvMy6cDvreJ".into()), - }, - pre_releases: false, - version_upper_bound: Some("1.0.1".into()), - release_prefix: None, - submodules: false, - }; - let version = pin.update(None).await?; - assert_eq!( - version, - GenericVersion { - version: "v1.0.0".into(), - } - ); - // Test whether updating works - pin.version_upper_bound = None; - let version = pin.update(None).await?; - assert_eq!( - version, - GenericVersion { - version: "v1.0.1".into(), - } - ); - // Test fetching - assert_eq!( - pin.fetch(&version).await?, - ReleasePinHashes { - revision: "122f7072f026644fbed6abc17c5c2ab3ae107046".into(), - url: Some("https://git.helsinki.tools/api/v4/projects/npins-test%2Fnpins-private-test/repository/archive.tar.gz?private_token=xqgHNxVNdzvMy6cDvreJ".parse().unwrap()), - hash: "0vdhx429r1w6yffh8gqhyj5g7zkp5dab2jgc630wllplziyfqg7z".into(), - } - ); - Ok(()) - } - - #[tokio::test] - async fn test_gitlab_private_update_from_env() -> Result<()> { - let _lock = lock_test(); - let _test = set_env(OsString::from("GITLAB_TOKEN"), "glpat-MSsRZG1SNdJU1MzBNosV"); - let pin = GitPin { - repository: Repository::GitLab { - repo_path: "npins-test/npins-private-test".into(), - server: "https://gitlab.com/".parse().unwrap(), - private_token: None, - }, - branch: "main".into(), - submodules: false, - }; - let version = pin.update(None).await?; - assert_eq!( - version, - git::GitRevision { - revision: "122f7072f026644fbed6abc17c5c2ab3ae107046".into(), - } - ); - // The token was not written to the URL - assert_eq!(pin.repository.url(&version.revision)?.expect("no url returned"), - "https://gitlab.com/api/v4/projects/npins-test%2Fnpins-private-test/repository/archive.tar.gz?sha=122f7072f026644fbed6abc17c5c2ab3ae107046".parse().unwrap() - ); - Ok(()) - } } diff --git a/src/main.rs b/src/main.rs index a523751..6e17b4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,11 @@ use std::path::PathBuf; use anyhow::Result; +use clap::Parser; use diff::{Diff, OptionExt}; use reqwest::IntoUrl; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -use structopt::StructOpt; pub mod channel; pub mod cli; @@ -277,13 +277,18 @@ impl diff::Diff for GenericUrlHashes { #[tokio::main] async fn main() -> Result<()> { + let opts = cli::Opts::parse(); + env_logger::builder() - .filter_level(log::LevelFilter::Info) + .filter_level(if opts.verbose { + log::LevelFilter::Debug + } else { + log::LevelFilter::Info + }) .format_timestamp(None) .format_target(false) .init(); - let opts = cli::Opts::from_args(); opts.run().await?; Ok(()) } diff --git a/src/nix.rs b/src/nix.rs index 9825f3d..99567d5 100644 --- a/src/nix.rs +++ b/src/nix.rs @@ -1,4 +1,5 @@ use anyhow::{Context, Result}; +use log::debug; #[allow(unused)] pub struct PrefetchInfo { @@ -8,6 +9,10 @@ pub struct PrefetchInfo { pub async fn nix_prefetch_tarball(url: impl AsRef) -> Result { let url = url.as_ref(); + log::debug!( + "Executing `nix-prefetch-url --unpack --type sha256 {}`", + url + ); let output = tokio::process::Command::new("nix-prefetch-url") .arg("--unpack") // force calculation of the unpacked NAR hash .arg("--type") @@ -27,6 +32,7 @@ pub async fn nix_prefetch_tarball(url: impl AsRef) -> Result { } let stdout = String::from_utf8_lossy(&output.stdout); + log::debug!("Got hash: {}", stdout); Ok(String::from(stdout.trim())) } @@ -36,11 +42,23 @@ pub async fn nix_prefetch_git( submodules: bool, ) -> Result { let url = url.as_ref(); + log::debug!( + "Executing: `nix-prefetch-git {}{} {}`", + if submodules { + "--fetch-submodules " + } else { + "" + }, + url, + git_ref.as_ref() + ); let mut output = tokio::process::Command::new("nix-prefetch-git"); if submodules { output.arg("--fetch-submodules"); } let output = output + // Disable any interactive login attempts, failing gracefully instead + .env("GIT_TERMINAL_PROMPT", "0") .arg(url) .arg(git_ref.as_ref()) .output() @@ -78,6 +96,10 @@ pub async fn nix_prefetch_git( leave_dot_git: bool, } + debug!( + "nix-prefetch-git output: {}", + String::from_utf8_lossy(&output.stdout) + ); let info: NixPrefetchGitResponse = serde_json::from_slice(&output.stdout) .context("Failed to deserialize nix-pfetch-git JSON response.")?; diff --git a/test.nix b/test.nix index 632b316..672b34b 100644 --- a/test.nix +++ b/test.nix @@ -104,7 +104,7 @@ let npins python3 netcat - nix + lix gitMinimal jq nix-prefetch-git @@ -157,7 +157,7 @@ let npins python3 netcat - nix + lix gitMinimal jq ]; @@ -224,7 +224,7 @@ let npins python3 netcat - nix + lix gitMinimal jq ];