Make error message wording consistent (closes #165)
check / check (push) Waiting to run

Error messages in mfer/ and internal/cli/ are lowercase except names and
acronyms, carry no "failed to" or command-name prefix, and each wrap names
only the operation and thing the wrapped error does not already name, so a
stacked message names what failed once. Wraps around errors that already
name their operation and path (os and afero path errors, url.Error, the
builder's path errors, the gpg helpers' own errors) are dropped. gpg's
stderr is appended to a gpg failure, and to the error for a signing key gpg
did not report, only when gpg wrote some. errHTTPStatus reads "unexpected
HTTP status"; both inner-not-set sentinels read "inner message not set".
No sentinel, errors.Is result or exit status changes.

Model: opus-5-5
This commit is contained in:
2026-10-07 14:13:57 +00:00
parent dce5e050c3
commit 4ed0e5a24c
18 changed files with 278 additions and 175 deletions
+16 -21
View File
@@ -239,7 +239,7 @@ func reportDownloadProgress(progress <-chan DownloadProgress, done chan<- struct
func manifestBaseURL(manifestURL string) (*url.URL, error) {
parsed, err := url.Parse(manifestURL)
if err != nil {
return nil, fmt.Errorf("fetch: invalid manifest URL: %w", err)
return nil, fmt.Errorf("invalid manifest URL: %w", err)
}
// JoinPath cleans the path it builds, so ".." drops the manifest's
@@ -268,7 +268,7 @@ func downloadManifestFiles(
// Sanitize the path to prevent path traversal attacks
localPath, err := sanitizePath(f.GetPath())
if err != nil {
return 0, 0, fmt.Errorf("invalid path in manifest: %w", err)
return 0, 0, fmt.Errorf("invalid file entry: %w", err)
}
if alreadyPresent(dest, localPath, f) {
@@ -284,7 +284,7 @@ func downloadManifestFiles(
err = downloadFile(ctx, client, fileURL, dest, localPath, f, progress)
if err != nil {
return 0, 0, fmt.Errorf("failed to download %s: %w", f.GetPath(), err)
return 0, 0, fmt.Errorf("download %s: %w", f.GetPath(), err)
}
downloaded++
@@ -376,7 +376,7 @@ func (mfa *CLIApp) fetchManifestOperation(
err = os.MkdirAll(dest, dirPerms)
if err != nil {
return fmt.Errorf("failed to create destination directory %s: %w", dest, err)
return err
}
// Create progress channel and start progress reporter goroutine
@@ -403,7 +403,7 @@ func (mfa *CLIApp) fetchManifestOperation(
// "mfer check" can verify the tree later.
err = saveManifest(dest, manifestData)
if err != nil {
return fmt.Errorf("failed to save manifest: %w", err)
return fmt.Errorf("save manifest: %w", err)
}
// Print summary
@@ -446,11 +446,11 @@ func (mfa *CLIApp) fetchManifest(
return readErr
})
if err != nil {
return nil, nil, fmt.Errorf("failed to fetch manifest: %w", err)
return nil, nil, fmt.Errorf("download manifest: %w", err)
}
if int64(len(manifestData)) > mfa.maxManifestSize {
return nil, nil, fmt.Errorf("failed to fetch manifest: %w of %d bytes",
return nil, nil, fmt.Errorf("download manifest: %w of %d bytes",
errManifestTooLarge, mfa.maxManifestSize)
}
@@ -458,7 +458,7 @@ func (mfa *CLIApp) fetchManifest(
//nolint:contextcheck // mfer loads a manifest without a context
manifest, err := mfer.NewManifestFromReader(bytes.NewReader(manifestData))
if err != nil {
return nil, nil, fmt.Errorf("failed to parse manifest: %w", err)
return nil, nil, fmt.Errorf("parse manifest: %w", err)
}
requiredSigner := cmd.String(flagRequireSignature)
@@ -561,7 +561,7 @@ func verifyFetchedSigner(manifestData []byte, requiredSigner string) error {
Fs: memFs,
})
if err != nil {
return fmt.Errorf("failed to load manifest: %w", err)
return fmt.Errorf("load manifest: %w", err)
}
return verifyRequiredSigner(chk, requiredSigner)
@@ -653,7 +653,7 @@ func checkNoSymlinks(dest, p string) error {
}
if err != nil {
return fmt.Errorf("failed to check %s for a symlink: %w", current, err)
return err
}
if info.Mode()&os.ModeSymlink != 0 {
@@ -770,7 +770,7 @@ func tempPathFor(localPath string) string {
func verifyDownloadedHash(digest []byte, entry *mfer.MFFilePath) error {
computed, err := multihash.Encode(digest, multihash.SHA2_256)
if err != nil {
return fmt.Errorf("failed to encode hash: %w", err)
return fmt.Errorf("encode hash: %w", err)
}
for _, hash := range entry.GetHashes() {
@@ -797,7 +797,7 @@ func downloadFile(
// so every entry point to downloadFile gets the same treatment.
localPath, err := sanitizePath(localPath)
if err != nil {
return fmt.Errorf("invalid path: %w", err)
return fmt.Errorf("invalid file entry: %w", err)
}
// Create parent directories if needed
@@ -812,7 +812,7 @@ func downloadFile(
err = os.MkdirAll(dir, dirPerms)
if err != nil {
return fmt.Errorf("failed to create directory %s: %w", dir, err)
return err
}
}
@@ -846,7 +846,7 @@ func createTempFile(dest, tmpPath string) (*os.File, error) {
out, err := os.OpenFile( //nolint:gosec // G304: see comment above
path, os.O_RDWR|os.O_CREATE|os.O_EXCL, filePerms)
if err != nil {
return nil, fmt.Errorf("failed to create temp file: %w", err)
return nil, err
}
return out, nil
@@ -859,12 +859,7 @@ func moveIntoPlace(dest, tmpPath, localPath string) error {
return err
}
err = os.Rename(filepath.Join(dest, tmpPath), filepath.Join(dest, localPath))
if err != nil {
return fmt.Errorf("failed to rename temp file: %w", err)
}
return nil
return os.Rename(filepath.Join(dest, tmpPath), filepath.Join(dest, localPath))
}
// saveResponse writes resp's body to tmpPath, verifies it against entry,
@@ -899,7 +894,7 @@ func saveResponse(
_ = out.Close()
_ = os.Remove(filepath.Join(dest, tmpPath))
return fmt.Errorf("failed to set mode: %w", err)
return err
}
}