983 Commits

Author SHA1 Message Date
Zeke Fast
48ef918d51 Migrate "hagrid-tester" to Clap v4 derive based API. Clean up code along the way.
Changes:
- Add "derive" feature for "clap" in tester/Cargo.toml.
- Move about description from tester/src/cli.rs to "description" field in
  tester/Cargo.toml. So, "clap" can access it via #[command(about)]
  macro configuration.
- Update Cargo.lock.
- Replace in tester/src/cli.rs usage of clap::App from Clap 2.34.0
  with clap::Parser derive macro based API, cli::Cli struct and cli::Command
  enum.
- Remove "--config/-c <FILE>" option for "tester" as it wasn't used and
  I believe it was a copy-paste from "hagridctl".
- Omit explicit specification of args name which resulted in upper
  casing cmd option's parameters, e.g. "<cert count>" -> "<CERT_COUNT>".
- Replace in cli::dispatch_cmd() "if let" based logic with simple match
  on cli::Command enum variants.
- Get rid of manual parsing of options' and commands' values in
  cli::dispatch_cmd(). As it is hadled by derived
  value_parser (https://docs.rs/clap/latest/clap/_derive/index.html#arg-attributes)
  based on field types.
- Make "fprs_path" parameter of tester::generate::do_generate function
  obligatory (previously it was Option<&Path>) as this argument has a
  default value to "fingerprints.txt" which is populated by clap. So, it
  never be None.
  In addition, clean up logic related to optional "fprs_path" parameter
  in tester::generate::do_generate function.
- Change signatures of the following functions to accept
  "impl AsRef<Path>" instead of &Path or Option<&Path>:
  - tester::generate::do_generate()
  - tester::genreqs::do_genreqs()
  That allows us to pass as function arguments anything from which Path
  can be borrowed, e.g. PathBuf without the need to explicitly transform
  the value at call site with calls like .as_path() or .as_deref().
- Replace in tester/src/main.rs cli::app().get_matches() (which is Clap
  v2 API) with cli::Cli::parse() (Clap v4 API).
2025-05-04 10:58:49 +02:00
Zeke Fast
333727a6dc Bump "clap" dependency version in Cargo.toml: "2" -> ">= 4.5.37".
Commands:

    cargo update clap@2.34.0

Additional Changes:
- Update Cargo.lock.
2025-05-04 10:58:49 +02:00
Zeke Fast
a7186bb6df Extract error printing logic from src/delete/main.rs to cli::print_errors function.
Changes:
- Extract error printing logic from src/delete/main.rs to cli::print_errors function.
- Move return error code from magic constant to crate::delete:ERROR_EXIT_CODE constant.
- Rename crate::delete::real_main() to crate::delete::run().
2025-05-04 10:58:48 +02:00
Zeke Fast
83b0515274 Extract "delete" action from src/delete/main.rs to its own module ("delete").
This is to better separate CLI handling, wiring and action logic.
2025-05-04 10:58:48 +02:00
Zeke Fast
b296157c08 Extract cmd dispatch code from src/delete/main.rs to delete::cli module.
Changes:
- Introduce cli::dispatch_cmd() function which just delegate to delete function.
2025-05-04 10:58:48 +02:00
Zeke Fast
abeafbe3d4 Move option parsing logic from src/delete/main.rs to newly introduced delete::cli module.
Changes:
- Introduce "delete::cli" module in "hagrid" crate.
- Move option parsing logic there from src/delete/main.rs (former src/delete.rs).
2025-05-04 10:58:47 +02:00
Zeke Fast
d35136b0d6 Promote src/delete.rs module to directory in "hagrid" crate.
Additional Changes:
- Change "hagrid-delete" bin declaration in Cargo.toml accordingly.
2025-05-04 10:58:47 +02:00
Zeke Fast
9acb4b52db Extract config related code in "hagridctl" crate from main.rs to "config" module.
Changes:
- Move the following structs from main.rs to "config" module:
  - HagridConfigs
  - HagridConfig
- Introduce "config::load" function and move configuration loading code into it.
- Adjust imports accordingly.
- Share ArgMatches returned by App::get_matches between
  config::load and cli::dispatch_cmd functions.
- Make HagridConfigs struct private to the config module as rest of the
  system doesn't need to know about it and interacts only with
  HagridConfig struct.
2025-05-04 10:58:47 +02:00
Zeke Fast
c0c8247c42 Extract CLI UI code in "hagridctl" crate from main.rs to "cli" module.
Additional Changes:
- Split "app" construction and command dispatch phases into different
  functions, hence app() and dispatch_cmd() functions.
2025-05-04 10:58:11 +02:00
Zeke Fast
f8982939aa Extract CLI UI code in "tester" crate from main.rs to "cli" module.
Additional Changes:
- Split "app" construction and command dispatch phases into different
  functions, hence app() and dispatch_cmd() functions.
2025-05-03 11:06:05 +02:00
Zeke Fast
b66fb67302 Add "just" recipes and aliases for runing bin-artifacts.
This allows for much more convenient cmd binary launching without the need
to remember distinction bitween binaries in main crate (hagrid) and
others (hagridctl, tester) and need to provide additional -- to cargo to
pass arguments to binaries.

Apart from convenience it also provide kinda "documentation" of binary
artifacts in the project as "run" group in just collect all the
artifacts together.

Changes:
- Add new named aliases for `just run` which runs "hagrid" binary with web
  server:
  - run-hagrid
  - hagrid
- Add new recipe to run "hagrid-delete" binary "run-hagrid-delete".
- Alias "run-hagrid-delete" recipe as
  - hagrid-delete
  - delete
- Add new recipe to run "hagridctl" crate with default binary
  "run-hagridctl".
- Alias "run-hagridctl" recipe as
  - hagridctl
- Add new recipe to run "tester" crate with default binary "run-tester".
- Alias "run-tester" recipe as
  - tester
2025-05-03 09:43:00 +02:00
Zeke Fast
84cfb5afaf Move development dependencies documentation from DEPENDENCIES.md to README.md.
Code review issue: https://gitlab.com/keys.openpgp.org/hagrid/-/merge_requests/213#note_2481434850
2025-05-02 16:04:52 +02:00
Zeke Fast
e966c1fbb7 Remove not used file contrib/hagrid-daily-backup.
Code review issue: https://gitlab.com/keys.openpgp.org/hagrid/-/merge_requests/213#note_2481434830
2025-05-02 16:04:52 +02:00
Zeke Fast
70b0eeb3e7 Introduce DEPENDENCIES.md file with list of software help for development. Reference DEPENDENCIES.md from README.md.
Changes:
- Document software dependencies for development process in
  DEPENDENCIES.md. file.
- Reference DEPENDENCIES.md from README.md.
2025-05-02 16:04:51 +02:00
Zeke Fast
7156d92246 Introduce justfile with bunch of recipes to streamline project development.
To install `just` follow instructions in
documentation https://just.systems/man/en/packages.html .

Full list of recipes and their description can be viewed by running
`just` command in project's root directory.

But here is the list of added commands for documentation sake:
- init                    # Perform initial setup of developer's system.
- init-rocket-config      # Copy Rocket's template configuration from Rocket.toml.disk to Rocket.toml. Rocket is Rust web framework. See https://rocket.rs/guide/v0.5/configuration/#configuration
- just-fmt                # Format justfile
- cargo-fmt               # Format Rust code in all packages (aka path based dependencies)
- fmt                     # Format all code [alias: f]
- just-lint-fmt           # Check justfile formatting
- cargo-lint-fmt          # Check Rust code formatting in all packages (aka path based dependencies)
- lint-fmt                # Check formatting of all code [alias: lf]
- clippy-lint             # Lint Rust code with Clippy [alias: cl]
- lint                    # Lint all code [alias: l]
- clippy-fix *args        # Apply Clippy's lint suggestions, i.e. fix Clippy linting warnings or errors
- cargo-fix *args         # Fix compilation warnings by applying compiler suggestions
- fix *args               # Fix lint and compilation warnings and errors. Pass given arguments to all sub-recipes, i.e. `just fix --allow-dirty` calls `just cargo-fix --allow-dirty` and `just clippy-fix --allow-dirty`.
- check                   # Check Rust code errors [alias: c]
- build                   # Compile Rust code [alias: b]
- test args='--workspace' # Run all tests (i.e. --workspace), but when args given pass them to `cargo test`, e.g. `just test fs::tests::init` [alias: t]
- run                     # Run web server [alias: r]
- watch-check *args       # Run continuous check of Rust code errors. Detect file changes and repeat check automatically. Ctrl+c to exit. You can pass additional arguments, e.g. --notify (-N). [alias: wc]
- watch-run *args         # Run web server and automatically restart on changes. Ctrl+c to exit. You can pass additional arguments, e.g. --notify (-N). [alias: wr]
- watch-test *args        # Run tests every time files changed. Ctrl+c to exit. You can pass additional arguments, e.g. --notify (-N). [alias: wt]
- clean                   # Clean compilartion artifacts (i.e. "target" directory)
- clean-translations      # Clean changes to translation files
- translate-templates     # Translate *.hbs templates of web pages
- db                      # Open database prompt
2025-05-02 16:04:51 +02:00
Zeke Fast
893f99c460 Improve error reporting in Zsh scripts by providing -euo pipefail options.
Documentation: https://linux.die.net/man/1/zshoptions
-e Exit on non-zero return code from commands
-u NO_UNSET
-o pipefail propagates piping errors
2025-05-01 00:24:11 +02:00
Zeke Fast
90d00637a0 Replace usage of deprecated cmd option "--all" with "--workspace" for "cargo test" command in .gitlab-ci.yml file.
`cargo help test` on 1.86.0 version says:

>       --all
>           Deprecated alias for --workspace.
2025-05-01 00:19:46 +02:00
Zeke Fast
3a3aba5db1 Replace redundant match expression with .unwrap_or_else. 2025-04-30 09:25:06 +02:00
Zeke Fast
0a829824dc Eliminate redundant conversions to Option and usage of filter_map. Use flat_map directly instead.
Documentation:
- https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map
- https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.flat_map

Additional Changes:
- Use point-less style and pass Email::try_from function directly to
  flat_map.
  flat_map passes uid to Email::try_from implicitly. That's why it's
  called point-less style. IMO it looks nicer!
2025-04-30 09:25:06 +02:00
Zeke Fast
51a66d643d Get rid of aliasing of "hagrid_database" as "database".
It improves code readability and consistency. In addition, less names
used in the code base.
2025-04-30 09:25:06 +02:00
Zeke Fast
2059c69226 Get rid of aliasing of "sequoia_openpgp" as "openpgp".
It improves code readability and consistency. In addition, less names
used in the code base.
2025-04-30 09:25:06 +02:00
Zeke Fast
0bea4f0f2a Remove imports of anyhow::Error and use named path anyhow::Error in place.
This is done for the same reason as for anyhow::Result and
core::result::Result types.

Error is whidely used name and IMO it usually good to keep it standard.
Apart from that I think assosicated type specification looks fore
readable when anyhow::Error is used in place. For example:

    type Error = Error;

was replaced with

    type Error = anyhow::Error;

Changes:
- Replace usage of imported unquolified Error type with anyhow::Error.
- Remove imports of anyhow::Error.
2025-04-30 09:25:05 +02:00
Zeke Fast
4d57dc1eb2 Replace imported anyhow::Result with usage of anyhow::Result in place.
This is to make this few files to much in style rest of code base.
2025-04-30 09:25:05 +02:00
Zeke Fast
0cfd412907 Clean up linting warnings about unused imports.
warning: unused import: `std::result`
     --> database/src/types.rs:3:5
      |
    3 | use std::result;
      |     ^^^^^^^^^^^
      |
      = note: `#[warn(unused_imports)]` on by default
2025-04-30 09:25:05 +02:00
Zeke Fast
9094b09b27 Format code. 2025-04-30 09:25:05 +02:00
Zeke Fast
c28e6af441 Restore default Result type to std::result::Result (aka core::result::Result).
Result it widely used type and the name is highly overloaded as almost
every library tend to define they own Result type.
When default Result type deviates from default it is usually harder to
read code and requires a bit of investigation work to understand this
particular Result corresponds to.

In Hagrid code base in many places anyhow::Result was made a default
type. It usually was imported through indirection, i.e.

    use anyhow::Result;

was imported in files like

- database/src/lib.rs
- hagridctl/src/import.rs
- hagridctl/src/main.rs
- src/main.rs

and in submodules that above import was reimported with something like

    use crate::Result;

or

    use super::Result;

So, I qualified such Result as anyhow::Result which IMO make code easier
to understand and "anyhow" is short enough name to use along with
Result.
All imports and reimports was cleaned up.

Changes:
- Full qualify anyhow's Result name as anyhow::Result in places where it
  is used to make code easier to read and understand.
- Remove imports and reimports of anyhow::Result.
- Restore default Result type to core::result::Result (aka std::result::Result).
- Clean up unnecesary name path qualification for Result type
  like "std::result" or "result" as it becomes a default one and doesn't
  overriden any more.
2025-04-30 09:25:04 +02:00
Zeke Fast
37e6b2cb09 Remove "lazy_static" crate dependency from Cargo.toml.
Additional Changes:
- Update Cargo.lock.
2025-04-29 23:28:30 +02:00
Zeke Fast
fefebaaffe Replace usage of lazy_static! macro with std::sync::LazyLock.
Now as we on new version of Rust (1.86.0) we can benefit from fairly
recent addition to std, like LazyLock. Nice benefit is one less crate to
depend on.

Documentation:
- https://crates.io/crates/lazy-static
- https://blog.rust-lang.org/2024/07/25/Rust-1.80.0/#lazycell-and-lazylock
- https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html

Not particularly useful for code changes, but might be helpful for thus
who want to navigate these Once, Lazy, Cell, Lock types and figure out
differences between them.

Additional Documentation:
- https://crates.io/crates/once_cell
- https://blog.rust-lang.org/2023/06/01/Rust-1.70.0/#oncecell-and-oncelock
- https://doc.rust-lang.org/stable/core/cell/index.html
- https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html

Changes:
- Move the following statics out of lazy_static! macro and initialize
  them using std::sync::LazyLock:
  - POPULAR_DOMAINS
  - KEY_UPLOAD
  - MAIL_SENT
  - KEY_ADDRESS_PUBLISHED
  - KEY_ADDRESS_UNPUBLISHED
- Remove lazy_static imports.
2025-04-29 23:28:30 +02:00
Zeke Fast
9bc3ccecac Format code (mostly imports).
Commands:

    cargo fmt --all
2025-04-28 00:38:39 +02:00
Zeke Fast
09072200d6 Replace "extern crate" and #[macro_use] declarations with "use" imports.
Both "extern crate" and #[macro_use] are artifacts of earlier editions
of Rust language. Nowadays we can entirely rely on "use" instead.

Changes:
- Replace "extern crate" with "use" imports.
- Replace

    #[macro_use]
    extern crate ...;

  declarations with "use" imports of used macros. For example,

    #[macro_use]
    extern crate anyhow;

  was replaced with

    use anyhow::anyhow;

  in every file where anyhow! macro were used.
- Favor direct usage of import path instead of aliased one.
  For example, in many places "sequoia_opengpg" were aliased as "openpgp",
  during imports replacements I tried to avoid usage of "openpgp" or
  introduced additional aliases (like "use sequoia_openpgp as openpgp")
  and used "sequoia_opengpg".
  I think this way it is easier to understand where name came from
  instead of search and jumping to lib.rs or main.rs files trying to
  find where name were aliased.
  Another example of such favoring is usage of "hagrid_database" over
  the "database" in imports.
  NOTE: the usage is still inconsistent and requires further clean up.
2025-04-27 23:36:59 +02:00
Zeke Fast
5399e6c2d3 Update CI image in .gitlab-ci.yml: "rust:1-bullseye" -> "rust:1.86-bookworm". 2025-04-27 18:48:29 +02:00
Zeke Fast
77372abb7c Add "rustfmt" and "clippy" to components in rust-toolchain.toml file.
Documentation:
- https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file
- https://rust-lang.github.io/rustup/concepts/components.html
2025-04-27 18:31:58 +02:00
Zeke Fast
0200c15266 Format code.
Commands:

    cargo fmt --all
2025-04-27 18:12:57 +02:00
Zeke Fast
e4aac748be Clean up linting warnings: this manual char comparison can be written more succinctly.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: this manual char comparison can be written more succinctly
       --> src/web/vks_api.rs:117:37
        |
    117 |         .flat_map(|lang| lang.split(|c| c == '-' || c == ';' || c == '_').next())
        |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['-', ';', '_']`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison
        = note: `#[warn(clippy::manual_pattern_char_comparison)]` on by default
2025-04-27 18:04:41 +02:00
Zeke Fast
8b6049cb45 Clean up linting warnings: manual implementation of split_once.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: manual implementation of `split_once`
       --> src/mail.rs:340:17
        |
    340 |                 let mut it = line.splitn(2, ": ");
        |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    341 |                 let h = it.next().unwrap();
        |                 --------------------------- first usage here
    342 |                 let v = it.next().unwrap();
        |                 --------------------------- second usage here
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once
        = note: `#[warn(clippy::manual_split_once)]` on by default
    help: replace with `split_once`
        |
    340 ~                 let (h, v) = line.split_once(": ").unwrap();
    341 ~
    342 ~
        |
2025-04-27 17:53:56 +02:00
Zeke Fast
45402ddd07 Clean up linting warnings: unnecessary closure used with `bool::then.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: unnecessary closure used with `bool::then`
       --> src/dump.rs:125:21
        |
    125 |                     pp.decrypt(algo, &sk.session_key).is_ok().then(|| algo)
        |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations
        = note: `#[warn(clippy::unnecessary_lazy_evaluations)]` on by default
    help: use `then_some` instead
        |
    125 -                     pp.decrypt(algo, &sk.session_key).is_ok().then(|| algo)
    125 +                     pp.decrypt(algo, &sk.session_key).is_ok().then_some(algo)
        |
2025-04-27 17:46:04 +02:00
Zeke Fast
e85e414619 Clean up linting warnings: allocating a new String only to create a temporary &str from it.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: allocating a new `String` only to create a temporary `&str` from it
       --> database/src/test.rs:109:37
        |
    109 |         let email = Email::from_str(&String::from_utf8(uid.value().to_vec()).unwrap()).unwrap();
        |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
        = note: `#[warn(clippy::unnecessary_to_owned)]` on by default
    help: convert from `&[u8]` to `&str` directly
        |
    109 -         let email = Email::from_str(&String::from_utf8(uid.value().to_vec()).unwrap()).unwrap();
    109 +         let email = Email::from_str(core::str::from_utf8(uid.value()).unwrap()).unwrap();
        |

    warning: allocating a new `String` only to create a temporary `&str` from it
       --> database/src/test.rs:137:37
        |
    137 |         let email = Email::from_str(&String::from_utf8(uid.value().to_vec()).unwrap()).unwrap();
        |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
    help: convert from `&[u8]` to `&str` directly
        |
    137 -         let email = Email::from_str(&String::from_utf8(uid.value().to_vec()).unwrap()).unwrap();
    137 +         let email = Email::from_str(core::str::from_utf8(uid.value()).unwrap()).unwrap();
        |
2025-04-27 17:36:39 +02:00
Zeke Fast
fcc9689ef3 Clean up linting warnings: manually reimplementing div_ceil.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: manually reimplementing `div_ceil`
      --> hagridctl/src/import.rs:58:22
       |
    58 |     let chunk_size = (input_files.len() + (num_threads - 1)) / num_threads;
       |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `input_files.len().div_ceil(num_threads)`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil
       = note: `#[warn(clippy::manual_div_ceil)]` on by default
2025-04-27 17:26:52 +02:00
Zeke Fast
896206d6ca Clean up linting warnings: this if has identical blocks.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: this `if` has identical blocks
      --> database/src/openpgp_utils.rs:89:27
       |
    89 |           if !is_exportable {
       |  ___________________________^
    90 | |             false
    91 | |         } else if is_status_revoked(uid.revocation_status(&POLICY, None)) {
       | |_________^
       |
    note: same as this
      --> database/src/openpgp_utils.rs:91:75
       |
    91 |           } else if is_status_revoked(uid.revocation_status(&POLICY, None)) {
       |  ___________________________________________________________________________^
    92 | |             false
    93 | |         } else if let Ok(email) = Email::try_from(uid.userid()) {
       | |_________^
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
       = note: `#[warn(clippy::if_same_then_else)]` on by default
2025-04-27 17:11:24 +02:00
Zeke Fast
f4699a4545 Clean up linting warnings: accessing first element with index 0.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: accessing first element with `self.catalogs.get(0)`
      --> src/i18n.rs:21:32
       |
    21 |             .unwrap_or_else(|| self.catalogs.get(0).unwrap());
       |                                ^^^^^^^^^^^^^^^^^^^^ help: try: `self.catalogs.first()`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#get_first
       = note: `#[warn(clippy::get_first)]` on by default

    warning: accessing first element with `tpk_status
                     .email_status.get(0)`
       --> src/web/vks.rs:364:23
        |
    364 |       let primary_uid = tpk_status
        |  _______________________^
    365 | |         .email_status
    366 | |         .get(0)
        | |_______________^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#get_first
    help: try
        |
    364 ~     let primary_uid = tpk_status
    365 +         .email_status.first()
        |
2025-04-27 16:59:14 +02:00
Zeke Fast
57a8e3a3a8 Clean up linting warnings: length comparison to zero.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: length comparison to zero
       --> database/src/sqlite.rs:518:17
        |
    518 |         assert!(db.merge(k1).unwrap().into_tpk_status().email_status.len() > 0);
        |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!db.merge(k1).unwrap().into_tpk_status().email_status.is_empty()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
        = note: `#[warn(clippy::len_zero)]` on by default

    warning: length comparison to zero
       --> database/src/sqlite.rs:520:13
        |
    520 | /             db.merge(k2.clone())
    521 | |                 .unwrap()
    522 | |                 .into_tpk_status()
    523 | |                 .email_status
    524 | |                 .len()
    525 | |                 > 0
        | |___________________^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
    help: using `!is_empty` is clearer and more explicit
        |
    520 ~             !db.merge(k2.clone())
    521 +                 .unwrap()
    522 +                 .into_tpk_status()
    523 +                 .email_status.is_empty()
        |

    warning: length comparison to zero
       --> database/src/sqlite.rs:529:13
        |
    529 | /             db.merge(k3.clone())
    530 | |                 .unwrap()
    531 | |                 .into_tpk_status()
    532 | |                 .email_status
    533 | |                 .len()
    534 | |                 > 0
        | |___________________^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
    help: using `!is_empty` is clearer and more explicit
        |
    529 ~             !db.merge(k3.clone())
    530 +                 .unwrap()
    531 +                 .into_tpk_status()
    532 +                 .email_status.is_empty()
        |

    warning: length comparison to zero
       --> src/dump.rs:999:24
        |
    999 |                     if reason.len() > 0 { ", " } else { "" },
        |                        ^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!reason.is_empty()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
        = note: `#[warn(clippy::len_zero)]` on by default
2025-04-27 16:51:28 +02:00
Zeke Fast
1f67668500 Clean up linting warnings: redundant return statements.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: unneeded `return` statement
       --> database/src/sqlite.rs:293:18
        |
    293 |             _ => return None,
        |                  ^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_return
        = note: `#[warn(clippy::needless_return)]` on by default
    help: remove `return`
        |
    293 -             _ => return None,
    293 +             _ => None,
        |

    warning: unneeded `()`
       --> hagridctl/src/import.rs:153:25
        |
    153 |             _ => return (),
        |                         ^^ help: remove the `()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
        = note: `#[warn(clippy::unused_unit)]` on by default

    warning: unneeded `()`
       --> hagridctl/src/import.rs:176:20
        |
    176 |             return ();
        |                    ^^ help: remove the `()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit

    warning: unneeded `return` statement
       --> src/web/hkp.rs:169:5
        |
    169 | /     return format!(
    170 | |         "Upload successful. Please note that identity information will only be published after verification. See {baseuri}/about/usage#gnupg-upload",
    171 | |         baseuri = origin.get_base_uri()
    172 | |     );
        | |_____^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_return
        = note: `#[warn(clippy::needless_return)]` on by default
    help: remove `return`
        |
    169 ~     format!(
    170 +         "Upload successful. Please note that identity information will only be published after verification. See {baseuri}/about/usage#gnupg-upload",
    171 +         baseuri = origin.get_base_uri()
    172 ~     )
        |
2025-04-27 16:22:10 +02:00
Zeke Fast
27b68dc826 Clean up linting warnings: related to iterators, mostly replacement of flatten() with filter_map() or flat_map().
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
       --> database/src/fs.rs:614:14
        |
    614 |             .last()
        |              ^^^^^^ help: try: `next_back()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#double_ended_iterator_last
        = note: `#[warn(clippy::double_ended_iterator_last)]` on by default

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/fs.rs:708:18
        |
    708 |                   .map(Fingerprint::try_from)
        |  __________________^
    709 | |                 .flatten();
        | |__________________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(Fingerprint::try_from)`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
        = note: `#[warn(clippy::map_flatten)]` on by default

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/sqlite.rs:424:18
        |
    424 |                   .map(|email| Email::from_str(email))
        |  __________________^
    425 | |                 .flatten()
        | |__________________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|email| Email::from_str(email))`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/sqlite.rs:422:18
        |
    422 |                   .map(|uid| uid.userid().email2().unwrap())
        |  __________________^
    423 | |                 .flatten()
        | |__________________________^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|uid| uid.userid().email2().unwrap())`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/sqlite.rs:431:18
        |
    431 |                   .map(|email| Email::from_str(&email.unwrap()))
        |  __________________^
    432 | |                 .flatten()
        | |__________________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|email| Email::from_str(&email.unwrap()))`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/sqlite.rs:453:18
        |
    453 |                   .map(Fingerprint::try_from)
        |  __________________^
    454 | |                 .flatten()
        | |__________________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(Fingerprint::try_from)`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/lib.rs:266:14
        |
    266 |               .map(|binding| {
        |  ______________^
    267 | |                 if let Ok(email) = Email::try_from(binding.userid()) {
    268 | |                     Some((binding, email))
    269 | |                 } else {
    ...   |
    272 | |             })
    273 | |             .flatten()
        | |______________________^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
    help: try replacing `map` with `filter_map` and remove the `.flatten()`
        |
    266 ~             .filter_map(|binding| {
    267 +                 if let Ok(email) = Email::try_from(binding.userid()) {
    268 +                     Some((binding, email))
    269 +                 } else {
    270 +                     None
    271 +                 }
    272 +             })
        |

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/lib.rs:315:22
        |
    315 |                       .map(|uid| Email::try_from(uid).ok())
        |  ______________________^
    316 | |                     .flatten()
        | |______________________________^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|uid| Email::try_from(uid).ok())`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/lib.rs:492:14
        |
    492 |               .map(|uid| Email::try_from(uid).ok())
        |  ______________^
    493 | |             .flatten()
        | |______________________^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|uid| Email::try_from(uid).ok())`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/lib.rs:509:14
        |
    509 |               .map(|binding| Email::try_from(binding.userid()))
        |  ______________^
    510 | |             .flatten()
        | |______________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|binding| Email::try_from(binding.userid()))`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/lib.rs:582:14
        |
    582 |               .map(|binding| Email::try_from(binding.userid()))
        |  ______________^
    583 | |             .flatten()
        | |______________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|binding| Email::try_from(binding.userid()))`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/lib.rs:590:14
        |
    590 |               .map(|binding| Email::try_from(binding.userid()))
        |  ______________^
    591 | |             .flatten()
        | |______________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|binding| Email::try_from(binding.userid()))`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/lib.rs:650:14
        |
    650 |               .map(|binding| Email::try_from(binding.userid()))
        |  ______________^
    651 | |             .flatten()
        | |______________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|binding| Email::try_from(binding.userid()))`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: called `map(..).flatten()` on `Iterator`
       --> database/src/lib.rs:708:10
        |
    708 |           .map(|binding| Email::try_from(binding.userid()))
        |  __________^
    709 | |         .flatten()
        | |__________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|binding| Email::try_from(binding.userid()))`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

    warning: useless conversion to the same type: `openpgp::cert::prelude::KeyAmalgamationIter<'_, openpgp::packet:🔑:PublicParts, openpgp::packet:🔑:UnspecifiedRole>`
       --> database/src/lib.rs:716:5
        |
    716 | /     tpk.keys()
    717 | |         .into_iter()
        | |____________________^ help: consider removing `.into_iter()`: `tpk.keys()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
        = note: `#[warn(clippy::useless_conversion)]` on by default

    warning: called `map(..).flatten()` on `Iterator`
      --> src/web/manage.rs:78:22
       |
    78 |                       .map(|u| u.userid().to_string().parse::<Email>())
       |  ______________________^
    79 | |                     .flatten()
       | |______________________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|u| u.userid().to_string().parse::<Email>())`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
       = note: `#[warn(clippy::map_flatten)]` on by default

    warning: called `map(..).flatten()` on `Iterator`
       --> src/web/vks.rs:225:10
        |
    225 |           .map(|address| address.parse::<Email>())
        |  __________^
    226 | |         .flatten()
        | |__________________^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|address| address.parse::<Email>())`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
2025-04-27 16:09:54 +02:00
Zeke Fast
535668c507 Clean up linting warnings: replace usage of explicit lifetimes with elision.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: the following explicit lifetimes could be elided: 'a
       --> database/src/fs.rs:348:6
        |
    348 | impl<'a> FilesystemTransaction<'a> {
        |      ^^                        ^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
        = note: `#[warn(clippy::needless_lifetimes)]` on by default
    help: elide the lifetimes
        |
    348 - impl<'a> FilesystemTransaction<'a> {
    348 + impl FilesystemTransaction<'_> {
        |

    warning: the following explicit lifetimes could be elided: 'a
       --> database/src/sqlite.rs:141:6
        |
    141 | impl<'a> DatabaseTransaction<'a> for SqliteTransaction {
        |      ^^                      ^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
    help: elide the lifetimes
        |
    141 - impl<'a> DatabaseTransaction<'a> for SqliteTransaction {
    141 + impl DatabaseTransaction<'_> for SqliteTransaction {
        |

    warning: the following explicit lifetimes could be elided: 'a
      --> src/dump.rs:40:6
       |
    40 | impl<'a> std::fmt::Display for SessionKeyDisplay<'a> {
       |      ^^                                          ^^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
       = note: `#[warn(clippy::needless_lifetimes)]` on by default
    help: elide the lifetimes
       |
    40 - impl<'a> std::fmt::Display for SessionKeyDisplay<'a> {
    40 + impl std::fmt::Display for SessionKeyDisplay<'_> {
       |
2025-04-27 15:09:23 +02:00
Zeke Fast
c77bf9d3db Clean up linting warnings: deref coersion related.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: called `.as_ref().map(|f| f.as_path())` on an `Option` value
      --> tester/src/main.rs:78:13
       |
    78 |             output_fprs.as_ref().map(|f| f.as_path()),
       |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `output_fprs.as_deref()`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref
       = note: `#[warn(clippy::option_as_ref_deref)]` on by default

    warning: deref which would be done by auto-deref
       --> src/web/vks_web.rs:358:52
        |
    358 |     for ValueField { name, value } in Form::values(&*String::from_utf8_lossy(&buf)) {
        |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&String::from_utf8_lossy(&buf)`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref
        = note: `#[warn(clippy::explicit_auto_deref)]` on by default
2025-04-27 15:01:26 +02:00
Zeke Fast
fec6763b75 Clean up linting warnings: remove unnecessary borrowings.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: the borrowed expression implements the required traits
       --> database/src/fs.rs:258:40
        |
    258 |         let typ = fs::symlink_metadata(&path).ok()?.file_type();
        |                                        ^^^^^ help: change this to: `path`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args
        = note: `#[warn(clippy::needless_borrows_for_generic_args)]` on by default

    warning: the borrowed expression implements the required traits
       --> database/src/fs.rs:287:44
        |
    287 |             let typ = fs::symlink_metadata(&path)?.file_type();
        |                                            ^^^^^ help: change this to: `path`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args

    warning: the borrowed expression implements the required traits
       --> database/src/fs.rs:328:13
        |
    328 |     symlink(&symlink_content, &symlink_name_tmp)?;
        |             ^^^^^^^^^^^^^^^^ help: change this to: `symlink_content`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args

    warning: the borrowed expression implements the required traits
       --> database/src/fs.rs:329:31
        |
    329 |     rename(&symlink_name_tmp, &symlink_name)?;
        |                               ^^^^^^^^^^^^^ help: change this to: `symlink_name`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args

    warning: the borrowed expression implements the required traits
       --> database/src/fs.rs:334:35
        |
    334 |     if let Ok(target) = read_link(&link) {
        |                                   ^^^^^ help: change this to: `link`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args

    warning: this expression creates a reference which is immediately dereferenced by the compiler
       --> database/src/sqlite.rs:424:46
        |
    424 |                 .map(|email| Email::from_str(&email))
        |                                              ^^^^^^ help: change this to: `email`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
        = note: `#[warn(clippy::needless_borrow)]` on by default

    warning: this expression creates a reference which is immediately dereferenced by the compiler
       --> database/src/lib.rs:546:51
        |
    546 |                 self.set_email_unpublished_filter(&tx, &current_fpr, |uid| {
        |                                                   ^^^ help: change this to: `tx`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    warning: this expression creates a reference which is immediately dereferenced by the compiler
       --> database/src/lib.rs:602:29
        |
    602 |         self.regenerate_wkd(&tx, fpr_primary, &published_tpk_clean)?;
        |                             ^^^ help: change this to: `tx`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    warning: this expression creates a reference which is immediately dereferenced by the compiler
       --> hagridctl/src/import.rs:161:86
        |
    161 |                         db.set_email_published(&key_fpr.clone().try_into().unwrap(), &email)
        |                                                                                      ^^^^^^ help: change this to: `email`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
        = note: `#[warn(clippy::needless_borrow)]` on by default

    warning: this expression creates a reference which is immediately dereferenced by the compiler
      --> src/sealed_state.rs:20:37
       |
    20 |         let cipher = Aes256Gcm::new(&key);
       |                                     ^^^^ help: change this to: `key`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
       = note: `#[warn(clippy::needless_borrow)]` on by default

    warning: the borrowed expression implements the required traits
      --> src/template_helpers.rs:46:77
       |
    46 |                         remove_extension(remove_extension(path.strip_prefix(&template_path)?));
       |                                                                             ^^^^^^^^^^^^^^ help: change this to: `template_path`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args
       = note: `#[warn(clippy::needless_borrows_for_generic_args)]` on by default

    warning: the borrowed expression implements the required traits
       --> src/web/vks.rs:216:46
        |
    216 |         Err(e) => return UploadResponse::err(&e.to_string()),
        |                                              ^^^^^^^^^^^^^^ help: change this to: `e.to_string()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args

    warning: the borrowed expression implements the required traits
       --> src/web/vks.rs:248:40
        |
    248 |             return UploadResponse::err(&format!("error sending email to {}", &email));
        |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: change this to: `format!("error sending email to {}", &email)`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args
2025-04-27 15:01:12 +02:00
Zeke Fast
80df057617 Clean up linting warnings: lines_filter_map_ok.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: `flatten()` will run forever if the iterator repeatedly produces an `Err`
      --> tester/src/genreqs.rs:12:70
       |
    12 |     let fingerprints: Vec<String> = io::BufReader::new(file).lines().flatten().collect();
       |                                                                      ^^^^^^^^^ help: replace with: `map_while(Result::ok)`
       |
    note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error
      --> tester/src/genreqs.rs:12:37
       |
    12 |     let fingerprints: Vec<String> = io::BufReader::new(file).lines().flatten().collect();
       |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok
       = note: `#[warn(clippy::lines_filter_map_ok)]` on by default
2025-04-27 15:00:50 +02:00
Zeke Fast
5731f8aa2b Clean up linting warnings: redundant import.
Commands:

    cargo clippy --tests --no-deps --workspace

Warnings:

    warning: this import is redundant
      --> database/src/fs.rs:12:1
       |
    12 | use tempfile;
       | ^^^^^^^^^^^^^ help: remove it entirely
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports
       = note: `#[warn(clippy::single_component_path_imports)]` on by default
2025-04-27 15:00:16 +02:00
Zeke Fast
62b936864d Run cargo fmt --all to format code to pass CI checks.
Commands:

    cargo fmt --all
2025-04-27 13:37:18 +02:00
Zeke Fast
4f86585ac3 Resolve dependency version differences for "sequoia-openpgp" crate.
It eliminates the following output of `cargo autoinherit` command:

    `sequoia-openpgp` won't be auto-inherited because there are multiple sources for it:
      - version: =1.17.0
      - version: ^1.17.0

Changes:
- Allow "sequoia-openpgp" crate to use workspace dependencies by resolving
  version differences constraints in Cargo.toml files.
2025-04-27 13:20:00 +02:00