Compare commits

...

15 Commits

Author SHA1 Message Date
06678499d4 Add missing format arg. 2018-09-15 16:49:46 -07:00
fad17065fe Update README. 2018-09-15 15:26:42 -07:00
63e0cbeacb Update CHANGELOG for release. 2018-09-15 15:10:44 -07:00
231b98dd68 Add kgz, a gzip tool. 2018-09-15 15:08:37 -07:00
Kyle Isom
160a42ec26 travis: drop go 1.8 2018-04-24 10:47:35 -07:00
Kyle Isom
b6b33e00c8 cmd/showimp: support ignoring directories. 2018-04-24 09:44:45 -07:00
Kyle Isom
9e1aed257b rhash: use io.Copy to avoid reading the full file. 2018-04-24 09:44:45 -07:00
Kyle Isom
411907c0ad Merge pull request #5 from cbroglie/master
Make key and extended usages output stable
2017-11-22 16:24:57 -08:00
Christopher Broglie
06c7f8f42f Make key and extended usages output stable 2017-11-21 15:14:51 -08:00
Kyle Isom
8b638065d1 Fix ahash test Sprintf's. 2017-11-21 13:00:20 -08:00
Kyle Isom
9ac378eaa5 go lint → golint 2017-11-21 12:55:51 -08:00
Kyle Isom
eaaaabe439 go vet → golint 2017-11-21 12:52:26 -08:00
Kyle Isom
4122f01644 Fix travis errors. 2017-11-21 12:42:53 -08:00
Kyle Isom
263a5d3973 Add travis config. 2017-11-21 12:30:06 -08:00
Kyle Isom
afef3eea62 Fix Logger interface. 2017-11-21 12:19:38 -08:00
14 changed files with 273 additions and 24 deletions

17
.travis.yml Normal file
View File

@@ -0,0 +1,17 @@
sudo: false
language: go
go:
- tip
- 1.9
script:
- go get github.com/golang/lint/golint
- go get golang.org/x/tools/cmd/cover
- go get github.com/kisom/goutils/...
- go test -cover github.com/kisom/goutils/...
- golint github.com/kisom/goutils/...
notifications:
email:
recipients:
- coder@kyleisom.net
on_success: change
on_failure: change

View File

@@ -1,3 +1,11 @@
Release 1.2.1 - 2018-09-15
+ Add missing format argument to Errorf call in kgz.
Release 1.2.0 - 2018-09-15
+ Adds the kgz command line utility.
Release 1.1.0 - 2017-11-16 Release 1.1.0 - 2017-11-16
+ A number of new command line utilities were added + A number of new command line utilities were added

View File

@@ -3,6 +3,9 @@ GOUTILS
This is a collection of small utility code I've written in Go; the `cmd/` This is a collection of small utility code I've written in Go; the `cmd/`
directory has a number of command-line utilities. Rather than keep all directory has a number of command-line utilities. Rather than keep all
of these in superfluous repositories of their own, I'm putting them here. of these in superfluous repositories of their own, I'm putting them here.
Note that for packaging purposes, the goutils-pkg repo should be used: it
pins the library versions to working copies and vendors all depdencies. See
https://github.com/kisom/goutils-pkg for more details.
Contents: Contents:
@@ -25,6 +28,8 @@ Contents:
csrpubdump/ Dump the public key from an X.509 certificate request. csrpubdump/ Dump the public key from an X.509 certificate request.
fragment/ Print a fragment of a file. fragment/ Print a fragment of a file.
jlp/ JSON linter/prettifier. jlp/ JSON linter/prettifier.
kgz/ Custom gzip compressor / decompressor that handles 99%
of my use cases.
pem2bin/ Dump the binary body of a PEM-encoded block. pem2bin/ Dump the binary body of a PEM-encoded block.
pembody/ Print the body of a PEM certificate. pembody/ Print the body of a PEM certificate.
pemit/ Dump data to a PEM file. pemit/ Dump data to a PEM file.

View File

@@ -97,7 +97,7 @@ func TestHash32(t *testing.T) {
h.Write(data) h.Write(data)
sum, ok = h.Sum32() sum, ok = h.Sum32()
assert.BoolT(t, ok, algo+" should be able to return a Sum32") assert.BoolT(t, ok, algo+" should be able to return a Sum32")
assert.BoolT(t, expected != sum, fmt.Sprintf("%s returned %d but shouldn't have", algo, sum, expected)) assert.BoolT(t, expected != sum, fmt.Sprintf("%s returned %d but shouldn't have", algo, sum))
} }
func TestHash64(t *testing.T) { func TestHash64(t *testing.T) {
@@ -129,7 +129,7 @@ func TestHash64(t *testing.T) {
h.Write(data) h.Write(data)
sum, ok = h.Sum64() sum, ok = h.Sum64()
assert.BoolT(t, ok, algo+" should be able to return a Sum64") assert.BoolT(t, ok, algo+" should be able to return a Sum64")
assert.BoolT(t, expected != sum, fmt.Sprintf("%s returned %d but shouldn't have", algo, sum, expected)) assert.BoolT(t, expected != sum, fmt.Sprintf("%s returned %d but shouldn't have", algo, sum))
} }
func TestListLengthSanity(t *testing.T) { func TestListLengthSanity(t *testing.T) {

View File

@@ -14,6 +14,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"sort"
"strings" "strings"
"github.com/cloudflare/cfssl/helpers" "github.com/cloudflare/cfssl/helpers"
@@ -83,6 +84,7 @@ func keyUsages(ku x509.KeyUsage) string {
uses = append(uses, s) uses = append(uses, s)
} }
} }
sort.Strings(uses)
return strings.Join(uses, ", ") return strings.Join(uses, ", ")
} }
@@ -92,6 +94,7 @@ func extUsage(ext []x509.ExtKeyUsage) string {
for i := range ext { for i := range ext {
ns = append(ns, extKeyUsages[ext[i]]) ns = append(ns, extKeyUsages[ext[i]])
} }
sort.Strings(ns)
return strings.Join(ns, ", ") return strings.Join(ns, ", ")
} }

