/* goredo -- djb's redo implementation on pure Go Copyright (C) 2020-2023 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package main import ( "flag" "fmt" "io" "log" "os" "path" "path/filepath" "strings" ) const ( CleanupFull = "full" CleanupLog = "log" CleanupTmp = "tmp" CleanupLock = "lock" ) var DryRun *bool func init() { if CmdName() != CmdNameRedoCleanup { return } DryRun = flag.Bool("n", false, "do no delete files during cleanup, just show them") } func redoDirClean(root, what string) error { root, err := filepath.Abs(root) if err != nil { panic(err) } dir, err := os.Open(root) if err != nil { return err } defer dir.Close() for { fis, err := dir.Readdir(1 << 10) if err != nil { if err == io.EOF { break } return err } var pth string for _, fi := range fis { pth = cwdMustRel(root, fi.Name()) switch what { case CleanupLog: if strings.HasSuffix(fi.Name(), LogSuffix) || strings.HasSuffix(fi.Name(), LogRecSuffix) { fmt.Println(pth) if !*DryRun { if err = os.Remove(pth); err != nil { return err } } } case CleanupLock: if strings.HasSuffix(fi.Name(), LockSuffix) { fmt.Println(pth) if !*DryRun { if err = os.Remove(pth); err != nil { return err } } } case CleanupTmp: if strings.HasPrefix(fi.Name(), TmpPrefix) { fmt.Println(pth) if !*DryRun { if err = os.Remove(pth); err != nil { return err } } } default: log.Fatalln("unknown cleanup target") } } } return nil } func cleanupWalker(root, what string) error { root, err := filepath.Abs(root) if err != nil { panic(err) } dir, err := os.Open(root) if err != nil { return err } defer dir.Close() for { fis, err := dir.Readdir(1 << 10) if err != nil { if err == io.EOF { break } return err } for _, fi := range fis { pth := path.Join(root, fi.Name()) pthRel := cwdMustRel(root, fi.Name()) if fi.IsDir() { if fi.Name() == RedoDir { if what == CleanupFull { fmt.Println(pthRel) if !*DryRun { err = os.RemoveAll(pth) } } else { err = redoDirClean(pth, what) } } else if (what == CleanupTmp || what == CleanupFull) && strings.HasPrefix(fi.Name(), TmpPrefix) { fmt.Println(pthRel) if !*DryRun { err = os.RemoveAll(pth) } } else { err = cleanupWalker(pth, what) } if err != nil { return err } continue } if (what == CleanupTmp || what == CleanupFull) && strings.HasPrefix(fi.Name(), TmpPrefix) { fmt.Println(pthRel) if !*DryRun { if err = os.Remove(pth); err != nil { return err } } } } } return nil }