Files
secret/internal/cli/info_helper.go
sneak 9ee216f629
All checks were successful
check / check (push) Successful in 1m8s
Update golangci-lint to v2.12.2 with canonical config
- 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
2026-08-07 17:27:23 +00:00

123 lines
2.9 KiB
Go

package cli
import (
"path/filepath"
"time"
"git.eeqj.de/sneak/secret/internal/secret"
"github.com/spf13/afero"
)
// vaultStats accumulates statistics while walking vault directories
type vaultStats struct {
totalSecrets int
totalSize int64
oldestTime time.Time
latestTime time.Time
}
// addVersion accumulates size and timestamp info for one version directory
func (s *vaultStats) addVersion(fs afero.Fs, versionPath string) {
// Add size of encrypted data
dataPath := filepath.Join(versionPath, "data.age")
stat, err := fs.Stat(dataPath)
if err == nil {
s.totalSize += stat.Size()
}
// Add size of metadata
metaPath := filepath.Join(versionPath, "metadata.age")
stat, err = fs.Stat(metaPath)
if err == nil {
s.totalSize += stat.Size()
}
// Track timestamps
stat, err = fs.Stat(versionPath)
if err == nil {
modTime := stat.ModTime()
if s.oldestTime.IsZero() || modTime.Before(s.oldestTime) {
s.oldestTime = modTime
}
if s.latestTime.IsZero() || modTime.After(s.latestTime) {
s.latestTime = modTime
}
}
}
// addSecret accumulates stats for one secret directory
func (s *vaultStats) addSecret(fs afero.Fs, secretsPath, secretName string) {
s.totalSecrets++
secretPath := filepath.Join(secretsPath, secretName)
// Get size and timestamps from all versions
versionsPath := filepath.Join(secretPath, "versions")
versionEntries, err := afero.ReadDir(fs, versionsPath)
if err != nil {
secret.Warn("Could not read versions directory for secret",
"secret", secretName, "error", err)
return
}
for _, versionEntry := range versionEntries {
if !versionEntry.IsDir() {
continue
}
s.addVersion(fs, filepath.Join(versionsPath, versionEntry.Name()))
}
}
// addVault accumulates stats for one vault directory
func (s *vaultStats) addVault(fs afero.Fs, vaultsDir, vaultName string) {
vaultPath := filepath.Join(vaultsDir, vaultName)
secretsPath := filepath.Join(vaultPath, "secrets.d")
// Count secrets in this vault
secretEntries, err := afero.ReadDir(fs, secretsPath)
if err != nil {
secret.Warn("Could not read secrets directory for vault",
"vault", vaultName, "error", err)
return
}
for _, secretEntry := range secretEntries {
if !secretEntry.IsDir() {
continue
}
s.addSecret(fs, secretsPath, secretEntry.Name())
}
}
// gatherVaultStats collects statistics from all vaults, returning the
// total secret count, total size, and oldest/latest secret timestamps
func gatherVaultStats(
fs afero.Fs,
vaultsDir string,
) (int, int64, time.Time, time.Time, error) {
vaultEntries, err := afero.ReadDir(fs, vaultsDir)
if err != nil {
return 0, 0, time.Time{}, time.Time{}, err
}
var stats vaultStats
for _, vaultEntry := range vaultEntries {
if !vaultEntry.IsDir() {
continue
}
stats.addVault(fs, vaultsDir, vaultEntry.Name())
}
return stats.totalSecrets, stats.totalSize,
stats.oldestTime, stats.latestTime, nil
}