Commit graph

31 commits

Author SHA1 Message Date
Jiahao XU
c08b8d232a
feat: Impl new option --continue-on-failure (#1559)
* feat: Impl new option `--continue-on-failure`

Resolve #1548

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Add new e2e-tests continue-on-failure

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Rm dup line ion `e2e-tests/live.sh`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix shellcheck

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `BinstallError::crate_errors` if `errors.len()` is 1

In that case, it should return `Some(Self::CrateContext(_))` instead of
`Some(Self::Errors(_))`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Add more tests to `e2e-tests/continue-on-failure.sh`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Propagate crate errors on `confirm()` err

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Test having two errors in `e2e-tests/continue-on-failure.sh`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

---------

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2024-01-08 12:09:45 +00:00
Félix Saparelli
32beba507b
Initial signing support (#1345)
* Add CLI options

* Add manifest types

* Thread signature policy through to fetchers

* Thread signing section through from metadata

* Implement signing validation

* Clippy

* Attempt testing

* Yes and

* Why

* fmt

* Update crates/bin/src/args.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/gh_crate_meta.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/bin/src/args.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/signing.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/signing.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/signing.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/signing.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* fixes

* Finish feature

* Document

* Include all fields in the signing.file template

* Readme document

* Review fixes

* Fail on non-utf8 sig

* Thank goodness for tests

* Run test in ci

* Add rsign2 commands

* Log utf8 error

* Update e2e-tests/signing.sh

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `e2e-tests/signing.sh` MacOS CI failure

Move the tls cert creation into `signing.sh` and sleep for 10s to wait
for https server to start.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Refactor e2e-tests-signing files

 - Use a tempdir generated by `mktemp` for all certificates-related
   files
 - Put other checked-in files into `e2e-tests/signing`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fixed `e2e-tests-signing` connection err in MacOS CI

Wait for server to start up by trying to connect to it.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `e2e-tests-signing` passing `-subj` to `openssl` on Windows

Use single quote instead of double quote to avoid automatic expansion
from bash

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `e2e-tests-signing` waiting for server to startup

Remove `timeout` since it is not supported on MacOS.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Try to fix windows CI by setting `MSYS_NO_PATHCONV=1` on `openssl` cmds

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fixed `e2e-tests-signing` on windows

By using double `//` for the value passed to option `-subj`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fixed infinite loop in `signing/wait-for-server` on Windows

Pass `--ssl-revoke-best-effort` to prevent schannel from checking ssl
revocation status.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Add cap on retry attempt in `signing/wait-for-server.sh`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Let `singing/server.py` print output to stderr

so that we can see the error message there.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix running `signing/server.py` on MacOS CI

use `python3` since macos-latest still has python2 installed and
`python` is a symlink to `python2` there.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

---------

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-09-23 04:02:56 +00:00
Jiahao XU
0c5a65fb35
Refactor: Extract new crate binstalk-bins (#1294)
To reduce `binstalk` codegen and enable reuse of it.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-08-15 21:48:42 +00:00
Jiahao XU
76c72469eb
Refactor: Extract new crate binstalk-fetchers (#1291)
To reduce `binstalk` codegen and enable better reuse.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-08-14 03:20:34 +00:00
Jiahao XU
623f7ff4ed
Refactor: Extract new crate binstalk-registry (#1289)
To speedup codegen of `binstalk` and enable it to be reused.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-08-13 07:16:53 +00:00
Jiahao XU
8ff13c1b36
Refactor: Extract cargo_toml_workspace as a new crate (#1287)
To reduce codegen time of `binstalk` and also enable others to reuse
this crate.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-08-12 12:05:10 +00:00
Jiahao XU
7dea40a99a
Support --registry and more options from .cargo/config.toml (#1195)
Fixed #885

Now we can take advantage of new argument `--registry` and
env overrides:
 - `CARGO_REGISTRIES_DEFAULT` if `--registry` is not specified
 - `CARGO_REGISTRIES_{registry_name}_INDEX` for the registry index url

We can also read from `.cargo/config.toml` for:
 - default registry and registries configurations
 - additional CA bundle `http.cainfo`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-07-10 03:37:41 +00:00
Jiahao XU
01a87ac606
feat: Impl support for alternative registries (#1184)
Fixed #1168

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-06-30 03:52:40 +00:00
Jiahao XU
ca00cbaccc
feat: Support install directly from git repo (#1162)
Fixed #3

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-06-24 01:01:31 +00:00
Jiahao XU
d8419ea5a2
feat: Add more variables for template (#1160)
Fixed #775

 - Add dep target-lexicon v0.12.7
 - Add `target-{family, arch, libc, vendor}` to
   `package.metadata.binstall`.

For `{universal, universal2}-apple-darwin`, the `target-arch` is set to
`universal`.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-06-20 22:05:13 +00:00
Jiahao XU
22b3419fce
feat: Add GraphQL support to GhApiClient (#1124)
Fixed #868

 - Add new fn `remote::Client::post`
 - Add new fn `remote::RequestBuilder::body`
 - Re-export `reqwest::Body` in `remote`
 - Add dep percent-encoding v2.2.0 to binstalk-downloader
 - Add dep serde-tuple-vec-map v1.0.1 to binstalk-downloader
 - Add GraphQL to `GhApiClient`, fallback to Restful API if token is not
   provided or authorization failed.
 - Fixed `GhReleaseArtifact::try_extract_artifact_from_str`: decode
   percent encoded http url path and add regression tests
 - Added variant `GhApiError::Context` & `GhApiContextError`
 - Added variant `GhApiError::GraphQLErrors` & `GhGraphQLErrors`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-06-04 14:09:49 +00:00
Jiahao XU
a27d5aebf6
Use leon for template in binstalk & detect malformed pkg-url/pkg-fmt early (#933)
Fixed #851

* Add new dep leon to crate binstalk
* Add new variant `BinstallError::Template{Parse, Render}Error`
* Use `leon::Template` in mod `bins`
* Use `leon::Template` in mod `fetchers::gh_crate_meta`
* Refactor mod `bins`: Rm unused associated fn & fields from `Context`
* Simplify unit testing in mod `fetchers::gh_crate_meta`
* Rm soft-deprecated field `fetchers::gh_crate_meta::Context::format`
  and change the `match` to resolve `archive` => `self.archive_format`.
* Make macro_rules `leon::template!` far easier to use
* Construct `leon::Template<'_>` as constant in `gh_crate_meta::hosting`
* Simplify `leon::Values` trait
   Change its method `get_value` signature to
   
   ```rust
       fn get_value(&self, key: &str) -> Option<Cow<'_, str>>;
   ```
   
   Now, `ValuesFn` also accepts non-`'static` function, but now
   `leon::Values` is only implemented for `&ValuesFn<F>` now.
   
   This makes it a little bit more cumbersome to use but I think it's a
   reasonable drawback.
* Rm `Send` bound req from `ValuesFn`
* Impl new fn `leon::Template::cast`
   for casting `Template<'s>` to `Template<'t>` where `'s: 't`
* Rename `leon::Template::has_keys` => `has_any_of_keys`
* Make checking whether format related keys are present more robust
* Optimize `GhCrateMeta::launch_baseline_find_tasks`: Skip checking all fmt ext
   if none of the format related keys ("format", "archive-format",
   "archive-suffix") are present.
* Only ret `.exe` in `PkgFmt::extensions` on windows
   by adding a new param `is_windows: bool`
* Improve debug msg in `GhCrateMeta::fetch_and_extract`
* Add warnings to `GhCrateMeta::find`
* Rm dep tinytemplate
* `impl<'s, 'rhs: 's> ops::AddAssign<&Template<'rhs>> for Template<'s>`
* `impl<'s, 'rhs: 's> ops::AddAssign<Template<'rhs>> for Template<'s>`
* `impl<'s, 'item: 's> ops::AddAssign<Item<'item>> for Template<'s>`
* `impl<'s, 'item: 's> ops::AddAssign<&Item<'item>> for Template<'s>`
* `impl<'s, 'rhs: 's> ops::Add<Template<'rhs>> for Template<'s>` (improved existing `Add` impl)
* `impl<'s, 'rhs: 's> ops::Add<&Template<'rhs>> for Template<'s>`
* `impl<'s, 'item: 's> ops::Add<Item<'item>> for Template<'s>`
* `impl<'s, 'item: 's> ops::Add<&Item<'item>> for Template<'s>`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
Co-authored-by: Félix Saparelli <felix@passcod.name>
2023-03-26 16:11:10 +11:00
Jiahao XU
8eee318ccd
Replace dep crates_io_api with in-house solution (#846)
It also uses `max_stable_version` in the json downloaded from https://crates.io/api/v1/crates/$name if possible, which is equivalent to the version shown on https://crates.io/crates/$name .

 - Add new feat `json` to `binstalk-downloader`
 - Impl new async fn `Response::json`
 - use `Response::json` in `GhApiClient` impl
 - Mark all err types in binstalk-downloader as `non_exhaustive`
 - Ret `remote::Error` in `remote::Certificate::{from_pem, from_der}` instead of `ReqwestError`.
 - Refactor `BinstallError`: Merge variant `Unzip`, `Reqwest` & `Http`
    into one variant `Download`.
 - Manually download and parse json from httos://crates.io/api/v1
 - Remove unused deps `crates_io_api`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-03-02 18:25:34 +11:00
Jiahao XU
599bcaf333
Impl GhApiClient and use it in cargo-binstall to speedup resolution process (#832)
Fixed #776

 - Add new feature gh-api-client to binstalk-downloader
 - Impl new type `binstalk_downloader::remote::{RequestBuilder, Response}`
 - Impl `binstalk_downloader::gh_api_client::GhApiClient`, exposed if `cfg(feature = "gh-api-client")` and add e2e and unit tests for it
 - Use `binstalk_downloader::gh_api_client::GhApiClient` to speedup `cargo-binstall`
 - Add new option `--github-token` to supply the token for GitHub restful API, or read from env variable `GITHUB_TOKEN` if not present.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-03-02 12:04:22 +11:00
Jiahao XU
d9dd611b9e
Improve fmt::Display impl for all Error types (#781)
Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-02-10 14:01:22 +11:00
Jiahao XU
e510511487
Improve GhCrateMeta: Detect cases where pkg-fmt is not specified (#757)
* Fix fmt of mod `<GhCrateMeta as Fetcher>::find`
* Add new variant `BinstallError::InvalidPkgFmt`
* Impl new fn `PkgFmt::guess_pkg_format`
* Improve `GhCrateMeta`: Detect cases where `pkg-fmt` is not specified
  
  but `pkg-url` also does not contain format, archive-format or
  archive-suffix which is required for automatically deducing the pkg-fmt.
  
  In these cases, we would call `PkgFmt::guess_pkg_format` to try out best
  to figure out the pkg-fmt, otherwise we just return an error.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-02-04 10:47:57 +13:00
Jiahao XU
daec880008
Rm unused variant binstalk_downloader::download::DownloadError::UserAbort (#653)
Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-01-06 02:08:57 +13:00
Jiahao XU
887ebb6f6f
Fix BinstallError::CrateContext: Forward diagnostics of field CrateContextError::err (#586)
Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-12-03 12:12:04 +00:00
Jiahao XU
a69db83aa6
Fix error reporting in main and move all arg validation into fn args::parse (#585)
* Fix reporting parsing error from `args::parse`
   Report it in `args::parse` by using `Args::command().error(...).exit()`
   instead of returning `BinstallError`.
* Rm unused variant `BinstallError::OverrideOptionUsedWithMultiInstall`
* Refactor: Move `strategies` validation into `args::parse`
* Rm unused variant `BinstallError::InvalidStrategies`
* Add new unit test `args::test::verify_cli`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-12-03 11:57:50 +00:00
Jiahao XU
8a5577297e
Optimize BinstallError: Reduce size from 40B to 32B (#581)
* Optimize `BinstallError::CratesIoApi`: Extract new type `errors::CratesIoApiError` and box it
   Also improve `<CratesIoApiError as Display>::fmt` impl.
* Optimize `BinstallError::SubProcess`: Use `Box<str>` instead of `String`
* Optimize `BinstallError::CargoManifest`: Box `CargoTomlError`
* Optimize `BinstallError::VersionParse`: Extract `VersionParseError` and box it
   Also improve `<VersionParseError as Display>::fmt` impl.
* Optimize `BinstallError::CrateContext`: Extract `CrateContextError` and box it in
* Optimize `install_from_source`: Only format `cmd` on err

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-12-01 20:05:00 +13:00
Jiahao XU
83b2de3ea2
Enforce strict strategies parsing rule: Reject duplicate strategy in --strategies (#545)
`cargo-binstall` should reject duplicate strategy in `--strategies` as it is illegal input and it cannot be interpreted reasonably.

* Reject duplicate strategy in `--strategies`
* Optimize `compute_resolvers`: Use `Vec::retain`
   instead of `Iterator::filter` plus collecting into `Vec`.
* Optimize `compute_resolvers`: Reject `strategies.len() > Strategy::COUNT`
* Improve err msg for cases where user disabled all strategies
* Simplify `BinstallError::InvalidStrategies`: Takes `&'static str`
   instead of `&'static &'static str` since other variants are larger than 8B.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-11-21 12:02:58 +11:00
Jiahao XU
c34a2850b3
Optimization: Box variants in Error to reduce size and remove unused variants in BinstallError (#530)
* Box `HttpError` in `binsalk_downloader::remote::Error::Http`
   as `HttpError` contains `Url` which are too big.
* Box `HttpError` in `BinstallError::Http` same as the previous commit.
* Box `TinyTemplateError` in `BinstallError::Template`
  since `TinyTemplateError` is 56 bytes large where most of the other variants are below 40 bytes large.
* Rm unsed variant `BinstallError::VersionUnavailable`
* Box `CratesIoApiError` in `BinstallError::CratesIoApi`
   It is 32 bytes large while other variants are below 40 bytes large.
* Improve err msg for `BinstallError::CrateContext`
* Rm unused variant `BinstallError::VersionReq`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-11-15 02:46:32 +13:00
Jiahao XU
90495b35d8
Enable coloring in console log (#528)
* Enable feat ansi of dep tracing-subscriber
* Rm use of `tracing_appender::non_blocking`
  since `cargo-binstall` is so simple that it doesn't need it.
* Use `tracing::{error, info}` in `MainExit::report`
* Use `tracing::{error, warn}` in `BinstallError::report`
* Add dep supports-color v1.3.1 to crates/bin
* Enable ansi of `tracing_subscriber::fmt` if stdout supports it

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-11-13 22:45:19 +13:00
Jiahao XU
9e80cf0700
Feature: Impl opt-out options (#510)
Fixed #136

* Impl opt-out optioins in binstalk
* Replace field `Options::{gh_crate, quickinstall}_fetcher` with `resolver`
  which can determine order of resolver used.
* Add new field `Args::{disable_}strategies`
* Add new variant `BinstallError::InvalidStrategies`
* Add variant `BinstallError::NoFallbackToCargoInstall`
* Add code for supporting strategies in mod entry
* Test `--disable-strategies` in `tests.sh`
* Test for `--strategies` in `tests.sh`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-11-11 05:24:46 +00:00
Jiahao XU
89fa5b1769
Refactor: Extract new crate binstalk-{signal, downloader} (#518)
* Refactor: Extract new crate binstalk-downloader
* Re-export `PkgFmt` from `binstalk_manifests`
* Update release-pr.yml
* Update dependabot

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-11-11 04:02:54 +00:00
Jiahao XU
3841762a5b
Replace simplelog with tracing_subscriber::fmt (#525)
* Disable feat log-always of dep tracing
* Add dep tracing-log 0.1.3 with no feat
* Add new dep tracing-appender v0.2.2
* Add dep tracing-subscriber 0.3.16 with feat fmt and json
* Fix `MainExit::report`: Do not use `log::{error, warn}`
  since `MainExit::report` might be called with no `log`ger, it can only
  use `println!` and `eprintln!`.
* Use `tracing_subscriber::fmt` instead of `simple_log`
* Rm unused dep simplelog from crates/bin
* Fix `BinstallError::report`: Avoid `log::{warn, error}`
   since they might be called after `tracing_appender::WorkerGuard` is
   dropped.
* Make tracing output more readable to end users
* Add new dep tracing-core v0.1.30
* Add new dep once_cell v1.16.0
* Refactor: Extract new mod `logging`
* Add new option `Args::json_output`
* Fix `MainExit::report`: Ignore io error
* Fix `BinstallError::report`: Ignore IO error

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-11-11 12:05:09 +13:00
Jiahao XU
aa6012baae
Make extraction cancellable for bin and tar based formats (#481)
Extraction wasn't cancellable by `cancel_on_user_sig_term` used in `entry` since it calls `block_in_place`.

This PR adds cancellation support to it by adding a `static` variable `OnceCell` to `wait_on_cancellation_signal` so that once it returns `Ok(())`, all other calls to it after that point also returns `Ok(())` immediately.

`StreamReadable`, which is used in cancellation process, then stores a boxed future of `wait_on_cancellation_signal` and polled it in `BufReader::fill_buf`.

Note that for zip, the extraction process takes `File` instead of `StreamReadable` due to `io::Seek` requirement, so it cancelling during extraction for zip is still not possible.

This PR also optimized `extract_bin` and `extract_zip` by using `StreamReadable::copy` introduced to this PR instead of `io::copy`, which allocates an internal buffer on stack, which imposes extra copy.

It also fixed `StreamReadable::fill_buf` by ensuring that empty buffer is only returned on eof.

* Make `wait_on_cancellation_signal` pub
* Enable feature `parking_lot` of dep tokio
* Mod `wait_on_cancellation_signal`: Use `OnceCell` internally
   to archive the effect that once call to it return `Ok(())`, all calls to
   it after that also returns `Ok(())`.
* Impl `From<BinstallError>` for `io::Error`
* Impl cancellation on user signal in `StreamReadable`
* Fix err msg when cancelling during extraction in `ops::resolve`
* Optimize: Impl & use `StreamReadable::copy`
   which is same as `io::copy` but does not allocate any internal buffer
   since `StreamReadable` is buffered.
* Fix `next_stream`: Return non-empty bytes on `Ok(Some(bytes))`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-10-13 13:31:13 +13:00
Jiahao XU
3421403e75
Refactor and Optimizations (#459)
* Refactor: Avoid parsing `package.version()` twice in `ops::resolve` and `ops::install`
* Optimize Resolution: Replace `Package<Meta>` with two `CompactStrings`: `name` and `version`
* Use `CompactString` for `BinstallError::CratesIoApi::crate_name`
* Use `CompactString` for `BinstallError::VersionParse::v`
* Use `CompactString` for `BinstallError::VersionReq::req`
* Use `CompactString` for `BinstallError::VersionUnavailable::crate_name`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-10-06 04:19:12 +13:00
Jiahao XU
3da5cb9d9c
Check source_file_path to ensure it is valid (#421)
* Add new variant `BinstallError::DuplicateSourceFilePath`
* Check `bin.source` in `collect_bin_files`
* Add new variant `BinstallError::InvalidSourceFilePath`
* Make sure generated source_file_path cannot access outside curdir
* Add new variant `BinstallError::EmptySourceFilePath`
* Ensure source_file_path is not empty

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-09-25 13:32:34 +00:00
Jiahao XU
fa79e7f105
Verify that bin_files exist in resolve stage (#382)
* Refactor: Extract new fn `BinFile::check_source_exists`
* Impl new async fn `AutoAbortJoinHandle::flattened_join`
* Impl new fn `Fetcher::fetcher_name`
* Verify that `bin_files` exist in `resolve` stage
   To ensure that the installation stage won't fail because of missing
   binaries.
* Rm unused `MultiFecther`
* Simplify `Future` impl for `AutoAbortJoinHandle`
* Add new variant `BinstallError::CargoTomlMissingPackage`
* Replace `unwrap` in `resolve_inner` with proper error handling
* Make `Fetcher::new` as a regular function
   instead of an `async` function.
* Ret `Arc<dyn Fetcher>` in trait fn `Fetcher::new`
* Refactor `resolve_inner`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-09-17 09:28:22 +00:00
Félix Saparelli
e25aa50ec9
Rename lib to binstalk (#361) 2022-09-10 16:44:18 +10:00
Renamed from crates/lib/src/errors.rs (Browse further)