Files
directory-deletor/main.go
PhatPhuckDave 51903397f0 feat: add .gitignore, upgrade to Go 1.23 with deps, improve logging,
config loading, and glob-based deletion, and push image in deploy script
2025-08-07 11:18:08 +02:00

135 lines
3.0 KiB
Go

package main
import (
"flag"
"os"
"path/filepath"
"strings"
"time"
logger "git.site.quack-lab.dev/dave/cylogger"
"github.com/bmatcuk/doublestar/v4"
)
type Config struct {
WorkDir string
ScanSeconds int
Patterns []string
}
func getenv(key, def string) string {
if v, ok := os.LookupEnv(key); ok {
return v
}
return def
}
func loadConfig() Config {
flagWDir := flag.String("wd", "", "working directory")
flagScan := flag.Int("scan", 60, "scan interval in seconds")
logger.InitFlag()
flag.Parse()
workdir := filepath.Clean(*flagWDir)
if pfx := strings.TrimSpace(getenv("PATH_PREFIX", "")); pfx != "" {
workdir = filepath.Join(workdir, pfx)
}
workdir = filepath.ToSlash(workdir)
// Gather patterns: args + FORBIDDEN env (comma-separated)
patterns := []string{}
patterns = append(patterns, flag.Args()...)
if env := strings.TrimSpace(getenv("FORBIDDEN", "")); env != "" {
for _, p := range strings.Split(env, ",") {
p = strings.TrimSpace(p)
if p != "" {
patterns = append(patterns, p)
}
}
}
// Normalize patterns to slash style; patterns are relative to workdir
for i := range patterns {
patterns[i] = filepath.ToSlash(strings.TrimSpace(patterns[i]))
}
logger.Info("Config:")
logger.Info(" WorkDir: %s", workdir)
logger.Info(" ScanSeconds: %d", *flagScan)
logger.Info(" Patterns: %v", patterns)
return Config{
WorkDir: workdir,
ScanSeconds: *flagScan,
Patterns: patterns,
}
}
func deleteMatches(cfg Config) {
log := logger.Default.WithPrefix("deleteMatches")
// Ensure workdir exists
if cfg.WorkDir == "" {
log.Error("WorkDir is empty")
return
}
if _, err := os.Stat(cfg.WorkDir); err != nil {
log.Error("WorkDir not accessible %s: %v", cfg.WorkDir, err)
return
}
for _, pat := range cfg.Patterns {
if pat == "" {
continue
}
// Use doublestar.Glob against the workdir FS; it returns relative paths
matches, err := doublestar.Glob(os.DirFS(cfg.WorkDir), pat)
if err != nil {
log.Error("glob %q: %v", pat, err)
continue
}
if len(matches) == 0 {
log.Debug("No matches for pattern %q", pat)
continue
}
for _, rel := range matches {
full := filepath.Join(cfg.WorkDir, rel)
full = filepath.Clean(full)
info, err := os.Stat(full)
if err != nil {
log.Warning("stat %s: %v", full, err)
continue
}
if info.IsDir() {
log.Info("Removing directory %s", full)
} else {
log.Info("Removing file %s", full)
}
if err := os.RemoveAll(full); err != nil {
log.Error("remove %s: %v", full, err)
continue
}
}
}
}
func main() {
cfg := loadConfig()
logger.Info("Starting forbidden cleaner")
// Run immediately, then on interval
deleteMatches(cfg)
ticker := time.NewTicker(time.Duration(cfg.ScanSeconds) * time.Second)
defer ticker.Stop()
for {
ts := <-ticker.C
logger.Info("Tick %d", ts.UnixMilli())
deleteMatches(cfg)
}
}