From ad4c4220f558329d1af864a52d11ff4b9a21aec1 Mon Sep 17 00:00:00 2001 From: rmanach Date: Tue, 12 Apr 2022 18:50:05 +0200 Subject: [PATCH] implement WritterError + add arg to remove files after zip --- .gitignore | 4 ++- main.go | 97 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 80 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 86432cf..3d58038 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ # binary file packer # zip file -*.zip \ No newline at end of file +*.zip +# test folder +test \ No newline at end of file diff --git a/main.go b/main.go index 40838e3..5fe7deb 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,11 @@ // packer - a simple CLI tool to find and zip file corresponding to a given regex +// the archive keeps the folder structure // find + zip linux CLI works too package main import ( "archive/zip" + "errors" "fmt" "github.com/akamensky/argparse" "io" @@ -13,25 +15,45 @@ import ( re "regexp" ) +// WritterError +// Useless, just to play with `errors.As()` to check specific error +type WritterError struct { + message error +} + +type ErrorCode interface { + Code() int +} + +func (we WritterError) Error() string { + return fmt.Sprintf("error occured while creating archive : %s", we.message) +} + +func (we WritterError) Code() int { + return 500 +} + // parseArguments - get needed arguments to launch the `packer` // returns 3 strings : // * regex -// * outputPath -// * directory -func parseArguments() (string, string, string, error) { +// * outputPath - full path of the zip archive +// * directory - which directory to check +// * remove - delete all file after creating zip archive +func parseArguments() (string, string, string, bool, error) { parser := argparse.NewParser("packer", "packer - zip file where filenames match with a regex") var err error regex := parser.String("r", "regex", &argparse.Options{Required: true, Help: "filename Regex"}) outputPath := parser.String("o", "output-path", &argparse.Options{Required: true, Help: "zip output path (including zip name)"}) directory := parser.String("d", "directory", &argparse.Options{Required: false, Help: "root directory to check files", Default: "."}) + remove := parser.Flag("x", "remove", &argparse.Options{Required: false, Help: "remove files after archive creation", Default: false}) parseError := parser.Parse(os.Args) if parseError != nil { err = fmt.Errorf("parsing error: %s", parseError) } - return *regex, *directory, *outputPath, err + return *regex, *directory, *outputPath, *remove, err } // buildRegex - build POSIX regex from a string @@ -71,7 +93,7 @@ func writeFileContent(f *os.File, zf io.Writer) (err error) { b := make([]byte, chunkSize) for { - _, err := f.Read(b) + _, err = f.Read(b) if err != nil { if err != io.EOF { continue @@ -87,12 +109,12 @@ func writeFileContent(f *os.File, zf io.Writer) (err error) { // generateZip - create a zip archive // * outputPath: zip archive full path // * filePaths: files path -func generateZip(outputPath string, filepaths []string) (err error) { +func generateZip(outputPath string, filepaths []string) error { // create a zipfile from `outputPath` - zipPath, err := os.Create(outputPath) - if err != nil { - return err + zipPath, createErr := os.Create(outputPath) + if createErr != nil { + return createErr } defer zipPath.Close() @@ -101,37 +123,56 @@ func generateZip(outputPath string, filepaths []string) (err error) { for _, filepath := range filepaths { // open matching regex file - f, err := os.Open(filepath) - if err != nil { - log.Println("[ERROR] :", err) + f, openErr := os.Open(filepath) + if openErr != nil { + log.Println("[ERROR] :", openErr) continue } // create a zipped file - zf, err := w.Create(filepath) - if err != nil { - log.Println("[ERROR] :", err) + zf, zipErr := w.Create(filepath) + if zipErr != nil { + log.Println("[ERROR] :", zipErr) f.Close() continue } // write file content into zipped file - err = writeFileContent(f, zf) + writeErr := writeFileContent(f, zf) + // catch sentinel error `io.EOF` + if writeErr != nil && writeErr != io.EOF { + log.Println("[ERROR] :", writeErr) + f.Close() + continue + } // clean up opened file f.Close() } // make sure to check the error on Close. - err = w.Close() + closeErr := w.Close() + if closeErr != nil { + return WritterError{message: fmt.Errorf("error occured while closing the zip archive : %w", closeErr)} + } - return err + return nil +} + +// removeFiles - can't be more obvious... +func removeFiles(filepaths []string) { + for _, filepath := range filepaths { + err := os.Remove(filepath) + if err != nil { + log.Println("[ERROR] :", err) + } + } } func main() { // parse arguments - regex, directory, outputPath, err := parseArguments() + regex, directory, outputPath, remove, err := parseArguments() if err != nil { log.Fatal("error while parsing args : ", err) } @@ -151,7 +192,23 @@ func main() { // generating zip archive log.Printf("files found : %d", len(files)) - generateZip(outputPath, files) + err = generateZip(outputPath, files) + + // check if errors occured during zip + var errorCode interface { + Code() int + } + if err != nil { + if errors.As(err, &errorCode) { + log.Fatal("zip archive writing error : ", err) + } + log.Fatal(err) + } + + if remove { + log.Printf("clean up archive files...") + removeFiles(files) + } log.Printf("zip archive generated in %s", outputPath) }