diff --git a/.github/workflows/autorelease.yml b/.github/workflows/autorelease.yml index db97533a51..e2a26d374e 100644 --- a/.github/workflows/autorelease.yml +++ b/.github/workflows/autorelease.yml @@ -30,7 +30,7 @@ jobs: name: Set up Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: '1.22' + go-version: '1.23' - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/go/pkg/mod diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f012d154cd..fcb7262e5f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,6 +30,8 @@ jobs: raw.githubusercontent.com:443 storage.googleapis.com:443 sum.golang.org:443 + golang.org:443 + go.dev:443 - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: @@ -38,7 +40,7 @@ jobs: - name: Set up Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: '1.22' + go-version: '1.23' - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/go/pkg/mod @@ -92,7 +94,7 @@ jobs: - name: Set up Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: '1.22' + go-version: '1.23' - run: git config --global user.name nobody - run: git config --global user.email foo.bar@example.org @@ -115,7 +117,7 @@ jobs: - name: Set up Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: '1.22' + go-version: '1.23' - run: git config --global user.name nobody - run: git config --global user.email foo.bar@example.org diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 3fe6932a6e..7ebb685e71 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -38,7 +38,7 @@ jobs: - name: Set up Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: '1.22' + go-version: '1.23' - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - name: golangci-lint uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0 diff --git a/.github/workflows/grype.yml b/.github/workflows/grype.yml index 372f81f7de..e3f2486e17 100644 --- a/.github/workflows/grype.yml +++ b/.github/workflows/grype.yml @@ -30,7 +30,7 @@ jobs: - name: Set up Go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: '1.22' + go-version: '1.23' - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/go/pkg/mod diff --git a/docs/backends/age.md b/docs/backends/age.md index 3dd110f19b..181986f973 100644 --- a/docs/backends/age.md +++ b/docs/backends/age.md @@ -27,6 +27,16 @@ This will automatically create a new age keypair and initialize the new store. Existing stores can be migrated using `gopass convert --crypto age`. +N.B. for a fully scripted or **non-interactive setup**, you can use the `GOPASS_AGE_PASSWORD` env variable +to set your identity file secret passphrase, and specify the age identity and recipients +that should be used for encrypting/decrypting passwords as follows: +``` +$ gopass age identity add +$ GOPASS_AGE_PASSWORD=mypassword gopass init --crypto age +``` +Notice the extra space in front of the command to skip most shell's history. +You'll need to set your name and username using `git` directly if you're using it as storage backend (the default one). + ## Features * Encryption using `age` library, can be decrypted using the `age` CLI diff --git a/docs/config.md b/docs/config.md index 7aa55c5279..5488748071 100644 --- a/docs/config.md +++ b/docs/config.md @@ -7,6 +7,7 @@ Some configuration options are only available through setting environment variab | **Option** | **Type** | **Description** | |------------------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `CHECKPOINT_DISABLE` | `bool` | Set to any non-empty value to disable calling the GitHub API when running `gopass version`. | +| `GOPASS_AGE_PASSWORD` | `string` | Set to any value (including the empty string) to use as a password for the age identity file containing your secret age identities. | | `GOPASS_AUTOSYNC_INTERVAL` | `int` | Set this to the number of days between autosync runs. | | `GOPASS_CHARACTER_SET` | `bool` | Set to any non-empty value to restrict the characters used in generated passwords | | `GOPASS_CLIPBOARD_CLEAR_CMD` | `string` | Use an external command to remove a password from the clipboard. See [GPaste](usecases/gpaste.md) for an example | @@ -20,7 +21,7 @@ Some configuration options are only available through setting environment variab | `GOPASS_DEBUG_LOG_SECRETS` | `bool` | Set to any non-empty value to enable logging of credentials | | `GOPASS_DEBUG_LOG` | `string` | Set to a filename to enable debug logging (only set GOPASS_DEBUG to log to stderr) | | `GOPASS_DEBUG` | `bool` | Set to any non-empty value to enable verbose debug output, by default on stderr, unless GOPASS_DEBUG_LOG is set | -| `GOPASS_DEBUG_VERBOSE` | `int` | Set to any integer value larger than zero to increase the verbosity of debug output | +| `GOPASS_DEBUG_VERBOSE` | `int` | Set to any integer value larger than zero to increase the verbosity of debug output | | `GOPASS_EXTERNAL_PWGEN` | `string` | Use an external password generator. See [Features](features.md#using-custom-password-generators) for details | | `GOPASS_FORCE_CHECK` | `string` | (internal) Force the updater to check for updates. Used for testing. | | `GOPASS_FORCE_UPDATE` | `bool` | Set to any non-empty value to force an update (if available) | diff --git a/go.mod b/go.mod index 505c8ddea2..d70780dd18 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/gopasspw/gopass -go 1.22.1 +go 1.23.2 require ( filippo.io/age v1.2.1-0.20240618131852-7eedd929a6cf diff --git a/internal/action/action_test.go b/internal/action/action_test.go index 48c182414a..c8eca8adfb 100644 --- a/internal/action/action_test.go +++ b/internal/action/action_test.go @@ -39,7 +39,8 @@ func newMock(ctx context.Context, path string) (*Action, error) { c := cli.NewContext(cli.NewApp(), fs, nil) c.Context = ctx if err := act.IsInitialized(c); err != nil { - return nil, err + // we still return the action since this might be expected sometimes + return act, err } return act, nil diff --git a/internal/action/copy.go b/internal/action/copy.go index 835b0b8293..cfe2eeaae7 100644 --- a/internal/action/copy.go +++ b/internal/action/copy.go @@ -3,13 +3,14 @@ package action import ( "context" "fmt" - "github.com/gopasspw/gopass/internal/tree" "path/filepath" "strings" "github.com/gopasspw/gopass/internal/action/exit" + "github.com/gopasspw/gopass/internal/tree" "github.com/gopasspw/gopass/pkg/ctxutil" "github.com/gopasspw/gopass/pkg/termio" + "github.com/urfave/cli/v2" ) @@ -45,7 +46,6 @@ func (s *Action) copy(ctx context.Context, from, to string, force bool) error { func (s *Action) copyFlattenDir(ctx context.Context, from, to string, force bool) error { entries, err := s.Store.List(ctx, tree.INF) - if err != nil { return exit.Error(exit.List, err, "failed to list entries in %q", from) } @@ -69,7 +69,6 @@ func (s *Action) copyFlattenDir(ctx context.Context, from, to string, force bool } func (s *Action) copyRegular(ctx context.Context, from, to string, force bool) error { - if !force { if s.Store.Exists(ctx, to) && !termio.AskForConfirmation(ctx, fmt.Sprintf("%s already exists. Overwrite it?", to)) { return exit.Error(exit.Aborted, nil, "not overwriting your current secret") diff --git a/internal/action/copy_test.go b/internal/action/copy_test.go index d3858c6d18..19b887b9b9 100644 --- a/internal/action/copy_test.go +++ b/internal/action/copy_test.go @@ -270,5 +270,4 @@ func TestCopyWithTrailingSlash(t *testing.T) { require.NoError(t, act.show(ctx, c, "new/baz", false)) assert.Equal(t, "another\n", buf.String()) buf.Reset() - } diff --git a/internal/action/generate.go b/internal/action/generate.go index a31c2f2a25..ed46fb7d21 100644 --- a/internal/action/generate.go +++ b/internal/action/generate.go @@ -249,13 +249,13 @@ func getPwLengthFromEnvOrAskUser(ctx context.Context) (int, error) { return pwlen, nil } -func clamp(min, max, value int) int { - if value < min { - return min +func clamp(mi, ma, value int) int { + if value < mi { + return mi } - if value > max && max > 0 { - return max + if value > ma && ma > 0 { + return ma } return value diff --git a/internal/action/setup.go b/internal/action/setup.go index 21ccffd207..ced29b7c39 100644 --- a/internal/action/setup.go +++ b/internal/action/setup.go @@ -148,26 +148,27 @@ func (s *Action) initGenerateIdentity(ctx context.Context, crypto backend.Crypto passphrase := xkcdgen.Random() pwGenerated := true - want, err := termio.AskForBool(ctx, "⚠ Do you want to enter a passphrase? (otherwise we generate one for you)", false) - if err != nil { - return err - } - if want { - pwGenerated = false - sv, err := termio.AskForPassword(ctx, "passphrase for your new keypair", true) - if err != nil { - return fmt.Errorf("failed to read passphrase: %w", err) - } - passphrase = sv - } - // support fully automated setup (e.g. for tests) - if !ctxutil.IsInteractive(ctx) && ctxutil.HasPasswordCallback(ctx) { + //nolint:nestif + if ctxutil.HasPasswordCallback(ctx) { pw, err := ctxutil.GetPasswordCallback(ctx)("", true) if err == nil { passphrase = string(pw) } pwGenerated = false + } else { + want, err := termio.AskForBool(ctx, "⚠ Do you want to enter a passphrase? (otherwise we generate one for you)", false) + if err != nil { + return err + } + if want { + pwGenerated = false + sv, err := termio.AskForPassword(ctx, "passphrase for your new keypair", true) + if err != nil { + return fmt.Errorf("failed to read passphrase: %w", err) + } + passphrase = sv + } } if crypto.Name() == "gpgcli" { diff --git a/internal/action/setup_test.go b/internal/action/setup_test.go index 29caffeda1..b75834dd01 100644 --- a/internal/action/setup_test.go +++ b/internal/action/setup_test.go @@ -29,10 +29,8 @@ func TestSetupAgeGitFS(t *testing.T) { }) ctx = ctxutil.WithPasswordPurgeCallback(ctx, func(s string) {}) //nolint:staticcheck - t.Skip("TODO: fix setup test") - act, err := newMock(ctx, u.StoreDir("")) - require.NoError(t, err) + require.ErrorContains(t, err, "not initialized") require.NotNil(t, act) buf := &bytes.Buffer{} @@ -56,11 +54,11 @@ func TestSetupAgeGitFS(t *testing.T) { require.NotNil(t, crypto) assert.Equal(t, "age", crypto.Name()) assert.True(t, act.initHasUseablePrivateKeys(ctx, crypto)) - require.Error(t, act.initGenerateIdentity(ctx, crypto, "foo bar", "foo.bar@example.org")) + require.NoError(t, act.initGenerateIdentity(ctx, crypto, "foo bar", "foo.bar@example.org")) buf.Reset() act.printRecipients(ctx, "") - assert.Contains(t, buf.String(), "0xDEADBEEF") + assert.Contains(t, buf.String(), "age1") buf.Reset() } @@ -89,8 +87,6 @@ func TestSetupPlainFS(t *testing.T) { require.NoError(t, act.IsInitialized(c)) buf.Reset() - t.Skip("TODO: fix these tests") - require.Error(t, act.Init(c)) assert.Contains(t, buf.String(), "already initialized") buf.Reset() diff --git a/internal/audit/audit.go b/internal/audit/audit.go index 7a53dc0061..10320b2bfc 100644 --- a/internal/audit/audit.go +++ b/internal/audit/audit.go @@ -138,9 +138,9 @@ func (a *Auditor) Batch(ctx context.Context, secrets []string) (*Report, error) // https://github.com/gopasspw/gopass/pull/245 // maxJobs := a.s.Concurrency() - if max := config.Int(ctx, "audit.concurrency"); max > 0 { - if maxJobs > max { - maxJobs = max + if maxVal := config.Int(ctx, "audit.concurrency"); maxVal > 0 { + if maxJobs > maxVal { + maxJobs = maxVal } } diff --git a/internal/backend/crypto/age/identities.go b/internal/backend/crypto/age/identities.go index 1d9e71e860..499c0dc9ab 100644 --- a/internal/backend/crypto/age/identities.go +++ b/internal/backend/crypto/age/identities.go @@ -242,7 +242,11 @@ func IdentityToRecipient(id age.Identity) age.Recipient { // GenerateIdentity creates a new identity. func (a *Age) GenerateIdentity(ctx context.Context, _ string, _ string, pw string) error { + // we don't check if the password callback is set, since it could only be + // set through an env variable, and here pw can only be set through an + // actual user input. if pw != "" { + debug.Log("age GenerateIdentity using provided pw") ctx = ctxutil.WithPasswordCallback(ctx, func(prompt string, confirm bool) ([]byte, error) { return []byte(pw), nil }) diff --git a/internal/backend/crypto/age/loader.go b/internal/backend/crypto/age/loader.go index 22640c7455..b1f7b71696 100644 --- a/internal/backend/crypto/age/loader.go +++ b/internal/backend/crypto/age/loader.go @@ -7,6 +7,7 @@ import ( "github.com/gopasspw/gopass/internal/backend" "github.com/gopasspw/gopass/internal/out" "github.com/gopasspw/gopass/pkg/debug" + "github.com/gopasspw/gopass/pkg/fsutil" ) const ( @@ -26,7 +27,8 @@ func (l loader) New(ctx context.Context) (backend.Crypto, error) { } func (l loader) Handles(ctx context.Context, s backend.Storage) error { - if s.Exists(ctx, OldIDFile) || s.Exists(ctx, OldKeyring) { + // OldKeyring is meant to be in the config folder, not necessarily in the store + if s.Exists(ctx, OldIDFile) || fsutil.IsNonEmptyFile(OldKeyring) { if err := migrate(ctx, s); err != nil { out.Errorf(ctx, "Failed to migrate age backend: %s", err) } diff --git a/internal/store/root/store.go b/internal/store/root/store.go index 9c1d3a1b7f..784a0fa1c7 100644 --- a/internal/store/root/store.go +++ b/internal/store/root/store.go @@ -106,11 +106,3 @@ func (r *Store) Concurrency() int { return min(c, runtime.NumCPU()) } - -func min(a, b int) int { - if a < b { - return a - } - - return b -} diff --git a/main.go b/main.go index 3a78c65c32..4ff389bf56 100644 --- a/main.go +++ b/main.go @@ -330,6 +330,15 @@ func initContext(ctx context.Context, cfg *config.Config) context.Context { } } + // using a password callback for age identity file or not? + if pw, isSet := os.LookupEnv("GOPASS_AGE_PASSWORD"); isSet { + ctx = ctxutil.WithPasswordCallback(ctx, func(_ string, _ bool) ([]byte, error) { + debug.Log("using age password callback from env variable GOPASS_AGE_PASSWORD") + + return []byte(pw), nil + }) + } + return ctx } diff --git a/pkg/clipboard/clipboard.go b/pkg/clipboard/clipboard.go index c79ee1419e..e96223bc05 100644 --- a/pkg/clipboard/clipboard.go +++ b/pkg/clipboard/clipboard.go @@ -46,7 +46,7 @@ func CopyTo(ctx context.Context, name string, content []byte, timeout int) error } if timeout < 1 { - debug.Log("Auto-clear of clipboard disabled.") + debug.Log("Auto-clearClip of clipboard disabled.") out.Printf(ctx, "✔ Copied %s to clipboard.", color.YellowString(name)) _ = notify.Notify(ctx, "gopass - clipboard", fmt.Sprintf("✔ Copied %s to clipboard.", name)) @@ -54,14 +54,14 @@ func CopyTo(ctx context.Context, name string, content []byte, timeout int) error return nil } - if err := clear(ctx, name, content, timeout); err != nil { - _ = notify.Notify(ctx, "gopass - clipboard", "failed to clear clipboard") + if err := clearClip(ctx, name, content, timeout); err != nil { + _ = notify.Notify(ctx, "gopass - clipboard", "failed to clearClip clipboard") - return fmt.Errorf("failed to clear clipboard: %w", err) + return fmt.Errorf("failed to clearClip clipboard: %w", err) } - out.Printf(ctx, "✔ Copied %s to clipboard. Will clear in %d seconds.", color.YellowString(name), timeout) - _ = notify.Notify(ctx, "gopass - clipboard", fmt.Sprintf("✔ Copied %s to clipboard. Will clear in %d seconds.", name, timeout)) + out.Printf(ctx, "✔ Copied %s to clipboard. Will clearClip in %d seconds.", color.YellowString(name), timeout) + _ = notify.Notify(ctx, "gopass - clipboard", fmt.Sprintf("✔ Copied %s to clipboard. Will clearClip in %d seconds.", name, timeout)) return nil } diff --git a/pkg/clipboard/clipboard_others.go b/pkg/clipboard/clipboard_others.go index ea41acc8d1..cf3a781fef 100644 --- a/pkg/clipboard/clipboard_others.go +++ b/pkg/clipboard/clipboard_others.go @@ -16,11 +16,11 @@ import ( "github.com/gopasspw/gopass/internal/pwschemes/argon2id" ) -// clear will spawn a copy of gopass that waits in a detached background +// clearClip will spawn a copy of gopass that waits in a detached background // process group until the timeout is expired. It will then compare the contents // of the clipboard and erase it if it still contains the data gopass copied // to it. -func clear(ctx context.Context, name string, content []byte, timeout int) error { +func clearClip(ctx context.Context, name string, content []byte, timeout int) error { hash, err := argon2id.Generate(string(content), 0) if err != nil { return fmt.Errorf("failed to generate checksum: %w", err) diff --git a/pkg/clipboard/clipboard_test.go b/pkg/clipboard/clipboard_test.go index 1b2f6e723c..34abc64430 100644 --- a/pkg/clipboard/clipboard_test.go +++ b/pkg/clipboard/clipboard_test.go @@ -47,7 +47,7 @@ func TestUnsupportedCopyToClipboard(t *testing.T) { func TestClearClipboard(t *testing.T) { ctx, cancel := context.WithCancel(config.NewContextInMemory()) - require.NoError(t, clear(ctx, "foo", []byte("bar"), 0)) + require.NoError(t, clearClip(ctx, "foo", []byte("bar"), 0)) cancel() time.Sleep(50 * time.Millisecond) } diff --git a/pkg/clipboard/clipboard_windows.go b/pkg/clipboard/clipboard_windows.go index c4404ca29d..7ea9691930 100644 --- a/pkg/clipboard/clipboard_windows.go +++ b/pkg/clipboard/clipboard_windows.go @@ -13,11 +13,11 @@ import ( "github.com/gopasspw/gopass/internal/pwschemes/argon2id" ) -// clear will spwan a copy of gopass that waits in a detached background +// clearClip will spwan a copy of gopass that waits in a detached background // process group until the timeout is expired. It will then compare the contents // of the clipboard and erase it if it still contains the data gopass copied // to it. -func clear(ctx context.Context, name string, content []byte, timeout int) error { +func clearClip(ctx context.Context, name string, content []byte, timeout int) error { hash, err := argon2id.Generate(string(content), 0) if err != nil { return err diff --git a/pkg/clipboard/copy_darwin.go b/pkg/clipboard/copy_darwin.go index 5340abee67..91732d00d1 100644 --- a/pkg/clipboard/copy_darwin.go +++ b/pkg/clipboard/copy_darwin.go @@ -38,7 +38,7 @@ func copyViaOsascript(ctx context.Context, password string) error { "-e", "set type to current application's NSPasteboardTypeString", // pb = a reference to the system's pasteboard "-e", "set pb to current application's NSPasteboard's generalPasteboard()", - // Must clear contents before adding a new item to pasteboard + // Must clearClip contents before adding a new item to pasteboard "-e", "pb's clearContents()", // Set the flag ConcealedType so clipboard history managers don't record the password. // The first argument can by anything, but an empty string will do fine. diff --git a/pkg/clipboard/unclip.go b/pkg/clipboard/unclip.go index 1a0edc13a2..3be6109cb2 100644 --- a/pkg/clipboard/unclip.go +++ b/pkg/clipboard/unclip.go @@ -16,9 +16,9 @@ func Clear(ctx context.Context, name string, checksum string, force bool) error clipboardClearCMD := os.Getenv("GOPASS_CLIPBOARD_CLEAR_CMD") if clipboardClearCMD != "" { if err := callCommand(ctx, clipboardClearCMD, name, []byte(checksum)); err != nil { - _ = notify.Notify(ctx, "gopass - clipboard", "failed to call clipboard clear command") + _ = notify.Notify(ctx, "gopass - clipboard", "failed to call clipboard clearClip command") - return fmt.Errorf("failed to call clipboard clear command: %w", err) + return fmt.Errorf("failed to call clipboard clearClip command: %w", err) } debug.Log("clipboard cleared (%s)", checksum) @@ -47,15 +47,15 @@ func Clear(ctx context.Context, name string, checksum string, force bool) error } if err := clipboard.WriteAll(""); err != nil { - _ = notify.Notify(ctx, "gopass - clipboard", "Failed to clear clipboard") + _ = notify.Notify(ctx, "gopass - clipboard", "Failed to clearClip clipboard") return fmt.Errorf("failed to write clipboard: %w", err) } if err := clearClipboardHistory(ctx); err != nil { - _ = notify.Notify(ctx, "gopass - clipboard", "Failed to clear clipboard history") + _ = notify.Notify(ctx, "gopass - clipboard", "Failed to clearClip clipboard history") - return fmt.Errorf("failed to clear clipboard history: %w", err) + return fmt.Errorf("failed to clearClip clipboard history: %w", err) } if err := notify.Notify(ctx, "gopass - clipboard", "Clipboard has been cleared"); err != nil { diff --git a/pkg/ctxutil/ctxutil.go b/pkg/ctxutil/ctxutil.go index db789c3a1b..5208209125 100644 --- a/pkg/ctxutil/ctxutil.go +++ b/pkg/ctxutil/ctxutil.go @@ -396,7 +396,10 @@ func GetImportFunc(ctx context.Context) store.ImportCallback { return imf } -// PasswordCallback is a password prompt callback. +// PasswordCallback is a password prompt callback used in our age crypto backend. +// The arguments are typically the filename and whether or not to ask for a confirmation +// of the provided password, we use it notably together with askPass. +// It is linked to the GOPASS_AGE_PASSWORD env variable. type PasswordCallback func(string, bool) ([]byte, error) // WithPasswordCallback returns a context with the password callback set. diff --git a/pkg/fsutil/fsutil.go b/pkg/fsutil/fsutil.go index aacf844140..c5ce6c9333 100644 --- a/pkg/fsutil/fsutil.go +++ b/pkg/fsutil/fsutil.go @@ -241,14 +241,6 @@ func FileContains(path, needle string) bool { return false } -func min(a, b int64) int64 { - if a < b { - return a - } - - return b -} - // CopyFile copies a file from src to dst. Permissions will be preserved. It is expected to // fail if the destination does exist but is not writeable. func CopyFile(from, to string) error { diff --git a/pkg/gitconfig/gitconfig_test.go b/pkg/gitconfig/gitconfig_test.go index 24404f90ec..ab8f5d85de 100644 --- a/pkg/gitconfig/gitconfig_test.go +++ b/pkg/gitconfig/gitconfig_test.go @@ -44,7 +44,7 @@ var configSampleDocs = `# var configSampleComplex = ` [alias] - + # add a = add # add aa = add --all @@ -152,7 +152,7 @@ var configSampleComplex = ` # merge merc = merge --no-ff grog = log --graph --abbrev-commit --decorate --all --format=format:\"%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(dim white) - %an%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n %C(white)%s%C(reset)\" - + [apply] # Detect whitespace errors when applying a patch whitespace = fix @@ -179,7 +179,7 @@ var configSampleComplex = ` # Use colors in Git commands that are capable of colored output when outputting to the terminal ui = auto -[diff] +[diff] [format] pretty = format:%C(blue)%ad%Creset %C(yellow)%h%C(green)%d%Creset %C(blue)%s %C(magenta) [%an]%Creset @@ -355,9 +355,6 @@ func TestParseDocs(t *testing.T) { c := ParseConfig(strings.NewReader(configSampleComplex)) //nolint:staticcheck - // TODO(#2479) - fix parsing - t.Skip("TODO - broken") - v, ok := c.Get("core.sshCommand") assert.True(t, ok) assert.Equal(t, "ssh -oControlMaster=auto -oControlPersist=600 -oControlPath=/tmp/.ssh-%C", v) diff --git a/pkg/pwgen/pwrules/pwrules.go b/pkg/pwgen/pwrules/pwrules.go index 88f51dd35d..d8d9643a51 100644 --- a/pkg/pwgen/pwrules/pwrules.go +++ b/pkg/pwgen/pwrules/pwrules.go @@ -75,10 +75,10 @@ func ParseRule(in string) Rule { key := strings.TrimSpace(p[0]) strVal := strings.TrimSpace(p[1]) - max := len(strVal) + maxVal := len(strVal) if i := strings.Index(strVal, "["); i > 0 { - max = i + maxVal = i } switch key { @@ -89,9 +89,9 @@ func ParseRule(in string) Rule { case "max-consecutive": r.Maxconsec, err = strconv.Atoi(strVal) case "required": - r.Required = append(r.Required, strings.Split(strVal[0:max], ",")...) + r.Required = append(r.Required, strings.Split(strVal[0:maxVal], ",")...) case "allowed": - r.Allowed = append(r.Allowed, strings.Split(strVal[0:max], ",")...) + r.Allowed = append(r.Allowed, strings.Split(strVal[0:maxVal], ",")...) } if err != nil { diff --git a/pkg/pwgen/rand.go b/pkg/pwgen/rand.go index 7bff1ecab7..9e75add6a7 100644 --- a/pkg/pwgen/rand.go +++ b/pkg/pwgen/rand.go @@ -16,13 +16,13 @@ func init() { var randFallback *rand.Rand -func randomInteger(max int) int { - i, err := crand.Int(crand.Reader, big.NewInt(int64(max))) +func randomInteger(maxVal int) int { + i, err := crand.Int(crand.Reader, big.NewInt(int64(maxVal))) if err == nil { return int(i.Int64()) } fmt.Fprintln(os.Stderr, "WARNING: No crypto/rand available. Falling back to PRNG") - return randFallback.Intn(max) + return randFallback.Intn(maxVal) } diff --git a/pkg/termio/progress.go b/pkg/termio/progress.go index 420120e130..98825b1eab 100644 --- a/pkg/termio/progress.go +++ b/pkg/termio/progress.go @@ -50,7 +50,7 @@ func (p *ProgressBar) Add(v int64) { } cur := atomic.AddInt64(&p.current, v) - if max := atomic.LoadInt64(&p.total); cur > max { + if maxVal := atomic.LoadInt64(&p.total); cur > maxVal { atomic.StoreInt64(&p.total, cur) } @@ -64,7 +64,7 @@ func (p *ProgressBar) Inc() { } cur := atomic.AddInt64(&p.current, 1) - if max := atomic.LoadInt64(&p.total); cur > max { + if maxVal := atomic.LoadInt64(&p.total); cur > maxVal { atomic.StoreInt64(&p.total, cur) } @@ -79,7 +79,7 @@ func (p *ProgressBar) Set(v int64) { atomic.StoreInt64(&p.current, v) - if max := atomic.LoadInt64(&p.total); v > max { + if maxVal := atomic.LoadInt64(&p.total); v > maxVal { atomic.StoreInt64(&p.total, v) } @@ -143,7 +143,7 @@ func (p *ProgressBar) tryPrint() { func (p *ProgressBar) doPrint() { clearLine() - cur, max, pct := p.percent() + cur, maxVal, pct := p.percent() pctStr := fmt.Sprintf("%.2f%%", pct*100) // ensure consistent length for len(pctStr) < 7 { @@ -158,17 +158,17 @@ func (p *ProgressBar) doPrint() { } barWidth := uint(termWidth) - digits := int(math.Log10(float64(max))) + 1 + digits := int(math.Log10(float64(maxVal))) + 1 // Log10(0) is undefined - if max < 1 { + if maxVal < 1 { digits = 1 } - text := fmt.Sprintf(fmt.Sprintf(" %%%dd / %%%dd ", digits, digits), cur, max) + text := fmt.Sprintf(fmt.Sprintf(" %%%dd / %%%dd ", digits, digits), cur, maxVal) if p.Bytes { curStr := humanize.Bytes(uint64(cur)) - maxStr := humanize.Bytes(uint64(max)) + maxStr := humanize.Bytes(uint64(maxVal)) digits := len(maxStr) + 1 text = fmt.Sprintf(fmt.Sprintf(" %%%ds / %%%ds ", digits, digits), curStr, maxStr) } @@ -210,22 +210,14 @@ func gteZero(a int) int { return 0 } -func min(a, b int) int { - if a < b { - return a - } - - return b -} - func boundedMin(a, b int) int { return gteZero(min(a, b)) } func (p *ProgressBar) percent() (int64, int64, float64) { cur := atomic.LoadInt64(&p.current) - max := atomic.LoadInt64(&p.total) - pct := float64(cur) / float64(max) + maxVal := atomic.LoadInt64(&p.total) + pct := float64(cur) / float64(maxVal) if p.total < 1 { if p.current < 1 { @@ -236,7 +228,7 @@ func (p *ProgressBar) percent() (int64, int64, float64) { } // normalized between 0.0 and 1.0 - return cur, max, math.Min(1, math.Max(0, pct)) + return cur, maxVal, math.Min(1, math.Max(0, pct)) } func clearLine() { diff --git a/pkg/termio/progress_test.go b/pkg/termio/progress_test.go index ea63bd72ce..99c85fdd86 100644 --- a/pkg/termio/progress_test.go +++ b/pkg/termio/progress_test.go @@ -8,10 +8,10 @@ import ( ) func ExampleProgressBar() { //nolint:testableexamples - max := 100 - pb := NewProgressBar(int64(max)) + maxVal := 100 + pb := NewProgressBar(int64(maxVal)) - for range max + 20 { + for range maxVal + 20 { pb.Inc() pb.Add(23) pb.Set(42) @@ -23,8 +23,8 @@ func ExampleProgressBar() { //nolint:testableexamples } func TestProgress(t *testing.T) { - max := 2 - pb := NewProgressBar(int64(max)) + maxVal := 2 + pb := NewProgressBar(int64(maxVal)) pb.Hidden = true pb.Inc() assert.Equal(t, int64(1), pb.current) @@ -40,8 +40,8 @@ func TestProgressNil(t *testing.T) { } func TestProgressBytes(t *testing.T) { - max := 2 << 24 - pb := NewProgressBar(int64(max)) + maxSize := 2 << 24 + pb := NewProgressBar(int64(maxSize)) pb.Hidden = true pb.Bytes = true @@ -49,6 +49,6 @@ func TestProgressBytes(t *testing.T) { pb.Set(2 << (i + 1)) } - assert.Equal(t, int64(max), pb.current) + assert.Equal(t, int64(maxSize), pb.current) pb.Done() }