mirror of
https://github.com/pnpm/pnpm.git
synced 2026-07-19 04:02:32 -04:00
fix(diagnostics): report ERR_PNPM_* error codes, never pacquet ones (#13091)
Error codes are a public contract — users match on them in CI and scripts, and pnpm documents them at https://pnpm.io/errors. 284 of pacquet's `#[diagnostic(code(...))]` sites reported something else: $ pnpm root -g Error: pacquet_cli::root_global_unsupported `pacquet` is an in-repo crate name that means nothing to a user of the `pnpm` binary. A second group reported unprefixed codes (`GIT_CHECKOUT_FAILED`), which are the *short* names pnpm passes to `PnpmError`; its constructor prepends `ERR_PNPM_` before the code is ever observed, so pacquet was emitting a code pnpm never emits. Rename all 259 offending codes across 284 sites under two rules: 1. Where pnpm defines a code for the same error, use pnpm's exact code. `pacquet_package_manager::outdated_lockfile` becomes `ERR_PNPM_OUTDATED_LOCKFILE` — which its own doc comment already claimed it was — and `GIT_CHECKOUT_FAILED` becomes `ERR_PNPM_GIT_CHECKOUT_FAILED`. 2. Otherwise derive from the full path minus the crate prefix, so `pacquet::patch_state_read` becomes `ERR_PNPM_PATCH_STATE_READ`. The namespace is retained rather than the leaf alone: six distinct `create_dir` errors would otherwise collapse onto one code. Three merge onto codes pacquet already used elsewhere for the same condition, which is the intent, not a clash. pnpm has a single `ERR_PNPM_TRUST_DOWNGRADE` and matches on it by name in `deps-resolver`, so pacquet's resolver-side and lockfile-side trust downgrades now share it. Two errors were mislabelled and are corrected rather than renamed: - `frozen_lockfile_with_outdated_lockfile` is not pnpm's outdated-lockfile error. The variant is `FrozenLockfileWithUpdateChecksums` and the message is about combining --frozen-lockfile with --update-checksums. It takes `ERR_PNPM_CONFIG_CONFLICT_FROZEN_LOCKFILE_WITH_UPDATE_CHECKSUMS`, following the existing ERR_PNPM_CONFIG_CONFLICT_* convention, and its doc comment no longer claims to be the error it isn't. - Three package-manifest errors have pnpm equivalents under a different name, which rule 1 cannot see because it matches on the name: "package.json file already exists" is pnpm's `PACKAGE_JSON_EXISTS` (thrown by `pnpm init`), "No package.json was found" is `NO_IMPORTER_MANIFEST_FOUND`, and "Missing script" is `NO_SCRIPT`. All 610 diagnostic codes are now ERR_PNPM_*.
This commit is contained in:
5
.changeset/pacquet-err-pnpm-error-codes.md
Normal file
5
.changeset/pacquet-err-pnpm-error-codes.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"pacquet": patch
|
||||
---
|
||||
|
||||
Every error code is now an `ERR_PNPM_*` code, matching the codes pnpm has always used. Errors previously reported internal Rust-crate codes such as `pacquet_package_manager::outdated_lockfile` or unprefixed codes such as `GIT_CHECKOUT_FAILED`; these are now `ERR_PNPM_OUTDATED_LOCKFILE` and `ERR_PNPM_GIT_CHECKOUT_FAILED`. Where pnpm defines a code for the same error, pnpm's exact code is used. Scripts and CI that match on the old codes need updating.
|
||||
@@ -202,7 +202,7 @@ enum AddUserError {
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum ClassicLoginOpError {
|
||||
#[display("The registry requires a one-time password to complete the login")]
|
||||
#[diagnostic(code(pacquet_auth_commands::login_otp_required))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_LOGIN_OTP_REQUIRED))]
|
||||
Otp {
|
||||
#[error(not(source))]
|
||||
challenge: OtpChallenge,
|
||||
@@ -217,7 +217,7 @@ pub enum ClassicLoginOpError {
|
||||
NoToken,
|
||||
|
||||
#[display("The login request failed: {reason}")]
|
||||
#[diagnostic(code(pacquet_auth_commands::login_request_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_LOGIN_REQUEST_FAILED))]
|
||||
Transport {
|
||||
#[error(not(source))]
|
||||
reason: String,
|
||||
|
||||
@@ -23,7 +23,7 @@ pub enum LoginError {
|
||||
"The registry returned a login URL containing control characters and was rejected as a \
|
||||
possible terminal-spoofing attempt"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_auth_commands::login_unsafe_url))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_LOGIN_UNSAFE_URL))]
|
||||
UnsafeLoginUrl,
|
||||
|
||||
#[display("Username, password, and email are all required")]
|
||||
@@ -47,25 +47,25 @@ pub enum LoginError {
|
||||
WebAuthTimeout(WebAuthTimeoutError),
|
||||
|
||||
#[display("Failed to render the login QR code: {_0}")]
|
||||
#[diagnostic(code(pacquet_auth_commands::login_qr_code))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_LOGIN_QR_CODE))]
|
||||
QrCode(#[error(source)] GenerateQrCodeError),
|
||||
|
||||
#[display("The login request failed: {reason}")]
|
||||
#[diagnostic(code(pacquet_auth_commands::login_request_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_LOGIN_REQUEST_FAILED))]
|
||||
Request {
|
||||
#[error(not(source))]
|
||||
reason: String,
|
||||
},
|
||||
|
||||
#[display("Failed to read the login prompt: {reason}")]
|
||||
#[diagnostic(code(pacquet_auth_commands::login_prompt_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_LOGIN_PROMPT_FAILED))]
|
||||
Prompt {
|
||||
#[error(not(source))]
|
||||
reason: String,
|
||||
},
|
||||
|
||||
#[display("Failed to read auth.ini at {}: {error}", path.display())]
|
||||
#[diagnostic(code(pacquet_auth_commands::read_auth_ini))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_READ_AUTH_INI))]
|
||||
ReadAuthIni {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -73,7 +73,7 @@ pub enum LoginError {
|
||||
},
|
||||
|
||||
#[display("Failed to write auth.ini at {}: {error}", path.display())]
|
||||
#[diagnostic(code(pacquet_auth_commands::write_auth_ini))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_WRITE_AUTH_INI))]
|
||||
WriteAuthIni {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -366,7 +366,7 @@ async fn should_surface_a_non_interrupt_prompt_failure_as_a_prompt_error() {
|
||||
assert!(matches!(err, LoginError::Prompt { .. }), "got {err:?}");
|
||||
assert_eq!(
|
||||
err.pipe_ref(miette::Diagnostic::code).map(|code| code.to_string()).as_deref(),
|
||||
Some("pacquet_auth_commands::login_prompt_failed"),
|
||||
Some("ERR_PNPM_AUTH_COMMANDS_LOGIN_PROMPT_FAILED"),
|
||||
);
|
||||
assert!(
|
||||
err.to_string().starts_with("Failed to read the login prompt:"),
|
||||
|
||||
@@ -140,7 +140,7 @@ async fn should_surface_a_web_login_transport_failure_as_a_request_error() {
|
||||
assert!(matches!(err, LoginError::Request { .. }), "got {err:?}");
|
||||
assert_eq!(
|
||||
err.pipe_ref(miette::Diagnostic::code).map(|code| code.to_string()).as_deref(),
|
||||
Some("pacquet_auth_commands::login_request_failed"),
|
||||
Some("ERR_PNPM_AUTH_COMMANDS_LOGIN_REQUEST_FAILED"),
|
||||
);
|
||||
assert!(err.to_string().starts_with("The login request failed:"), "unexpected message: {err}");
|
||||
}
|
||||
@@ -173,7 +173,7 @@ async fn should_fail_when_the_login_url_cannot_be_rendered_as_a_qr_code() {
|
||||
assert!(matches!(err, LoginError::QrCode(_)), "got {err:?}");
|
||||
assert_eq!(
|
||||
err.pipe_ref(miette::Diagnostic::code).map(|code| code.to_string()).as_deref(),
|
||||
Some("pacquet_auth_commands::login_qr_code"),
|
||||
Some("ERR_PNPM_AUTH_COMMANDS_LOGIN_QR_CODE"),
|
||||
);
|
||||
assert!(
|
||||
err.to_string().starts_with("Failed to render the login QR code:"),
|
||||
@@ -243,7 +243,7 @@ async fn rejects_a_login_url_containing_control_characters() {
|
||||
assert!(matches!(err, LoginError::UnsafeLoginUrl), "got {err:?}");
|
||||
assert_eq!(
|
||||
err.pipe_ref(miette::Diagnostic::code).map(|code| code.to_string()).as_deref(),
|
||||
Some("pacquet_auth_commands::login_unsafe_url"),
|
||||
Some("ERR_PNPM_AUTH_COMMANDS_LOGIN_UNSAFE_URL"),
|
||||
);
|
||||
assert!(infos().iter().all(|message| !message.contains('\u{1b}')), "got {:?}", infos());
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ pub enum LogoutError {
|
||||
LogoutFailed { registry: String, config_path: PathBuf },
|
||||
|
||||
#[display("Failed to read auth.ini at {}: {error}", path.display())]
|
||||
#[diagnostic(code(pacquet_auth_commands::read_auth_ini))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_READ_AUTH_INI))]
|
||||
ReadAuthIni {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -245,7 +245,7 @@ pub enum LogoutError {
|
||||
},
|
||||
|
||||
#[display("Failed to write auth.ini at {}: {error}", path.display())]
|
||||
#[diagnostic(code(pacquet_auth_commands::write_auth_ini))]
|
||||
#[diagnostic(code(ERR_PNPM_AUTH_COMMANDS_WRITE_AUTH_INI))]
|
||||
WriteAuthIni {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -152,7 +152,7 @@ pub enum ConfigError {
|
||||
// The rejected value is deliberately not echoed — it may be a credential
|
||||
// (e.g. a token with a stray newline pasted from an env var).
|
||||
#[display("Cannot write a value containing a control character to an INI config file")]
|
||||
#[diagnostic(code(pacquet_cli::config_set_invalid_control_character))]
|
||||
#[diagnostic(code(ERR_PNPM_CLI_CONFIG_SET_INVALID_CONTROL_CHARACTER))]
|
||||
SetIniControlCharacter,
|
||||
}
|
||||
|
||||
|
||||
@@ -574,7 +574,7 @@ fn set_ini_value_with_control_char_is_rejected() {
|
||||
|
||||
assert_eq!(
|
||||
err.code().unwrap().to_string(),
|
||||
"pacquet_cli::config_set_invalid_control_character",
|
||||
"ERR_PNPM_CLI_CONFIG_SET_INVALID_CONTROL_CHARACTER",
|
||||
);
|
||||
// The file must not have been written.
|
||||
assert!(!tmp.path().join(".npmrc").exists());
|
||||
|
||||
@@ -104,7 +104,7 @@ pub enum DlxError {
|
||||
BadPathDir { dir: String, delimiter: char },
|
||||
|
||||
#[display("Failed to read the installed manifest at {path}: {source}")]
|
||||
#[diagnostic(code(pacquet_cli::dlx_read_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_CLI_DLX_READ_MANIFEST))]
|
||||
ReadManifest {
|
||||
path: String,
|
||||
#[error(source)]
|
||||
@@ -112,7 +112,7 @@ pub enum DlxError {
|
||||
},
|
||||
|
||||
#[display("Failed to prepare the dlx cache directory {dir}: {source}")]
|
||||
#[diagnostic(code(pacquet_cli::dlx_cache))]
|
||||
#[diagnostic(code(ERR_PNPM_CLI_DLX_CACHE))]
|
||||
Cache {
|
||||
dir: String,
|
||||
#[error(source)]
|
||||
@@ -120,7 +120,7 @@ pub enum DlxError {
|
||||
},
|
||||
|
||||
#[display("Failed to spawn command \"{command}\": {source}")]
|
||||
#[diagnostic(code(pacquet_cli::dlx_spawn))]
|
||||
#[diagnostic(code(ERR_PNPM_CLI_DLX_SPAWN))]
|
||||
Spawn {
|
||||
command: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -67,7 +67,7 @@ pub enum ExecError {
|
||||
CommandNotFound { command: String },
|
||||
|
||||
#[display("Failed to spawn command \"{command}\": {source}")]
|
||||
#[diagnostic(code(pacquet_cli::exec_spawn))]
|
||||
#[diagnostic(code(ERR_PNPM_CLI_EXEC_SPAWN))]
|
||||
Spawn {
|
||||
command: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -53,7 +53,7 @@ pub enum PatchError {
|
||||
EditDirNotEmpty { edit_dir: PathBuf },
|
||||
|
||||
#[display("Unable to read the target directory '{}': {source}", edit_dir.display())]
|
||||
#[diagnostic(code(pacquet::patch_edit_dir_read))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_EDIT_DIR_READ))]
|
||||
ReadEditDir {
|
||||
edit_dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -61,7 +61,7 @@ pub enum PatchError {
|
||||
},
|
||||
|
||||
#[display("Unable to create the default patch edit directory '{}': {source}", edit_dir.display())]
|
||||
#[diagnostic(code(pacquet::patch_edit_dir_create))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_EDIT_DIR_CREATE))]
|
||||
CreateEditDir {
|
||||
edit_dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -69,7 +69,7 @@ pub enum PatchError {
|
||||
},
|
||||
|
||||
#[display("Unable to resolve the default patch edit directory '{}': {source}", edit_dir.display())]
|
||||
#[diagnostic(code(pacquet::patch_edit_dir_resolve))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_EDIT_DIR_RESOLVE))]
|
||||
ResolveEditDir {
|
||||
edit_dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -77,11 +77,11 @@ pub enum PatchError {
|
||||
},
|
||||
|
||||
#[display("The default patch edit directory is outside node_modules: '{}'", edit_dir.display())]
|
||||
#[diagnostic(code(pacquet::patch_edit_dir_outside_modules_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_EDIT_DIR_OUTSIDE_MODULES_DIR))]
|
||||
EditDirOutsideModulesDir { edit_dir: PathBuf },
|
||||
|
||||
#[display("The default patch edit directory must not use a symbolic link: '{}'", edit_dir.display())]
|
||||
#[diagnostic(code(pacquet::patch_edit_dir_symlink))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_EDIT_DIR_SYMLINK))]
|
||||
EditDirSymlink { edit_dir: PathBuf },
|
||||
|
||||
#[display("Canceled")]
|
||||
@@ -124,7 +124,7 @@ pub enum PatchError {
|
||||
PatchFileNotRegular { patch_file: String },
|
||||
|
||||
#[display("Failed to read patch file metadata for {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_read_patch_file_metadata))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_READ_PATCH_FILE_METADATA))]
|
||||
ReadPatchFileMetadata {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -43,11 +43,11 @@ pub enum PatchCommitError {
|
||||
InvalidPatchDir { patch_dir: PathBuf },
|
||||
|
||||
#[display("Missing package manifest field `{field}` in {}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_commit_missing_manifest_field))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_COMMIT_MISSING_MANIFEST_FIELD))]
|
||||
MissingManifestField { path: PathBuf, field: &'static str },
|
||||
|
||||
#[display("Failed to read package manifest from {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_commit_read_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_COMMIT_READ_MANIFEST))]
|
||||
ReadManifest {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -59,7 +59,7 @@ pub enum PatchCommitError {
|
||||
PatchNoLockfile,
|
||||
|
||||
#[display("Failed to create patches directory {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_commit_create_patches_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_COMMIT_CREATE_PATCHES_DIR))]
|
||||
CreatePatchesDir {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -75,7 +75,7 @@ pub enum PatchCommitError {
|
||||
PatchFileOutsidePatchesDir { patch_file: String },
|
||||
|
||||
#[display("Failed to read patch file metadata for {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_commit_read_patch_file_metadata))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_COMMIT_READ_PATCH_FILE_METADATA))]
|
||||
ReadPatchFileMetadata {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -83,7 +83,7 @@ pub enum PatchCommitError {
|
||||
},
|
||||
|
||||
#[display("Failed to write patch file {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_commit_write_patch))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_COMMIT_WRITE_PATCH))]
|
||||
WritePatch {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -91,7 +91,7 @@ pub enum PatchCommitError {
|
||||
},
|
||||
|
||||
#[display("Failed to clean up temporary patch directory {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_commit_cleanup_temp_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_COMMIT_CLEANUP_TEMP_DIR))]
|
||||
CleanupTempDir {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -47,7 +47,7 @@ pub enum PatchRemoveError {
|
||||
PatchFileIsDirectory { patch_file: String },
|
||||
|
||||
#[display("Failed to remove patch file {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_remove_unlink_patch_file))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_REMOVE_UNLINK_PATCH_FILE))]
|
||||
RemovePatchFile {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -55,7 +55,7 @@ pub enum PatchRemoveError {
|
||||
},
|
||||
|
||||
#[display("Failed to read patch directory {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_remove_read_patch_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_REMOVE_READ_PATCH_DIR))]
|
||||
ReadPatchDir {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -63,7 +63,7 @@ pub enum PatchRemoveError {
|
||||
},
|
||||
|
||||
#[display("Failed to remove empty patch directory {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet::patch_remove_remove_patch_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_REMOVE_REMOVE_PATCH_DIR))]
|
||||
RemovePatchDir {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -28,7 +28,7 @@ pub(crate) struct EditDirState {
|
||||
#[non_exhaustive]
|
||||
pub(crate) enum StateFileError {
|
||||
#[display("Failed to read patch state file {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet::patch_state_read))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_STATE_READ))]
|
||||
Read {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -36,7 +36,7 @@ pub(crate) enum StateFileError {
|
||||
},
|
||||
|
||||
#[display("Failed to parse patch state file {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet::patch_state_parse))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_STATE_PARSE))]
|
||||
Parse {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -44,7 +44,7 @@ pub(crate) enum StateFileError {
|
||||
},
|
||||
|
||||
#[display("Failed to serialize patch state file {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet::patch_state_serialize))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_STATE_SERIALIZE))]
|
||||
Serialize {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -52,7 +52,7 @@ pub(crate) enum StateFileError {
|
||||
},
|
||||
|
||||
#[display("Failed to write patch state file {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet::patch_state_write))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_STATE_WRITE))]
|
||||
Write {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -60,15 +60,15 @@ pub(crate) enum StateFileError {
|
||||
},
|
||||
|
||||
#[display("Unsafe patch state path {path:?}: {reason}")]
|
||||
#[diagnostic(code(pacquet::patch_state_unsafe_path))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_STATE_UNSAFE_PATH))]
|
||||
UnsafePath { path: PathBuf, reason: &'static str },
|
||||
|
||||
#[display("Patch state file {path:?} is larger than {limit} bytes")]
|
||||
#[diagnostic(code(pacquet::patch_state_file_too_large))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_STATE_FILE_TOO_LARGE))]
|
||||
StateFileTooLarge { path: PathBuf, limit: usize },
|
||||
|
||||
#[display("Failed to resolve patch edit directory {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet::patch_state_resolve_edit_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PATCH_STATE_RESOLVE_EDIT_DIR))]
|
||||
ResolveEditDir {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -20,12 +20,12 @@ pub enum PrefixError {
|
||||
/// `@pnpm/global.commands`) is not ported to pacquet yet; refuse rather
|
||||
/// than print a wrong path.
|
||||
#[display("`pnpm prefix --global` is not supported yet.")]
|
||||
#[diagnostic(code(pacquet_cli::prefix_global_unsupported))]
|
||||
#[diagnostic(code(ERR_PNPM_CLI_PREFIX_GLOBAL_UNSUPPORTED))]
|
||||
GlobalUnsupported,
|
||||
|
||||
/// IO error while looking up the prefix.
|
||||
#[display("failed to access {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet_cli::prefix_io_error))]
|
||||
#[diagnostic(code(ERR_PNPM_CLI_PREFIX_IO_ERROR))]
|
||||
Io { path: PathBuf, source: std::io::Error },
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ pub enum RootError {
|
||||
/// `--global` is rejected because the global-dir machinery is not
|
||||
/// ported to pacquet yet; refuse rather than print a wrong path.
|
||||
#[display("`pnpm root --global` is not supported yet.")]
|
||||
#[diagnostic(code(pacquet_cli::root_global_unsupported))]
|
||||
#[diagnostic(code(ERR_PNPM_CLI_ROOT_GLOBAL_UNSUPPORTED))]
|
||||
GlobalUnsupported,
|
||||
}
|
||||
|
||||
|
||||
@@ -302,7 +302,8 @@ fn deploy_all_files_rejects_symlink_escape() {
|
||||
assert!(!output.status.success());
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
assert!(
|
||||
stderr.contains("path_escape") && stderr.contains("resolves outside"),
|
||||
stderr.contains("ERR_PNPM_DIRECTORY_FETCHER_PATH_ESCAPE")
|
||||
&& stderr.contains("resolves outside"),
|
||||
"unexpected stderr:\n{stderr}",
|
||||
);
|
||||
assert!(
|
||||
|
||||
@@ -984,7 +984,7 @@ fn install_resolves_catalog_protocol() {
|
||||
|
||||
/// A misconfigured catalog (specifier points at a missing entry) must
|
||||
/// fail the install with the upstream `ERR_PNPM_CATALOG_ENTRY_NOT_FOUND_FOR_SPEC`
|
||||
/// rather than the chain's `SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`.
|
||||
/// rather than the chain's `ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`.
|
||||
#[test]
|
||||
fn install_surfaces_catalog_misconfiguration() {
|
||||
let CommandTempCwd { pacquet, root, workspace, npmrc_info, .. } =
|
||||
@@ -1018,6 +1018,10 @@ fn install_surfaces_catalog_misconfiguration() {
|
||||
),
|
||||
"stderr did not mention the missing-catalog-entry error: {stderr}",
|
||||
);
|
||||
assert!(
|
||||
stderr.contains("ERR_PNPM_CATALOG_ENTRY_NOT_FOUND_FOR_SPEC"),
|
||||
"the catalog error must surface upstream's code, not the resolver chain's: {stderr}",
|
||||
);
|
||||
|
||||
drop((root, mock_instance));
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ fn frozen_lockfile_only_rejects_a_stale_lockfile() {
|
||||
// so assert on the stable diagnostic code instead of the prose.
|
||||
let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
|
||||
assert!(
|
||||
stderr.contains("outdated_lockfile"),
|
||||
stderr.contains("ERR_PNPM_OUTDATED_LOCKFILE"),
|
||||
"stderr must name the outdated-lockfile diagnostic; got:\n{stderr}",
|
||||
);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ source: crates/cli/tests/init.rs
|
||||
assertion_line: 43
|
||||
expression: "String::from_utf8_lossy(&output.stderr).trim_end()"
|
||||
---
|
||||
Error: pacquet_package_manifest::already_exist_error
|
||||
Error: ERR_PNPM_PACKAGE_JSON_EXISTS
|
||||
|
||||
× initialize package.json
|
||||
╰─▶ package.json file already exists
|
||||
|
||||
@@ -65,7 +65,7 @@ fn assert_frozen_outdated(workspace: &Path) {
|
||||
"frozen install accepted a stale importer\nstderr:\n{stderr}",
|
||||
);
|
||||
assert!(
|
||||
stderr.contains("pacquet_package_manager::outdated_lockfile"),
|
||||
stderr.contains("ERR_PNPM_OUTDATED_LOCKFILE"),
|
||||
"frozen install returned the wrong error\nstderr:\n{stderr}",
|
||||
);
|
||||
}
|
||||
@@ -316,7 +316,7 @@ fn missing_workspace_importer_is_not_accepted_by_frozen_install() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
assert!(!output.status.success(), "frozen install accepted a missing importer");
|
||||
assert!(
|
||||
stderr.contains("pacquet_package_manager::no_importer") && stderr.contains("pkg-a"),
|
||||
stderr.contains("ERR_PNPM_PACKAGE_MANAGER_NO_IMPORTER") && stderr.contains("pkg-a"),
|
||||
"missing importer returned the wrong error\nstderr:\n{stderr}",
|
||||
);
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ pub enum BinOrigin {
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum LinkBinsError {
|
||||
#[display("Failed to create bin directory at {dir:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_cmd_shim::create_bin_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_CMD_SHIM_CREATE_BIN_DIR))]
|
||||
CreateBinDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -103,7 +103,7 @@ pub enum LinkBinsError {
|
||||
},
|
||||
|
||||
#[display("Failed to read modules directory at {dir:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_cmd_shim::read_modules_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_CMD_SHIM_READ_MODULES_DIR))]
|
||||
ReadModulesDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -111,7 +111,7 @@ pub enum LinkBinsError {
|
||||
},
|
||||
|
||||
#[display("Failed to read package manifest at {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_cmd_shim::read_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_CMD_SHIM_READ_MANIFEST))]
|
||||
ReadManifest {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -119,7 +119,7 @@ pub enum LinkBinsError {
|
||||
},
|
||||
|
||||
#[display("Failed to parse package manifest at {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_cmd_shim::parse_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_CMD_SHIM_PARSE_MANIFEST))]
|
||||
ParseManifest {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -127,7 +127,7 @@ pub enum LinkBinsError {
|
||||
},
|
||||
|
||||
#[display("Failed to read shim source {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_cmd_shim::probe_shim_source))]
|
||||
#[diagnostic(code(ERR_PNPM_CMD_SHIM_PROBE_SHIM_SOURCE))]
|
||||
ProbeShimSource {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -135,7 +135,7 @@ pub enum LinkBinsError {
|
||||
},
|
||||
|
||||
#[display("Failed to write shim file at {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_cmd_shim::write_shim))]
|
||||
#[diagnostic(code(ERR_PNPM_CMD_SHIM_WRITE_SHIM))]
|
||||
WriteShim {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -143,7 +143,7 @@ pub enum LinkBinsError {
|
||||
},
|
||||
|
||||
#[display("Failed to chmod {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_cmd_shim::chmod))]
|
||||
#[diagnostic(code(ERR_PNPM_CMD_SHIM_CHMOD))]
|
||||
Chmod {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -151,7 +151,7 @@ pub enum LinkBinsError {
|
||||
},
|
||||
|
||||
#[display("Failed to remove stale bin at {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_cmd_shim::remove_stale_bin))]
|
||||
#[diagnostic(code(ERR_PNPM_CMD_SHIM_REMOVE_STALE_BIN))]
|
||||
RemoveStaleBin {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -159,7 +159,7 @@ pub enum LinkBinsError {
|
||||
},
|
||||
|
||||
#[display("Failed to link node runtime binary {src:?} -> {dst:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_cmd_shim::link_node_bin))]
|
||||
#[diagnostic(code(ERR_PNPM_CMD_SHIM_LINK_NODE_BIN))]
|
||||
LinkNodeBin {
|
||||
src: PathBuf,
|
||||
dst: PathBuf,
|
||||
|
||||
@@ -46,16 +46,16 @@ pub struct ShasumsFileItem {
|
||||
|
||||
/// Errors raised by [`fetch_shasums_file`] and [`fetch_shasums_file_raw`].
|
||||
///
|
||||
/// Mirrors upstream's `FAILED_DOWNLOAD_SHASUM_FILE` code, which the
|
||||
/// Mirrors upstream's `ERR_PNPM_FAILED_DOWNLOAD_SHASUM_FILE` code, which the
|
||||
/// install reporter parses as a network-stage failure.
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum FetchShasumsFileError {
|
||||
#[display("Failed to fetch integrity file: {url} (status: {status})")]
|
||||
#[diagnostic(code(FAILED_DOWNLOAD_SHASUM_FILE))]
|
||||
#[diagnostic(code(ERR_PNPM_FAILED_DOWNLOAD_SHASUM_FILE))]
|
||||
StatusNotOk { url: String, status: u16 },
|
||||
|
||||
#[display("Failed to fetch integrity file: {url}")]
|
||||
#[diagnostic(code(FAILED_DOWNLOAD_SHASUM_FILE))]
|
||||
#[diagnostic(code(ERR_PNPM_FAILED_DOWNLOAD_SHASUM_FILE))]
|
||||
Network {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -66,15 +66,15 @@ pub enum FetchShasumsFileError {
|
||||
/// Errors raised by [`fetch_verified_node_shasums`] and
|
||||
/// [`fetch_verified_node_shasums_file`].
|
||||
///
|
||||
/// Mirrors pnpm's `NODE_SHASUMS_FETCH_FAIL` and
|
||||
/// `NODE_SHASUMS_SIGNATURE_INVALID` codes. These are specific to
|
||||
/// Mirrors pnpm's `ERR_PNPM_NODE_SHASUMS_FETCH_FAIL` and
|
||||
/// `ERR_PNPM_NODE_SHASUMS_SIGNATURE_INVALID` codes. These are specific to
|
||||
/// Node.js runtime verification, where a repository-configurable
|
||||
/// mirror cannot be trusted to supply both the binary and the hash
|
||||
/// list unchecked.
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum FetchVerifiedNodeShasumsError {
|
||||
#[display("Failed to fetch {what} ({url}) to verify the Node.js download (status: {status})")]
|
||||
#[diagnostic(code(NODE_SHASUMS_FETCH_FAIL))]
|
||||
#[diagnostic(code(ERR_PNPM_NODE_SHASUMS_FETCH_FAIL))]
|
||||
StatusNotOk {
|
||||
#[error(not(source))]
|
||||
what: &'static str,
|
||||
@@ -84,7 +84,7 @@ pub enum FetchVerifiedNodeShasumsError {
|
||||
},
|
||||
|
||||
#[display("Failed to fetch {what} ({url}) to verify the Node.js download")]
|
||||
#[diagnostic(code(NODE_SHASUMS_FETCH_FAIL))]
|
||||
#[diagnostic(code(ERR_PNPM_NODE_SHASUMS_FETCH_FAIL))]
|
||||
Network {
|
||||
#[error(not(source))]
|
||||
what: &'static str,
|
||||
@@ -95,14 +95,14 @@ pub enum FetchVerifiedNodeShasumsError {
|
||||
},
|
||||
|
||||
#[display("Could not read the Node.js SHASUMS signature: {error}")]
|
||||
#[diagnostic(code(NODE_SHASUMS_SIGNATURE_INVALID))]
|
||||
#[diagnostic(code(ERR_PNPM_NODE_SHASUMS_SIGNATURE_INVALID))]
|
||||
SignatureUnreadable {
|
||||
#[error(source)]
|
||||
error: Arc<pgp::errors::Error>,
|
||||
},
|
||||
|
||||
#[display("The verified Node.js SHASUMS file at {url} is not valid UTF-8")]
|
||||
#[diagnostic(code(NODE_SHASUMS_SIGNATURE_INVALID))]
|
||||
#[diagnostic(code(ERR_PNPM_NODE_SHASUMS_SIGNATURE_INVALID))]
|
||||
InvalidUtf8 {
|
||||
#[error(not(source))]
|
||||
url: String,
|
||||
@@ -113,7 +113,7 @@ pub enum FetchVerifiedNodeShasumsError {
|
||||
#[display(
|
||||
"Embedded Node.js release key fingerprint mismatch: expected {expected}, got {actual}"
|
||||
)]
|
||||
#[diagnostic(code(NODE_SHASUMS_SIGNATURE_INVALID))]
|
||||
#[diagnostic(code(ERR_PNPM_NODE_SHASUMS_SIGNATURE_INVALID))]
|
||||
EmbeddedKeyFingerprintMismatch {
|
||||
#[error(not(source))]
|
||||
expected: &'static str,
|
||||
@@ -124,7 +124,7 @@ pub enum FetchVerifiedNodeShasumsError {
|
||||
#[display(
|
||||
"The OpenPGP signature of {url} does not match any trusted Node.js release key. The downloaded Node.js runtime cannot be verified as a genuine release."
|
||||
)]
|
||||
#[diagnostic(code(NODE_SHASUMS_SIGNATURE_INVALID))]
|
||||
#[diagnostic(code(ERR_PNPM_NODE_SHASUMS_SIGNATURE_INVALID))]
|
||||
SignatureInvalid {
|
||||
#[error(not(source))]
|
||||
url: String,
|
||||
@@ -134,20 +134,20 @@ pub enum FetchVerifiedNodeShasumsError {
|
||||
/// Errors raised by [`pick_file_checksum_from_shasums_file`].
|
||||
///
|
||||
/// Two upstream codes survive the port verbatim — they are the
|
||||
/// per-file equivalents of `FAILED_DOWNLOAD_SHASUM_FILE`'s download
|
||||
/// per-file equivalents of `ERR_PNPM_FAILED_DOWNLOAD_SHASUM_FILE`'s download
|
||||
/// failure and signal that the body the verifier already has does not
|
||||
/// answer the question being asked.
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum PickFileChecksumError {
|
||||
#[display("SHA-256 hash not found in SHASUMS256.txt for: {file_name}")]
|
||||
#[diagnostic(code(NODE_INTEGRITY_HASH_NOT_FOUND))]
|
||||
#[diagnostic(code(ERR_PNPM_NODE_INTEGRITY_HASH_NOT_FOUND))]
|
||||
NotFound {
|
||||
#[error(not(source))]
|
||||
file_name: String,
|
||||
},
|
||||
|
||||
#[display("Malformed SHA-256 for {file_name}: {sha256}")]
|
||||
#[diagnostic(code(NODE_MALFORMED_INTEGRITY_HASH))]
|
||||
#[diagnostic(code(ERR_PNPM_NODE_MALFORMED_INTEGRITY_HASH))]
|
||||
Malformed { file_name: String, sha256: String },
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ pub enum DirectoryFetcherError {
|
||||
/// Broken symlinks are *not* surfaced here — they degrade to a
|
||||
/// skipped entry inside the walker.
|
||||
#[display("I/O error while walking directory {dir:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_directory_fetcher::io))]
|
||||
#[diagnostic(code(ERR_PNPM_DIRECTORY_FETCHER_IO))]
|
||||
Io {
|
||||
dir: String,
|
||||
#[error(source)]
|
||||
@@ -26,7 +26,7 @@ pub enum DirectoryFetcherError {
|
||||
path.display(),
|
||||
directory.display()
|
||||
)]
|
||||
#[diagnostic(code(pacquet_directory_fetcher::path_escape))]
|
||||
#[diagnostic(code(ERR_PNPM_DIRECTORY_FETCHER_PATH_ESCAPE))]
|
||||
PathOutsideDirectory { path: PathBuf, directory: PathBuf },
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
|
||||
@@ -21,7 +21,7 @@ const BARE_SPEC_PREFIX: &str = "runtime:";
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum BunResolverError {
|
||||
#[display("Could not resolve Bun version specified as {spec}")]
|
||||
#[diagnostic(code(BUN_RESOLUTION_FAILURE))]
|
||||
#[diagnostic(code(ERR_PNPM_BUN_RESOLUTION_FAILURE))]
|
||||
ResolutionFailure {
|
||||
#[error(not(source))]
|
||||
spec: String,
|
||||
|
||||
@@ -25,7 +25,7 @@ pub enum ReadBunAssetsError {
|
||||
FetchShasumsFile(#[error(source)] FetchShasumsFileError),
|
||||
|
||||
#[display("Failed to parse integrity {integrity} for {file_name}")]
|
||||
#[diagnostic(code(BUN_PARSE_INTEGRITY))]
|
||||
#[diagnostic(code(ERR_PNPM_BUN_PARSE_INTEGRITY))]
|
||||
Integrity {
|
||||
integrity: String,
|
||||
file_name: String,
|
||||
|
||||
@@ -18,12 +18,12 @@ const RESOLVED_VIA: &str = "github.com/denoland/deno";
|
||||
const BARE_SPEC_PREFIX: &str = "runtime:";
|
||||
|
||||
/// Errors emitted by [`DenoResolver`], carrying the
|
||||
/// `DENO_RESOLUTION_FAILURE` / `DENO_MISSING_ASSETS` /
|
||||
/// `DENO_GITHUB_FAILURE` / `DENO_PARSE_HASH` codes.
|
||||
/// `ERR_PNPM_DENO_RESOLUTION_FAILURE` / `ERR_PNPM_DENO_MISSING_ASSETS` /
|
||||
/// `ERR_PNPM_DENO_GITHUB_FAILURE` / `ERR_PNPM_DENO_PARSE_HASH` codes.
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum DenoResolverError {
|
||||
#[display("Could not resolve Deno version specified as {spec}")]
|
||||
#[diagnostic(code(DENO_RESOLUTION_FAILURE))]
|
||||
#[diagnostic(code(ERR_PNPM_DENO_RESOLUTION_FAILURE))]
|
||||
ResolutionFailure {
|
||||
#[error(not(source))]
|
||||
spec: String,
|
||||
|
||||
@@ -30,14 +30,14 @@ use ssri::Integrity;
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum ReadDenoAssetsError {
|
||||
#[display("No assets found for Deno v{version}")]
|
||||
#[diagnostic(code(DENO_MISSING_ASSETS))]
|
||||
#[diagnostic(code(ERR_PNPM_DENO_MISSING_ASSETS))]
|
||||
MissingAssets {
|
||||
#[error(not(source))]
|
||||
version: String,
|
||||
},
|
||||
|
||||
#[display("Failed to GET sha256 at {url}")]
|
||||
#[diagnostic(code(DENO_GITHUB_FAILURE))]
|
||||
#[diagnostic(code(ERR_PNPM_DENO_GITHUB_FAILURE))]
|
||||
GithubFailure {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -45,18 +45,18 @@ pub enum ReadDenoAssetsError {
|
||||
},
|
||||
|
||||
#[display("Failed to GET sha256 at {url} (status: {status})")]
|
||||
#[diagnostic(code(DENO_GITHUB_FAILURE))]
|
||||
#[diagnostic(code(ERR_PNPM_DENO_GITHUB_FAILURE))]
|
||||
GithubStatus { url: String, status: u16 },
|
||||
|
||||
#[display("No SHA256 in {url}")]
|
||||
#[diagnostic(code(DENO_PARSE_HASH))]
|
||||
#[diagnostic(code(ERR_PNPM_DENO_PARSE_HASH))]
|
||||
ParseHash {
|
||||
#[error(not(source))]
|
||||
url: String,
|
||||
},
|
||||
|
||||
#[display("Failed to GET release index for Deno v{version}")]
|
||||
#[diagnostic(code(DENO_GITHUB_FAILURE))]
|
||||
#[diagnostic(code(ERR_PNPM_DENO_GITHUB_FAILURE))]
|
||||
FetchReleaseIndex {
|
||||
version: String,
|
||||
#[error(source)]
|
||||
@@ -64,7 +64,7 @@ pub enum ReadDenoAssetsError {
|
||||
},
|
||||
|
||||
#[display("Failed to decode release index for Deno v{version}")]
|
||||
#[diagnostic(code(DENO_GITHUB_FAILURE))]
|
||||
#[diagnostic(code(ERR_PNPM_DENO_GITHUB_FAILURE))]
|
||||
DecodeReleaseIndex {
|
||||
version: String,
|
||||
#[error(source)]
|
||||
@@ -72,7 +72,7 @@ pub enum ReadDenoAssetsError {
|
||||
},
|
||||
|
||||
#[display("Failed to parse integrity for {url}")]
|
||||
#[diagnostic(code(DENO_PARSE_HASH))]
|
||||
#[diagnostic(code(ERR_PNPM_DENO_PARSE_HASH))]
|
||||
Integrity {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -130,7 +130,7 @@ pub async fn read_deno_assets(
|
||||
// `fetch_sha256` already validates that `sha256` is a 64-char
|
||||
// lower-case hex run via `extract_sha256`, so `decode_hex`
|
||||
// cannot fail here. Map the impossible-failure branch to
|
||||
// `DENO_PARSE_HASH` rather than silently falling back to an
|
||||
// `ERR_PNPM_DENO_PARSE_HASH` rather than silently falling back to an
|
||||
// empty byte slice so a future change to `extract_sha256`
|
||||
// that loosens the validator surfaces with the right error
|
||||
// code instead of an opaque integrity-parse failure.
|
||||
|
||||
@@ -44,17 +44,17 @@ const BARE_SPEC_PREFIX: &str = "runtime:";
|
||||
/// Errors emitted by [`NodeResolver::resolve`] / [`NodeResolver::resolve_latest`].
|
||||
///
|
||||
/// Each variant maps to one of the node-resolver error codes
|
||||
/// (`NO_OFFLINE_NODEJS_RESOLUTION`, `NODEJS_VERSION_NOT_FOUND`,
|
||||
/// `INVALID_NODE_RELEASE_CHANNEL`, plus the network failure modes
|
||||
/// (`ERR_PNPM_NO_OFFLINE_NODEJS_RESOLUTION`, `ERR_PNPM_NODEJS_VERSION_NOT_FOUND`,
|
||||
/// `ERR_PNPM_INVALID_NODE_RELEASE_CHANNEL`, plus the network failure modes
|
||||
/// surfaced by the shasums-file and release-index fetchers).
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum NodeResolverError {
|
||||
#[display("Offline Node.js resolution is not supported")]
|
||||
#[diagnostic(code(NO_OFFLINE_NODEJS_RESOLUTION))]
|
||||
#[diagnostic(code(ERR_PNPM_NO_OFFLINE_NODEJS_RESOLUTION))]
|
||||
Offline,
|
||||
|
||||
#[display("Could not find a Node.js version that satisfies {spec}")]
|
||||
#[diagnostic(code(NODEJS_VERSION_NOT_FOUND))]
|
||||
#[diagnostic(code(ERR_PNPM_NODEJS_VERSION_NOT_FOUND))]
|
||||
VersionNotFound {
|
||||
#[error(not(source))]
|
||||
spec: String,
|
||||
@@ -73,7 +73,7 @@ pub enum NodeResolverError {
|
||||
FetchVerifiedNodeShasums(#[error(source)] FetchVerifiedNodeShasumsError),
|
||||
|
||||
#[display("Failed to parse integrity {integrity} for {file_name}")]
|
||||
#[diagnostic(code(NODE_INTEGRITY_PARSE_FAILED))]
|
||||
#[diagnostic(code(ERR_PNPM_NODE_INTEGRITY_PARSE_FAILED))]
|
||||
ParseIntegrity {
|
||||
integrity: String,
|
||||
file_name: String,
|
||||
|
||||
@@ -51,7 +51,7 @@ async fn offline_raises_no_offline_nodejs_resolution() {
|
||||
err.downcast_ref::<super::NodeResolverError>().expect("error is a NodeResolverError");
|
||||
assert_eq!(
|
||||
code.code().map(|code| code.to_string()).as_deref(),
|
||||
Some("NO_OFFLINE_NODEJS_RESOLUTION"),
|
||||
Some("ERR_PNPM_NO_OFFLINE_NODEJS_RESOLUTION"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ async fn resolve_save_specifier_errors_when_no_version_satisfies() {
|
||||
let code: &dyn miette::Diagnostic = &err;
|
||||
assert_eq!(
|
||||
code.code().map(|code| code.to_string()).as_deref(),
|
||||
Some("NODEJS_VERSION_NOT_FOUND"),
|
||||
Some("ERR_PNPM_NODEJS_VERSION_NOT_FOUND"),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,13 @@ pub struct NodeSpecifier {
|
||||
|
||||
/// Errors raised by [`parse_node_specifier`].
|
||||
///
|
||||
/// Carries the `INVALID_NODE_RELEASE_CHANNEL` code so log consumers
|
||||
/// Carries the `ERR_PNPM_INVALID_NODE_RELEASE_CHANNEL` code so log consumers
|
||||
/// (e.g. `@pnpm/cli.default-reporter`) parse the same string.
|
||||
#[derive(Debug, Display, Error, Diagnostic, Clone, PartialEq, Eq)]
|
||||
pub enum ParseNodeSpecifierError {
|
||||
#[display("\"{channel}\" is not a valid Node.js release channel")]
|
||||
#[diagnostic(
|
||||
code(INVALID_NODE_RELEASE_CHANNEL),
|
||||
code(ERR_PNPM_INVALID_NODE_RELEASE_CHANNEL),
|
||||
help("Valid release channels are: nightly, rc, test, v8-canary, release")
|
||||
)]
|
||||
InvalidReleaseChannel {
|
||||
|
||||
@@ -47,7 +47,7 @@ struct RawNodeVersion {
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum ResolveNodeVersionError {
|
||||
#[display("Failed to fetch Node.js release index at {url}")]
|
||||
#[diagnostic(code(FETCH_NODE_INDEX_FAILED))]
|
||||
#[diagnostic(code(ERR_PNPM_FETCH_NODE_INDEX_FAILED))]
|
||||
FetchIndex {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -55,7 +55,7 @@ pub enum ResolveNodeVersionError {
|
||||
},
|
||||
|
||||
#[display("Failed to decode Node.js release index at {url}")]
|
||||
#[diagnostic(code(DECODE_NODE_INDEX_FAILED))]
|
||||
#[diagnostic(code(ERR_PNPM_DECODE_NODE_INDEX_FAILED))]
|
||||
DecodeIndex {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -68,7 +68,7 @@ pub enum ResolveNodeVersionError {
|
||||
/// `node_mirror_base_url` falls back to the official `release` channel
|
||||
/// when `None`. Returns `Ok(None)` when the index is reachable but no
|
||||
/// version satisfies the selector — the caller raises
|
||||
/// `NODEJS_VERSION_NOT_FOUND`.
|
||||
/// `ERR_PNPM_NODEJS_VERSION_NOT_FOUND`.
|
||||
pub async fn resolve_node_version(
|
||||
http_client: &ThrottledClient,
|
||||
version_spec: &str,
|
||||
|
||||
@@ -85,7 +85,7 @@ pub enum ConfigDepError {
|
||||
Import(#[error(source)] ImportIndexedDirError),
|
||||
|
||||
#[display("Failed to create config-dependency symlink at {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_env_installer::symlink))]
|
||||
#[diagnostic(code(ERR_PNPM_ENV_INSTALLER_SYMLINK))]
|
||||
Symlink {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -93,7 +93,7 @@ pub enum ConfigDepError {
|
||||
},
|
||||
|
||||
#[display("Failed to read config-modules directory {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_env_installer::read_config_modules))]
|
||||
#[diagnostic(code(ERR_PNPM_ENV_INSTALLER_READ_CONFIG_MODULES))]
|
||||
ReadConfigModules {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -24,11 +24,11 @@ use std::{
|
||||
#[non_exhaustive]
|
||||
pub enum ExecutorError {
|
||||
#[display("Failed to spawn command: {_0}")]
|
||||
#[diagnostic(code(pacquet_executor::spawn_command))]
|
||||
#[diagnostic(code(ERR_PNPM_EXECUTOR_SPAWN_COMMAND))]
|
||||
SpawnCommand(#[error(source)] std::io::Error),
|
||||
|
||||
#[display("Process exits with an error: {_0}")]
|
||||
#[diagnostic(code(pacquet_executor::wait_process))]
|
||||
#[diagnostic(code(ERR_PNPM_EXECUTOR_WAIT_PROCESS))]
|
||||
WaitProcess(#[error(source)] std::io::Error),
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ use std::{
|
||||
#[non_exhaustive]
|
||||
pub enum LifecycleScriptError {
|
||||
#[display("Failed to read package.json at {path}: {source}")]
|
||||
#[diagnostic(code(pacquet_executor::read_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_EXECUTOR_READ_MANIFEST))]
|
||||
ReadManifest {
|
||||
path: String,
|
||||
#[error(source)]
|
||||
@@ -34,11 +34,11 @@ pub enum LifecycleScriptError {
|
||||
},
|
||||
|
||||
#[display("{dep_path} {stage}: `{script}` exited with {status}")]
|
||||
#[diagnostic(code(pacquet_executor::lifecycle_script_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_EXECUTOR_LIFECYCLE_SCRIPT_FAILED))]
|
||||
ScriptFailed { dep_path: String, stage: String, script: String, status: ExitStatus },
|
||||
|
||||
#[display("Failed to spawn lifecycle script for {dep_path} {stage}: {source}")]
|
||||
#[diagnostic(code(pacquet_executor::spawn_lifecycle))]
|
||||
#[diagnostic(code(ERR_PNPM_EXECUTOR_SPAWN_LIFECYCLE))]
|
||||
Spawn {
|
||||
dep_path: String,
|
||||
stage: String,
|
||||
@@ -47,7 +47,7 @@ pub enum LifecycleScriptError {
|
||||
},
|
||||
|
||||
#[display("Failed waiting for lifecycle script for {dep_path} {stage}: {source}")]
|
||||
#[diagnostic(code(pacquet_executor::wait_lifecycle))]
|
||||
#[diagnostic(code(ERR_PNPM_EXECUTOR_WAIT_LIFECYCLE))]
|
||||
Wait {
|
||||
dep_path: String,
|
||||
stage: String,
|
||||
@@ -56,7 +56,7 @@ pub enum LifecycleScriptError {
|
||||
},
|
||||
|
||||
#[display("Invalid script shell for {dep_path} {stage}: {source}")]
|
||||
#[diagnostic(code(pacquet_executor::invalid_script_shell))]
|
||||
#[diagnostic(code(ERR_PNPM_EXECUTOR_INVALID_SCRIPT_SHELL))]
|
||||
ScriptShell {
|
||||
dep_path: String,
|
||||
stage: String,
|
||||
|
||||
@@ -22,7 +22,7 @@ use std::{
|
||||
#[non_exhaustive]
|
||||
pub enum RunScriptError {
|
||||
#[display("Failed to spawn script `{script}`: {source}")]
|
||||
#[diagnostic(code(pacquet_executor::run_script_spawn))]
|
||||
#[diagnostic(code(ERR_PNPM_EXECUTOR_RUN_SCRIPT_SPAWN))]
|
||||
Spawn {
|
||||
script: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -105,7 +105,7 @@ pub enum CreateExportableManifestError {
|
||||
Transform(#[error(source)] TransformError),
|
||||
|
||||
#[display("Failed to read README from {dir}: {source}")]
|
||||
#[diagnostic(code(pacquet_exportable_manifest::read_readme))]
|
||||
#[diagnostic(code(ERR_PNPM_EXPORTABLE_MANIFEST_READ_README))]
|
||||
ReadReadme {
|
||||
dir: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -62,7 +62,7 @@ mod tests;
|
||||
#[non_exhaustive]
|
||||
pub enum PacklistError {
|
||||
#[display("I/O error while computing packlist for {pkg_dir}: {source}")]
|
||||
#[diagnostic(code(pacquet_fs_packlist::io))]
|
||||
#[diagnostic(code(ERR_PNPM_FS_PACKLIST_IO))]
|
||||
Io {
|
||||
pkg_dir: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -3,8 +3,8 @@ use pacquet_diagnostics::miette::{self, Diagnostic};
|
||||
|
||||
/// Error type of [`crate::prepare_package()`].
|
||||
///
|
||||
/// The error codes (`GIT_DEP_PREPARE_NOT_ALLOWED`,
|
||||
/// `ERR_PNPM_PREPARE_PACKAGE`, `INVALID_PATH`) match pnpm's, so
|
||||
/// The error codes (`ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED`,
|
||||
/// `ERR_PNPM_PREPARE_PACKAGE`, `ERR_PNPM_INVALID_PATH`) match pnpm's, so
|
||||
/// `pnpm.io/errors/<code>` URL resolution keeps working.
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
#[non_exhaustive]
|
||||
@@ -14,7 +14,7 @@ pub enum PreparePackageError {
|
||||
"The git-hosted package \"{name}@{version}\" needs to execute build scripts but is not in the \"allowBuilds\" allowlist."
|
||||
)]
|
||||
#[diagnostic(
|
||||
code(GIT_DEP_PREPARE_NOT_ALLOWED),
|
||||
code(ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED),
|
||||
help(
|
||||
"Add the package to \"allowBuilds\" in your project's pnpm-workspace.yaml to allow it to run scripts. For example:\nallowBuilds:\n {name}: true",
|
||||
)
|
||||
@@ -31,16 +31,16 @@ pub enum PreparePackageError {
|
||||
},
|
||||
|
||||
/// `path` field on the resolution pointed outside the cloned dir
|
||||
/// or to a non-directory, rejected with the `INVALID_PATH` code.
|
||||
/// or to a non-directory, rejected with the `ERR_PNPM_INVALID_PATH` code.
|
||||
#[display("Path {path:?} is not a valid sub-directory of the git checkout")]
|
||||
#[diagnostic(code(INVALID_PATH))]
|
||||
#[diagnostic(code(ERR_PNPM_INVALID_PATH))]
|
||||
InvalidPath { path: String },
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
ReadManifest(#[error(source)] pacquet_package_manifest::PackageManifestError),
|
||||
|
||||
#[display("I/O error during preparePackage: {_0}")]
|
||||
#[diagnostic(code(pacquet_git_fetcher::prepare_package::io))]
|
||||
#[diagnostic(code(ERR_PNPM_GIT_FETCHER_PREPARE_PACKAGE_IO))]
|
||||
Io(#[error(source)] std::io::Error),
|
||||
}
|
||||
|
||||
@@ -51,20 +51,20 @@ pub enum GitFetcherError {
|
||||
/// `git` executable not found on `PATH`. Pacquet, like pnpm, does
|
||||
/// not bundle git — the user must install it themselves.
|
||||
#[display("`git` executable not found on PATH. Install git to fetch git-hosted packages.")]
|
||||
#[diagnostic(code(pacquet_git_fetcher::git_not_found))]
|
||||
#[diagnostic(code(ERR_PNPM_GIT_FETCHER_GIT_NOT_FOUND))]
|
||||
GitNotFound,
|
||||
|
||||
/// `git` exited non-zero on `clone` / `fetch` / `checkout` /
|
||||
/// `rev-parse`. `operation` is the subcommand, `stderr` is captured
|
||||
/// from the child so the failure surfaces in the install log.
|
||||
#[display("`git {operation}` failed ({status}): {stderr}")]
|
||||
#[diagnostic(code(pacquet_git_fetcher::git_exec_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_GIT_FETCHER_GIT_EXEC_FAILED))]
|
||||
GitExec { operation: &'static str, stderr: String, status: std::process::ExitStatus },
|
||||
|
||||
/// `git rev-parse HEAD` did not return the pinned commit, rejected
|
||||
/// with the `GIT_CHECKOUT_FAILED` code.
|
||||
/// with the `ERR_PNPM_GIT_CHECKOUT_FAILED` code.
|
||||
#[display("received commit {received} does not match expected value {expected}")]
|
||||
#[diagnostic(code(GIT_CHECKOUT_FAILED))]
|
||||
#[diagnostic(code(ERR_PNPM_GIT_CHECKOUT_FAILED))]
|
||||
CheckoutMismatch { expected: String, received: String },
|
||||
|
||||
/// `resolution.commit` is not a 40-character hexadecimal SHA. A
|
||||
@@ -75,11 +75,11 @@ pub enum GitFetcherError {
|
||||
#[display(
|
||||
"Invalid git commit hash {commit:?} for repository {repo:?}. Expected a 40-character hexadecimal SHA."
|
||||
)]
|
||||
#[diagnostic(code(INVALID_GIT_COMMIT))]
|
||||
#[diagnostic(code(ERR_PNPM_INVALID_GIT_COMMIT))]
|
||||
InvalidCommit { commit: String, repo: String },
|
||||
|
||||
#[display("I/O error during git fetch: {_0}")]
|
||||
#[diagnostic(code(pacquet_git_fetcher::io))]
|
||||
#[diagnostic(code(ERR_PNPM_GIT_FETCHER_IO))]
|
||||
Io(#[error(source)] std::io::Error),
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
|
||||
@@ -583,7 +583,7 @@ async fn fetcher_surfaces_prepare_failure() {
|
||||
|
||||
// Variant match first so the failure message at the panic site
|
||||
// is informative on a `Prepare(InvalidPath {...})` regression
|
||||
// (where the diagnostic code is `INVALID_PATH`, not the one we
|
||||
// (where the diagnostic code is `ERR_PNPM_INVALID_PATH`, not the one we
|
||||
// want here).
|
||||
match &err {
|
||||
GitFetcherError::Prepare(crate::error::PreparePackageError::LifecycleFailed { .. }) => {}
|
||||
|
||||
@@ -90,7 +90,7 @@ pub fn prepare_package<Reporter: self::Reporter>(
|
||||
}
|
||||
|
||||
// `allowBuild` check before any spawn. A dep path that isn't
|
||||
// allowed throws GIT_DEP_PREPARE_NOT_ALLOWED. The manifest comes
|
||||
// allowed throws ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED. The manifest comes
|
||||
// from the fetched artifact itself, so its name and version only
|
||||
// feed the error message; the dep path is the gated identity.
|
||||
let name = manifest.get("name").and_then(Value::as_str).unwrap_or("");
|
||||
|
||||
@@ -619,7 +619,7 @@ async fn fast_path_ignore_scripts_returns_input_without_queueing_row() {
|
||||
}
|
||||
|
||||
/// A `..`-laden `resolution.path` must be rejected by
|
||||
/// `prepare_package`'s `safe_join_path` with `INVALID_PATH` before
|
||||
/// `prepare_package`'s `safe_join_path` with `ERR_PNPM_INVALID_PATH` before
|
||||
/// any extraction happens (directory-traversal guard).
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn tarball_path_traversal_attack_is_rejected() {
|
||||
@@ -650,6 +650,14 @@ async fn tarball_path_traversal_attack_is_rejected() {
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
{
|
||||
use miette::Diagnostic;
|
||||
let code = err.code().map(|c| c.to_string()).unwrap_or_default();
|
||||
assert_eq!(
|
||||
code, "ERR_PNPM_INVALID_PATH",
|
||||
"diagnostic code must match the upstream error contract",
|
||||
);
|
||||
}
|
||||
match err {
|
||||
GitFetcherError::Prepare(PreparePackageError::InvalidPath { path }) => {
|
||||
assert_eq!(path, "../escape");
|
||||
@@ -659,7 +667,7 @@ async fn tarball_path_traversal_attack_is_rejected() {
|
||||
}
|
||||
|
||||
/// A `path` pointing at a sub-directory the tarball doesn't contain
|
||||
/// must surface as `INVALID_PATH` — silently packing the root would
|
||||
/// must surface as `ERR_PNPM_INVALID_PATH` — silently packing the root would
|
||||
/// produce a working install for the wrong package.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn tarball_path_to_missing_subdir_is_rejected() {
|
||||
@@ -690,6 +698,14 @@ async fn tarball_path_to_missing_subdir_is_rejected() {
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
{
|
||||
use miette::Diagnostic;
|
||||
let code = err.code().map(|c| c.to_string()).unwrap_or_default();
|
||||
assert_eq!(
|
||||
code, "ERR_PNPM_INVALID_PATH",
|
||||
"diagnostic code must match the upstream error contract",
|
||||
);
|
||||
}
|
||||
match err {
|
||||
GitFetcherError::Prepare(PreparePackageError::InvalidPath { path }) => {
|
||||
assert_eq!(path, "does/not/exist");
|
||||
|
||||
@@ -16,7 +16,7 @@ pub type ReadPackageResult = Arc<Value>;
|
||||
|
||||
/// An error raised while running a pnpmfile hook in Node.js.
|
||||
///
|
||||
/// Covers the `PNPMFILE_FAIL` / `BAD_READ_PACKAGE_HOOK_RESULT` conditions: a
|
||||
/// Covers the `ERR_PNPM_PNPMFILE_FAIL` / `ERR_PNPM_BAD_READ_PACKAGE_HOOK_RESULT` conditions: a
|
||||
/// throwing or syntactically invalid pnpmfile, or a `readPackage` hook that
|
||||
/// returns something that is not a package manifest, aborts the install.
|
||||
#[derive(Debug, Display, Clone)]
|
||||
|
||||
@@ -13,15 +13,15 @@ use std::{
|
||||
#[non_exhaustive]
|
||||
pub enum LoadLockfileError {
|
||||
#[display("Failed to get current_dir: {_0}")]
|
||||
#[diagnostic(code(pacquet_lockfile::current_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_LOCKFILE_CURRENT_DIR))]
|
||||
CurrentDir(io::Error),
|
||||
|
||||
#[display("Failed to read lockfile content: {_0}")]
|
||||
#[diagnostic(code(pacquet_lockfile::read_file))]
|
||||
#[diagnostic(code(ERR_PNPM_LOCKFILE_READ_FILE))]
|
||||
ReadFile(io::Error),
|
||||
|
||||
#[display("Failed to parse lockfile content as YAML: {_0}")]
|
||||
#[diagnostic(code(pacquet_lockfile::parse_yaml))]
|
||||
#[diagnostic(code(ERR_PNPM_LOCKFILE_PARSE_YAML))]
|
||||
ParseYaml(serde_saphyr::Error),
|
||||
}
|
||||
|
||||
|
||||
@@ -17,19 +17,19 @@ use std::{
|
||||
#[non_exhaustive]
|
||||
pub enum SaveLockfileError {
|
||||
#[display("Failed to get current_dir: {_0}")]
|
||||
#[diagnostic(code(pacquet_lockfile::current_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_LOCKFILE_CURRENT_DIR))]
|
||||
CurrentDir(io::Error),
|
||||
|
||||
#[display("Failed to serialize lockfile to YAML: {_0}")]
|
||||
#[diagnostic(code(pacquet_lockfile::serialize_yaml))]
|
||||
#[diagnostic(code(ERR_PNPM_LOCKFILE_SERIALIZE_YAML))]
|
||||
SerializeYaml(serde_json::Error),
|
||||
|
||||
#[display("Failed to write lockfile content: {_0}")]
|
||||
#[diagnostic(code(pacquet_lockfile::write_file))]
|
||||
#[diagnostic(code(ERR_PNPM_LOCKFILE_WRITE_FILE))]
|
||||
WriteFile(io::Error),
|
||||
|
||||
#[display("Failed to create virtual-store directory {dir:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_lockfile::create_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_LOCKFILE_CREATE_DIR))]
|
||||
CreateDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -37,7 +37,7 @@ pub enum SaveLockfileError {
|
||||
},
|
||||
|
||||
#[display("Failed to remove existing current-lockfile at {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_lockfile::remove_file))]
|
||||
#[diagnostic(code(ERR_PNPM_LOCKFILE_REMOVE_FILE))]
|
||||
RemoveFile {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -45,7 +45,7 @@ pub enum SaveLockfileError {
|
||||
},
|
||||
|
||||
#[display("Failed to rename temp file {tmp:?} over {target:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_lockfile::rename_file))]
|
||||
#[diagnostic(code(ERR_PNPM_LOCKFILE_RENAME_FILE))]
|
||||
RenameFile {
|
||||
tmp: PathBuf,
|
||||
target: PathBuf,
|
||||
|
||||
@@ -352,11 +352,11 @@ pub enum AllowBuildValue {
|
||||
#[non_exhaustive]
|
||||
pub enum ReadModulesError {
|
||||
#[display("Failed to read {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_modules_yaml::read_io))]
|
||||
#[diagnostic(code(ERR_PNPM_MODULES_YAML_READ_IO))]
|
||||
ReadFile { path: PathBuf, source: io::Error },
|
||||
|
||||
#[display("Failed to parse {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_modules_yaml::parse_yaml))]
|
||||
#[diagnostic(code(ERR_PNPM_MODULES_YAML_PARSE_YAML))]
|
||||
ParseYaml { path: PathBuf, source: Box<serde_saphyr::Error> },
|
||||
}
|
||||
|
||||
@@ -365,15 +365,15 @@ pub enum ReadModulesError {
|
||||
#[non_exhaustive]
|
||||
pub enum WriteModulesError {
|
||||
#[display("Failed to create directory {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_modules_yaml::create_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_MODULES_YAML_CREATE_DIR))]
|
||||
CreateDir { path: PathBuf, source: io::Error },
|
||||
|
||||
#[display("Failed to serialize manifest: {_0}")]
|
||||
#[diagnostic(code(pacquet_modules_yaml::serialize_json))]
|
||||
#[diagnostic(code(ERR_PNPM_MODULES_YAML_SERIALIZE_JSON))]
|
||||
SerializeJson(serde_json::Error),
|
||||
|
||||
#[display("Failed to write {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_modules_yaml::write_io))]
|
||||
#[diagnostic(code(ERR_PNPM_MODULES_YAML_WRITE_IO))]
|
||||
WriteFile { path: PathBuf, source: io::Error },
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
//! `workspace:` and bare filesystem paths, the node / deno / bun
|
||||
//! runtime specs, and `<alias>:` named-registry specs. A specifier no
|
||||
//! resolver in the chain claims surfaces as
|
||||
//! `SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`.
|
||||
//! `ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`.
|
||||
//!
|
||||
//! The one deviation from the install chain: the tarball resolver runs
|
||||
//! without a fetch context (no store to extract into on this
|
||||
@@ -240,7 +240,7 @@ fn run_resolve_blocking(
|
||||
// An empty bareSpecifier means "no range given" — pnpm v11's
|
||||
// resolver treated it like an absent pref (resolve the latest
|
||||
// matching version); passing it through verbatim would fall off
|
||||
// the resolver chain as SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER.
|
||||
// the resolver chain as ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER.
|
||||
bare_specifier: wanted.bare_specifier.filter(|spec| !spec.trim().is_empty()),
|
||||
injected: None,
|
||||
prev_specifier: None,
|
||||
@@ -261,7 +261,7 @@ fn run_resolve_blocking(
|
||||
})?;
|
||||
|
||||
// The inherent [`DefaultResolver::resolve`] (not the `Resolver`-trait
|
||||
// method) is chosen here: it raises `SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`
|
||||
// method) is chosen here: it raises `ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`
|
||||
// when no resolver in the chain claims the spec, rather than the
|
||||
// trait's `Ok(None)`.
|
||||
let resolved = runtime
|
||||
|
||||
@@ -80,7 +80,7 @@ fn errors_when_no_resolver_in_the_chain_claims_the_spec() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
// No alias and no bare specifier: every resolver in the chain declines,
|
||||
// so the dispatcher raises `SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER` rather
|
||||
// so the dispatcher raises `ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER` rather
|
||||
// than the old npm-only "not claimed" string.
|
||||
let wanted = WantedDependencyInput { alias: None, bare_specifier: None };
|
||||
let Err(error) = run_resolve_blocking(wanted, &options_for(dir.path())) else {
|
||||
|
||||
@@ -198,11 +198,11 @@ pub enum PackError {
|
||||
Lifecycle(#[error(source)] LifecycleScriptError),
|
||||
|
||||
#[display("The \"beforePacking\" hook from {pnpmfile} failed: {message}")]
|
||||
#[diagnostic(code(pacquet_pack::before_packing))]
|
||||
#[diagnostic(code(ERR_PNPM_PACK_BEFORE_PACKING))]
|
||||
BeforePacking { pnpmfile: String, message: String },
|
||||
|
||||
#[display("Failed to read {path}: {source}")]
|
||||
#[diagnostic(code(pacquet_pack::read_file))]
|
||||
#[diagnostic(code(ERR_PNPM_PACK_READ_FILE))]
|
||||
ReadFile {
|
||||
path: String,
|
||||
#[error(source)]
|
||||
@@ -210,7 +210,7 @@ pub enum PackError {
|
||||
},
|
||||
|
||||
#[display("Failed to create directory {path}: {source}")]
|
||||
#[diagnostic(code(pacquet_pack::create_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PACK_CREATE_DIR))]
|
||||
CreateDir {
|
||||
path: String,
|
||||
#[error(source)]
|
||||
@@ -218,7 +218,7 @@ pub enum PackError {
|
||||
},
|
||||
|
||||
#[display("Failed to write tarball to {path}: {source}")]
|
||||
#[diagnostic(code(pacquet_pack::write_tarball))]
|
||||
#[diagnostic(code(ERR_PNPM_PACK_WRITE_TARBALL))]
|
||||
WriteTarball {
|
||||
path: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -101,7 +101,7 @@ pub enum AddError {
|
||||
/// Fetching a brand-new dependency's `latest` tag from the registry
|
||||
/// failed while resolving the version to add.
|
||||
#[display("Failed to resolve the latest version of {name}: {error}")]
|
||||
#[diagnostic(code(pacquet_package_manager::add_resolve_latest))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_ADD_RESOLVE_LATEST))]
|
||||
ResolveLatest {
|
||||
name: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -23,11 +23,11 @@ pub enum BuildSnapshotError {
|
||||
#[display(
|
||||
"Package `{name}@{version}` was returned from the registry without an `integrity` field; cannot build a lockfile entry for it."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::build_snapshot::missing_integrity))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_BUILD_SNAPSHOT_MISSING_INTEGRITY))]
|
||||
MissingIntegrity { name: String, version: String },
|
||||
|
||||
#[display("Failed to parse package name `{name}`: {source}")]
|
||||
#[diagnostic(code(pacquet_package_manager::build_snapshot::parse_name))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_BUILD_SNAPSHOT_PARSE_NAME))]
|
||||
ParseName {
|
||||
name: String,
|
||||
#[error(source)]
|
||||
@@ -37,7 +37,7 @@ pub enum BuildSnapshotError {
|
||||
#[display(
|
||||
"Package `{name}` reported version `{version}` that cannot be parsed as a PkgVerPeer: {source}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::build_snapshot::parse_version))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_BUILD_SNAPSHOT_PARSE_VERSION))]
|
||||
ParseVersion {
|
||||
name: String,
|
||||
version: String,
|
||||
|
||||
@@ -74,7 +74,7 @@ pub struct CreateVirtualDirBySnapshot<'a> {
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum CreateVirtualDirError {
|
||||
#[display("Failed to recursively create node_modules directory at {dir:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_package_manager::create_node_modules_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_CREATE_NODE_MODULES_DIR))]
|
||||
CreateNodeModulesDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -94,7 +94,7 @@ pub enum CreateVirtualDirError {
|
||||
InvalidAlias(#[error(source)] InvalidDependencyAliasError),
|
||||
|
||||
#[display("Failed to remove obsolete child link at {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_package_manager::remove_obsolete_child))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_REMOVE_OBSOLETE_CHILD))]
|
||||
RemoveObsoleteChild {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -133,7 +133,7 @@ pub struct CreateVirtualStore<'a> {
|
||||
pub store_index_writer: &'a std::sync::Arc<StoreIndexWriter>,
|
||||
/// `allowBuilds` gate, shared with `BuildModules`. The cold-batch
|
||||
/// path threads this into the git fetcher so `preparePackage` can
|
||||
/// reject `GIT_DEP_PREPARE_NOT_ALLOWED` for packages that aren't
|
||||
/// reject `ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED` for packages that aren't
|
||||
/// allowlisted. Computed once per install in
|
||||
/// [`crate::InstallFrozenLockfile::run`].
|
||||
pub allow_build_policy: &'a crate::AllowBuildPolicy,
|
||||
@@ -192,13 +192,13 @@ pub enum CreateVirtualStoreError {
|
||||
#[display(
|
||||
"Lockfile has a snapshot entry `{snapshot_key}` with no matching metadata entry (`{metadata_key}`) in `packages:`."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::missing_package_metadata))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_MISSING_PACKAGE_METADATA))]
|
||||
MissingPackageMetadata { snapshot_key: String, metadata_key: String },
|
||||
|
||||
#[display(
|
||||
"Lockfile has a `snapshots:` section but no `packages:` section; every entry in `snapshots:` must have a matching metadata entry. The lockfile is malformed."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::missing_packages_section))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_MISSING_PACKAGES_SECTION))]
|
||||
MissingPackagesSection,
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ pub enum InstallError {
|
||||
#[display(
|
||||
"Headless installation requires a pnpm-lock.yaml file, but none was found. Run `pnpm install` without --frozen-lockfile to create one."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::no_lockfile))]
|
||||
#[diagnostic(code(ERR_PNPM_NO_LOCKFILE))]
|
||||
NoLockfile,
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
@@ -316,7 +316,7 @@ pub enum InstallError {
|
||||
/// frozen-path optimization may run. A throwing hook aborts the
|
||||
/// install.
|
||||
#[display("{_0}")]
|
||||
#[diagnostic(code(PNPMFILE_FAIL))]
|
||||
#[diagnostic(code(ERR_PNPM_PNPMFILE_FAIL))]
|
||||
CustomResolverForceResolve(#[error(not(source))] pacquet_hooks::HookError),
|
||||
|
||||
/// `--no-runtime` (or `config.skip_runtimes`) is honored only on
|
||||
@@ -328,7 +328,7 @@ pub enum InstallError {
|
||||
#[display(
|
||||
"--no-runtime / skipRuntimes is not supported without --frozen-lockfile yet. Re-run with --frozen-lockfile against an existing pnpm-lock.yaml, or drop the flag."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::unsupported_fresh_install_skip_runtimes))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_UNSUPPORTED_FRESH_INSTALL_SKIP_RUNTIMES))]
|
||||
UnsupportedFreshInstallSkipRuntimes,
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
@@ -369,7 +369,7 @@ pub enum InstallError {
|
||||
#[diagnostic(transparent)]
|
||||
SaveWantedLockfile(#[error(source)] SaveLockfileError),
|
||||
|
||||
#[diagnostic(code(pacquet_package_manager::remove_modules_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_REMOVE_MODULES_DIR))]
|
||||
#[display("Failed to remove modules directory contents: {_0}")]
|
||||
RemoveModulesDir(#[error(source)] std::io::Error),
|
||||
|
||||
@@ -388,7 +388,7 @@ pub enum InstallError {
|
||||
"Cannot install with \"frozen-lockfile\" because pnpm-lock.yaml is not up to date with package.json.\n\n Failure reason:\n {reason}"
|
||||
)]
|
||||
#[diagnostic(
|
||||
code(pacquet_package_manager::outdated_lockfile),
|
||||
code(ERR_PNPM_OUTDATED_LOCKFILE),
|
||||
help(
|
||||
"Regenerate the lockfile with `pnpm install --lockfile-only` so that pnpm-lock.yaml reflects the current package.json, then re-run `pnpm install --frozen-lockfile`."
|
||||
)
|
||||
@@ -402,14 +402,19 @@ pub enum InstallError {
|
||||
#[display(
|
||||
r#"Cannot install with "frozen-lockfile" because pnpm-lock.yaml has no `importers["{importer_id}"]` entry. Regenerate the lockfile with `pnpm install --lockfile-only`."#
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::no_importer))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_NO_IMPORTER))]
|
||||
NoImporter { importer_id: String },
|
||||
|
||||
/// The `ERR_PNPM_FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE` error.
|
||||
/// Two flags that cannot both hold: a frozen install never rewrites
|
||||
/// `pnpm-lock.yaml`, which is the only thing `--update-checksums`
|
||||
/// does. Not to be confused with pnpm's
|
||||
/// `ERR_PNPM_FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE`, which is a
|
||||
/// stale lockfile under `--frozen-lockfile` and lives in
|
||||
/// `pacquet_env_installer`.
|
||||
#[display(
|
||||
"Cannot use --frozen-lockfile together with --update-checksums: frozen installs never rewrite pnpm-lock.yaml, but --update-checksums exists to do exactly that."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::frozen_lockfile_with_outdated_lockfile))]
|
||||
#[diagnostic(code(ERR_PNPM_CONFIG_CONFLICT_FROZEN_LOCKFILE_WITH_UPDATE_CHECKSUMS))]
|
||||
FrozenLockfileWithUpdateChecksums,
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
@@ -459,7 +464,7 @@ pub enum InstallError {
|
||||
/// the package-map metadata Node consumes when the user opts into
|
||||
/// `--experimental-package-map`.
|
||||
#[display("Failed to write node_modules/.package-map.json: {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manager::write_package_map))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_WRITE_PACKAGE_MAP))]
|
||||
WritePackageMap(#[error(source)] crate::WritePackageMapError),
|
||||
|
||||
/// A value in `pnpm.overrides` couldn't be parsed — the selector
|
||||
@@ -1982,7 +1987,7 @@ pub(crate) enum FreshnessCheckError {
|
||||
#[display(
|
||||
r#"Cannot install with "frozen-lockfile" because pnpm-lock.yaml has no `importers["{importer_id}"]` entry. Regenerate the lockfile with `pnpm install --lockfile-only`."#
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::no_importer))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_NO_IMPORTER))]
|
||||
NoImporter { importer_id: String },
|
||||
|
||||
/// A value in `pnpm.overrides` couldn't be parsed.
|
||||
|
||||
@@ -189,7 +189,7 @@ pub enum InstallFrozenLockfileError {
|
||||
LockfileVerification(#[error(source)] VerifyError),
|
||||
|
||||
#[display("external lockfile verification failed: {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manager::external_lockfile_verification))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_EXTERNAL_LOCKFILE_VERIFICATION))]
|
||||
ExternalLockfileVerification(#[error(not(source))] String),
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
@@ -199,7 +199,7 @@ pub enum InstallFrozenLockfileError {
|
||||
/// A throwing pnpmfile aborts the install, matching the
|
||||
/// custom-resolver load on the fresh-lockfile path.
|
||||
#[display("{_0}")]
|
||||
#[diagnostic(code(PNPMFILE_FAIL))]
|
||||
#[diagnostic(code(ERR_PNPM_PNPMFILE_FAIL))]
|
||||
CustomFetcherHook(#[error(not(source))] pacquet_hooks::HookError),
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
@@ -283,7 +283,7 @@ pub enum InstallFrozenLockfileError {
|
||||
LinkHoistedModules(#[error(source)] LinkHoistedModulesError),
|
||||
|
||||
#[display("failed to write package map: {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manager::write_package_map))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_WRITE_PACKAGE_MAP))]
|
||||
WritePackageMap(#[error(source)] crate::WritePackageMapError),
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
@@ -1505,7 +1505,7 @@ pub(crate) enum HoistedLinkerError {
|
||||
#[diagnostic(transparent)]
|
||||
SymlinkDirectDependencies(#[error(source)] SymlinkDirectDependenciesError),
|
||||
#[display("failed to write package map: {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manager::write_package_map))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_WRITE_PACKAGE_MAP))]
|
||||
WritePackageMap(#[error(source)] crate::WritePackageMapError),
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ pub struct InstallPackageBySnapshot<'a> {
|
||||
pub metadata: &'a PackageMetadata,
|
||||
pub snapshot: &'a SnapshotEntry,
|
||||
/// `allowBuilds` gate. Routed into the git fetcher for
|
||||
/// `preparePackage`'s `GIT_DEP_PREPARE_NOT_ALLOWED` check.
|
||||
/// `preparePackage`'s `ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED` check.
|
||||
/// Computed once per install in
|
||||
/// [`crate::InstallFrozenLockfile::run`] and threaded through
|
||||
/// [`crate::CreateVirtualStore`].
|
||||
@@ -144,13 +144,13 @@ pub enum InstallPackageBySnapshotError {
|
||||
#[display(
|
||||
"Package `{package_key}` has a tarball resolution without an `integrity` field; pnpm cannot verify the download and refuses to install it."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::missing_tarball_integrity))]
|
||||
#[diagnostic(code(ERR_PNPM_MISSING_TARBALL_INTEGRITY))]
|
||||
MissingTarballIntegrity { package_key: String },
|
||||
|
||||
#[display(
|
||||
"Package `{package_key}` uses a `{resolution_kind}` resolution, which pnpm does not yet support."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::unsupported_resolution))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_UNSUPPORTED_RESOLUTION))]
|
||||
UnsupportedResolution { package_key: String, resolution_kind: &'static str },
|
||||
|
||||
/// Failure from either git fetcher: the git-CLI path for
|
||||
@@ -173,7 +173,7 @@ pub enum InstallPackageBySnapshotError {
|
||||
|
||||
/// A custom fetcher from the pnpmfile threw or returned an error.
|
||||
#[display("Custom fetcher failed: {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manager::custom_fetcher_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_CUSTOM_FETCHER_FAILED))]
|
||||
CustomFetcher(#[error(not(source))] String),
|
||||
|
||||
/// A custom-typed resolution reached the built-in dispatch — no
|
||||
@@ -183,7 +183,7 @@ pub enum InstallPackageBySnapshotError {
|
||||
#[display(
|
||||
"Cannot fetch dependency with custom resolution type \"{resolution_type}\". Custom resolutions must be handled by custom fetchers."
|
||||
)]
|
||||
#[diagnostic(code(UNSUPPORTED_RESOLUTION_TYPE))]
|
||||
#[diagnostic(code(ERR_PNPM_UNSUPPORTED_RESOLUTION_TYPE))]
|
||||
UnsupportedResolutionType { resolution_type: String },
|
||||
|
||||
/// No variant in a [`LockfileResolution::Variations`] matches the
|
||||
@@ -195,7 +195,7 @@ pub enum InstallPackageBySnapshotError {
|
||||
#[display(
|
||||
"Package `{package_key}` is a runtime dependency, but none of its declared variants matches the host triple (os = `{host_os}`, cpu = `{host_cpu}`, libc = `{host_libc:?}`). Available variants: {available_targets}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::no_matching_platform_variant))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_NO_MATCHING_PLATFORM_VARIANT))]
|
||||
NoMatchingPlatformVariant {
|
||||
package_key: String,
|
||||
host_os: &'static str,
|
||||
@@ -219,7 +219,7 @@ pub enum InstallPackageBySnapshotError {
|
||||
#[display(
|
||||
"Package `{package_key}` carries a runtime variant whose inner resolution is `{inner_kind}` rather than `binary`; pnpm only knows how to install binary-shaped variants."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::variant_has_non_binary_resolution))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_VARIANT_HAS_NON_BINARY_RESOLUTION))]
|
||||
VariantHasNonBinaryResolution { package_key: String, inner_kind: &'static str },
|
||||
|
||||
/// Serializing the synthesized runtime `package.json` failed.
|
||||
@@ -232,7 +232,7 @@ pub enum InstallPackageBySnapshotError {
|
||||
#[display(
|
||||
"Failed to serialize the synthesized package.json for runtime entry `{package_key}`: {error}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::synthesize_runtime_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_SYNTHESIZE_RUNTIME_MANIFEST))]
|
||||
SynthesizeRuntimeManifest {
|
||||
package_key: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -104,7 +104,7 @@ pub enum InstallPackageFromRegistryError {
|
||||
/// resolution carrying an integrity hash). Surfaces with a
|
||||
/// pacquet-internal code.
|
||||
#[display("Unsupported resolution shape for npm install path: {detail}")]
|
||||
#[diagnostic(code(pacquet_package_manager::unsupported_resolution))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_UNSUPPORTED_RESOLUTION))]
|
||||
UnsupportedResolution {
|
||||
#[error(not(source))]
|
||||
detail: String,
|
||||
|
||||
@@ -262,7 +262,7 @@ pub enum InstallWithFreshLockfileError {
|
||||
LinkHoistedModules(#[error(source)] crate::LinkHoistedModulesError),
|
||||
|
||||
#[display("failed to write package map: {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manager::write_package_map))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_WRITE_PACKAGE_MAP))]
|
||||
WritePackageMap(#[error(source)] crate::WritePackageMapError),
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
@@ -369,7 +369,7 @@ pub enum InstallWithFreshLockfileError {
|
||||
#[display(
|
||||
"First writer for virtual-store slot {virtual_store_name} dropped before signalling completion"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::first_writer_aborted))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_FIRST_WRITER_ABORTED))]
|
||||
FirstWriterAborted {
|
||||
#[error(not(source))]
|
||||
virtual_store_name: String,
|
||||
@@ -385,33 +385,33 @@ pub enum InstallWithFreshLockfileError {
|
||||
/// The `afterAllResolved` pnpmfile hook threw or otherwise failed.
|
||||
/// A throwing `afterAllResolved` aborts the install.
|
||||
#[display("{_0}")]
|
||||
#[diagnostic(code(PNPMFILE_FAIL))]
|
||||
#[diagnostic(code(ERR_PNPM_PNPMFILE_FAIL))]
|
||||
AfterAllResolvedHook(#[error(not(source))] pacquet_hooks::HookError),
|
||||
|
||||
/// The freshly-built lockfile could not be serialized to JSON to pass to
|
||||
/// the `afterAllResolved` pnpmfile hook.
|
||||
#[display("Failed to serialize lockfile for the afterAllResolved hook: {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manager::after_all_resolved_serialize))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_AFTER_ALL_RESOLVED_SERIALIZE))]
|
||||
AfterAllResolvedSerialize(#[error(source)] serde_json::Error),
|
||||
|
||||
/// The pnpmfile's `getCustomResolvers` hook threw while loading custom
|
||||
/// resolvers. A throwing custom-resolver hook aborts the install.
|
||||
#[display("{_0}")]
|
||||
#[diagnostic(code(PNPMFILE_FAIL))]
|
||||
#[diagnostic(code(ERR_PNPM_PNPMFILE_FAIL))]
|
||||
CustomResolverHook(#[error(not(source))] pacquet_hooks::HookError),
|
||||
|
||||
/// The pnpmfile threw while loading its custom `fetchers` export.
|
||||
/// Same fatality rule as [`Self::CustomResolverHook`] and the
|
||||
/// frozen-lockfile path's custom-fetcher load.
|
||||
#[display("{_0}")]
|
||||
#[diagnostic(code(PNPMFILE_FAIL))]
|
||||
#[diagnostic(code(ERR_PNPM_PNPMFILE_FAIL))]
|
||||
CustomFetcherHook(#[error(not(source))] pacquet_hooks::HookError),
|
||||
|
||||
/// A custom resolver's `shouldRefreshResolution` hook threw while
|
||||
/// checking whether to force re-resolution. A throwing hook aborts
|
||||
/// the install.
|
||||
#[display("{_0}")]
|
||||
#[diagnostic(code(PNPMFILE_FAIL))]
|
||||
#[diagnostic(code(ERR_PNPM_PNPMFILE_FAIL))]
|
||||
CustomResolverForceResolve(#[error(not(source))] pacquet_hooks::HookError),
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ fn read_bin_sources(
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum LinkVirtualStoreBinsError {
|
||||
#[display("Failed to read virtual store directory at {dir:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_package_manager::read_virtual_store))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_READ_VIRTUAL_STORE))]
|
||||
ReadVirtualStore {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -172,7 +172,7 @@ pub enum LinkManifestLinkDepsError {
|
||||
/// under a project dir it would place symlinks outside the
|
||||
/// intended modules directory.
|
||||
#[display("Refusing to link into invalid modules directory name {modules_dir_name:?}")]
|
||||
#[diagnostic(code(pacquet_package_manager::invalid_modules_dir_name))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_INVALID_MODULES_DIR_NAME))]
|
||||
InvalidModulesDirName {
|
||||
#[error(not(source))]
|
||||
modules_dir_name: String,
|
||||
@@ -187,7 +187,7 @@ pub enum LinkManifestLinkDepsError {
|
||||
/// Creating one `link:` dep's symlink failed (permission denied,
|
||||
/// a real directory squatting the alias path, disk full, ...).
|
||||
#[display("Failed to link manifest `link:` dependency {alias:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_package_manager::link_manifest_link_dep_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_LINK_MANIFEST_LINK_DEP_FAILED))]
|
||||
Symlink {
|
||||
alias: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -257,7 +257,7 @@ pub enum LinkRootComponentMembersError {
|
||||
/// An injected member's manifest could not be read to learn which
|
||||
/// siblings it declares.
|
||||
#[display("Failed to read manifest of root-component member {member:?} at {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_package_manager::root_component_manifest_read_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_ROOT_COMPONENT_MANIFEST_READ_FAILED))]
|
||||
ReadManifest {
|
||||
member: String,
|
||||
path: PathBuf,
|
||||
@@ -268,7 +268,7 @@ pub enum LinkRootComponentMembersError {
|
||||
/// A sibling-into-member symlink failed (e.g. permission denied,
|
||||
/// disk full, an existing non-symlink file squatting the path).
|
||||
#[display("Failed to link root-component sibling {sibling:?} into member {member:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_package_manager::root_component_symlink_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_ROOT_COMPONENT_SYMLINK_FAILED))]
|
||||
Symlink {
|
||||
member: String,
|
||||
sibling: String,
|
||||
|
||||
@@ -46,7 +46,7 @@ pub enum MinimumReleaseAgeError {
|
||||
Denied,
|
||||
|
||||
#[display("Failed to read minimumReleaseAge approval: {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manager::minimum_release_age_prompt))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_MINIMUM_RELEASE_AGE_PROMPT))]
|
||||
Prompt(#[error(source)] dialoguer::Error),
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
|
||||
@@ -41,7 +41,7 @@ use std::{collections::HashMap, sync::Arc};
|
||||
#[display(
|
||||
"Invalid version range in packageExtensions selector {selector:?}: {range:?} is not a valid semver range"
|
||||
)]
|
||||
#[diagnostic(code(INVALID_PACKAGE_EXTENSION_SELECTOR))]
|
||||
#[diagnostic(code(ERR_PNPM_INVALID_PACKAGE_EXTENSION_SELECTOR))]
|
||||
pub struct InvalidPackageExtensionSelector {
|
||||
#[error(not(source))]
|
||||
pub selector: String,
|
||||
|
||||
@@ -74,20 +74,20 @@ pub enum PatchTargetError {
|
||||
#[non_exhaustive]
|
||||
pub enum WritePackageForPatchError {
|
||||
#[display("Package `{package_key}` is missing from the current lockfile packages map.")]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_package_missing_metadata))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_PACKAGE_MISSING_METADATA))]
|
||||
MissingPackageMetadata { package_key: String },
|
||||
|
||||
#[display(
|
||||
"Package `{package}` uses a `{resolution_kind}` resolution, which `pnpm patch` does not yet support."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_unsupported_resolution))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_UNSUPPORTED_RESOLUTION))]
|
||||
UnsupportedResolution { package: String, resolution_kind: &'static str },
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
TarballResolution(#[error(source)] InstallPackageBySnapshotError),
|
||||
|
||||
#[display("Failed to inspect patch edit directory {dest:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_dest_stat))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_DEST_STAT))]
|
||||
PatchDestinationStat {
|
||||
dest: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -95,7 +95,7 @@ pub enum WritePackageForPatchError {
|
||||
},
|
||||
|
||||
#[display("Refusing to write package files to unsafe patch edit directory {dest:?}: {reason}")]
|
||||
#[diagnostic(code(pacquet_package_manager::unsafe_patch_dest))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_UNSAFE_PATCH_DEST))]
|
||||
UnsafePatchDestination { dest: PathBuf, reason: &'static str },
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
|
||||
@@ -25,7 +25,7 @@ pub enum PkgFilesForDiff {
|
||||
#[non_exhaustive]
|
||||
pub enum PatchCommitError {
|
||||
#[display("Failed to read package manifest in {}: {source}", dir.display())]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_read_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_READ_MANIFEST))]
|
||||
ReadManifest {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -33,7 +33,7 @@ pub enum PatchCommitError {
|
||||
},
|
||||
|
||||
#[display("Failed to compute package files for {}: {source}", dir.display())]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_packlist))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_PACKLIST))]
|
||||
Packlist {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -41,7 +41,7 @@ pub enum PatchCommitError {
|
||||
},
|
||||
|
||||
#[display("Failed to read directory {}: {source}", dir.display())]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_read_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_READ_DIR))]
|
||||
ReadDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -49,7 +49,7 @@ pub enum PatchCommitError {
|
||||
},
|
||||
|
||||
#[display("Failed to create temporary patch directory {}: {source}", dir.display())]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_create_temp_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_CREATE_TEMP_DIR))]
|
||||
CreateTempDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -57,7 +57,7 @@ pub enum PatchCommitError {
|
||||
},
|
||||
|
||||
#[display("Failed to remove temporary patch directory {}: {source}", dir.display())]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_remove_temp_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_REMOVE_TEMP_DIR))]
|
||||
RemoveTempDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -65,7 +65,7 @@ pub enum PatchCommitError {
|
||||
},
|
||||
|
||||
#[display("Unsafe temporary patch directory {}: {reason}", dir.display())]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_unsafe_temp_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_UNSAFE_TEMP_DIR))]
|
||||
UnsafeTempDir { dir: PathBuf, reason: &'static str },
|
||||
|
||||
#[display(
|
||||
@@ -73,7 +73,7 @@ pub enum PatchCommitError {
|
||||
source_path.display(),
|
||||
target.display()
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_link_file))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_LINK_FILE))]
|
||||
LinkFile {
|
||||
source_path: PathBuf,
|
||||
target: PathBuf,
|
||||
@@ -82,24 +82,24 @@ pub enum PatchCommitError {
|
||||
},
|
||||
|
||||
#[display("Package file path escapes package directory: {path}")]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_invalid_package_file_path))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_INVALID_PACKAGE_FILE_PATH))]
|
||||
InvalidPackageFilePath { path: String },
|
||||
|
||||
#[display(
|
||||
"Unable to diff directories. Make sure you have a recent version of 'git' available in PATH.\nThe following error was reported by 'git':\n{stderr}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_diff_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_DIFF_FAILED))]
|
||||
DiffFailed { stderr: String },
|
||||
|
||||
#[display("Failed to run git diff: {source}")]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_diff_spawn))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_DIFF_SPAWN))]
|
||||
DiffSpawn {
|
||||
#[error(source)]
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[display("git diff {stream} output exceeded {limit} bytes")]
|
||||
#[diagnostic(code(pacquet_package_manager::patch_commit_diff_output_too_large))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PATCH_COMMIT_DIFF_OUTPUT_TOO_LARGE))]
|
||||
DiffOutputTooLarge { stream: &'static str, limit: u64 },
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ pub enum PruneDirectDepsError {
|
||||
#[display(
|
||||
"Failed to read {path:?} while removing the bins of an excluded direct dependency: {error}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::prune_direct_deps_read_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PRUNE_DIRECT_DEPS_READ_MANIFEST))]
|
||||
ReadManifest {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -50,7 +50,7 @@ pub enum PruneDirectDepsError {
|
||||
#[display(
|
||||
"Failed to remove the bin shim at {path:?} of an excluded direct dependency: {error}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_package_manager::prune_direct_deps_remove_bin))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PRUNE_DIRECT_DEPS_REMOVE_BIN))]
|
||||
RemoveBin {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -58,7 +58,7 @@ pub enum PruneDirectDepsError {
|
||||
},
|
||||
|
||||
#[display("Failed to remove the excluded direct dependency at {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_package_manager::prune_direct_deps_remove_link))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_PRUNE_DIRECT_DEPS_REMOVE_LINK))]
|
||||
RemoveLink {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -123,7 +123,7 @@ pub enum SymlinkDirectDependenciesError {
|
||||
/// input.
|
||||
#[display("Refusing to install importer with unsafe path key {importer_id:?}")]
|
||||
#[diagnostic(
|
||||
code(pacquet_package_manager::unsafe_importer_path),
|
||||
code(ERR_PNPM_PACKAGE_MANAGER_UNSAFE_IMPORTER_PATH),
|
||||
help(
|
||||
"Importer keys in pnpm-lock.yaml must be POSIX paths relative to the workspace root (e.g. `packages/web`). Absolute paths, drive prefixes, and `..` components are rejected."
|
||||
)
|
||||
@@ -136,7 +136,7 @@ pub enum SymlinkDirectDependenciesError {
|
||||
/// Surfaces a per-package symlink failure (e.g. permission denied,
|
||||
/// disk full, an existing non-symlink file).
|
||||
#[display("Failed to symlink {name:?} for importer {importer_id:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_package_manager::symlink_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_SYMLINK_FAILED))]
|
||||
SymlinkPackage {
|
||||
importer_id: String,
|
||||
name: String,
|
||||
|
||||
@@ -120,7 +120,7 @@ pub enum UpdateError {
|
||||
/// Fetching a package's `latest` tag from the registry failed while
|
||||
/// computing the new manifest range for `--latest`.
|
||||
#[display("Failed to resolve the latest version of {name}: {error}")]
|
||||
#[diagnostic(code(pacquet_package_manager::update_resolve_latest))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANAGER_UPDATE_RESOLVE_LATEST))]
|
||||
ResolveLatest {
|
||||
name: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -14,32 +14,32 @@ use tempfile::NamedTempFile;
|
||||
#[derive(Debug, Display, Error, Diagnostic, From)]
|
||||
#[non_exhaustive]
|
||||
pub enum PackageManifestError {
|
||||
#[diagnostic(code(pacquet_package_manifest::serialization_error))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANIFEST_SERIALIZATION_ERROR))]
|
||||
Serialization(serde_json::Error), // TODO: remove derive(From), split this variant
|
||||
|
||||
#[diagnostic(code(pacquet_package_manifest::io_error))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANIFEST_IO_ERROR))]
|
||||
Io(std::io::Error), // TODO: remove derive(From), split this variant
|
||||
|
||||
#[display("package.json file already exists")]
|
||||
#[diagnostic(
|
||||
code(pacquet_package_manifest::already_exist_error),
|
||||
code(ERR_PNPM_PACKAGE_JSON_EXISTS),
|
||||
help("Your current working directory already has a package.json file.")
|
||||
)]
|
||||
AlreadyExist,
|
||||
|
||||
#[from(ignore)] // TODO: remove this after derive(From) has been removed
|
||||
#[display("invalid attribute: {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manifest::invalid_attribute))]
|
||||
#[diagnostic(code(ERR_PNPM_PACKAGE_MANIFEST_INVALID_ATTRIBUTE))]
|
||||
InvalidAttribute(#[error(not(source))] String),
|
||||
|
||||
#[from(ignore)] // TODO: remove this after derive(From) has been removed
|
||||
#[display("No package.json was found in {_0}")]
|
||||
#[diagnostic(code(pacquet_package_manifest::no_import_manifest_found))]
|
||||
#[diagnostic(code(ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND))]
|
||||
NoImporterManifestFound(#[error(not(source))] String),
|
||||
|
||||
#[from(ignore)] // TODO: remove this after derive(From) has been removed
|
||||
#[display("Missing script: {_0:?}")]
|
||||
#[diagnostic(code(pacquet_package_manifest::no_script_error))]
|
||||
#[diagnostic(code(ERR_PNPM_NO_SCRIPT))]
|
||||
NoScript(#[error(not(source))] String),
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ fn normalize_entry_path(path: &Path) -> String {
|
||||
#[derive(Debug, derive_more::Display, derive_more::Error, Diagnostic)]
|
||||
pub enum ExtractManifestError {
|
||||
#[display("Failed to read the archive {tarball_path}: {source}")]
|
||||
#[diagnostic(code(pacquet_publish::extract_manifest::read))]
|
||||
#[diagnostic(code(ERR_PNPM_PUBLISH_EXTRACT_MANIFEST_READ))]
|
||||
Read {
|
||||
tarball_path: String,
|
||||
#[error(source)]
|
||||
@@ -153,7 +153,7 @@ pub enum ExtractManifestError {
|
||||
},
|
||||
|
||||
#[display("Failed to parse package.json in {tarball_path}: {source}")]
|
||||
#[diagnostic(code(pacquet_publish::extract_manifest::parse))]
|
||||
#[diagnostic(code(ERR_PNPM_PUBLISH_EXTRACT_MANIFEST_PARSE))]
|
||||
Parse {
|
||||
tarball_path: String,
|
||||
#[error(source)]
|
||||
|
||||
@@ -28,22 +28,22 @@ pub struct NetworkError {
|
||||
pub enum RegistryError {
|
||||
#[from(ignore)] // TODO: remove this after derive(From) has been removed
|
||||
#[display("Missing latest tag on {_0}")]
|
||||
#[diagnostic(code(pacquet_registry::missing_latest_tag))]
|
||||
#[diagnostic(code(ERR_PNPM_REGISTRY_MISSING_LATEST_TAG))]
|
||||
MissingLatestTag(#[error(not(source))] String),
|
||||
|
||||
#[from(ignore)] // TODO: remove this after derive(From) has been removed
|
||||
#[display("Missing version {_0} on package {_1}")]
|
||||
#[diagnostic(code(pacquet_registry::missing_version_release))]
|
||||
#[diagnostic(code(ERR_PNPM_REGISTRY_MISSING_VERSION_RELEASE))]
|
||||
MissingVersionRelease(String, String),
|
||||
|
||||
#[diagnostic(code(pacquet_registry::network_error))]
|
||||
#[diagnostic(code(ERR_PNPM_REGISTRY_NETWORK_ERROR))]
|
||||
Network(NetworkError), // TODO: remove derive(Error), split this variant
|
||||
|
||||
#[diagnostic(code(pacquet_registry::io_error))]
|
||||
#[diagnostic(code(ERR_PNPM_REGISTRY_IO_ERROR))]
|
||||
Io(std::io::Error), // TODO: remove derive(Error), split this variant
|
||||
|
||||
#[from(ignore)] // TODO: remove this after derive(From) has been removed
|
||||
#[display("Serialization failed: {_0}")]
|
||||
#[diagnostic(code(pacquet_registry::serialization_error))]
|
||||
#[diagnostic(code(ERR_PNPM_REGISTRY_SERIALIZATION_ERROR))]
|
||||
Serialization(#[error(not(source))] String),
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ impl DefaultResolver {
|
||||
|
||||
/// Walk the chain and return the first resolver's claim. Returns
|
||||
/// [`SpecNotSupportedByAnyResolverError`]
|
||||
/// (`SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`) when no resolver claims
|
||||
/// (`ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`) when no resolver claims
|
||||
/// the wanted dependency.
|
||||
pub async fn resolve(
|
||||
&self,
|
||||
@@ -101,7 +101,7 @@ impl Resolver for DefaultResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/// The `SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER` error code raised when
|
||||
/// The `ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER` error code raised when
|
||||
/// every resolver in the chain returned `Ok(None)` for a wanted
|
||||
/// dependency.
|
||||
///
|
||||
@@ -109,7 +109,7 @@ impl Resolver for DefaultResolver {
|
||||
/// (either half omitted when absent) and quoted when non-empty.
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
#[display("{quoted} isn't supported by any available resolver.")]
|
||||
#[diagnostic(code(SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER))]
|
||||
#[diagnostic(code(ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER))]
|
||||
pub struct SpecNotSupportedByAnyResolverError {
|
||||
/// Quoted offending specifier, formatted at construction so the
|
||||
/// `Display` impl stays allocation-free. Empty string when both
|
||||
|
||||
@@ -226,9 +226,9 @@ pub enum ResolveDependencyTreeError {
|
||||
LockedOptionalResolutionFailure(#[error(not(source))] Box<ResolveDependencyTreeError>),
|
||||
|
||||
/// No resolver in the chain claimed the spec, raised with the
|
||||
/// `SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER` code.
|
||||
/// `ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER` code.
|
||||
#[display("\"{specifier}\" isn't supported by any available resolver.")]
|
||||
#[diagnostic(code(SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER))]
|
||||
#[diagnostic(code(ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER))]
|
||||
SpecNotSupported {
|
||||
#[error(not(source))]
|
||||
specifier: String,
|
||||
@@ -251,11 +251,11 @@ pub enum ResolveDependencyTreeError {
|
||||
|
||||
/// A transitive dependency was resolved through an exotic
|
||||
/// protocol (git, tarball, file, ...) while `block_exotic_subdeps`
|
||||
/// is on, raised with the `EXOTIC_SUBDEP` code.
|
||||
/// is on, raised with the `ERR_PNPM_EXOTIC_SUBDEP` code.
|
||||
#[display(
|
||||
"Exotic dependency \"{specifier}\" (resolved via {resolved_via}) is not allowed in subdependencies when blockExoticSubdeps is enabled"
|
||||
)]
|
||||
#[diagnostic(code(EXOTIC_SUBDEP))]
|
||||
#[diagnostic(code(ERR_PNPM_EXOTIC_SUBDEP))]
|
||||
ExoticSubdep {
|
||||
#[error(not(source))]
|
||||
specifier: String,
|
||||
@@ -276,10 +276,13 @@ pub enum ResolveDependencyTreeError {
|
||||
},
|
||||
|
||||
/// A pnpmfile hook (`readPackage`) threw, timed out, or returned an
|
||||
/// invalid package manifest. Carries the `PNPMFILE_FAIL` /
|
||||
/// `BAD_READ_PACKAGE_HOOK_RESULT` code: a bad hook aborts the install.
|
||||
/// invalid package manifest; a bad hook aborts the install. Carries
|
||||
/// `ERR_PNPM_PNPMFILE_FAIL` for all of those. pnpm splits them across
|
||||
/// two codes, reserving `ERR_PNPM_BAD_READ_PACKAGE_HOOK_RESULT` for a
|
||||
/// hook that returns a non-manifest; pacquet does not distinguish the
|
||||
/// two yet.
|
||||
#[display("{_0}")]
|
||||
#[diagnostic(code(PNPMFILE_FAIL))]
|
||||
#[diagnostic(code(ERR_PNPM_PNPMFILE_FAIL))]
|
||||
PnpmfileHook(#[error(not(source))] pacquet_hooks::HookError),
|
||||
}
|
||||
|
||||
@@ -2723,7 +2726,7 @@ fn is_optional_child(snapshot: Option<&SnapshotEntry>, alias: &str) -> bool {
|
||||
///
|
||||
/// Catalog resolution runs only on importer-level deps. A misconfigured
|
||||
/// entry surfaces immediately rather than masquerading as a
|
||||
/// `SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`.
|
||||
/// `ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER`.
|
||||
pub(crate) fn resolve_catalog_specifiers(
|
||||
specs: Vec<WantedSpec>,
|
||||
catalogs: &Catalogs,
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
//! - [`resolve_from_local_scheme`] — claims a wanted dep iff its bare
|
||||
//! specifier starts with `link:`, `workspace:`, or `file:`. The
|
||||
//! `path:` prefix is rejected with [`PathProtocolNotSupportedError`]
|
||||
//! (the `PATH_IS_UNSUPPORTED_PROTOCOL` error).
|
||||
//! (the `ERR_PNPM_PATH_IS_UNSUPPORTED_PROTOCOL` error).
|
||||
//! - [`resolve_from_local_path`] — claims a wanted dep purely by path
|
||||
//! shape (relative path, absolute path, drive letter, tarball
|
||||
//! filename). Bare-specifier dispatchers run this *after*
|
||||
|
||||
@@ -112,18 +112,18 @@ pub enum ResolveLocalError {
|
||||
Spec(#[error(source)] LocalSpecError),
|
||||
|
||||
/// `file:` directory or tarball points at a path that doesn't
|
||||
/// exist. Carries the `LINKED_PKG_DIR_NOT_FOUND` code.
|
||||
/// exist. Carries the `ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND` code.
|
||||
#[display("Could not install from \"{path}\" as it does not exist.")]
|
||||
#[diagnostic(code(LINKED_PKG_DIR_NOT_FOUND))]
|
||||
#[diagnostic(code(ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND))]
|
||||
LinkedPkgDirNotFound {
|
||||
#[error(not(source))]
|
||||
path: String,
|
||||
},
|
||||
|
||||
/// `<spec.fetchSpec>` exists but isn't a directory (ENOTDIR).
|
||||
/// Carries the `NOT_PACKAGE_DIRECTORY` code.
|
||||
/// Carries the `ERR_PNPM_NOT_PACKAGE_DIRECTORY` code.
|
||||
#[display("Could not install from \"{path}\" as it is not a directory.")]
|
||||
#[diagnostic(code(NOT_PACKAGE_DIRECTORY))]
|
||||
#[diagnostic(code(ERR_PNPM_NOT_PACKAGE_DIRECTORY))]
|
||||
NotPackageDirectory {
|
||||
#[error(not(source))]
|
||||
path: String,
|
||||
@@ -191,7 +191,7 @@ async fn resolve_spec(
|
||||
};
|
||||
|
||||
if matches!(spec.kind, LocalSpecKind::File) {
|
||||
// A missing tarball file raises the same `LINKED_PKG_DIR_NOT_FOUND`
|
||||
// A missing tarball file raises the same `ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND`
|
||||
// code the directory branch uses for a missing `file:` target,
|
||||
// so both kinds of missing `file:` target share one error code.
|
||||
let integrity = match compute_tarball_integrity(&spec.fetch_spec).await {
|
||||
@@ -249,7 +249,7 @@ async fn resolve_spec(
|
||||
}
|
||||
|
||||
/// Decide the fall-back when `package.json` is missing. For `file:`
|
||||
/// specs (copy-shaped) this throws `LINKED_PKG_DIR_NOT_FOUND` when the
|
||||
/// specs (copy-shaped) this throws `ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND` when the
|
||||
/// directory itself doesn't exist; for `link:` with a missing
|
||||
/// `package.json` it warns and substitutes a manifest with the
|
||||
/// directory basename and `version: '0.0.0'`.
|
||||
@@ -280,7 +280,7 @@ fn synthesize_fallback_manifest(
|
||||
// slipped past tarball-shape detection because the spec used
|
||||
// the `link:` scheme). On Windows `read(<file>/package.json)`
|
||||
// returns `NotFound` rather than `NotADirectory`, so this
|
||||
// explicit check surfaces `NOT_PACKAGE_DIRECTORY` on every
|
||||
// explicit check surfaces `ERR_PNPM_NOT_PACKAGE_DIRECTORY` on every
|
||||
// platform.
|
||||
return Err(ResolveLocalError::NotPackageDirectory {
|
||||
path: spec.fetch_spec.display().to_string(),
|
||||
@@ -297,7 +297,7 @@ fn synthesize_fallback_manifest(
|
||||
/// Map a [`PackageManifestError`] from
|
||||
/// [`safe_read_package_json_from_dir`] into the resolver's error
|
||||
/// surface, dispatching on the inner code: `ENOTDIR` →
|
||||
/// `NOT_PACKAGE_DIRECTORY`, `ENOENT` → fall-back manifest, anything
|
||||
/// `ERR_PNPM_NOT_PACKAGE_DIRECTORY`, `ENOENT` → fall-back manifest, anything
|
||||
/// else → re-throw.
|
||||
fn handle_manifest_read_failure(
|
||||
err: PackageManifestError,
|
||||
|
||||
@@ -58,7 +58,7 @@ pub(crate) struct ParseOptions {
|
||||
"Local dependencies via `path:` protocol are not supported. \
|
||||
Use the `link:` protocol for folder dependencies and `file:` for local tarballs"
|
||||
)]
|
||||
#[diagnostic(code(PATH_IS_UNSUPPORTED_PROTOCOL))]
|
||||
#[diagnostic(code(ERR_PNPM_PATH_IS_UNSUPPORTED_PROTOCOL))]
|
||||
pub struct PathProtocolNotSupportedError {
|
||||
pub bare_specifier: String,
|
||||
pub protocol: String,
|
||||
|
||||
@@ -380,7 +380,7 @@ async fn fail_when_resolving_from_not_existing_directory_an_injected_dependency(
|
||||
|
||||
/// A `file:./missing.tgz` spec funnels through the tarball branch
|
||||
/// where `compute_tarball_integrity` raises ENOENT. The resolver must
|
||||
/// surface the same `LINKED_PKG_DIR_NOT_FOUND` code the directory
|
||||
/// surface the same `ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND` code the directory
|
||||
/// branch raises for a missing `file:` target — both kinds of
|
||||
/// missing `file:` target share one error path.
|
||||
#[tokio::test]
|
||||
@@ -394,6 +394,14 @@ async fn fail_when_resolving_missing_tarball_with_file_protocol() {
|
||||
.await
|
||||
.expect_err("expected LINKED_PKG_DIR_NOT_FOUND");
|
||||
let expected = project_dir.join("missing.tgz").display().to_string();
|
||||
{
|
||||
use miette::Diagnostic;
|
||||
let code = err.code().map(|c| c.to_string()).unwrap_or_default();
|
||||
assert_eq!(
|
||||
code, "ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND",
|
||||
"diagnostic code must match the upstream error contract",
|
||||
);
|
||||
}
|
||||
match err {
|
||||
ResolveLocalError::LinkedPkgDirNotFound { path } => assert_eq!(path, expected),
|
||||
other => panic!("unexpected error: {other:?}"),
|
||||
|
||||
@@ -21,7 +21,7 @@ use miette::Diagnostic;
|
||||
#[non_exhaustive]
|
||||
pub enum FetchMetadataError {
|
||||
#[display("Failed to fetch metadata from {url}: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::network_error))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_NETWORK_ERROR))]
|
||||
Network {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -37,7 +37,7 @@ pub enum FetchMetadataError {
|
||||
/// [`FetchMetadataError::Decode`] — see
|
||||
/// [`FetchMetadataError::is_body_retryable`].
|
||||
#[display("Failed to read metadata response body from {url}: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::body_read_error))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_BODY_READ_ERROR))]
|
||||
BodyRead {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -45,7 +45,7 @@ pub enum FetchMetadataError {
|
||||
},
|
||||
|
||||
#[display("Failed to decode metadata from {url}: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::decode_error))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_DECODE_ERROR))]
|
||||
Decode {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -60,7 +60,7 @@ pub enum FetchMetadataError {
|
||||
/// Kept out of [`FetchMetadataError::is_body_retryable`] for that
|
||||
/// reason.
|
||||
#[display("Failed to filter metadata from {url}: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::filter_metadata_error))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_FILTER_METADATA_ERROR))]
|
||||
FilterMetadata {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -81,7 +81,7 @@ pub enum FetchMetadataError {
|
||||
/// its headers but vanished before the full read on a 304 response
|
||||
/// — concurrent cache cleanup, antivirus, etc.
|
||||
#[display("Metadata cache for {pkg_name} disappeared between headers read and full read.")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::cache_missing_after_304))]
|
||||
#[diagnostic(code(ERR_PNPM_CACHE_MISSING_AFTER_304))]
|
||||
CacheMissingAfter304 {
|
||||
#[error(not(source))]
|
||||
pkg_name: String,
|
||||
@@ -90,7 +90,7 @@ pub enum FetchMetadataError {
|
||||
/// The blocking task that deserializes a packument body panicked
|
||||
/// or was cancelled by runtime shutdown.
|
||||
#[display("Failed to parse metadata from {url}: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::parse_task))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_PARSE_TASK))]
|
||||
ParseTask {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -154,7 +154,7 @@ impl FetchMetadataError {
|
||||
#[display(
|
||||
"Every version of {name} matching the request was rejected by the resolver guard ({reason})."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::all_versions_blocked))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_ALL_VERSIONS_BLOCKED))]
|
||||
pub struct AllVersionsBlockedError {
|
||||
#[error(not(source))]
|
||||
pub name: String,
|
||||
@@ -169,7 +169,7 @@ pub struct AllVersionsBlockedError {
|
||||
#[display(
|
||||
"Resolving {name} hit the resolver guard's {limit}-version re-pick limit; too many candidates were rejected ({reason})."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::guard_repick_limit))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_GUARD_REPICK_LIMIT))]
|
||||
pub struct GuardRepickLimitError {
|
||||
#[error(not(source))]
|
||||
pub name: String,
|
||||
|
||||
@@ -93,14 +93,14 @@ pub struct MetaHeaders {
|
||||
#[non_exhaustive]
|
||||
pub enum SaveMetaError {
|
||||
#[display("Failed to create mirror directory {dir:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::mirror::create_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_MIRROR_CREATE_DIR))]
|
||||
CreateDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
error: io::Error,
|
||||
},
|
||||
#[display("Failed to write mirror temp file {temp:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::mirror::write_temp))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_MIRROR_WRITE_TEMP))]
|
||||
WriteTemp {
|
||||
temp: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -110,7 +110,7 @@ pub enum SaveMetaError {
|
||||
#[diagnostic(transparent)]
|
||||
Encode(#[error(source)] EncodeMetaError),
|
||||
#[display("Failed to rename mirror temp {temp:?} → {target:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::mirror::rename))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_MIRROR_RENAME))]
|
||||
Rename {
|
||||
temp: PathBuf,
|
||||
target: PathBuf,
|
||||
@@ -165,14 +165,14 @@ pub fn get_pkg_mirror_path(
|
||||
#[non_exhaustive]
|
||||
pub enum EncodeRegistryError {
|
||||
#[display("Failed to parse registry URL {url:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::mirror::parse_registry))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_MIRROR_PARSE_REGISTRY))]
|
||||
ParseUrl {
|
||||
#[error(not(source))]
|
||||
url: String,
|
||||
error: String,
|
||||
},
|
||||
#[display("Registry URL {url:?} has no host")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::mirror::missing_host))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_MIRROR_MISSING_HOST))]
|
||||
MissingHost {
|
||||
#[error(not(source))]
|
||||
url: String,
|
||||
@@ -235,7 +235,7 @@ struct MirrorIndex {
|
||||
/// Error from [`save_meta_indexed`]'s record-encoding step.
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
#[display("Failed to encode mirror records: {_0}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::mirror::encode))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_MIRROR_ENCODE))]
|
||||
pub struct EncodeMetaError(#[error(source)] serde_json::Error);
|
||||
|
||||
impl EncodeMetaError {
|
||||
|
||||
@@ -1100,19 +1100,19 @@ pub fn persist_meta_to_mirror(
|
||||
#[non_exhaustive]
|
||||
pub enum MirrorPersistError {
|
||||
#[display("Failed to encode mirror path: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::pick_package::encode_path))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_PICK_PACKAGE_ENCODE_PATH))]
|
||||
EncodePath {
|
||||
#[error(not(source))]
|
||||
error: String,
|
||||
},
|
||||
#[display("Failed to serialize mirror entry: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::pick_package::serialize))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_PICK_PACKAGE_SERIALIZE))]
|
||||
Serialize {
|
||||
#[error(not(source))]
|
||||
error: String,
|
||||
},
|
||||
#[display("Failed to write mirror entry: {error}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::pick_package::write))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_PICK_PACKAGE_WRITE))]
|
||||
Write {
|
||||
#[error(not(source))]
|
||||
error: String,
|
||||
|
||||
@@ -68,12 +68,12 @@ pub enum ResolveFromWorkspaceError {
|
||||
#[display(
|
||||
"Cannot resolve package from workspace because workspace packages were not loaded into the resolver"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::workspace_packages_not_loaded))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_WORKSPACE_PACKAGES_NOT_LOADED))]
|
||||
WorkspacePackagesNotLoaded,
|
||||
|
||||
/// The npm parser refused the translated bare specifier.
|
||||
#[display("Invalid workspace: spec ({bare_specifier})")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::invalid_workspace_translated_spec))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_INVALID_WORKSPACE_TRANSLATED_SPEC))]
|
||||
UnparsableSpec {
|
||||
#[error(not(source))]
|
||||
bare_specifier: String,
|
||||
|
||||
@@ -47,7 +47,7 @@ pub enum TrustViolation {
|
||||
/// a "could not be checked" violation reason at the verifier
|
||||
/// boundary.
|
||||
#[display("trust check failed: {reason}")]
|
||||
#[diagnostic(code(pacquet_resolving_npm_resolver::trust_check_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_RESOLVING_NPM_RESOLVER_TRUST_CHECK_FAILED))]
|
||||
TrustCheckFailed {
|
||||
#[error(not(source))]
|
||||
reason: String,
|
||||
@@ -58,7 +58,7 @@ pub enum TrustViolation {
|
||||
/// the `TRUST_DOWNGRADE` code.
|
||||
#[display("High-risk trust downgrade for \"{name}@{version}\" (possible package takeover)")]
|
||||
#[diagnostic(
|
||||
code(pacquet_resolving_npm_resolver::trust_downgrade),
|
||||
code(ERR_PNPM_TRUST_DOWNGRADE),
|
||||
help(
|
||||
"Trust checks are based solely on publish date, not semver. A package cannot be installed if any earlier-published version had stronger trust evidence. Earlier versions had {past_pretty}, but this version has {current_pretty}. A trust downgrade may indicate a supply chain incident."
|
||||
)
|
||||
|
||||
@@ -98,14 +98,14 @@ const SLOT_HI: u8 = 0x7f;
|
||||
#[non_exhaustive]
|
||||
pub enum DecodeError {
|
||||
#[display("Unexpected end of MessagePack buffer at offset {offset}")]
|
||||
#[diagnostic(code(pacquet_store_dir::msgpackr_records::unexpected_eof))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_MSGPACKR_RECORDS_UNEXPECTED_EOF))]
|
||||
UnexpectedEof { offset: usize },
|
||||
|
||||
#[display(
|
||||
"Reference to unknown record slot 0x{slot:02x} at offset {offset} — \
|
||||
the definition was missing or appeared later than its use"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_store_dir::msgpackr_records::unknown_slot))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_MSGPACKR_RECORDS_UNKNOWN_SLOT))]
|
||||
UnknownSlot { slot: u8, offset: usize },
|
||||
|
||||
#[display(
|
||||
@@ -113,7 +113,7 @@ pub enum DecodeError {
|
||||
is outside the valid reference range 0x40..=0x7f — any reference \
|
||||
written for this slot would be unreachable"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_store_dir::msgpackr_records::slot_out_of_range))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_MSGPACKR_RECORDS_SLOT_OUT_OF_RANGE))]
|
||||
SlotOutOfRange { slot: u8, offset: usize },
|
||||
|
||||
#[display(
|
||||
@@ -121,7 +121,7 @@ pub enum DecodeError {
|
||||
for a record-definition field-name list at offset {offset}, got \
|
||||
byte 0x{byte:02x}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_store_dir::msgpackr_records::expected_array_header))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_MSGPACKR_RECORDS_EXPECTED_ARRAY_HEADER))]
|
||||
ExpectedArrayHeader { byte: u8, offset: usize },
|
||||
|
||||
#[display(
|
||||
@@ -129,22 +129,22 @@ pub enum DecodeError {
|
||||
for a record-definition field name at offset {offset}, got byte \
|
||||
0x{byte:02x}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_store_dir::msgpackr_records::expected_string_header))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_MSGPACKR_RECORDS_EXPECTED_STRING_HEADER))]
|
||||
ExpectedStringHeader { byte: u8, offset: usize },
|
||||
|
||||
#[display(
|
||||
"Field name in a record definition at offset {offset} contains \
|
||||
invalid UTF-8"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_store_dir::msgpackr_records::invalid_field_name_utf8))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_MSGPACKR_RECORDS_INVALID_FIELD_NAME_UTF8))]
|
||||
InvalidFieldNameUtf8 { offset: usize },
|
||||
|
||||
#[display("Unsupported msgpack header byte 0x{byte:02x} at offset {offset}")]
|
||||
#[diagnostic(code(pacquet_store_dir::msgpackr_records::unsupported))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_MSGPACKR_RECORDS_UNSUPPORTED))]
|
||||
Unsupported { byte: u8, offset: usize },
|
||||
|
||||
#[display("{count} bytes left over after decoding the top-level value")]
|
||||
#[diagnostic(code(pacquet_store_dir::msgpackr_records::trailing_bytes))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_MSGPACKR_RECORDS_TRAILING_BYTES))]
|
||||
TrailingBytes { count: usize },
|
||||
}
|
||||
|
||||
@@ -655,7 +655,7 @@ pub enum EncodeError {
|
||||
likely means the encoder is being reused for a payload it \
|
||||
wasn't designed for."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_store_dir::msgpackr_records::out_of_record_slots))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_MSGPACKR_RECORDS_OUT_OF_RECORD_SLOTS))]
|
||||
OutOfRecordSlots { max: usize },
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ use std::{
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum RegisterProjectError {
|
||||
#[display("Failed to create the projects registry directory at {dir:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_store_dir::register_project::create_registry_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_REGISTER_PROJECT_CREATE_REGISTRY_DIR))]
|
||||
CreateRegistryDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -33,7 +33,7 @@ pub enum RegisterProjectError {
|
||||
#[display(
|
||||
"Failed to inspect the existing entry at {link_path:?} while registering project {project_dir:?}: {error}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_store_dir::register_project::inspect_existing))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_REGISTER_PROJECT_INSPECT_EXISTING))]
|
||||
InspectExisting {
|
||||
project_dir: PathBuf,
|
||||
link_path: PathBuf,
|
||||
@@ -44,7 +44,7 @@ pub enum RegisterProjectError {
|
||||
#[display(
|
||||
"Failed to remove stale entry at {link_path:?} (pointed at {old_target:?}, expected {project_dir:?}): {error}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_store_dir::register_project::remove_stale))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_REGISTER_PROJECT_REMOVE_STALE))]
|
||||
RemoveStale {
|
||||
project_dir: PathBuf,
|
||||
link_path: PathBuf,
|
||||
@@ -56,7 +56,7 @@ pub enum RegisterProjectError {
|
||||
#[display(
|
||||
"Failed to create the project registry symlink at {link_path:?} pointing to {project_dir:?}: {error}"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_store_dir::register_project::create_symlink))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_REGISTER_PROJECT_CREATE_SYMLINK))]
|
||||
CreateSymlink {
|
||||
project_dir: PathBuf,
|
||||
link_path: PathBuf,
|
||||
@@ -153,7 +153,7 @@ pub fn register_project(
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
pub enum GetRegisteredProjectsError {
|
||||
#[display("Failed to read the projects registry directory at {dir:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_store_dir::get_registered_projects::read_registry_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_GET_REGISTERED_PROJECTS_READ_REGISTRY_DIR))]
|
||||
ReadRegistryDir {
|
||||
dir: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -165,7 +165,7 @@ pub enum GetRegisteredProjectsError {
|
||||
/// `ENOENT` / `EINVAL` (those two are silently skipped).
|
||||
#[display("Cannot read project registry entry {link_path:?}: {error}")]
|
||||
#[diagnostic(
|
||||
code(pacquet_store_dir::get_registered_projects::entry_inaccessible),
|
||||
code(ERR_PNPM_STORE_DIR_GET_REGISTERED_PROJECTS_ENTRY_INACCESSIBLE),
|
||||
help("To remove this project from the registry, delete the entry at: {link_path:?}")
|
||||
)]
|
||||
EntryInaccessible {
|
||||
@@ -182,7 +182,7 @@ pub enum GetRegisteredProjectsError {
|
||||
/// references.
|
||||
#[display("Cannot access registered project {project_dir:?} (via {link_path:?}): {error}")]
|
||||
#[diagnostic(
|
||||
code(pacquet_store_dir::get_registered_projects::project_inaccessible),
|
||||
code(ERR_PNPM_PROJECT_INACCESSIBLE),
|
||||
help("To remove this project from the registry, delete the entry at: {link_path:?}")
|
||||
)]
|
||||
ProjectInaccessible {
|
||||
@@ -193,7 +193,7 @@ pub enum GetRegisteredProjectsError {
|
||||
},
|
||||
|
||||
#[display("Failed to remove stale project registry entry at {link_path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_store_dir::get_registered_projects::unlink_stale))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_GET_REGISTERED_PROJECTS_UNLINK_STALE))]
|
||||
UnlinkStale {
|
||||
link_path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -40,7 +40,7 @@ pub enum PruneError {
|
||||
ListProjects(#[error(source)] GetRegisteredProjectsError),
|
||||
|
||||
#[display("Failed to remove unreferenced slot at {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_store_dir::prune::remove_slot))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_PRUNE_REMOVE_SLOT))]
|
||||
RemoveSlot {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -53,7 +53,7 @@ pub enum PruneError {
|
||||
/// "empty" would leave unreachable slot directories in place
|
||||
/// the next time the prune walker can't see them either.
|
||||
#[display("Failed to read sweep directory {path:?}: {error}")]
|
||||
#[diagnostic(code(pacquet_store_dir::prune::read_sweep_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_PRUNE_READ_SWEEP_DIR))]
|
||||
ReadSweepDir {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -325,7 +325,7 @@ impl StoreIndexWriter {
|
||||
#[non_exhaustive]
|
||||
pub enum StoreIndexError {
|
||||
#[display("Failed to create directory for index.db at {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_store_dir::store_index::create_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_STORE_INDEX_CREATE_DIR))]
|
||||
CreateDir {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -333,7 +333,7 @@ pub enum StoreIndexError {
|
||||
},
|
||||
|
||||
#[display("Failed to open index.db at {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_store_dir::store_index::open))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_STORE_INDEX_OPEN))]
|
||||
Open {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -343,7 +343,7 @@ pub enum StoreIndexError {
|
||||
/// The store path could not be turned into the `file:` URI that the
|
||||
/// immutable open requires (see [`StoreIndex::open_immutable`]).
|
||||
#[display("Failed to build a file: URI for index.db at {path:?}")]
|
||||
#[diagnostic(code(pacquet_store_dir::store_index::file_uri))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_STORE_INDEX_FILE_URI))]
|
||||
FileUri {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -351,21 +351,21 @@ pub enum StoreIndexError {
|
||||
},
|
||||
|
||||
#[display("Failed to initialize index.db schema: {source}")]
|
||||
#[diagnostic(code(pacquet_store_dir::store_index::init_schema))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_STORE_INDEX_INIT_SCHEMA))]
|
||||
InitSchema {
|
||||
#[error(source)]
|
||||
source: rusqlite::Error,
|
||||
},
|
||||
|
||||
#[display("Failed to read from index.db: {source}")]
|
||||
#[diagnostic(code(pacquet_store_dir::store_index::read))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_STORE_INDEX_READ))]
|
||||
Read {
|
||||
#[error(source)]
|
||||
source: rusqlite::Error,
|
||||
},
|
||||
|
||||
#[display("Failed to write to index.db: {source}")]
|
||||
#[diagnostic(code(pacquet_store_dir::store_index::write))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_STORE_INDEX_WRITE))]
|
||||
Write {
|
||||
#[error(source)]
|
||||
source: rusqlite::Error,
|
||||
@@ -379,7 +379,7 @@ pub enum StoreIndexError {
|
||||
},
|
||||
|
||||
#[display("Failed to decode PackageFilesIndex from msgpack: {source}")]
|
||||
#[diagnostic(code(pacquet_store_dir::store_index::decode))]
|
||||
#[diagnostic(code(ERR_PNPM_STORE_DIR_STORE_INDEX_DECODE))]
|
||||
Decode {
|
||||
#[error(source)]
|
||||
source: rmp_serde::decode::Error,
|
||||
|
||||
@@ -143,19 +143,19 @@ pub struct VerifyChecksumError {
|
||||
#[derive(Debug, Display, Error, Diagnostic, From)]
|
||||
#[non_exhaustive]
|
||||
pub enum TarballError {
|
||||
#[diagnostic(code(pacquet_tarball::fetch_tarball))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_FETCH_TARBALL))]
|
||||
FetchTarball(NetworkError),
|
||||
|
||||
#[diagnostic(code(pacquet_tarball::http_status))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_HTTP_STATUS))]
|
||||
HttpStatus(HttpStatusError),
|
||||
|
||||
#[from(ignore)]
|
||||
#[diagnostic(code(pacquet_tarball::io_error))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_IO_ERROR))]
|
||||
ReadTarballEntries(std::io::Error),
|
||||
|
||||
#[from(ignore)]
|
||||
#[display("Failed to read local tarball {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet_tarball::read_local_tarball))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_READ_LOCAL_TARBALL))]
|
||||
ReadLocalTarball {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -163,7 +163,7 @@ pub enum TarballError {
|
||||
},
|
||||
|
||||
#[diagnostic(
|
||||
code(pacquet_tarball::verify_checksum_error),
|
||||
code(ERR_PNPM_TARBALL_INTEGRITY),
|
||||
help(
|
||||
"The downloaded tarball does not match the integrity recorded in the lockfile. If you trust the new content (legitimate republish, or stale local metadata cache), run `pnpm install --update-checksums`. Otherwise treat this as a potential supply-chain issue and verify the new content first."
|
||||
)
|
||||
@@ -172,7 +172,7 @@ pub enum TarballError {
|
||||
|
||||
#[from(ignore)]
|
||||
#[display("Failed to decode gzip: {_0}")]
|
||||
#[diagnostic(code(pacquet_tarball::decode_gzip))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_DECODE_GZIP))]
|
||||
DecodeGzip(InflateDecodeErrors),
|
||||
|
||||
#[from(ignore)]
|
||||
@@ -186,14 +186,14 @@ pub enum TarballError {
|
||||
WriteStoreIndex(StoreIndexError),
|
||||
|
||||
#[from(ignore)]
|
||||
#[diagnostic(code(pacquet_tarball::task_join_error))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_TASK_JOIN_ERROR))]
|
||||
TaskJoin(tokio::task::JoinError),
|
||||
|
||||
#[from(ignore)]
|
||||
#[display(
|
||||
"Archive at {url} advertised a Content-Length of {advertised_size} bytes, which exceeds what pnpm can allocate (either larger than `usize::MAX` on this target or memory pressure prevented a one-shot reservation)"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_tarball::tarball_too_large))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_TOO_LARGE))]
|
||||
TarballTooLarge { url: String, advertised_size: u64 },
|
||||
|
||||
/// A concurrent request for the same tarball URL went through
|
||||
@@ -206,7 +206,7 @@ pub enum TarballError {
|
||||
#[display(
|
||||
"A concurrent fetch for {url} failed; this request waited on the shared mem cache and inherits the failure"
|
||||
)]
|
||||
#[diagnostic(code(pacquet_tarball::sibling_fetch_failed))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_SIBLING_FETCH_FAILED))]
|
||||
SiblingFetchFailed { url: String },
|
||||
|
||||
/// Path-traversal rejection on a zip entry, carrying the
|
||||
@@ -215,7 +215,7 @@ pub enum TarballError {
|
||||
/// directory is rejected before any bytes are written to the CAS.
|
||||
#[from(ignore)]
|
||||
#[display("Refusing to extract zip entry {entry_path:?} from {url} — {reason}")]
|
||||
#[diagnostic(code(pacquet_tarball::path_traversal))]
|
||||
#[diagnostic(code(ERR_PNPM_PATH_TRAVERSAL))]
|
||||
PathTraversal { url: String, entry_path: String, reason: &'static str },
|
||||
|
||||
/// Zip-archive parse / read error. Wraps the underlying `zip`
|
||||
@@ -223,7 +223,7 @@ pub enum TarballError {
|
||||
/// mode beyond surfacing the entry path that triggered it.
|
||||
#[from(ignore)]
|
||||
#[display("Failed to read zip archive {url}: {source}")]
|
||||
#[diagnostic(code(pacquet_tarball::read_zip))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_READ_ZIP))]
|
||||
ReadZipArchive {
|
||||
url: String,
|
||||
#[error(source)]
|
||||
@@ -242,7 +242,7 @@ pub enum TarballError {
|
||||
/// rather than the tar-specific `ERR_PNPM_TARBALL_TAR`.
|
||||
#[from(ignore)]
|
||||
#[display("Failed to read zip entry {entry_path:?} from {url}: {source}")]
|
||||
#[diagnostic(code(pacquet_tarball::read_zip_entry))]
|
||||
#[diagnostic(code(ERR_PNPM_TARBALL_READ_ZIP_ENTRY))]
|
||||
ReadZipEntries {
|
||||
url: String,
|
||||
entry_path: String,
|
||||
|
||||
@@ -117,15 +117,15 @@ pub enum VersioningError {
|
||||
MaxBumpExceeded { pkg_name: String, bump_type: String, max_bump: String, raised_by: String },
|
||||
|
||||
#[display("Failed to read {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet_versioning::read_error))]
|
||||
#[diagnostic(code(ERR_PNPM_VERSIONING_READ_ERROR))]
|
||||
Read { path: PathBuf, source: std::io::Error },
|
||||
|
||||
#[display("Failed to write {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet_versioning::write_error))]
|
||||
#[diagnostic(code(ERR_PNPM_VERSIONING_WRITE_ERROR))]
|
||||
Write { path: PathBuf, source: std::io::Error },
|
||||
|
||||
#[display("Failed to remove {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet_versioning::remove_error))]
|
||||
#[diagnostic(code(ERR_PNPM_VERSIONING_REMOVE_ERROR))]
|
||||
Remove { path: PathBuf, source: std::io::Error },
|
||||
|
||||
#[display("{_0}")]
|
||||
|
||||
@@ -38,7 +38,7 @@ pub const WORKSPACE_MANIFEST_FILENAME: &str = "pnpm-workspace.yaml";
|
||||
#[non_exhaustive]
|
||||
pub enum UpdateWorkspaceManifestError {
|
||||
#[display("Failed to read {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_workspace_manifest_writer::read))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_MANIFEST_WRITER_READ))]
|
||||
Read {
|
||||
path: std::path::PathBuf,
|
||||
#[error(source)]
|
||||
@@ -46,7 +46,7 @@ pub enum UpdateWorkspaceManifestError {
|
||||
},
|
||||
|
||||
#[display("Failed to parse {path:?} as YAML: {source}")]
|
||||
#[diagnostic(code(pacquet_workspace_manifest_writer::parse))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_MANIFEST_WRITER_PARSE))]
|
||||
Parse {
|
||||
path: std::path::PathBuf,
|
||||
#[error(source)]
|
||||
@@ -54,7 +54,7 @@ pub enum UpdateWorkspaceManifestError {
|
||||
},
|
||||
|
||||
#[display("Failed to apply a YAML edit to {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_workspace_manifest_writer::edit))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_MANIFEST_WRITER_EDIT))]
|
||||
Edit {
|
||||
path: std::path::PathBuf,
|
||||
#[error(source)]
|
||||
@@ -62,7 +62,7 @@ pub enum UpdateWorkspaceManifestError {
|
||||
},
|
||||
|
||||
#[display("Failed to write {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_workspace_manifest_writer::write))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_MANIFEST_WRITER_WRITE))]
|
||||
Write {
|
||||
path: std::path::PathBuf,
|
||||
#[error(source)]
|
||||
@@ -70,7 +70,7 @@ pub enum UpdateWorkspaceManifestError {
|
||||
},
|
||||
|
||||
#[display("Failed to remove {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_workspace_manifest_writer::remove))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_MANIFEST_WRITER_REMOVE))]
|
||||
Remove {
|
||||
path: std::path::PathBuf,
|
||||
#[error(source)]
|
||||
@@ -80,19 +80,19 @@ pub enum UpdateWorkspaceManifestError {
|
||||
#[display(
|
||||
"Cannot write the override for {key:?} in {path:?}: it already has a non-string value (a parent-scoped object). Resolve it manually."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_workspace_manifest_writer::override_conflict))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_MANIFEST_WRITER_OVERRIDE_CONFLICT))]
|
||||
OverrideConflict { path: std::path::PathBuf, key: String },
|
||||
|
||||
#[display(
|
||||
"Cannot edit {key:?} in {path:?}: it uses an inline (flow) YAML value. Reformat it to block style and try again."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_workspace_manifest_writer::unsupported_inline_block))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_MANIFEST_WRITER_UNSUPPORTED_INLINE_BLOCK))]
|
||||
UnsupportedInlineBlock { path: std::path::PathBuf, key: String },
|
||||
|
||||
#[display(
|
||||
"Cannot write {value:?} to {path:?}: it contains a control character that would corrupt the YAML."
|
||||
)]
|
||||
#[diagnostic(code(pacquet_workspace_manifest_writer::invalid_control_character))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_MANIFEST_WRITER_INVALID_CONTROL_CHARACTER))]
|
||||
InvalidControlCharacter { path: std::path::PathBuf, value: String },
|
||||
}
|
||||
|
||||
|
||||
@@ -86,14 +86,14 @@ pub enum FilterError {
|
||||
/// A `testPattern` / `changedFilesIgnorePattern` glob did not
|
||||
/// compile.
|
||||
#[display("Invalid pattern {pattern:?}: {message}")]
|
||||
#[diagnostic(code(pacquet_workspace_projects_filter::invalid_pattern))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_PROJECTS_FILTER_INVALID_PATTERN))]
|
||||
InvalidPattern { pattern: String, message: String },
|
||||
|
||||
/// A selector resolved to neither a name pattern, a directory, nor a
|
||||
/// diff. The message includes the offending selector so CLI input is
|
||||
/// debuggable.
|
||||
#[display("Unsupported project selector: {selector}")]
|
||||
#[diagnostic(code(pacquet_workspace_projects_filter::unsupported_selector))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_PROJECTS_FILTER_UNSUPPORTED_SELECTOR))]
|
||||
UnsupportedSelector {
|
||||
#[error(not(source))]
|
||||
selector: String,
|
||||
|
||||
@@ -173,15 +173,15 @@ pub enum NodeLinker {
|
||||
#[non_exhaustive]
|
||||
pub enum UpdateWorkspaceStateError {
|
||||
#[display("Failed to create directory {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_workspace_state::create_dir))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_STATE_CREATE_DIR))]
|
||||
CreateDir { path: PathBuf, source: io::Error },
|
||||
|
||||
#[display("Failed to serialize workspace state: {_0}")]
|
||||
#[diagnostic(code(pacquet_workspace_state::serialize_json))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_STATE_SERIALIZE_JSON))]
|
||||
SerializeJson(serde_json::Error),
|
||||
|
||||
#[display("Failed to write {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_workspace_state::write_io))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_STATE_WRITE_IO))]
|
||||
WriteFile { path: PathBuf, source: io::Error },
|
||||
}
|
||||
|
||||
@@ -246,11 +246,11 @@ pub fn load_workspace_state(
|
||||
#[non_exhaustive]
|
||||
pub enum LoadWorkspaceStateError {
|
||||
#[display("Failed to read {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_workspace_state::read_io))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_STATE_READ_IO))]
|
||||
ReadFile { path: PathBuf, source: io::Error },
|
||||
|
||||
#[display("Failed to parse {path:?}: {source}")]
|
||||
#[diagnostic(code(pacquet_workspace_state::parse_json))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_STATE_PARSE_JSON))]
|
||||
ParseJson { path: PathBuf, source: serde_json::Error },
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ pub struct WorkspaceManifest {
|
||||
/// `serde_saphyr` rejects a non-array shape before this layer runs.
|
||||
/// Only the empty-string-entry check needs a dedicated variant.
|
||||
#[derive(Debug, Display, Error, Diagnostic)]
|
||||
#[diagnostic(code(pacquet_workspace::invalid_workspace_configuration))]
|
||||
#[diagnostic(code(ERR_PNPM_INVALID_WORKSPACE_CONFIGURATION))]
|
||||
#[non_exhaustive]
|
||||
pub enum InvalidWorkspaceManifestError {
|
||||
#[display("Missing or empty package")]
|
||||
|
||||
@@ -21,7 +21,7 @@ pub enum ReadProjectManifestError {
|
||||
Read(#[error(source)] PackageManifestError),
|
||||
|
||||
#[display("Failed to read {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet_workspace::read_project_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_READ_PROJECT_MANIFEST))]
|
||||
ReadFile {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -29,7 +29,7 @@ pub enum ReadProjectManifestError {
|
||||
},
|
||||
|
||||
#[display("Failed to parse {}: {source}", path.display())]
|
||||
#[diagnostic(code(pacquet_workspace::parse_project_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_PARSE_PROJECT_MANIFEST))]
|
||||
ParseYaml {
|
||||
path: PathBuf,
|
||||
#[error(source)]
|
||||
@@ -37,7 +37,7 @@ pub enum ReadProjectManifestError {
|
||||
},
|
||||
|
||||
#[display("Not supported manifest name {basename:?}")]
|
||||
#[diagnostic(code(pacquet_workspace::unsupported_project_manifest))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_UNSUPPORTED_PROJECT_MANIFEST))]
|
||||
UnsupportedName { basename: String },
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ pub enum ReadProjectManifestError {
|
||||
#[non_exhaustive]
|
||||
pub enum ReadProjectManifestOnlyError {
|
||||
#[display("No package.json or package.yaml was found in {:?}", project_dir.display())]
|
||||
#[diagnostic(code(pacquet_workspace::no_importer_manifest_found))]
|
||||
#[diagnostic(code(ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND))]
|
||||
NoImporterManifestFound { project_dir: PathBuf },
|
||||
|
||||
#[diagnostic(transparent)]
|
||||
|
||||
@@ -56,7 +56,7 @@ pub struct FindWorkspaceProjectsOpts {
|
||||
#[non_exhaustive]
|
||||
pub enum FindWorkspaceProjectsError {
|
||||
#[display("Invalid glob pattern in pnpm-workspace.yaml packages: {pattern:?}: {message}")]
|
||||
#[diagnostic(code(pacquet_workspace::invalid_glob))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_INVALID_GLOB))]
|
||||
InvalidGlob {
|
||||
pattern: String,
|
||||
// Built once at construction. wax errors carry a borrow of the
|
||||
@@ -65,7 +65,7 @@ pub enum FindWorkspaceProjectsError {
|
||||
},
|
||||
|
||||
#[display("Failed to walk workspace projects under {}: {source}", root.display())]
|
||||
#[diagnostic(code(pacquet_workspace::walk_error))]
|
||||
#[diagnostic(code(ERR_PNPM_WORKSPACE_WALK_ERROR))]
|
||||
Walk {
|
||||
root: PathBuf,
|
||||
#[error(source)]
|
||||
|
||||
@@ -39,7 +39,7 @@ pub(crate) const WORKSPACE_DIR_ENV_VAR_LOWER: &str = "npm_config_workspace_dir";
|
||||
"The workspace manifest file should be named \"pnpm-workspace.yaml\". File found: {}",
|
||||
path.display()
|
||||
)]
|
||||
#[diagnostic(code(pacquet_workspace::bad_workspace_manifest_name))]
|
||||
#[diagnostic(code(ERR_PNPM_BAD_WORKSPACE_MANIFEST_NAME))]
|
||||
pub struct BadWorkspaceManifestNameError {
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user