check / check (push) Waiting to run
The key index, --words, the --to recipients and the input file of age encrypt and age decrypt were checked only after the mnemonic had been obtained, so a run that could not succeed still prompted for it or ran the mnemonic command. options.Index now refuses an index above derive.MaxIndex, which covers every command group; the mnemonic command calls the new childmnemonic.CheckWords first; age encrypt reads its recipients with the new agekey.Recipients, and both age commands open their input, before the key is derived. Encrypt now takes the parsed recipients. The README says which checks come first. Model: opus-5-5
83 lines
2.1 KiB
Go
83 lines
2.1 KiB
Go
// Package options holds the flags that every command has and reads
|
|
// them back.
|
|
package options
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"github.com/spf13/cobra"
|
|
"sneak.berlin/go/keyfunc/internal/derive"
|
|
"sneak.berlin/go/keyfunc/internal/mnemonic"
|
|
)
|
|
|
|
// Add gives a command the flags that every command has. They are
|
|
// persistent, so every command below it has them too.
|
|
func Add(cmd *cobra.Command) {
|
|
cmd.PersistentFlags().String(
|
|
"mnemonic-command", "",
|
|
"shell command whose output is the mnemonic",
|
|
)
|
|
cmd.PersistentFlags().VarP(
|
|
new(Decimal), "index", "n",
|
|
"which key to derive",
|
|
)
|
|
}
|
|
|
|
// Index returns the key index the user asked for, and refuses one above
|
|
// derive.MaxIndex. Every command calls it before it looks for the
|
|
// mnemonic.
|
|
func Index(cmd *cobra.Command) (uint32, error) {
|
|
index, err := cmd.Flags().GetUint32("index")
|
|
if err != nil {
|
|
return 0, fmt.Errorf("reading the index: %w", err)
|
|
}
|
|
|
|
err = derive.CheckIndex(index)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return index, nil
|
|
}
|
|
|
|
// Mnemonic returns the mnemonic, from the first source that has one.
|
|
func Mnemonic(cmd *cobra.Command) (string, error) {
|
|
command, err := cmd.Flags().GetString("mnemonic-command")
|
|
if err != nil {
|
|
return "", fmt.Errorf("reading the mnemonic command: %w", err)
|
|
}
|
|
|
|
return mnemonic.Read(cmd.Context(), command)
|
|
}
|
|
|
|
// Decimal is a flag value for a number written in decimal digits only.
|
|
// The flag library's own uint32 flags read 010 as octal 8 and also
|
|
// take 0x10 or 1_0.
|
|
type Decimal uint32
|
|
|
|
// String returns the number in decimal digits.
|
|
func (d *Decimal) String() string {
|
|
return strconv.FormatUint(uint64(*d), 10)
|
|
}
|
|
|
|
// Set reads text as a decimal number that fits in 32 bits: a leading
|
|
// zero is still decimal, and a base prefix, an underscore or a sign is
|
|
// refused.
|
|
func (d *Decimal) Set(text string) error {
|
|
number, err := strconv.ParseUint(text, 10, 32)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*d = Decimal(number)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Type is what --help shows as the flag's type, and what GetUint32
|
|
// checks before it reads the value back.
|
|
func (d *Decimal) Type() string {
|
|
return "uint32"
|
|
}
|