Update golangci-lint to v2.12.2 with canonical config
All checks were successful
check / check (push) Successful in 1m8s
All checks were successful
check / check (push) Successful in 1m8s
- Replace .golangci.yml with the canonical strict config (all linters enabled except the standard disable list; lll 88, funlen 80/50, cyclop 15, dupl 100; test files now linted) - Pin the Dockerfile lint stage to golangci/golangci-lint:v2.12.2 by tag and digest (Debian-based) - Fix all ~1550 findings surfaced by the new config: line wrapping, wsl_v5/nlreturn blank lines, noinlineerr splits, err113 sentinel errors, perfsprint/modernize rewrites, goconst constants, thelper, testifylint, noctx CommandContext, testpackage conversions, t.Parallel() where safe, and complexity/dupl helper extraction - Record the change and follow-up items in TODO.md
This commit is contained in:
@@ -1,21 +1,22 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.eeqj.de/sneak/secret/internal/secret"
|
||||
"git.eeqj.de/sneak/secret/internal/vault"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// getSecretNamesCompletionFunc returns a completion function that provides secret names
|
||||
// getSecretNamesCompletionFunc returns a completion function that provides
|
||||
// secret names
|
||||
func getSecretNamesCompletionFunc(fs afero.Fs, stateDir string) func(
|
||||
cmd *cobra.Command, args []string, toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
return func(_ *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return func(
|
||||
_ *cobra.Command, _ []string, toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
// Get current vault
|
||||
vlt, err := vault.GetCurrentVault(fs, stateDir)
|
||||
if err != nil {
|
||||
@@ -30,6 +31,7 @@ func getSecretNamesCompletionFunc(fs afero.Fs, stateDir string) func(
|
||||
|
||||
// Filter secrets based on what user has typed
|
||||
var completions []string
|
||||
|
||||
for _, secret := range secrets {
|
||||
if strings.HasPrefix(secret, toComplete) {
|
||||
completions = append(completions, secret)
|
||||
@@ -40,11 +42,14 @@ func getSecretNamesCompletionFunc(fs afero.Fs, stateDir string) func(
|
||||
}
|
||||
}
|
||||
|
||||
// getUnlockerIDsCompletionFunc returns a completion function that provides unlocker IDs
|
||||
// getUnlockerIDsCompletionFunc returns a completion function that provides
|
||||
// unlocker IDs
|
||||
func getUnlockerIDsCompletionFunc(fs afero.Fs, stateDir string) func(
|
||||
cmd *cobra.Command, args []string, toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
return func(_ *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return func(
|
||||
_ *cobra.Command, _ []string, toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
// Get current vault
|
||||
vlt, err := vault.GetCurrentVault(fs, stateDir)
|
||||
if err != nil {
|
||||
@@ -66,61 +71,13 @@ func getUnlockerIDsCompletionFunc(fs afero.Fs, stateDir string) func(
|
||||
// Collect unlocker IDs
|
||||
var completions []string
|
||||
|
||||
unlockersDir := filepath.Join(vaultDir, "unlockers.d")
|
||||
|
||||
for _, metadata := range unlockerMetadataList {
|
||||
// Get the actual unlocker ID by creating the unlocker instance
|
||||
unlockersDir := filepath.Join(vaultDir, "unlockers.d")
|
||||
files, err := afero.ReadDir(fs, unlockersDir)
|
||||
if err != nil {
|
||||
secret.Warn("Could not read unlockers directory during completion", "error", err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if !file.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
unlockerDir := filepath.Join(unlockersDir, file.Name())
|
||||
metadataPath := filepath.Join(unlockerDir, "unlocker-metadata.json")
|
||||
|
||||
// Check if this is the right unlocker by comparing metadata
|
||||
metadataBytes, err := afero.ReadFile(fs, metadataPath)
|
||||
if err != nil {
|
||||
secret.Warn("Could not read unlocker metadata during completion", "path", metadataPath, "error", err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
var diskMetadata secret.UnlockerMetadata
|
||||
if err := json.Unmarshal(metadataBytes, &diskMetadata); err != nil {
|
||||
secret.Warn("Could not parse unlocker metadata during completion", "path", metadataPath, "error", err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Match by type and creation time
|
||||
if diskMetadata.Type == metadata.Type && diskMetadata.CreatedAt.Equal(metadata.CreatedAt) {
|
||||
// Create the appropriate unlocker instance
|
||||
var unlocker secret.Unlocker
|
||||
switch metadata.Type {
|
||||
case "passphrase":
|
||||
unlocker = secret.NewPassphraseUnlocker(fs, unlockerDir, diskMetadata)
|
||||
case "keychain":
|
||||
unlocker = secret.NewKeychainUnlocker(fs, unlockerDir, diskMetadata)
|
||||
case "pgp":
|
||||
unlocker = secret.NewPGPUnlocker(fs, unlockerDir, diskMetadata)
|
||||
}
|
||||
|
||||
if unlocker != nil {
|
||||
id := unlocker.GetID()
|
||||
if strings.HasPrefix(id, toComplete) {
|
||||
completions = append(completions, id)
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
id := findUnlockerIDByMetadata(fs, unlockersDir, metadata, false)
|
||||
if id != "" && strings.HasPrefix(id, toComplete) {
|
||||
completions = append(completions, id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,17 +85,21 @@ func getUnlockerIDsCompletionFunc(fs afero.Fs, stateDir string) func(
|
||||
}
|
||||
}
|
||||
|
||||
// getVaultNamesCompletionFunc returns a completion function that provides vault names
|
||||
// getVaultNamesCompletionFunc returns a completion function that provides
|
||||
// vault names
|
||||
func getVaultNamesCompletionFunc(fs afero.Fs, stateDir string) func(
|
||||
cmd *cobra.Command, args []string, toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
return func(_ *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return func(
|
||||
_ *cobra.Command, _ []string, toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
vaults, err := vault.ListVaults(fs, stateDir)
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
var completions []string
|
||||
|
||||
for _, v := range vaults {
|
||||
if strings.HasPrefix(v, toComplete) {
|
||||
completions = append(completions, v)
|
||||
@@ -149,57 +110,81 @@ func getVaultNamesCompletionFunc(fs afero.Fs, stateDir string) func(
|
||||
}
|
||||
}
|
||||
|
||||
// getVaultSecretCompletionFunc returns a completion function for vault:secret format
|
||||
// It completes vault names with ":" suffix, and after ":" it completes secrets from that vault
|
||||
// completeVaultQualifiedSecrets completes "vault:secret" references once a
|
||||
// colon is present in the input
|
||||
func completeVaultQualifiedSecrets(
|
||||
fs afero.Fs, stateDir, toComplete string,
|
||||
) []string {
|
||||
var completions []string
|
||||
|
||||
// Complete secret names for the specified vault
|
||||
parts := strings.SplitN(toComplete, ":", vaultSecretParts)
|
||||
vaultName := parts[0]
|
||||
secretPrefix := parts[1]
|
||||
|
||||
vlt := vault.NewVault(fs, stateDir, vaultName)
|
||||
|
||||
secrets, err := vlt.ListSecrets()
|
||||
if err == nil {
|
||||
for _, secretName := range secrets {
|
||||
if strings.HasPrefix(secretName, secretPrefix) {
|
||||
completions = append(completions, vaultName+":"+secretName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
// completeUnqualifiedVaultSecrets completes vault names (with a ":"
|
||||
// suffix) and secrets from the current vault
|
||||
func completeUnqualifiedVaultSecrets(
|
||||
fs afero.Fs, stateDir, toComplete string,
|
||||
) []string {
|
||||
var completions []string
|
||||
|
||||
// Complete vault names with ":" suffix
|
||||
vaults, err := vault.ListVaults(fs, stateDir)
|
||||
if err == nil {
|
||||
for _, v := range vaults {
|
||||
if strings.HasPrefix(v, toComplete) {
|
||||
completions = append(completions, v+":")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also complete secrets from current vault (for within-vault moves)
|
||||
currentVlt, err := vault.GetCurrentVault(fs, stateDir)
|
||||
if err == nil {
|
||||
secrets, err := currentVlt.ListSecrets()
|
||||
if err == nil {
|
||||
for _, secretName := range secrets {
|
||||
if strings.HasPrefix(secretName, toComplete) {
|
||||
completions = append(completions, secretName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
// getVaultSecretCompletionFunc returns a completion function for the
|
||||
// vault:secret format. It completes vault names with ":" suffix, and
|
||||
// after ":" it completes secrets from that vault.
|
||||
func getVaultSecretCompletionFunc(fs afero.Fs, stateDir string) func(
|
||||
cmd *cobra.Command, args []string, toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
return func(_ *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
var completions []string
|
||||
|
||||
return func(
|
||||
_ *cobra.Command, _ []string, toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
// Check if we're completing after a vault: prefix
|
||||
if strings.Contains(toComplete, ":") {
|
||||
// Complete secret names for the specified vault
|
||||
const vaultSecretParts = 2
|
||||
parts := strings.SplitN(toComplete, ":", vaultSecretParts)
|
||||
vaultName := parts[0]
|
||||
secretPrefix := parts[1]
|
||||
|
||||
vlt := vault.NewVault(fs, stateDir, vaultName)
|
||||
secrets, err := vlt.ListSecrets()
|
||||
if err == nil {
|
||||
for _, secretName := range secrets {
|
||||
if strings.HasPrefix(secretName, secretPrefix) {
|
||||
completions = append(completions, vaultName+":"+secretName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return completions, cobra.ShellCompDirectiveNoFileComp
|
||||
return completeVaultQualifiedSecrets(fs, stateDir, toComplete),
|
||||
cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
// Complete vault names with ":" suffix
|
||||
vaults, err := vault.ListVaults(fs, stateDir)
|
||||
if err == nil {
|
||||
for _, v := range vaults {
|
||||
if strings.HasPrefix(v, toComplete) {
|
||||
completions = append(completions, v+":")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also complete secrets from current vault (for within-vault moves)
|
||||
if currentVlt, err := vault.GetCurrentVault(fs, stateDir); err == nil {
|
||||
secrets, err := currentVlt.ListSecrets()
|
||||
if err == nil {
|
||||
for _, secretName := range secrets {
|
||||
if strings.HasPrefix(secretName, toComplete) {
|
||||
completions = append(completions, secretName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return completions, cobra.ShellCompDirectiveNoSpace
|
||||
return completeUnqualifiedVaultSecrets(fs, stateDir, toComplete),
|
||||
cobra.ShellCompDirectiveNoSpace
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user