143 lines
2.7 KiB
Go
143 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"compress/gzip"
|
|
"fmt"
|
|
"io"
|
|
"math/rand"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/urfave/cli"
|
|
)
|
|
|
|
func main() {
|
|
app := cli.NewApp()
|
|
app.Name = "gogzip"
|
|
app.Description = "golang `compress/gzip` cli, in likeness to GNU gzip"
|
|
app.Version = "0.1"
|
|
app.Flags = []cli.Flag{
|
|
cli.BoolFlag{
|
|
Name: "a,ascii",
|
|
Usage: "(noop here for compatibility)",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "c,stdout,to-stdout",
|
|
Usage: "write output to stdout",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "d",
|
|
Usage: "decompress",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "f,force",
|
|
Usage: "force",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "k,keep",
|
|
Usage: "keep original file when compressing",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "l,list",
|
|
Usage: "for each compressed file, list the size tables",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "L,license",
|
|
Usage: "license",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "N,name",
|
|
Usage: "license",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "q,quiet",
|
|
Usage: "suppress warnings",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "r,recursive",
|
|
Usage: "if any of the file arguments are directories, recurse them",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "S,suffix",
|
|
Value: ".gz",
|
|
Usage: "when compressing use suffix value instead of default",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "synchronous",
|
|
Usage: "sync",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "#,best,fast",
|
|
Usage: "compression level",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "rsyncable",
|
|
Usage: "rsyncable",
|
|
},
|
|
cli.VersionFlag,
|
|
}
|
|
app.Action = defaultAction
|
|
app.Run(os.Args)
|
|
}
|
|
|
|
func defaultAction(c *cli.Context) error {
|
|
// TODO check whether stdin or its a pty terminal, if no args
|
|
|
|
if c.Bool("decompress") {
|
|
if c.NArg() == 0 {
|
|
grdr, err := gzip.NewReader(os.Stdin)
|
|
if err != nil {
|
|
return cli.NewExitError(err, 2)
|
|
}
|
|
defer grdr.Close()
|
|
if _, err = io.Copy(os.Stdout, grdr); err != nil {
|
|
return cli.NewExitError(err, 2)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
for _, arg := range c.Args() {
|
|
err := func() error {
|
|
fh, err := os.OpenFile(arg, os.O_RDONLY, 0600)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer fh.Close()
|
|
|
|
fi, err := fh.Stat()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newName := gzBasename(c, arg)
|
|
newFh, err := os.OpenFile(newName, os.O_CREATE|os.O_WRONLY, fi.Mode())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer newFh.Close()
|
|
|
|
if _, err := io.Copy(newFh, fh); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}()
|
|
if err != nil {
|
|
return cli.NewExitError(err, 2)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func gzBasename(c *cli.Context, s string) string {
|
|
if filepath.Ext(s) == c.String("suffix") {
|
|
return filepath.Base(s)
|
|
}
|
|
return fmt.Sprint("%s.%d", s, rand.New(rand.NewSource(time.Now().UnixNano())).Intn(100))
|
|
}
|