From ac367fce91ac0cfdc66fd3eaebcf3923736bff95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kh=E1=BA=A3i?= Date: Thu, 11 Jun 2026 05:43:22 +0700 Subject: [PATCH] chore(rust/clippy): pedantic, nursery, and some (#12209) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: enable clippy::pedantic lint group for pacquet workspace * style(pacquet): comply with clippy::pedantic Apply clippy's machine-applicable pedantic fixes across the workspace (inlined format args, removed needless borrows/closures, added must_use, etc.), fix a few doc-comment backtick nits, and drop pointless #[inline(always)] on trivial accessors. Opt specific pedantic lints back out in [workspace.lints.clippy] with documented justifications, grouped into false positives, library-API hygiene that doesn't fit an internal CLI, suggestions that conflict with the cardinal rule of porting pnpm 1:1, and opinionated style. * style: taplo-format Cargo.toml lint table * style(pnpr): comply with clippy::pedantic in merged auth backend code Re-apply pedantic compliance to the networked-SQLite auth backend that landed on main (#12186, #12199/#12206): doc-comment backticks, #[must_use] on constructors and status_code, i64::from over `as`, map_or, and a method-reference closure. * docs(clippy): trim and inline the pedantic allow-list comments * docs(clippy): note perfectionist supersedes many_single_char_names * docs(clippy): note pnpm-mirroring rationale on structure/naming lints * docs(clippy): mark unused_async as deferred pending audit * style: enable clippy::match_wildcard_for_single_variants * refactor: enable clippy::unused_self Convert two self-less private methods (overrides pick_most_specific, tarball head_only_result) to associated functions. * refactor: enable clippy::ref_option Widen engine_json to Option<&str>; #[expect] the two serde serialize_with helpers, which serde must call as f(&field, ser). * perf: enable clippy::trivially_copy_pass_by_ref Pass the 1-byte Copy types NodeLinker and FilterWorkspaceProjectsOptions by value; #[expect] the serde skip_serializing_if helper is_false. * perf: enable clippy::assigning_clones Use clone_from for seven field assignments to reuse allocations. * style: enable clippy::manual_let_else Convert 27 match/if-let guards to let-else; preserve the non-UTF-8 skip rationale comment in the directory walker. * style: enable clippy::default_trait_access Name the concrete type on Default::default() call sites; #[expect] two struct-literal test fixtures where naming each field type would force ~20 imports. * refactor: enable clippy::format_push_string Replace push_str(&format!(...)) with write!/writeln! into the target String (local 'use std::fmt::Write as _'); writeln! preserves the exact LF/CRLF shell-shim output. * refactor: enable clippy::needless_pass_by_value Take by reference where the argument is only read (incl. dropping some redundant clones in resolve_peers' recursion). Where converting would cascade badly, #[expect] with a reason: functions that destructure/consume the arg (build_resolve_result, PrefetchingResolver, S3Store::new), the by-value `impl IntoIterator + Clone` in build_direct_deps_by_importer, and the serde/test helpers whose owned fixtures keep call sites clean. * fix(perfectionist): satisfy dylint after format_push_string changes Add trailing commas to the multi-line writeln! shell-shim templates (macro_trailing_comma) and merge the new `fmt::Write as _` imports into each file's existing `use std::{...}` block (import_granularity). * docs(clippy): explain missing_errors_doc suppression; mark missing_panics_doc deferred * fix(perfectionist): collapse fmt::{self, Write as _} in work_env imports The format_push_string Write import landed as a sibling fmt:: path next to the existing fmt import; merge them so import_granularity passes. * style: enable clippy::return_self_not_must_use Add #[must_use] to the WorkspaceTreeCtx builder methods, matching the #[must_use] already on the parallel TreeCtx builders. * perf: enable clippy::large_stack_arrays Heap-allocate the 64 KiB read buffer in verify_file_integrity with a Vec instead of placing it on the stack. * chore(clippy): enable clippy::nursery group Enable the nursery lint group on the pacquet/pnpr workspace and bring the code into compliance. Fixed in code: - iter_on_single_items: [x].into_iter()/.iter() -> std::iter::once - equatable_if_let: pattern match -> equality check (the install_accelerator rewrite wraps in a multi-line matches!, which gets a trailing comma for perfectionist::macro_trailing_comma) - needless_pass_by_ref_mut: load_pending_row/apply_write_msg take &StoreIndex Opted back out in Cargo.toml, each with a documented justification: use_self, too_long_first_doc_paragraph, missing_const_for_fn, option_if_let_else, significant_drop_tightening, redundant_pub_crate, derive_partial_eq_without_eq, branches_sharing_code, useless_let_if_seq, single_option_map, iter_with_drain, literal_string_with_formatting_args, collection_is_never_read. Dropped the now-redundant individual nursery warns (needless_collect, or_fun_call, redundant_clone) the group now covers, plus the default-on unnecessary_lazy_evaluations. Kept clone_on_ref_ptr and if_then_some_else_none (restriction lints not enabled by any group). * style: bring merged main code into clippy pedantic compliance The 17 commits merged from main predate this branch's pedantic/nursery lint config, so their new code tripped pedantic lints. Apply the machine-applicable fixes (uninlined_format_args, if_not_else, elidable_lifetime_names, must_use_candidate, single_match_else, map_unwrap_or, default_trait_access, assigning_clones, doc_markdown, ...) and re-add the documented #[expect(needless_pass_by_value)] on S3Store::new that this branch had carried on the now-replaced file. * style: bring merged main code into clippy pedantic compliance The 28 commits merged from main predate this branch's lint config, so their new code tripped pedantic lints. Apply the machine-applicable fixes (uninlined_format_args, manual_let_else, needless_raw_string_hashes, redundant_closure_for_method_calls, map_unwrap_or, elidable_lifetime_names, doc_markdown, ...) plus a few by hand: - derive Copy on LinkSlotsParallel (all fields are Copy/refs) to clear needless_pass_by_value without a signature change - deduplicate_all takes &[Vec] (it only borrows the duplicates) - pick_most_specific becomes an associated fn (it never used self) - default_trait_access -> concrete types; assigning_clones -> clone_from; format_push_string -> write! - #[expect] with reasons where a fix would churn main's feature code: needless_pass_by_value on the recursive resolve_node and a test helper, and float_cmp on two deterministic-fixture assertions * style: enable clippy::allow_attributes and allow_attributes_without_reason Both are restriction lints (not implied by any group), enabled alongside the existing clone_on_ref_ptr / if_then_some_else_none. Convert every #[allow(...)] (including one nested in cfg_attr) to #[expect(...)]; all already carried a reason, so allow_attributes_without_reason is satisfied. Drop two now-redundant suppressions surfaced by the conversion: a duplicated #[expect(too_many_arguments)] on fetch_and_extract_zip_once (a prior merge left both an allow and an expect), and the #[expect(dead_code)] on MissingPeerInfo's fields (the #[derive(Debug, Clone)] already reads them, so dead_code never fired). clone_on_ref_ptr was already enabled. mod_module_files is intentionally NOT enabled: it mandates mod.rs, the opposite of the flat module.rs pattern this project requires (CODE_STYLE_GUIDE.md, enforced by perfectionist::flat_module_pattern). * style: enable clippy::mod_module_files to enforce the flat module layout mod_module_files bans mod.rs files, enforcing the flat module.rs pattern this project already uses (0 mod.rs in the tree, so no violations). Update CODE_STYLE_GUIDE.md to cite it as the enforcer; perfectionist's flat_module_pattern is being retired in favor of this Clippy rule. * fix(perfectionist): trailing comma on wrapped assert_eq! in workspace_yaml tests The default_trait_access fix lengthened the assert_eq! so fmt wrapped it to multi-line, which perfectionist::macro_trailing_comma requires to end with a trailing comma. * fix(fs): use cfg_attr expect instead of allow for Windows-unused mode args With clippy::allow_attributes enabled, the #[cfg_attr(windows, allow(unused))] on make_file_executable and the ensure_file/write_atomic mode params fails Windows CI. Switch to #[cfg_attr(windows, expect(unused, reason = ...))]; on Windows the lint fires (Unix mode unused there) so the expectation is fulfilled, and the attribute stays inert on Unix. * fix(fs): drop the Windows unused suppression on ensure_file's mode arg ensure_file forwards mode to verify_or_rewrite unconditionally, so it is used on Windows too; the #[cfg_attr(windows, expect(unused))] was therefore unfulfilled and failed Windows CI under -D warnings. write_atomic and make_file_executable keep their expect — they use mode/file only under #[cfg(unix)], so the lint fires (and the expectation holds) on Windows. * chore(git): revert "fix(fs): drop the Windows unused suppression on ensure_file's mode arg" This reverts commit 1d617c3e1f2697370717ed6c2cd9d041e3a0d6ef. * chore(git): revert "fix(fs): use cfg_attr expect instead of allow for Windows-unused mode args" This reverts commit 155e4a3dde7bc355202127c7984c6dc81b9b6205. * chore(git): revert "style: enable clippy::allow_attributes and allow_attributes_without_reason" This reverts commit a47d7926f2e6506b5cdd50ab64eae99f33b4e9cf. * style: bring merged main code into clippy compliance + fix merge mismatch - Add & at the two run_postinstall_hooks / run_project_lifecycle_scripts call sites: this branch widened lifecycle.rs to take &RunPostinstallHooks, but main's by-value call sites came in via the conflict resolution. - pedantic fixes on main's new code: must_use_candidate, unnested_or_patterns, manual_let_else, default_trait_access, iter_on_single_items, and trivially_copy_pass_by_ref (map_node_linker takes NodeLinker by value). --------- Co-authored-by: Claude --- Cargo.toml | 53 +++- pacquet/CODE_STYLE_GUIDE.md | 2 +- .../catalogs-protocol-parser/src/lib.rs | 1 + pacquet/crates/catalogs-resolver/src/lib.rs | 1 + pacquet/crates/cli/src/cli_args.rs | 5 +- pacquet/crates/cli/src/cli_args/add.rs | 6 +- pacquet/crates/cli/src/cli_args/dlx.rs | 14 +- pacquet/crates/cli/src/cli_args/dlx/tests.rs | 6 +- pacquet/crates/cli/src/cli_args/install.rs | 15 +- pacquet/crates/cli/src/cli_args/outdated.rs | 2 +- pacquet/crates/cli/src/cli_args/run.rs | 13 +- .../crates/cli/src/cli_args/run/recursive.rs | 2 +- pacquet/crates/cli/src/config_overrides.rs | 2 +- pacquet/crates/cli/src/lib.rs | 3 +- pacquet/crates/cli/tests/_utils.rs | 3 +- pacquet/crates/cli/tests/hoist.rs | 8 +- .../crates/cli/tests/hoisted_node_linker.rs | 4 + pacquet/crates/cli/tests/install.rs | 4 + pacquet/crates/cli/tests/outdated.rs | 2 +- pacquet/crates/cli/tests/run.rs | 10 +- pacquet/crates/cli/tests/update.rs | 6 +- pacquet/crates/cmd-shim/src/bin_resolver.rs | 1 + .../crates/cmd-shim/src/bin_resolver/tests.rs | 8 +- pacquet/crates/cmd-shim/src/link_bins.rs | 6 +- .../crates/cmd-shim/src/link_bins/tests.rs | 2 +- pacquet/crates/cmd-shim/src/shim.rs | 34 ++- pacquet/crates/cmd-shim/src/shim/tests.rs | 6 +- .../crates/config-parse-overrides/src/lib.rs | 1 + pacquet/crates/config/src/api.rs | 2 +- pacquet/crates/config/src/defaults.rs | 17 +- pacquet/crates/config/src/env_overlay.rs | 1 + pacquet/crates/config/src/lib.rs | 35 +-- pacquet/crates/config/src/matcher.rs | 5 + pacquet/crates/config/src/matcher/tests.rs | 2 +- pacquet/crates/config/src/npmrc_auth.rs | 3 +- pacquet/crates/config/src/npmrc_auth/tests.rs | 2 +- .../crates/config/src/pnpm_default_parity.rs | 6 +- pacquet/crates/config/src/store_path.rs | 6 +- pacquet/crates/config/src/store_path/tests.rs | 8 +- pacquet/crates/config/src/tests.rs | 8 +- pacquet/crates/config/src/version_policy.rs | 1 + pacquet/crates/config/src/workspace_yaml.rs | 1 + .../crates/config/src/workspace_yaml/tests.rs | 68 ++--- pacquet/crates/crypto-hash/src/lib.rs | 3 + pacquet/crates/crypto-shasums-file/src/lib.rs | 7 +- .../src/node_release_keys.rs | 112 ++++---- .../crates/crypto-shasums-file/src/tests.rs | 4 +- pacquet/crates/deps-path/src/dep_path.rs | 1 + .../deps-path/src/dep_path_to_filename.rs | 1 + .../deps-path/src/is_runtime_dep_path.rs | 1 + .../src/link_path_to_peer_version.rs | 1 + pacquet/crates/deps-path/src/peer_id.rs | 1 + pacquet/crates/deps-path/src/suffix_index.rs | 3 + .../deps-path/src/try_get_package_id.rs | 1 + pacquet/crates/detect-libc/src/elf.rs | 2 +- pacquet/crates/detect-libc/src/lib.rs | 6 +- .../crates/directory-fetcher/src/walker.rs | 16 +- .../directory-fetcher/src/walker/tests.rs | 8 +- .../src/read_deno_assets.rs | 2 +- .../src/get_node_artifact_address.rs | 1 + .../src/get_node_mirror.rs | 1 + .../src/normalize_arch.rs | 1 + .../src/resolve_node_version.rs | 8 +- .../env-installer/src/install_config_deps.rs | 7 +- pacquet/crates/env-installer/src/tests.rs | 2 +- pacquet/crates/env-replace/src/lib.rs | 1 + pacquet/crates/executor/src/extend_path.rs | 1 + .../crates/executor/src/extend_path/tests.rs | 2 +- pacquet/crates/executor/src/lifecycle.rs | 8 +- .../crates/executor/src/lifecycle/tests.rs | 14 +- pacquet/crates/executor/src/make_env.rs | 4 +- pacquet/crates/executor/src/make_env/tests.rs | 2 +- pacquet/crates/executor/src/run_script.rs | 2 +- .../crates/executor/src/run_script/tests.rs | 2 +- pacquet/crates/executor/src/shell.rs | 3 +- pacquet/crates/executor/src/shell/tests.rs | 2 +- .../crates/exportable-manifest/src/replace.rs | 24 +- pacquet/crates/fs/src/ensure_file.rs | 8 +- pacquet/crates/fs/src/file_mode.rs | 1 + pacquet/crates/fs/src/is_subdir.rs | 1 + pacquet/crates/fs/src/lexical_normalize.rs | 1 + pacquet/crates/fs/src/symlink_dir.rs | 91 ++++--- pacquet/crates/git-fetcher/src/fetcher.rs | 4 +- .../crates/git-fetcher/src/fetcher/tests.rs | 3 +- .../crates/git-fetcher/src/preferred_pm.rs | 2 + .../crates/git-fetcher/src/prepare_package.rs | 11 +- .../git-fetcher/src/prepare_package/tests.rs | 2 +- .../crates/git-fetcher/src/tarball_fetcher.rs | 4 +- .../graph-hasher/src/dep_state/tests.rs | 10 +- .../crates/graph-hasher/src/engine_name.rs | 7 +- .../src/global_virtual_store_path.rs | 3 + .../src/global_virtual_store_path/tests.rs | 6 +- .../crates/graph-hasher/src/object_hasher.rs | 4 + pacquet/crates/hooks/src/finder.rs | 4 + pacquet/crates/hooks/src/node_runtime.rs | 35 +-- pacquet/crates/hooks/tests/node_hooks.rs | 40 +-- .../lockfile-preferred-versions/src/lib.rs | 1 + .../lockfile-preferred-versions/src/tests.rs | 4 + .../src/version_selector_type.rs | 1 + .../crates/lockfile-verification/src/cache.rs | 24 +- .../lockfile-verification/src/cache/tests.rs | 4 +- .../lockfile-verification/src/errors.rs | 22 +- .../lockfile-verification/src/errors/tests.rs | 18 +- .../src/hash_lockfile.rs | 1 + .../src/hash_lockfile/tests.rs | 2 +- .../src/record_lockfile_verified.rs | 2 +- .../src/verify_lockfile_resolutions.rs | 2 +- .../src/verify_lockfile_resolutions/tests.rs | 4 +- pacquet/crates/lockfile/src/comver.rs | 1 + pacquet/crates/lockfile/src/env_lockfile.rs | 1 + pacquet/crates/lockfile/src/freshness.rs | 7 +- .../crates/lockfile/src/freshness/tests.rs | 2 +- pacquet/crates/lockfile/src/lib.rs | 2 + .../crates/lockfile/src/lockfile_version.rs | 1 + .../lockfile/src/pkg_id_with_patch_hash.rs | 1 + pacquet/crates/lockfile/src/pkg_name/tests.rs | 7 +- .../crates/lockfile/src/pkg_name_suffix.rs | 2 +- .../crates/lockfile/src/pkg_name_ver/tests.rs | 5 + .../crates/lockfile/src/pkg_name_ver_peer.rs | 2 + .../lockfile/src/pkg_name_ver_peer/tests.rs | 5 + pacquet/crates/lockfile/src/pkg_ver_peer.rs | 7 + .../crates/lockfile/src/pkg_ver_peer/tests.rs | 2 +- .../crates/lockfile/src/project_snapshot.rs | 3 +- pacquet/crates/lockfile/src/resolution.rs | 5 + .../lockfile/src/resolved_dependency.rs | 6 + pacquet/crates/lockfile/src/save_lockfile.rs | 3 +- .../lockfile/src/save_lockfile/tests.rs | 4 +- pacquet/crates/lockfile/src/serialize_yaml.rs | 1 + .../crates/lockfile/src/snapshot_dep_ref.rs | 3 + pacquet/crates/lockfile/src/snapshot_entry.rs | 4 + pacquet/crates/lockfile/src/yaml_documents.rs | 2 + pacquet/crates/lockfile/src/yaml_emit.rs | 17 +- pacquet/crates/modules-yaml/src/lib.rs | 3 +- pacquet/crates/modules-yaml/tests/real_fs.rs | 2 +- pacquet/crates/network/src/auth.rs | 10 +- pacquet/crates/network/src/auth/tests.rs | 2 +- pacquet/crates/network/src/lib.rs | 9 +- pacquet/crates/network/src/retry.rs | 6 +- pacquet/crates/network/src/retry/tests.rs | 14 +- pacquet/crates/network/src/tests.rs | 8 +- pacquet/crates/network/src/tls.rs | 7 +- .../src/check_engine.rs | 6 +- .../src/package_is_installable.rs | 1 + pacquet/crates/package-manager/src/add.rs | 3 +- .../package-manager/src/build_modules.rs | 23 +- .../src/build_modules/tests.rs | 6 +- .../package-manager/src/build_sequence.rs | 4 +- .../src/build_sequence/tests.rs | 8 +- .../src/build_snapshot/tests.rs | 2 +- .../src/create_virtual_dir_by_snapshot.rs | 2 +- .../create_virtual_dir_by_snapshot/tests.rs | 2 +- .../src/create_virtual_store.rs | 33 +-- .../src/create_virtual_store/tests.rs | 2 +- .../package-manager/src/current_lockfile.rs | 1 + .../src/dependencies_graph_to_lockfile.rs | 1 + .../dependencies_graph_to_lockfile/tests.rs | 6 +- .../crates/package-manager/src/deps_graph.rs | 1 + pacquet/crates/package-manager/src/hoist.rs | 16 +- .../crates/package-manager/src/hoist/tests.rs | 4 +- .../package-manager/src/hoisted_dep_graph.rs | 30 ++- .../package-manager/src/hoisting_limits.rs | 1 + .../package-manager/src/import_indexed_dir.rs | 2 +- pacquet/crates/package-manager/src/install.rs | 37 ++- .../package-manager/src/install/tests.rs | 85 +++--- .../src/install_frozen_lockfile.rs | 12 +- .../src/install_package_by_snapshot.rs | 2 +- .../src/install_package_by_snapshot/tests.rs | 27 +- .../src/install_package_from_registry.rs | 4 +- .../install_package_from_registry/tests.rs | 5 + .../src/install_with_fresh_lockfile.rs | 58 ++--- .../package-manager/src/installability.rs | 5 + .../src/installability/tests.rs | 4 +- .../crates/package-manager/src/link_bins.rs | 4 +- .../package-manager/src/link_bins/tests.rs | 18 +- .../crates/package-manager/src/link_file.rs | 2 +- .../package-manager/src/link_file/tests.rs | 2 +- .../src/link_hoisted_modules.rs | 2 +- .../src/link_hoisted_modules/tests.rs | 4 +- .../src/optimistic_repeat_install.rs | 43 ++-- .../src/optimistic_repeat_install/tests.rs | 10 +- .../crates/package-manager/src/overrides.rs | 18 +- .../package-manager/src/overrides/tests.rs | 4 + .../package-manager/src/package_extender.rs | 2 + .../src/prefetching_resolver.rs | 5 + pacquet/crates/package-manager/src/remove.rs | 8 +- .../package-manager/src/remove/tests.rs | 6 +- .../src/symlink_direct_dependencies.rs | 2 +- .../src/virtual_store_layout.rs | 3 + .../src/virtual_store_layout/tests.rs | 4 +- pacquet/crates/package-manifest/src/lib.rs | 33 ++- pacquet/crates/package-manifest/src/tests.rs | 15 +- pacquet/crates/patching/src/apply.rs | 3 +- pacquet/crates/patching/src/apply/tests.rs | 4 +- pacquet/crates/patching/src/key.rs | 1 + pacquet/crates/patching/src/resolve/tests.rs | 4 +- pacquet/crates/patching/src/verify/tests.rs | 9 +- pacquet/crates/pnpr-client/src/lib.rs | 4 +- pacquet/crates/real-hoist/src/lib.rs | 64 +++-- pacquet/crates/real-hoist/src/tests.rs | 30 +-- pacquet/crates/registry/src/package.rs | 5 +- pacquet/crates/registry/src/package/tests.rs | 14 +- pacquet/crates/registry/src/package_tag.rs | 2 +- .../crates/registry/src/package_version.rs | 2 + .../registry/src/package_version/tests.rs | 4 +- pacquet/crates/reporter/src/lib.rs | 4 +- pacquet/crates/reporter/src/tests.rs | 8 +- .../resolving-default-resolver/src/lib.rs | 4 +- .../src/dedupe_peer_dependents.rs | 8 +- .../src/dedupe_peer_dependents/tests.rs | 2 +- .../src/hoist_peers.rs | 7 +- .../src/hoist_peers/tests.rs | 24 +- .../resolving-deps-resolver/src/node_id.rs | 1 + .../src/resolve_dependency_tree.rs | 241 +++++++++--------- .../src/resolve_importer.rs | 2 +- .../src/resolve_importer/tests.rs | 14 +- .../src/resolve_peers.rs | 27 +- .../src/resolve_workspace/tests.rs | 4 + .../src/resolved_tree.rs | 4 +- .../resolving-deps-resolver/src/tests.rs | 8 + .../src/validate_dependency_alias.rs | 1 + .../src/create_git_hosted_pkg_id.rs | 1 + .../resolving-git-resolver/src/hosted_git.rs | 7 + .../src/parse_bare_specifier.rs | 5 +- .../src/parse_bare_specifier/tests.rs | 2 +- .../resolving-git-resolver/src/runners.rs | 23 +- .../resolving-local-resolver/src/chain.rs | 5 +- .../src/local_resolver.rs | 1 + .../src/parse_bare_specifier.rs | 15 +- .../create_npm_resolution_verifier/tests.rs | 4 +- .../src/fetch_attestation_published_at.rs | 5 +- .../resolving-npm-resolver/src/mirror.rs | 3 +- .../src/mirror/tests.rs | 4 +- .../src/named_registry.rs | 3 + .../src/named_registry_resolver.rs | 5 +- .../src/named_registry_resolver/tests.rs | 4 + .../src/npm_resolver.rs | 33 +-- .../src/npm_resolver/tests.rs | 4 +- .../src/pick_package.rs | 15 +- .../src/pick_package/tests.rs | 4 +- .../src/pick_package_from_meta.rs | 16 +- .../src/pick_package_from_meta/tests.rs | 6 +- .../src/registry_url.rs | 5 +- .../src/resolve_from_workspace/tests.rs | 4 +- .../src/trust_checks.rs | 13 +- .../src/trust_checks/tests.rs | 8 +- .../resolving-npm-resolver/tests/chain.rs | 10 +- .../src/lib.rs | 1 + .../src/validate_npm_package_name.rs | 1 + .../src/publish_time.rs | 1 + .../resolving-resolver-base/src/resolve.rs | 2 + .../resolving-resolver-base/src/tests.rs | 2 +- .../src/tarball_resolver.rs | 9 +- .../store-dir/src/add_files_from_dir.rs | 5 +- pacquet/crates/store-dir/src/cas_file.rs | 4 +- .../src/check_pkg_files_integrity.rs | 14 +- .../src/check_pkg_files_integrity/tests.rs | 4 +- .../crates/store-dir/src/msgpackr_records.rs | 48 ++-- .../store-dir/src/msgpackr_records/tests.rs | 2 +- .../crates/store-dir/src/project_registry.rs | 4 +- pacquet/crates/store-dir/src/prune.rs | 2 +- pacquet/crates/store-dir/src/store_dir.rs | 2 +- pacquet/crates/store-dir/src/store_index.rs | 52 ++-- .../crates/store-dir/src/store_index/tests.rs | 2 +- .../store-dir/tests/verify_writer_race.rs | 4 +- pacquet/crates/tarball/src/lib.rs | 53 ++-- pacquet/crates/tarball/src/tests.rs | 40 +-- pacquet/crates/testing-utils/src/bin.rs | 2 + pacquet/crates/testing-utils/src/env_guard.rs | 2 +- pacquet/crates/testing-utils/src/fs.rs | 4 + .../crates/testing-utils/src/known_failure.rs | 1 + pacquet/crates/testing-utils/src/registry.rs | 3 +- .../workspace-manifest-writer/src/edit.rs | 90 +++---- .../workspace-manifest-writer/src/render.rs | 2 +- .../workspace-projects-filter/src/filter.rs | 6 +- .../src/create_projects_graph.rs | 1 + .../workspace-range-resolver/src/lib.rs | 1 + pacquet/crates/workspace-state/src/lib.rs | 7 +- pacquet/crates/workspace/src/importer_id.rs | 1 + pacquet/crates/workspace/src/projects.rs | 7 +- pacquet/crates/workspace/src/root_finder.rs | 1 + .../integrated-benchmark/src/latency_proxy.rs | 2 +- .../tasks/integrated-benchmark/src/main.rs | 2 +- .../tasks/integrated-benchmark/src/verify.rs | 2 +- .../integrated-benchmark/src/work_env.rs | 36 +-- .../src/work_env/tests.rs | 10 +- pacquet/tasks/registry-mock/src/dirs.rs | 1 + pacquet/tasks/registry-mock/src/main.rs | 2 +- .../tasks/registry-mock/src/mock_instance.rs | 3 +- pacquet/tasks/registry-mock/src/pick_port.rs | 1 + .../tasks/registry-mock/src/pnpr_command.rs | 15 +- .../registry-mock/src/registry_anchor.rs | 3 +- .../tasks/registry-mock/src/registry_info.rs | 4 +- pnpr/crates/pnpr-fixtures/src/lib.rs | 3 +- pnpr/crates/pnpr/src/auth.rs | 26 +- pnpr/crates/pnpr/src/config.rs | 22 +- pnpr/crates/pnpr/src/config/tests.rs | 8 +- pnpr/crates/pnpr/src/error.rs | 3 +- pnpr/crates/pnpr/src/main.rs | 4 +- pnpr/crates/pnpr/src/package_name.rs | 21 +- pnpr/crates/pnpr/src/policy.rs | 7 + pnpr/crates/pnpr/src/publish.rs | 2 +- pnpr/crates/pnpr/src/resolver.rs | 8 +- .../crates/pnpr/src/resolver/verdict_cache.rs | 7 +- pnpr/crates/pnpr/src/s3.rs | 12 +- pnpr/crates/pnpr/src/server.rs | 39 ++- pnpr/crates/pnpr/src/storage.rs | 4 +- pnpr/crates/pnpr/src/storage/tests.rs | 4 +- pnpr/crates/pnpr/tests/auth_persistence.rs | 4 + pnpr/crates/pnpr/tests/auth_publish.rs | 8 +- pnpr/crates/pnpr/tests/auth_user_endpoints.rs | 11 +- pnpr/crates/pnpr/tests/common/storage.rs | 4 + pnpr/crates/pnpr/tests/s3_backend.rs | 4 +- pnpr/crates/pnpr/tests/server.rs | 15 +- 313 files changed, 1709 insertions(+), 1371 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9f47ae59f5..6f7b2b8abc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -184,12 +184,53 @@ allow_branch = "main" unexpected_cfgs = { level = "warn", check-cfg = ['cfg(dylint_lib, values("perfectionist"))'] } [workspace.lints.clippy] -clone_on_ref_ptr = "warn" -if_then_some_else_none = "warn" -needless_collect = "warn" -or_fun_call = "warn" -redundant_clone = "warn" -unnecessary_lazy_evaluations = "warn" +pedantic = { level = "warn", priority = -1 } +nursery = { level = "warn", priority = -1 } + +doc_link_with_quotes = "allow" # false positive: matches markdown link titles +unreadable_literal = "allow" # false positive: octal file modes +case_sensitive_file_extension_comparisons = "allow" # extension checks are intentionally case-sensitive +implicit_hasher = "allow" # only matters across a public API +unnecessary_debug_formatting = "allow" # keeps the quoted `Path` output +option_option = "allow" # distinguishes missing from null +cast_possible_truncation = "allow" # deliberate numeric narrowing +cast_sign_loss = "allow" +cast_possible_wrap = "allow" +cast_precision_loss = "allow" +missing_errors_doc = "allow" # error enums are self-documenting (#[display] + #[diagnostic(code)]); a # Errors section would just restate them +missing_panics_doc = "allow" # deferred: refactor away / document / #[expect] each panic before enabling +too_many_lines = "allow" # pacquet mirrors pnpm's function decomposition +struct_excessive_bools = "allow" # option structs mirror pnpm's +fn_params_excessive_bools = "allow" # mirrors pnpm's option parameters +match_same_arms = "allow" # arms kept explicit to mirror pnpm's switch cases +unnecessary_wraps = "allow" +unused_async = "allow" # deferred: audit each async signature (trait/seam-required?) before enabling +similar_names = "allow" # names ported verbatim from pnpm +items_after_statements = "allow" +needless_continue = "allow" +many_single_char_names = "allow" # perfectionist's single_letter_* lints already cover this with finer per-position control + +# nursery-group opt-outs (the group is experimental; these lints are either +# false positives on this code or fight conventions the project keeps on purpose) +use_self = "allow" # spelling out the concrete type name over Self is left to author discretion +too_long_first_doc_paragraph = "allow" # doc comments deliberately open with a detailed pnpm-parity summary, not a one-line lede +missing_const_for_fn = "allow" # const-ness is a forward semver commitment and this nursery lint is noisy / churns as const-eval grows +option_if_let_else = "allow" # the suggested map_or_else closures read worse than the if-let they replace +significant_drop_tightening = "allow" # the flagged guards are held deliberately (atomic check-then-act); early-dropping is FP-prone and behavioral +redundant_pub_crate = "allow" # pub(crate) is kept to document intended visibility even where technically redundant +derive_partial_eq_without_eq = "allow" # deriving Eq is a forward semver commitment that all fields stay Eq +branches_sharing_code = "allow" # false-positive-prone: clippy itself flags its own suggestion as needing adjustment +useless_let_if_seq = "allow" # rewrites large init blocks into an awkward if-as-expression +single_option_map = "allow" # flags test helpers that exist precisely to dedupe a `.map` over an Option +iter_with_drain = "allow" # false positive: drain(..) reuses the batch Vec's allocation across loop iterations; into_iter() would consume it +literal_string_with_formatting_args = "allow" # false positive: `${VAR:-default}` strings are .npmrc / env-replace fixtures, not Rust format args +collection_is_never_read = "allow" # false positive: the flagged Vec owns sockets to keep them alive, it is never meant to be read + +# restriction lints opted into individually — not part of any default group or +# the nursery group, so these lines are what enable them (kept on purpose). +clone_on_ref_ptr = "warn" +if_then_some_else_none = "warn" +mod_module_files = "warn" # forbids mod.rs, enforcing the flat module.rs layout (see CODE_STYLE_GUIDE.md) [profile.release] opt-level = 3 diff --git a/pacquet/CODE_STYLE_GUIDE.md b/pacquet/CODE_STYLE_GUIDE.md index 7119d01bbd..2dcdfd4ff0 100644 --- a/pacquet/CODE_STYLE_GUIDE.md +++ b/pacquet/CODE_STYLE_GUIDE.md @@ -46,7 +46,7 @@ Follow [the Rust API guidelines](https://rust-lang.github.io/api-guidelines/nami ### Module Organization -- Use the flat file pattern (`module.rs`) rather than `module/mod.rs` for submodules. Enforced by [`perfectionist::flat_module_pattern`](https://github.com/KSXGitHub/perfectionist/blob/0.0.0-rc.17/rules/flat_module_pattern.md). +- Use the flat file pattern (`module.rs`) rather than `module/mod.rs` for submodules. Enforced by [`clippy::mod_module_files`](https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files), which bans `mod.rs` files. (`perfectionist::flat_module_pattern` covered this previously and is being retired in favor of the Clippy rule.) - List `pub mod` declarations first, then `pub use` re-exports, then private imports and items. - Use `pub use` to re-export key types at the module level for convenience. diff --git a/pacquet/crates/catalogs-protocol-parser/src/lib.rs b/pacquet/crates/catalogs-protocol-parser/src/lib.rs index 84ccc690ba..6d32e890cc 100644 --- a/pacquet/crates/catalogs-protocol-parser/src/lib.rs +++ b/pacquet/crates/catalogs-protocol-parser/src/lib.rs @@ -18,6 +18,7 @@ const CATALOG_PROTOCOL: &str = "catalog:"; /// /// Mirrors upstream's `parseCatalogProtocol` /// ([source](https://github.com/pnpm/pnpm/blob/a8a8cbce6d/catalogs/protocol-parser/src/parseCatalogProtocol.ts#L3-L16)). +#[must_use] pub fn parse_catalog_protocol(bare_specifier: &str) -> Option<&str> { let raw = bare_specifier.strip_prefix(CATALOG_PROTOCOL)?.trim(); Some(if raw.is_empty() { DEFAULT_CATALOG_NAME } else { raw }) diff --git a/pacquet/crates/catalogs-resolver/src/lib.rs b/pacquet/crates/catalogs-resolver/src/lib.rs index e34e5462d2..2670f6b79a 100644 --- a/pacquet/crates/catalogs-resolver/src/lib.rs +++ b/pacquet/crates/catalogs-resolver/src/lib.rs @@ -114,6 +114,7 @@ pub enum CatalogResolutionError { /// /// Mirrors upstream's `resolveFromCatalog` /// ([source](https://github.com/pnpm/pnpm/blob/a8a8cbce6d/catalogs/resolver/src/resolveFromCatalog.ts#L60-L130)). +#[must_use] pub fn resolve_from_catalog( catalogs: &Catalogs, wanted_dependency: &WantedDependency, diff --git a/pacquet/crates/cli/src/cli_args.rs b/pacquet/crates/cli/src/cli_args.rs index 0611fb20ef..84661399e5 100644 --- a/pacquet/crates/cli/src/cli_args.rs +++ b/pacquet/crates/cli/src/cli_args.rs @@ -313,8 +313,7 @@ impl CliArgs { let manifest = PackageManifest::from_path(manifest_path()) .wrap_err("getting the package.json in current directory")?; if let Some(script) = manifest.script("test", false)? { - execute_shell(script) - .wrap_err(format!("executing command: \"{0}\"", script))?; + execute_shell(script).wrap_err(format!("executing command: \"{script}\""))?; } } CliCommand::Run(args) => { @@ -343,7 +342,7 @@ impl CliArgs { let manifest = PackageManifest::from_path(manifest_path()) .wrap_err("getting the package.json in current directory")?; let command = manifest.script("start", true)?.unwrap_or("node server.js"); - execute_shell(command).wrap_err(format!("executing command: \"{0}\"", command))?; + execute_shell(command).wrap_err(format!("executing command: \"{command}\""))?; } CliCommand::Store(command) => command.run(|| config().map(|m| &*m))?, } diff --git a/pacquet/crates/cli/src/cli_args/add.rs b/pacquet/crates/cli/src/cli_args/add.rs index 5ee147b1e9..2279b67f3f 100644 --- a/pacquet/crates/cli/src/cli_args/add.rs +++ b/pacquet/crates/cli/src/cli_args/add.rs @@ -27,7 +27,6 @@ impl AddDependencyOptions { /// Whether to add entry to `"dependencies"`. /// /// **NOTE:** no `--save-*` flags implies save as prod. - #[inline(always)] fn save_prod(&self) -> bool { let &AddDependencyOptions { save_prod, save_dev, save_optional, save_peer } = self; save_prod || (!save_dev && !save_optional && !save_peer) @@ -36,20 +35,17 @@ impl AddDependencyOptions { /// Whether to add entry to `"devDependencies"`. /// /// **NOTE:** `--save-peer` without any other `--save-*` flags implies save as dev. - #[inline(always)] fn save_dev(&self) -> bool { let &AddDependencyOptions { save_prod, save_dev, save_optional, save_peer } = self; save_dev || (!save_prod && !save_optional && save_peer) } /// Whether to add entry to `"optionalDependencies"`. - #[inline(always)] fn save_optional(&self) -> bool { self.save_optional } /// Whether to add entry to `"peerDependencies"`. - #[inline(always)] fn save_peer(&self) -> bool { self.save_peer } @@ -104,7 +100,7 @@ pub struct AddArgs { /// is created. Mirrors pnpm's `--lockfile-only`. #[clap(long = "lockfile-only")] pub lockfile_only: bool, - /// The directory with links to the store (default is node_modules/.pacquet). + /// The directory with links to the store (default is `node_modules/.pacquet`). /// All direct and indirect dependencies of the project are linked into this directory #[clap(long = "virtual-store-dir", default_value = "node_modules/.pacquet")] pub virtual_store_dir: Option, // TODO: make use of this diff --git a/pacquet/crates/cli/src/cli_args/dlx.rs b/pacquet/crates/cli/src/cli_args/dlx.rs index 77a1ac59fd..82a4c86bd4 100644 --- a/pacquet/crates/cli/src/cli_args/dlx.rs +++ b/pacquet/crates/cli/src/cli_args/dlx.rs @@ -195,9 +195,10 @@ impl DlxArgs { .wrap_err("canonicalizing the dlx cache directory")?; let cache_link = dlx_command_cache_dir.join("pkg"); - let cached_dir = match get_valid_cache_dir(&cache_link, max_age, SystemTime::now()) { - Some(dir) => dir, - None => { + let cached_dir = + if let Some(dir) = get_valid_cache_dir(&cache_link, max_age, SystemTime::now()) { + dir + } else { let prepare_dir = get_prepare_dir(&dlx_command_cache_dir, SystemTime::now(), std::process::id()); if let Err(error) = install_into_cache::( @@ -221,8 +222,7 @@ impl DlxArgs { // ignore the failure and run from our own prepare dir. let _ = force_symlink_dir(&prepare_dir, &cache_link); prepare_dir - } - }; + }; let bins_dir = cached_dir.join("node_modules").join(".bin"); let bin_name = @@ -445,7 +445,7 @@ fn get_valid_cache_dir( /// prepared in. Ports `getPrepareDir` /// (). fn get_prepare_dir(cache_path: &Path, now: SystemTime, pid: u32) -> PathBuf { - let millis = now.duration_since(UNIX_EPOCH).map(|elapsed| elapsed.as_millis()).unwrap_or(0); + let millis = now.duration_since(UNIX_EPOCH).map_or(0, |elapsed| elapsed.as_millis()); cache_path.join(format!("{millis:x}-{pid:x}")) } @@ -503,7 +503,7 @@ fn read_json(path: &Path) -> Result { /// (dlx.ts:297-302). fn scopeless(pkg_name: &str) -> &str { if let Some(rest) = pkg_name.strip_prefix('@') { - rest.split_once('/').map(|(_, name)| name).unwrap_or(pkg_name) + rest.split_once('/').map_or(pkg_name, |(_, name)| name) } else { pkg_name } diff --git a/pacquet/crates/cli/src/cli_args/dlx/tests.rs b/pacquet/crates/cli/src/cli_args/dlx/tests.rs index dcbeef90e0..d7b9dbc5a0 100644 --- a/pacquet/crates/cli/src/cli_args/dlx/tests.rs +++ b/pacquet/crates/cli/src/cli_args/dlx/tests.rs @@ -177,10 +177,14 @@ fn get_valid_cache_dir_honors_max_age() { ); // Past the window: expired. - let past = mtime + Duration::from_secs(1440 * 60 + 60); + let past = mtime + Duration::from_mins(1441); assert!(get_valid_cache_dir(&link, 1440, past).is_none(), "an expired link must be rejected"); } +#[expect( + clippy::needless_pass_by_value, + reason = "test helper called from multiple sites with owned literals; by-value keeps the call sites clean" +)] fn write_pkg(dir: &std::path::Path, name: &str, manifest: serde_json::Value) { let pkg_dir = dir.join("node_modules").join(name); fs::create_dir_all(&pkg_dir).expect("create pkg dir"); diff --git a/pacquet/crates/cli/src/cli_args/install.rs b/pacquet/crates/cli/src/cli_args/install.rs index 35d35a04c9..39ca801363 100644 --- a/pacquet/crates/cli/src/cli_args/install.rs +++ b/pacquet/crates/cli/src/cli_args/install.rs @@ -37,13 +37,13 @@ impl NodeLinkerArg { #[derive(Debug, Args)] pub struct InstallDependencyOptions { /// pacquet will not install any package listed in devDependencies and will remove those insofar - /// they were already installed, if the NODE_ENV environment variable is set to production. - /// Use this flag to instruct pacquet to ignore NODE_ENV and take its production status from this + /// they were already installed, if the `NODE_ENV` environment variable is set to production. + /// Use this flag to instruct pacquet to ignore `NODE_ENV` and take its production status from this /// flag instead. #[arg(short = 'P', long)] prod: bool, /// Only devDependencies are installed and dependencies are removed insofar they were - /// already installed, regardless of the NODE_ENV. + /// already installed, regardless of the `NODE_ENV`. #[arg(short = 'D', long)] dev: bool, /// optionalDependencies are not installed. @@ -302,7 +302,7 @@ impl InstallArgs { // `--node-linker` flag (if passed) overrides the // yaml/npmrc value for this invocation. Mirrors pnpm's // override-on-explicit-flag semantics. - let node_linker = node_linker.map(NodeLinkerArg::into_config).unwrap_or(config.node_linker); + let node_linker = node_linker.map_or(config.node_linker, NodeLinkerArg::into_config); // The lockfile-verification gate keys its on-disk cache off // `/pnpm-lock.yaml`. Once workspace support // lands (pacquet#431), this becomes `workspace_root` to @@ -466,9 +466,10 @@ async fn install_via_pnpr( .map_err(|err| miette::miette!("failed to serialize overrides: {err}"))?; let benchmark_registry_override = PnprBenchmarkRegistryOverride::from_env(&state.config.registry); - let resolve_registry = benchmark_registry_override - .as_ref() - .map_or_else(|| state.config.registry.clone(), |registry| registry.resolve_registry()); + let resolve_registry = benchmark_registry_override.as_ref().map_or_else( + || state.config.registry.clone(), + PnprBenchmarkRegistryOverride::resolve_registry, + ); // Send the on-disk lockfile + the full client policy so the server // verifies the input lockfile under *our* policy before resolving; diff --git a/pacquet/crates/cli/src/cli_args/outdated.rs b/pacquet/crates/cli/src/cli_args/outdated.rs index efb7568065..3ab451ef28 100644 --- a/pacquet/crates/cli/src/cli_args/outdated.rs +++ b/pacquet/crates/cli/src/cli_args/outdated.rs @@ -438,7 +438,7 @@ fn change_priority(change: Change) -> u8 { fn sort_outdated(outdated: &mut [OutdatedPackage], sort_by: Option) { match sort_by { Some(SortBy::Name) => { - outdated.sort_by(|left, right| left.package_name.cmp(&right.package_name)) + outdated.sort_by(|left, right| left.package_name.cmp(&right.package_name)); } None => outdated.sort_by(|left, right| { let by_change = change_priority(classify(&left.current, &left.target)) diff --git a/pacquet/crates/cli/src/cli_args/run.rs b/pacquet/crates/cli/src/cli_args/run.rs index fc217339f5..59aab72590 100644 --- a/pacquet/crates/cli/src/cli_args/run.rs +++ b/pacquet/crates/cli/src/cli_args/run.rs @@ -8,6 +8,7 @@ use serde_json::Value; use std::{ collections::HashMap, env, + fmt::Write as _, path::{Path, PathBuf}, }; @@ -295,7 +296,7 @@ pub(super) fn run_stages( /// Run one lifecycle stage. Returns `Ok(None)` when pnpm's per-stage /// no-op guards apply (empty body, or `npx only-allow pnpm` with no /// args), so the caller can record "didn't actually run" without -/// inventing a synthetic ExitStatus. A non-success ExitStatus is +/// inventing a synthetic `ExitStatus`. A non-success `ExitStatus` is /// returned to the caller — single-project `RunArgs::run` exits with /// the code; recursive `run_recursive` records `Failure` and decides /// whether to bail. @@ -322,7 +323,7 @@ pub(super) fn run_stage( return Ok(None); } - let status = run_script(RunScript { + let status = run_script(&RunScript { manifest: ctx.manifest.value(), stage, script, @@ -443,16 +444,14 @@ fn render_project_commands(manifest: &Value) -> String { let mut output = String::new(); if !lifecycle.is_empty() { - output.push_str(&format!("Lifecycle scripts:\n{}", render_commands(&lifecycle))); + write!(output, "Lifecycle scripts:\n{}", render_commands(&lifecycle)).unwrap(); } if !other.is_empty() { if !output.is_empty() { output.push_str("\n\n"); } - output.push_str(&format!( - "Commands available via \"pnpm run\":\n{}", - render_commands(&other), - )); + write!(output, "Commands available via \"pnpm run\":\n{}", render_commands(&other)) + .unwrap(); } output } diff --git a/pacquet/crates/cli/src/cli_args/run/recursive.rs b/pacquet/crates/cli/src/cli_args/run/recursive.rs index a01bf610c6..b0ae433d04 100644 --- a/pacquet/crates/cli/src/cli_args/run/recursive.rs +++ b/pacquet/crates/cli/src/cli_args/run/recursive.rs @@ -12,7 +12,7 @@ //! Scope versus upstream: projects are sorted topologically (upstream's //! default) and run sequentially. `--no-sort`, `--reverse`, //! `--workspace-concurrency` parallelism, `--filter` narrowing of the -//! selected set, and the RegExp script selector are not ported yet — the +//! selected set, and the `RegExp` script selector are not ported yet — the //! selected set is every workspace project, matching pacquet's //! currently-unfiltered `install`. diff --git a/pacquet/crates/cli/src/config_overrides.rs b/pacquet/crates/cli/src/config_overrides.rs index 8215e26efd..5e3af3347a 100644 --- a/pacquet/crates/cli/src/config_overrides.rs +++ b/pacquet/crates/cli/src/config_overrides.rs @@ -55,7 +55,7 @@ impl ConfigOverrides { /// Mirrors pnpm 11's "CLI > yaml > .npmrc > defaults" precedence. pub fn apply(&self, config: &mut Config) { if let Some(registry) = &self.registry { - config.registry = registry.clone(); + config.registry.clone_from(registry); } } } diff --git a/pacquet/crates/cli/src/lib.rs b/pacquet/crates/cli/src/lib.rs index 8ab2924672..1a7bd913d8 100644 --- a/pacquet/crates/cli/src/lib.rs +++ b/pacquet/crates/cli/src/lib.rs @@ -70,8 +70,7 @@ fn configure_rayon_pool() { return; } let n = std::thread::available_parallelism() - .map(std::num::NonZeroUsize::get) - .unwrap_or(1) + .map_or(1, std::num::NonZeroUsize::get) .saturating_mul(2) // `.max(4)` is an intentional minimum: even on quota-limited // 1-2-CPU runners, dropping below 4 puts us back into the diff --git a/pacquet/crates/cli/tests/_utils.rs b/pacquet/crates/cli/tests/_utils.rs index fe69dba5e9..11edfa2b9d 100644 --- a/pacquet/crates/cli/tests/_utils.rs +++ b/pacquet/crates/cli/tests/_utils.rs @@ -25,9 +25,10 @@ pub fn enable_gvs_in_workspace_yaml(workspace: &Path, extra_yaml: &str) { /// Snapshot-friendly view of every row in `/v11/index.db`. /// -/// The outer key is the SQLite key (`"{integrity}\t{pkgId}"`). The inner +/// The outer key is the `SQLite` key (`"{integrity}\t{pkgId}"`). The inner /// map is the package's files — one entry per path inside the tarball. /// `checked_at` is scrubbed because its value depends on install time. +#[must_use] pub fn index_file_contents(store_dir: &Path) -> BTreeMap> { let store = StoreDir::new(store_dir); // open_readonly: we're just reading for snapshot assertions, so don't diff --git a/pacquet/crates/cli/tests/hoist.rs b/pacquet/crates/cli/tests/hoist.rs index 01c18943f8..ea1fe1daf5 100644 --- a/pacquet/crates/cli/tests/hoist.rs +++ b/pacquet/crates/cli/tests/hoist.rs @@ -61,6 +61,10 @@ fn write_workspace_yaml(workspace: &Path, extra: &str) { } /// Write a one-dependency `package.json` and return the manifest path. +#[expect( + clippy::needless_pass_by_value, + reason = "test helper called many times with json!(...) literals; owned arg keeps call sites clean" +)] fn write_manifest(workspace: &Path, deps: serde_json::Value) { let manifest = serde_json::json!({ "dependencies": deps }); fs::write(workspace.join("package.json"), manifest.to_string()).expect("write package.json"); @@ -409,7 +413,7 @@ fn public_hoist_bin_is_linked_via_root_bin_dir() { } /// Workspace install (pnpm/pacquet#431) lands per-importer -/// node_modules layouts; hoist must walk every importer's direct +/// `node_modules` layouts; hoist must walk every importer's direct /// deps, not just the root, so transitives unique to a workspace /// project still reach the shared `/node_modules` private /// hoist. Sets up a two-importer workspace where the workspace @@ -812,7 +816,7 @@ mod known_failures { } /// Upstream: [`hoist.ts:514` "should recreate node_modules with hoisting"](https://github.com/pnpm/pnpm/blob/94240bc046/installing/deps-installer/test/install/hoist.ts#L514). - /// Removes node_modules and re-installs from the lockfile — + /// Removes `node_modules` and re-installs from the lockfile — /// needs partial-install state for the rehoist comparison. #[test] fn should_recreate_node_modules_with_hoisting() { diff --git a/pacquet/crates/cli/tests/hoisted_node_linker.rs b/pacquet/crates/cli/tests/hoisted_node_linker.rs index 4efef68e7f..b7610226b4 100644 --- a/pacquet/crates/cli/tests/hoisted_node_linker.rs +++ b/pacquet/crates/cli/tests/hoisted_node_linker.rs @@ -41,6 +41,10 @@ fn write_workspace_yaml(workspace: &Path, extra: &str) { } /// Write a `package.json` with the given `dependencies` object. +#[expect( + clippy::needless_pass_by_value, + reason = "test helper called many times with json!(...) literals; owned arg keeps call sites clean" +)] fn write_manifest(workspace: &Path, deps: serde_json::Value) { let manifest = serde_json::json!({ "dependencies": deps }); fs::write(workspace.join("package.json"), manifest.to_string()).expect("write package.json"); diff --git a/pacquet/crates/cli/tests/install.rs b/pacquet/crates/cli/tests/install.rs index e3b28631a4..e6898a7c23 100644 --- a/pacquet/crates/cli/tests/install.rs +++ b/pacquet/crates/cli/tests/install.rs @@ -953,6 +953,10 @@ fn compatible_existing_peer_contexts_survive_writable_lockfile_regeneration() { drop((root, mock_instance)); // cleanup } +#[expect( + clippy::needless_pass_by_value, + reason = "test fixture; the value is embedded whole into a serde_json::json! object" +)] fn install_with_peer_alias_deps(dependencies: serde_json::Value) -> String { let CommandTempCwd { pacquet, root, workspace, npmrc_info, .. } = CommandTempCwd::init().add_mocked_registry(); diff --git a/pacquet/crates/cli/tests/outdated.rs b/pacquet/crates/cli/tests/outdated.rs index 69cc66aaca..551fd126ba 100644 --- a/pacquet/crates/cli/tests/outdated.rs +++ b/pacquet/crates/cli/tests/outdated.rs @@ -263,7 +263,7 @@ fn outdated_long_shows_deprecation_details() { } /// An npm-aliased dependency is reported under its real registry name, -/// not the alias. Ports pnpm's "outdated() aliased dependency". +/// not the alias. Ports pnpm's "`outdated()` aliased dependency". #[test] fn outdated_npm_alias_reports_real_name() { let (root, workspace, anchor) = setup(); diff --git a/pacquet/crates/cli/tests/run.rs b/pacquet/crates/cli/tests/run.rs index 1605474f07..d13804badb 100644 --- a/pacquet/crates/cli/tests/run.rs +++ b/pacquet/crates/cli/tests/run.rs @@ -45,9 +45,9 @@ fn run_executes_declared_script() { } /// Positional arguments after the script name flow through to the -/// spawned shell verbatim, joined by spaces. Mirrors `pnpm run -///