implement WritterError + add arg to remove files after zip

This commit is contained in:
rmanach 2022-04-12 18:50:05 +02:00
parent ca0b717a02
commit ad4c4220f5
2 changed files with 80 additions and 21 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
packer packer
# zip file # zip file
*.zip *.zip
# test folder
test

97
main.go
View File

@ -1,9 +1,11 @@
// packer - a simple CLI tool to find and zip file corresponding to a given regex // 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 // find + zip linux CLI works too
package main package main
import ( import (
"archive/zip" "archive/zip"
"errors"
"fmt" "fmt"
"github.com/akamensky/argparse" "github.com/akamensky/argparse"
"io" "io"
@ -13,25 +15,45 @@ import (
re "regexp" 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` // parseArguments - get needed arguments to launch the `packer`
// returns 3 strings : // returns 3 strings :
// * regex // * regex
// * outputPath // * outputPath - full path of the zip archive
// * directory // * directory - which directory to check
func parseArguments() (string, string, string, error) { // * 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") parser := argparse.NewParser("packer", "packer - zip file where filenames match with a regex")
var err error var err error
regex := parser.String("r", "regex", &argparse.Options{Required: true, Help: "filename Regex"}) 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)"}) 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: "."}) 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) parseError := parser.Parse(os.Args)
if parseError != nil { if parseError != nil {
err = fmt.Errorf("parsing error: %s", parseError) 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 // 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) b := make([]byte, chunkSize)
for { for {
_, err := f.Read(b) _, err = f.Read(b)
if err != nil { if err != nil {
if err != io.EOF { if err != io.EOF {
continue continue
@ -87,12 +109,12 @@ func writeFileContent(f *os.File, zf io.Writer) (err error) {
// generateZip - create a zip archive // generateZip - create a zip archive
// * outputPath: zip archive full path // * outputPath: zip archive full path
// * filePaths: files path // * filePaths: files path
func generateZip(outputPath string, filepaths []string) (err error) { func generateZip(outputPath string, filepaths []string) error {
// create a zipfile from `outputPath` // create a zipfile from `outputPath`
zipPath, err := os.Create(outputPath) zipPath, createErr := os.Create(outputPath)
if err != nil { if createErr != nil {
return err return createErr
} }
defer zipPath.Close() defer zipPath.Close()
@ -101,37 +123,56 @@ func generateZip(outputPath string, filepaths []string) (err error) {
for _, filepath := range filepaths { for _, filepath := range filepaths {
// open matching regex file // open matching regex file
f, err := os.Open(filepath) f, openErr := os.Open(filepath)
if err != nil { if openErr != nil {
log.Println("[ERROR] :", err) log.Println("[ERROR] :", openErr)
continue continue
} }
// create a zipped file // create a zipped file
zf, err := w.Create(filepath) zf, zipErr := w.Create(filepath)
if err != nil { if zipErr != nil {
log.Println("[ERROR] :", err) log.Println("[ERROR] :", zipErr)
f.Close() f.Close()
continue continue
} }
// write file content into zipped file // 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 // clean up opened file
f.Close() f.Close()
} }
// make sure to check the error on 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() { func main() {
// parse arguments // parse arguments
regex, directory, outputPath, err := parseArguments() regex, directory, outputPath, remove, err := parseArguments()
if err != nil { if err != nil {
log.Fatal("error while parsing args : ", err) log.Fatal("error while parsing args : ", err)
} }
@ -151,7 +192,23 @@ func main() {
// generating zip archive // generating zip archive
log.Printf("files found : %d", len(files)) 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) log.Printf("zip archive generated in %s", outputPath)
} }