23
cmd/kgz/README Normal file
View File

@@ -0,0 +1,23 @@
kgz
kgz is like gzip, but supports compressing and decompressing to a different
directory than the source file is in.
Usage: kgz [-l] source [target]
If target is a directory, the basename of the sourcefile will be used
as the target filename. Compression and decompression is selected
based on whether the source filename ends in ".gz".
Flags:
-l level Compression level (0-9). Only meaninful when
compressing a file.

182
cmd/kgz/main.go Normal file
View File

@@ -0,0 +1,182 @@
package main
import (
"compress/flate"
"compress/gzip"
"flag"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
)
const gzipExt = ".gz"
func compress(path, target string, level int) error {
sourceFile, err := os.Open(path)
if err != nil {
return errors.Wrap(err, "opening file for read")
}
defer sourceFile.Close()
destFile, err := os.Create(target)
if err != nil {
return errors.Wrap(err, "opening file for write")
}
defer destFile.Close()
gzipCompressor, err := gzip.NewWriterLevel(destFile, level)
if err != nil {
return errors.Wrap(err, "invalid compression level")
}
defer gzipCompressor.Close()
_, err = io.Copy(gzipCompressor, sourceFile)
if err != nil {
return errors.Wrap(err, "compressing file")
}
if err != nil {
return errors.Wrap(err, "stat(2)ing destination file")
}
return nil
}
func uncompress(path, target string) error {
sourceFile, err := os.Open(path)
if err != nil {
return errors.Wrap(err, "opening file for read")
}
defer sourceFile.Close()
gzipUncompressor, err := gzip.NewReader(sourceFile)
if err != nil {
return errors.Wrap(err, "reading gzip headers")
}
defer gzipUncompressor.Close()
destFile, err := os.Create(target)
if err != nil {
return errors.Wrap(err, "opening file for write")
}
defer destFile.Close()
_, err = io.Copy(destFile, gzipUncompressor)
if err != nil {
return errors.Wrap(err, "uncompressing file")
}
return nil
}
func usage(w io.Writer) {
fmt.Fprintf(w, `Usage: %s [-l] source [target]
kgz is like gzip, but supports compressing and decompressing to a different
directory than the source file is in.
Flags:
-l level Compression level (0-9). Only meaninful when
compressing a file.
`, os.Args[0])
}
func init() {
flag.Usage = func() { usage(os.Stderr) }
}
func isDir(path string) bool {
file, err := os.Open(path)
if err == nil {
defer file.Close()
stat, err := file.Stat()
if err != nil {
return false
}
if stat.IsDir() {
return true
}
}
return false
}
func pathForUncompressing(source, dest string) (string, error) {
if !isDir(dest) {
return dest, nil
}
source = filepath.Base(source)
if !strings.HasSuffix(source, gzipExt) {
return "", errors.Errorf("%s is a not gzip-compressed file", source)
}
outFile := source[:len(source)-len(gzipExt)]
outFile = filepath.Join(dest, outFile)
return outFile, nil
}
func pathForCompressing(source, dest string) (string, error) {
if !isDir(dest) {
return dest, nil
}
source = filepath.Base(source)
if strings.HasSuffix(source, gzipExt) {
return "", errors.Errorf("%s is a gzip-compressed file", source)
}
dest = filepath.Join(dest, source+gzipExt)
return dest, nil
}
func main() {
var level int
var path string
var target = "."
flag.IntVar(&level, "l", flate.DefaultCompression, "compression level")
flag.Parse()
if flag.NArg() < 1 || flag.NArg() > 2 {
usage(os.Stderr)
os.Exit(1)
}
path = flag.Arg(0)
if flag.NArg() == 2 {
target = flag.Arg(1)
}
if strings.HasSuffix(path, gzipExt) {
target, err := pathForUncompressing(path, target)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
err = uncompress(path, target)
if err != nil {
os.Remove(target)
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
} else {
target, err := pathForCompressing(path, target)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
err = compress(path, target, level)
if err != nil {
os.Remove(target)
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
}
}

View File

@@ -46,7 +46,6 @@ func newName(path string) (string, error) {
func move(dst, src string, force bool) (err error) { func move(dst, src string, force bool) (err error) {
if fileutil.FileDoesExist(dst) && !force { if fileutil.FileDoesExist(dst) && !force {
return fmt.Errorf("%s exists (pass the -f flag to overwrite)", dst) return fmt.Errorf("%s exists (pass the -f flag to overwrite)", dst)
return nil
} }
dstFile, err := os.Create(dst) dstFile, err := os.Create(dst)
if err != nil { if err != nil {

View File

@@ -4,7 +4,6 @@ import (
"flag" "flag"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@@ -15,20 +14,6 @@ import (
"github.com/kisom/goutils/lib" "github.com/kisom/goutils/lib"
) )
func fetch(remote string) ([]byte, error) {
resp, err := http.Get(remote)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
func usage(w io.Writer) { func usage(w io.Writer) {
fmt.Fprintf(w, `Usage: %s [-a algo] [-h] [-l set] urls... fmt.Fprintf(w, `Usage: %s [-a algo] [-h] [-l set] urls...
Compute the hash over each URL. Compute the hash over each URL.
@@ -91,13 +76,19 @@ func main() {
continue continue
} }
body, err := fetch(remote) resp, err := http.Get(remote)
if err != nil { if err != nil {
lib.Warn(err, "fetching %s", remote) lib.Warn(err, "fetching %s", remote)
continue continue
} }
sum, err := ahash.Sum(algo, body) if err != nil {
lib.Warn(err, "fetching %s", remote)
continue
}
sum, err := ahash.SumReader(algo, resp.Body)
resp.Body.Close()
if err != nil { if err != nil {
lib.Err(lib.ExitFailure, err, "while hashing data") lib.Err(lib.ExitFailure, err, "while hashing data")
} }

View File

@@ -67,6 +67,10 @@ func init() {
} }
func walkFile(path string, info os.FileInfo, err error) error { func walkFile(path string, info os.FileInfo, err error) error {
if ignores[path] {
return filepath.SkipDir
}
if !sourceRegexp.MatchString(path) { if !sourceRegexp.MatchString(path) {
return nil return nil
} }
@@ -97,10 +101,24 @@ func walkFile(path string, info os.FileInfo, err error) error {
return nil return nil
} }
var ignores = map[string]bool{}
func main() { func main() {
var ignoreLine string
var noVendor bool
flag.StringVar(&ignoreLine, "i", "", "comma-separated list of directories to ignore")
flag.BoolVar(&noVendor, "nv", false, "ignore the vendor directory")
flag.BoolVar(&debug, "v", false, "log debugging information") flag.BoolVar(&debug, "v", false, "log debugging information")
flag.Parse() flag.Parse()
if noVendor {
ignores["vendor"] = true
}
for _, word := range strings.Split(ignoreLine, ",") {
ignores[strings.TrimSpace(word)] = true
}
err := filepath.Walk(".", walkFile) err := filepath.Walk(".", walkFile)
die.If(err) die.If(err)

View File

@@ -72,7 +72,7 @@ Flags:
func usageExamples() { func usageExamples() {
usage(os.Stdout) usage(os.Stdout)
fmt.Println(` fmt.Printf(`
Examples (note that the examples are done in the America/Los_Angeles / Examples (note that the examples are done in the America/Los_Angeles /
PST8PDT time zone): PST8PDT time zone):
@@ -134,6 +134,7 @@ PST8PDT time zone):
(Converting from GMT (offset +0000) to UTC (offset +0000).) (Converting from GMT (offset +0000) to UTC (offset +0000).)
================================================================== ==================================================================
2016-06-14 23:46 = 2016-06-14 23:46 2016-06-14 23:46 = 2016-06-14 23:46
`) `)
} }

View File

@@ -20,6 +20,8 @@ func (fl *File) Close() error {
if fl.fe != nil { if fl.fe != nil {
return fl.fe.Close() return fl.fe.Close()
} }
return nil
} }
// NewFile creates a new Logger that writes all logs to the file // NewFile creates a new Logger that writes all logs to the file

View File

@@ -21,7 +21,7 @@ type Logger interface {
Status() error Status() error
// Close gives the Logger the opportunity to perform any cleanup. // Close gives the Logger the opportunity to perform any cleanup.
Close() Close() error
// Log messages consist of four components: // Log messages consist of four components:
// //
@@ -276,4 +276,4 @@ func (lw *LogWriter) SetLevel(l Level) {
} }
// Close is a no-op that satisfies the Logger interface. // Close is a no-op that satisfies the Logger interface.
func (lw *LogWriter) Close() {} func (lw *LogWriter) Close() error { return nil }

View File

@@ -168,7 +168,7 @@ func TestRWByte(t *testing.T) {
} }
if c != 42 { if c != 42 {
t.Fatal("Expected 42, have %d", c) t.Fatalf("Expected 42, have %d", c)
} }
_, err = buf.ReadByte() _, err = buf.ReadByte()