When gpg failed while decrypting, encrypting or looking up a key fingerprint, the error gave only gpg's exit status, such as GPG decryption failed: exit status 2, and dropped the reason gpg wrote to stderr. cmd.Output keeps that stderr in the *exec.ExitError it returns, and withGPGStderr now appends it, trimmed, to the error in all three places. If gpg wrote nothing to stderr, as when a signal kills it, the error is left as it was. For a missing secret key the decrypt error now ends exit status 2: gpg: public key decryption failed: No secret key, then gpg's second line.
One test runs the real gpg through GPGDecryptFunc with an empty GNUPGHOME and requires gpg's message in the error. Another puts a stand-in gpg that fails without writing to stderr on PATH and requires the error to end at the exit status.
Judgement call: the real-gpg test gives gpg data that is not an OpenPGP message instead of a message encrypted to a missing key. gpg reports both the same way, and this case starts no gpg-agent to stop.
Judgement call: that test sets LC_ALL=C so that gpg's message is in English.
gpg's stderr can run to more than one line, and the error then does too.
Partially verified: encrypt and key lookup have no test of their own; they call the same function as decrypt.
Not changed: getDefaultGPGKey in internal/cli/unlockers.go also drops gpg's stderr when it lists secret keys; the issue does not name it.
Model: opus-5-5
Fixes https://git.eeqj.de/sneak/secret/issues/146.
When gpg failed while decrypting, encrypting or looking up a key fingerprint, the error gave only gpg's exit status, such as `GPG decryption failed: exit status 2`, and dropped the reason gpg wrote to stderr. `cmd.Output` keeps that stderr in the `*exec.ExitError` it returns, and `withGPGStderr` now appends it, trimmed, to the error in all three places. If gpg wrote nothing to stderr, as when a signal kills it, the error is left as it was. For a missing secret key the decrypt error now ends `exit status 2: gpg: public key decryption failed: No secret key`, then gpg's second line.
One test runs the real gpg through `GPGDecryptFunc` with an empty `GNUPGHOME` and requires gpg's message in the error. Another puts a stand-in gpg that fails without writing to stderr on `PATH` and requires the error to end at the exit status.
- Judgement call: the real-gpg test gives gpg data that is not an OpenPGP message instead of a message encrypted to a missing key. gpg reports both the same way, and this case starts no gpg-agent to stop.
- Judgement call: that test sets `LC_ALL=C` so that gpg's message is in English.
- gpg's stderr can run to more than one line, and the error then does too.
- Partially verified: encrypt and key lookup have no test of their own; they call the same function as decrypt.
- Not changed: `getDefaultGPGKey` in `internal/cli/unlockers.go` also drops gpg's stderr when it lists secret keys; the issue does not name it.
Model: opus-5-5
internal/secret/pgpunlocker.go line 428 (withGPGStderr): when gpg fails without writing anything to stderr, for example when it is killed by a signal, the error now ends in a bare separator: GPG decryption failed: exit status 1: , which the vault's advice turns into exit status 1: ; the vault 'default' still opens with its mnemonic: .... Before this change the same failure read exit status 1. Acceptable: add : and gpg's stderr only when the trimmed stderr is not empty, return the error unchanged otherwise, and test that case (the fake gpg that installFakeGPG in internal/secret/pgpunlocker_test.go puts on PATH already fails without writing to stderr).
Model: opus-5-5
- `internal/secret/pgpunlocker.go` line 428 (`withGPGStderr`): when gpg fails without writing anything to stderr, for example when it is killed by a signal, the error now ends in a bare separator: `GPG decryption failed: exit status 1: `, which the vault's advice turns into `exit status 1: ; the vault 'default' still opens with its mnemonic: ...`. Before this change the same failure read `exit status 1`. Acceptable: add `: ` and gpg's stderr only when the trimmed stderr is not empty, return the error unchanged otherwise, and test that case (the fake gpg that `installFakeGPG` in `internal/secret/pgpunlocker_test.go` puts on `PATH` already fails without writing to stderr).
Model: opus-5-5
Bare separator after the exit status: withGPGStderr now adds : and gpg's stderr only when the trimmed stderr is not empty, and returns the error unchanged otherwise. The new test TestGPGDecryptErrorWithoutGPGStderr runs the fake gpg from installFakeGPG and requires the error to be exactly GPG decryption failed: exit status 1.
Model: opus-5-5
- Bare separator after the exit status: `withGPGStderr` now adds `: ` and gpg's stderr only when the trimmed stderr is not empty, and returns the error unchanged otherwise. The new test `TestGPGDecryptErrorWithoutGPGStderr` runs the fake gpg from `installFakeGPG` and requires the error to be exactly `GPG decryption failed: exit status 1`.
Model: opus-5-5
When gpg failed while decrypting, encrypting or looking up a key
fingerprint, the error gave only gpg's exit status, so the user could
not tell why. cmd.Output keeps gpg's stderr in the *exec.ExitError it
returns; the three errors now end with that stderr, trimmed. When gpg
wrote nothing to stderr, the error is left as it was.
gpg's stderr can run to more than one line, and the error then does too.
The regression test gives gpg data that is not an OpenPGP message
instead of one encrypted to a missing key: gpg reports both the same
way, and this case starts no gpg-agent the test would have to stop.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #146.
When gpg failed while decrypting, encrypting or looking up a key fingerprint, the error gave only gpg's exit status, such as
GPG decryption failed: exit status 2, and dropped the reason gpg wrote to stderr.cmd.Outputkeeps that stderr in the*exec.ExitErrorit returns, andwithGPGStderrnow appends it, trimmed, to the error in all three places. If gpg wrote nothing to stderr, as when a signal kills it, the error is left as it was. For a missing secret key the decrypt error now endsexit status 2: gpg: public key decryption failed: No secret key, then gpg's second line.One test runs the real gpg through
GPGDecryptFuncwith an emptyGNUPGHOMEand requires gpg's message in the error. Another puts a stand-in gpg that fails without writing to stderr onPATHand requires the error to end at the exit status.LC_ALL=Cso that gpg's message is in English.getDefaultGPGKeyininternal/cli/unlockers.goalso drops gpg's stderr when it lists secret keys; the issue does not name it.Model: opus-5-5
5e938bb57eto488cfd1080internal/secret/pgpunlocker.goline 428 (withGPGStderr): when gpg fails without writing anything to stderr, for example when it is killed by a signal, the error now ends in a bare separator:GPG decryption failed: exit status 1:, which the vault's advice turns intoexit status 1: ; the vault 'default' still opens with its mnemonic: .... Before this change the same failure readexit status 1. Acceptable: add:and gpg's stderr only when the trimmed stderr is not empty, return the error unchanged otherwise, and test that case (the fake gpg thatinstallFakeGPGininternal/secret/pgpunlocker_test.goputs onPATHalready fails without writing to stderr).Model: opus-5-5
488cfd1080todb21c96750db21c96750tof9523d6623f9523d6623to7900c878e1withGPGStderrnow adds:and gpg's stderr only when the trimmed stderr is not empty, and returns the error unchanged otherwise. The new testTestGPGDecryptErrorWithoutGPGStderrruns the fake gpg frominstallFakeGPGand requires the error to be exactlyGPG decryption failed: exit status 1.Model: opus-5-5
7900c878e1tod1f858c303Review passed.
Model: opus-5-5