fix: fixes a collision when -i is used with input passed via stdin, uses /dev/tty instead

This commit is contained in:
Lewis Wynne 2026-02-11 15:27:29 +00:00
parent 5145816b0a
commit d0926c2c1d

View file

@ -97,12 +97,27 @@ func restore(cmd *cobra.Command, args []string) error {
recipient = identity.Recipient() recipient = identity.Recipient()
} }
var promptReader io.Reader
if promptOverwrite {
filePath, _ := cmd.Flags().GetString("file")
if strings.TrimSpace(filePath) == "" {
// Data comes from stdin — open /dev/tty for interactive prompts.
tty, err := os.Open("/dev/tty")
if err != nil {
return fmt.Errorf("cannot restore '%s': --interactive requires --file (-f) when reading from stdin on this platform", displayTarget)
}
defer tty.Close()
promptReader = tty
}
}
restored, err := restoreEntries(decoder, p, restoreOpts{ restored, err := restoreEntries(decoder, p, restoreOpts{
matchers: matchers, matchers: matchers,
promptOverwrite: promptOverwrite, promptOverwrite: promptOverwrite,
drop: drop, drop: drop,
identity: identity, identity: identity,
recipient: recipient, recipient: recipient,
promptReader: promptReader,
}) })
if err != nil { if err != nil {
return fmt.Errorf("cannot restore '%s': %v", displayTarget, err) return fmt.Errorf("cannot restore '%s': %v", displayTarget, err)
@ -137,6 +152,7 @@ type restoreOpts struct {
drop bool drop bool
identity *age.X25519Identity identity *age.X25519Identity
recipient *age.X25519Recipient recipient *age.X25519Recipient
promptReader io.Reader
} }
func restoreEntries(decoder *json.Decoder, storePath string, opts restoreOpts) (int, error) { func restoreEntries(decoder *json.Decoder, storePath string, opts restoreOpts) (int, error) {
@ -178,9 +194,16 @@ func restoreEntries(decoder *json.Decoder, storePath string, opts restoreOpts) (
if opts.promptOverwrite && idx >= 0 { if opts.promptOverwrite && idx >= 0 {
promptf("overwrite '%s'? (y/n)", entry.Key) promptf("overwrite '%s'? (y/n)", entry.Key)
var confirm string var confirm string
if opts.promptReader != nil {
fmt.Fprintf(os.Stdout, "%s ", keyword("2", "==>", stdoutIsTerminal()))
if _, err := fmt.Fscanln(opts.promptReader, &confirm); err != nil {
return 0, fmt.Errorf("entry %d: %v", entryNo, err)
}
} else {
if err := scanln(&confirm); err != nil { if err := scanln(&confirm); err != nil {
return 0, fmt.Errorf("entry %d: %v", entryNo, err) return 0, fmt.Errorf("entry %d: %v", entryNo, err)
} }
}
if strings.ToLower(confirm) != "y" { if strings.ToLower(confirm) != "y" {
continue continue
} }