Compare commits

...

18 Commits

Author SHA1 Message Date
74ce7bc58a Cleaning up the codebase. 2023-05-04 23:22:35 -07:00
8b2d10209e Clean up the README. 2023-05-04 22:58:21 -07:00
770100b688 fileutil: start working on symlink checking 2023-05-04 22:52:16 -07:00
29630c55a9 packaging is a dead end thus far
I think I'm going to have to write my own rules to do this.
2023-05-04 21:03:08 -07:00
3c2ec896f8 cmd/cruntar: avoid writing files outside archive 2023-05-04 17:20:22 -07:00
7828726ba4 Updating x/sys. 2023-05-04 17:13:06 -07:00
458f3ceaed update dependencies to fix dependabot warnings. 2023-05-04 17:10:41 -07:00
2c45ae7b4e syslog: add new logging package. 2023-05-04 16:20:39 -07:00
c1b8b72cf1 bazel-test: add sizes to all tests.
This gets rid of the warning about mismatched test sizes.
2023-05-04 16:08:18 -07:00
bfc7fedbf9 seekbuf: add test file 2023-05-04 16:08:11 -07:00
965312f48e update README/LICENSE
LICENSE: update years.

README: add missing pieces.
2023-05-04 16:07:34 -07:00
237aa46ddd cmd/diskimg: new disk imaging tool 2023-05-04 16:06:56 -07:00
f8c64d3be5 bazel: updating build files 2023-05-04 15:11:15 -07:00
d66cfe1145 Cut over to Bazel. 2023-05-04 14:00:30 -07:00
ad03c5f991 Mass rewrite imports -> git.wntrmute.dev repo. 2023-05-04 13:58:43 -07:00
Kyle Isom
0dd4e1c6ca Update README.md
Depart for other waters.
2023-05-04 13:46:40 -07:00
078230217d ahash: add SumLimitedReader 2023-05-04 13:41:33 -07:00
90318f861b Add EEPROM image generator. 2022-06-24 14:36:51 -07:00
98 changed files with 2052 additions and 160 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
bazel-bin
bazel-goutils
bazel-out
bazel-testlogs

22
BUILD.bazel Normal file
View File

@@ -0,0 +1,22 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@bazel_gazelle//:def.bzl", "gazelle")
# gazelle:prefix git.wntrmute.dev/kyle/goutils
gazelle(name = "gazelle")
go_library(
name = "goutils",
srcs = ["doc.go"],
importpath = "git.wntrmute.dev/kyle/goutils",
visibility = ["//visibility:public"],
)
gazelle(
name = "gazelle-update-repos",
args = [
"-from_file=go.mod",
"-to_macro=deps.bzl%go_dependencies",
"-prune",
],
command = "update-repos",
)

View File

@@ -1,4 +1,4 @@
Copyright (c) 2015 Kyle Isom <kyle@tyrfingr.is>
Copyright (c) 2015-2023 Kyle Isom <kyle@tyrfingr.is>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View File

@@ -2,7 +2,11 @@ GOUTILS
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
of these in superfluous repositories of their own, I'm putting them here.
of these in superfluous repositories of their own, or rewriting them
for each project, I'm putting them here.
The project can be built with the standard Go tooling, or it can be built
with Bazel.
Contents:
@@ -23,33 +27,46 @@ Contents:
cruntar/ Untar an archive with hard links, copying instead of
linking.
csrpubdump/ Dump the public key from an X.509 certificate request.
diskimg/ Write a disk image to a device.
eig/ EEPROM image generator.
fragment/ Print a fragment of a file.
jlp/ JSON linter/prettifier.
kgz/ Custom gzip compressor / decompressor that handles 99%
of my use cases.
parts/ Simple parts database management for my collection of
electronic components.
pem2bin/ Dump the binary body of a PEM-encoded block.
pembody/ Print the body of a PEM certificate.
pemit/ Dump data to a PEM file.
showimp/ List the external (e.g. non-stdlib and outside the
current working directory) imports for a Go file.
readchain/ Print the common name for the certificates
in a bundle.
renfnv/ Rename a file to base32-encoded 64-bit FNV-1a hash.
rhash/ Compute the digest of remote files.
showimp Display the external imports in a package.
showimp/ List the external (e.g. non-stdlib and outside the
current working directory) imports for a Go file.
ski Display the SKI for PEM-encoded TLS material.
sprox/ Simple TCP proxy.
stealchain/ Dump the verified chain from a TLS
connection.
connection to a server.
stealchain- Dump the verified chain from a TLS
server/ connection from a client.
subjhash/ Print or match subject info from a certificate.
tlskeypair/ Check whether a TLS certificate and key file match.
utc/ Convert times to UTC.
yamll/ A small YAML linter.
config/ A simple global configuration system where configuration
data is pulled from a file or an environment variable
transparently.
dbg/ A debug printer.
die/ Death of a program.
fileutil/ Common file functions.
lib/ Commonly-useful functions for writing Go programs.
logging/ A logging library.
mwc/ MultiwriteCloser implementation.
rand/ Utilities for working with math/rand.
sbuf/ A byte buffer that can be wiped.
seekbuf/ A read-seekable byte buffer.
syslog/ Syslog-type logging.
tee/ Emulate tee(1)'s functionality in io.Writers.
testio/ Various I/O utilities useful during testing.
testutil/ Various utility functions useful during testing.
@@ -58,4 +75,4 @@ Contents:
Each program should have a small README in the directory with more
information.
All code here is licensed under the MIT license.
All code here is licensed under the ISC license.

32
WORKSPACE Normal file
View File

@@ -0,0 +1,32 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
### Go tooling, including Gazelle to generate and maintain BUILD files.
http_archive(
name = "io_bazel_rules_go",
sha256 = "6b65cb7917b4d1709f9410ffe00ecf3e160edf674b78c54a894471320862184f",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.39.0/rules_go-v0.39.0.zip",
"https://github.com/bazelbuild/rules_go/releases/download/v0.39.0/rules_go-v0.39.0.zip",
],
)
http_archive(
name = "bazel_gazelle",
sha256 = "ecba0f04f96b4960a5b250c8e8eeec42281035970aa8852dda73098274d14a1d",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz",
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz",
],
)
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
load("//:deps.bzl", "go_dependencies")
# gazelle:repository_macro deps.bzl%go_dependencies
go_dependencies()
go_rules_dependencies()
go_register_toolchains(version = "1.20.4")
gazelle_dependencies()

24
ahash/BUILD.bazel Normal file
View File

@@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "ahash",
srcs = ["ahash.go"],
importpath = "git.wntrmute.dev/kyle/goutils/ahash",
visibility = ["//visibility:public"],
deps = [
"//assert",
"@org_golang_x_crypto//blake2b",
"@org_golang_x_crypto//blake2s",
"@org_golang_x_crypto//md4",
"@org_golang_x_crypto//ripemd160",
"@org_golang_x_crypto//sha3",
],
)
go_test(
name = "ahash_test",
size = "small",
srcs = ["ahash_test.go"],
embed = [":ahash"],
deps = ["//assert"],
)

View File

@@ -1,5 +1,6 @@
// Package ahash provides support for hashing data with a selectable
// hash function.
//
// hash function.
package ahash
import (
@@ -16,7 +17,7 @@ import (
"io"
"sort"
"git.sr.ht/~kisom/goutils/assert"
"git.wntrmute.dev/kyle/goutils/assert"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s"
"golang.org/x/crypto/md4"
@@ -44,13 +45,6 @@ func sha512Slicer(bs []byte) []byte {
return sum[:]
}
var sliceFunctions = map[string]func([]byte) []byte{
"sha224": sha224Slicer,
"sha256": sha256Slicer,
"sha384": sha384Slicer,
"sha512": sha512Slicer,
}
// Hash represents a generic hash function that may or may not be secure. It
// satisfies the hash.Hash interface.
type Hash struct {
@@ -213,6 +207,17 @@ func SumReader(algo string, r io.Reader) ([]byte, error) {
return h.Sum(nil), nil
}
// SumLimitedReader reads n bytes of data from the io.reader and returns the
// digest (not the hex digest) from the specified algorithm.
func SumLimitedReader(algo string, r io.Reader, n int64) ([]byte, error) {
limit := &io.LimitedReader{
R: r,
N: n,
}
return SumReader(algo, limit)
}
var insecureHashList, secureHashList, hashList []string
func init() {

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"testing"
"git.sr.ht/~kisom/goutils/assert"
"git.wntrmute.dev/kyle/goutils/assert"
)
func TestSecureHash(t *testing.T) {
@@ -139,3 +139,19 @@ func TestListLengthSanity(t *testing.T) {
assert.BoolT(t, len(all) == len(secure)+len(insecure))
}
func TestSumLimitedReader(t *testing.T) {
data := bytes.NewBufferString("hello, world")
dataLen := data.Len()
extendedData := bytes.NewBufferString("hello, world! this is an extended message")
expected := "09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b"
hash, err := SumReader("sha256", data)
assert.NoErrorT(t, err)
assert.BoolT(t, fmt.Sprintf("%x", hash) == expected, fmt.Sprintf("have hash %x, want %s", hash, expected))
extendedHash, err := SumLimitedReader("sha256", extendedData, int64(dataLen))
assert.NoErrorT(t, err)
assert.BoolT(t, bytes.Equal(hash, extendedHash), fmt.Sprintf("have hash %x, want %x", extendedHash, hash))
}

8
assert/BUILD.bazel Normal file
View File

@@ -0,0 +1,8 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "assert",
srcs = ["assert.go"],
importpath = "git.wntrmute.dev/kyle/goutils/assert",
visibility = ["//visibility:public"],
)

View File

@@ -94,7 +94,7 @@ func NoError(err error, s ...string) {
}
if nil != err {
die(err.Error())
die(err.Error(), s...)
}
}
@@ -170,5 +170,5 @@ func ErrorEqT(t *testing.T, expected, actual error) {
should = fmt.Sprintf("have '%s'", actual)
}
die(fmt.Sprintf("assert.Error2: expected '%s', but %s", expected, should))
t.Fatalf("assert.Error2: expected '%s', but %s", expected, should)
}

14
cmd/atping/BUILD.bazel Normal file
View File

@@ -0,0 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "atping_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/atping",
visibility = ["//visibility:private"],
)
go_binary(
name = "atping",
embed = [":atping_lib"],
visibility = ["//visibility:public"],
)

15
cmd/certchain/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "certchain_lib",
srcs = ["certchain.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/certchain",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "certchain",
embed = [":certchain_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -7,7 +7,7 @@ import (
"fmt"
"regexp"
"git.sr.ht/~kisom/goutils/die"
"git.wntrmute.dev/kyle/goutils/die"
)
var hasPort = regexp.MustCompile(`:\d+$`)

22
cmd/certdump/BUILD.bazel Normal file
View File

@@ -0,0 +1,22 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "certdump_lib",
srcs = [
"certdump.go",
"util.go",
],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/certdump",
visibility = ["//visibility:private"],
deps = [
"@com_github_cloudflare_cfssl//errors",
"@com_github_cloudflare_cfssl//helpers",
"@com_github_kr_text//:text",
],
)
go_binary(
name = "certdump",
embed = [":certdump_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "certexpiry_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/certexpiry",
visibility = ["//visibility:private"],
deps = [
"//die",
"//lib",
"@com_github_cloudflare_cfssl//helpers",
],
)
go_binary(
name = "certexpiry",
embed = [":certexpiry_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -10,9 +10,9 @@ import (
"strings"
"time"
"git.wntrmute.dev/kyle/goutils/die"
"git.wntrmute.dev/kyle/goutils/lib"
"github.com/cloudflare/cfssl/helpers"
"git.sr.ht/~kisom/goutils/die"
"git.sr.ht/~kisom/goutils/lib"
)
var warnOnly bool

View File

@@ -0,0 +1,20 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "certverify_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/certverify",
visibility = ["//visibility:private"],
deps = [
"//die",
"//lib",
"@com_github_cloudflare_cfssl//helpers",
"@com_github_cloudflare_cfssl//revoke",
],
)
go_binary(
name = "certverify",
embed = [":certverify_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -8,10 +8,10 @@ import (
"os"
"time"
"git.wntrmute.dev/kyle/goutils/die"
"git.wntrmute.dev/kyle/goutils/lib"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/revoke"
"git.sr.ht/~kisom/goutils/die"
"git.sr.ht/~kisom/goutils/lib"
)
func printRevocation(cert *x509.Certificate) {

20
cmd/clustersh/BUILD.bazel Normal file
View File

@@ -0,0 +1,20 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "clustersh_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/clustersh",
visibility = ["//visibility:private"],
deps = [
"//lib",
"@com_github_pkg_sftp//:sftp",
"@org_golang_x_crypto//ssh",
"@org_golang_x_crypto//ssh/agent",
],
)
go_binary(
name = "clustersh",
embed = [":clustersh_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -11,7 +11,7 @@ import (
"strings"
"sync"
"git.sr.ht/~kisom/goutils/lib"
"git.wntrmute.dev/kyle/goutils/lib"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"

15
cmd/cruntar/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "cruntar_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/cruntar",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "cruntar",
embed = [":cruntar_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -11,7 +11,8 @@ import (
"os"
"path/filepath"
"git.sr.ht/~kisom/goutils/die"
"git.wntrmute.dev/kyle/goutils/die"
"git.wntrmute.dev/kyle/goutils/fileutil"
)
var (
@@ -56,7 +57,7 @@ func processFile(tfr *tar.Reader, hdr *tar.Header, top string) error {
}
filePath := filepath.Clean(filepath.Join(top, hdr.Name))
switch hdr.Typeflag {
case tar.TypeReg, tar.TypeRegA:
case tar.TypeReg:
file, err := os.Create(filePath)
if err != nil {
return err
@@ -92,6 +93,17 @@ func processFile(tfr *tar.Reader, hdr *tar.Header, top string) error {
return err
}
case tar.TypeSymlink:
if !fileutil.ValidateSymlink(hdr.Linkname, top) {
return fmt.Errorf("symlink %s is outside the top-level %s",
hdr.Linkname, top)
}
path := linkTarget(hdr.Linkname, top)
if ok, err := filepath.Match(top+"/*", filepath.Clean(path)); !ok {
return fmt.Errorf("symlink %s isn't in %s", hdr.Linkname, top)
} else if err != nil {
return err
}
err := os.Symlink(linkTarget(hdr.Linkname, top), filePath)
if err != nil {
return err

View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "csrpubdump_lib",
srcs = ["pubdump.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/csrpubdump",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "csrpubdump",
embed = [":csrpubdump_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -10,7 +10,7 @@ import (
"io/ioutil"
"log"
"git.sr.ht/~kisom/goutils/die"
"git.wntrmute.dev/kyle/goutils/die"
)
func main() {

19
cmd/diskimg/BUILD.bazel Normal file
View File

@@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "diskimg_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/diskimg",
visibility = ["//visibility:private"],
deps = [
"//ahash",
"//dbg",
"//die",
],
)
go_binary(
name = "diskimg",
embed = [":diskimg_lib"],
visibility = ["//visibility:public"],
)

34
cmd/diskimg/README Normal file
View File

@@ -0,0 +1,34 @@
diskimg: write disk images
Usage:
diskimg [-a algo] [-v] image device
Flags:
-a algo Select the hashing algorithm to use. The default
is 'sha256'. Specifying an algorithm of 'list'
will print the supported algorithms to standard
output and exit with error code 2.
-v Enable verbose (debug) output.
Examples:
Copying images/server.img to /dev/sda:
$ sudo diskimg images/server.img /dev/sda
Write a bladerunner node image to /dev/sda:
$ sudo diskimg -v ~/code/bladerunner/packer/build/cm4-cnode-ubuntu-22.04.2.img /dev/sda
opening image /home/kyle/code/bladerunner/packer/build/cm4-cnode-ubuntu-22.04.2.img for read
/home/kyle/code/bladerunner/packer/build/cm4-cnode-ubuntu-22.04.2.img 416d4c8f890904167419e3d488d097e9c847273376b650546fdb1f6f9809c184
opening device /dev/sda for rw
writing /home/kyle/code/bladerunner/packer/build/cm4-cnode-ubuntu-22.04.2.img -> /dev/sda
wrote 4151312384 bytes to /dev/sda
syncing /dev/sda
verifying the image was written successfully
OK
Motivation:
I wanted to write something like balena's Etcher, but commandline only.

116
cmd/diskimg/main.go Normal file
View File

@@ -0,0 +1,116 @@
package main
import (
"bytes"
"flag"
"fmt"
"io"
"os"
"git.wntrmute.dev/kyle/goutils/ahash"
"git.wntrmute.dev/kyle/goutils/dbg"
"git.wntrmute.dev/kyle/goutils/die"
)
const defaultHashAlgorithm = "sha256"
var (
hAlgo string
debug = dbg.New()
)
func openImage(imageFile string) (image *os.File, hash []byte, err error) {
image, err = os.Open(imageFile)
if err != nil {
return
}
hash, err = ahash.SumReader(hAlgo, image)
if err != nil {
return
}
_, err = image.Seek(0, 0)
if err != nil {
return
}
debug.Printf("%s %x\n", imageFile, hash)
return
}
func openDevice(devicePath string) (device *os.File, err error) {
fi, err := os.Stat(devicePath)
if err != nil {
return
}
device, err = os.OpenFile(devicePath, os.O_RDWR|os.O_SYNC, fi.Mode())
if err != nil {
return
}
return
}
func main() {
flag.StringVar(&hAlgo, "a", defaultHashAlgorithm, "default hash algorithm")
flag.BoolVar(&debug.Enabled, "v", false, "enable debug logging")
flag.Parse()
if hAlgo == "list" {
fmt.Println("Supported hashing algorithms:")
for _, algo := range ahash.SecureHashList() {
fmt.Printf("\t- %s\n", algo)
}
os.Exit(2)
}
if flag.NArg() != 2 {
die.With("usage: diskimg image device")
}
imageFile := flag.Arg(0)
devicePath := flag.Arg(1)
debug.Printf("opening image %s for read\n", imageFile)
image, hash, err := openImage(imageFile)
if image != nil {
defer image.Close()
}
die.If(err)
debug.Printf("opening device %s for rw\n", devicePath)
device, err := openDevice(devicePath)
if device != nil {
defer device.Close()
}
die.If(err)
debug.Printf("writing %s -> %s\n", imageFile, devicePath)
n, err := io.Copy(device, image)
die.If(err)
debug.Printf("wrote %d bytes to %s\n", n, devicePath)
debug.Printf("syncing %s\n", devicePath)
err = device.Sync()
die.If(err)
debug.Println("verifying the image was written successfully")
_, err = device.Seek(0, 0)
die.If(err)
deviceHash, err := ahash.SumLimitedReader(hAlgo, device, n)
die.If(err)
if !bytes.Equal(deviceHash, hash) {
fmt.Fprintln(os.Stderr, "Hash mismatch:")
fmt.Fprintf(os.Stderr, "\t%s: %s\n", imageFile, hash)
fmt.Fprintf(os.Stderr, "\t%s: %s\n", devicePath, deviceHash)
os.Exit(1)
}
debug.Println("OK")
os.Exit(0)
}

15
cmd/eig/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "eig_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/eig",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "eig",
embed = [":eig_lib"],
visibility = ["//visibility:public"],
)

52
cmd/eig/main.go Normal file
View File

@@ -0,0 +1,52 @@
package main
import (
"flag"
"os"
"git.wntrmute.dev/kyle/goutils/die"
)
// size of a kilobit in bytes
const kilobit = 128
const pageSize = 4096
func main() {
size := flag.Int("s", 256*kilobit, "size of EEPROM image in kilobits")
fill := flag.Uint("f", 0, "byte to fill image with")
flag.Parse()
if *fill > 256 {
die.With("`fill` argument must be a byte value")
}
path := "eeprom.img"
if flag.NArg() > 0 {
path = flag.Arg(0)
}
fillByte := uint8(*fill)
buf := make([]byte, pageSize)
for i := 0; i < pageSize; i++ {
buf[i] = fillByte
}
pages := *size / pageSize
last := *size % pageSize
file, err := os.Create(path)
die.If(err)
defer file.Close()
for i := 0; i < pages; i++ {
_, err = file.Write(buf)
die.If(err)
}
if last != 0 {
_, err = file.Write(buf[:last])
die.If(err)
}
}

15
cmd/fragment/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "fragment_lib",
srcs = ["fragment.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/fragment",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "fragment",
embed = [":fragment_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -9,7 +9,7 @@ import (
"path/filepath"
"strconv"
"git.sr.ht/~kisom/goutils/die"
"git.wntrmute.dev/kyle/goutils/die"
)
func init() {

15
cmd/jlp/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "jlp_lib",
srcs = ["jlp.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/jlp",
visibility = ["//visibility:private"],
deps = ["//lib"],
)
go_binary(
name = "jlp",
embed = [":jlp_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -8,7 +8,7 @@ import (
"io/ioutil"
"os"
"git.sr.ht/~kisom/goutils/lib"
"git.wntrmute.dev/kyle/goutils/lib"
)
func prettify(file string, validateOnly bool) error {

15
cmd/kgz/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "kgz_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/kgz",
visibility = ["//visibility:private"],
deps = ["@com_github_pkg_errors//:errors"],
)
go_binary(
name = "kgz",
embed = [":kgz_lib"],
visibility = ["//visibility:public"],
)

15
cmd/parts/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "parts_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/parts",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "parts",
embed = [":parts_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -11,7 +11,7 @@ import (
"sort"
"strings"
"git.sr.ht/~kisom/goutils/die"
"git.wntrmute.dev/kyle/goutils/die"
)
const dbVersion = "1"

14
cmd/pem2bin/BUILD.bazel Normal file
View File

@@ -0,0 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "pem2bin_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/pem2bin",
visibility = ["//visibility:private"],
)
go_binary(
name = "pem2bin",
embed = [":pem2bin_lib"],
visibility = ["//visibility:public"],
)

15
cmd/pembody/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "pembody_lib",
srcs = ["pembody.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/pembody",
visibility = ["//visibility:private"],
deps = ["//lib"],
)
go_binary(
name = "pembody",
embed = [":pembody_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -7,7 +7,7 @@ import (
"io/ioutil"
"os"
"git.sr.ht/~kisom/goutils/lib"
"git.wntrmute.dev/kyle/goutils/lib"
)
func main() {

19
cmd/pemit/BUILD.bazel Normal file
View File

@@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "pemit_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/pemit",
visibility = ["//visibility:private"],
deps = [
"//assert",
"//die",
"//lib",
],
)
go_binary(
name = "pemit",
embed = [":pemit_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -8,9 +8,9 @@ import (
"io"
"os"
"git.sr.ht/~kisom/goutils/assert"
"git.sr.ht/~kisom/goutils/die"
"git.sr.ht/~kisom/goutils/lib"
"git.wntrmute.dev/kyle/goutils/assert"
"git.wntrmute.dev/kyle/goutils/die"
"git.wntrmute.dev/kyle/goutils/lib"
)
func usage(w io.Writer) {

14
cmd/readchain/BUILD.bazel Normal file
View File

@@ -0,0 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "readchain_lib",
srcs = ["chain.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/readchain",
visibility = ["//visibility:private"],
)
go_binary(
name = "readchain",
embed = [":readchain_lib"],
visibility = ["//visibility:public"],
)

18
cmd/renfnv/BUILD.bazel Normal file
View File

@@ -0,0 +1,18 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "renfnv_lib",
srcs = ["renfnv.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/renfnv",
visibility = ["//visibility:private"],
deps = [
"//fileutil",
"//lib",
],
)
go_binary(
name = "renfnv",
embed = [":renfnv_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -11,8 +11,8 @@ import (
"path/filepath"
"strings"
"git.sr.ht/~kisom/goutils/fileutil"
"git.sr.ht/~kisom/goutils/lib"
"git.wntrmute.dev/kyle/goutils/fileutil"
"git.wntrmute.dev/kyle/goutils/lib"
)
func hashName(path, encodedHash string) string {

19
cmd/rhash/BUILD.bazel Normal file
View File

@@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "rhash_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/rhash",
visibility = ["//visibility:private"],
deps = [
"//ahash",
"//die",
"//lib",
],
)
go_binary(
name = "rhash",
embed = [":rhash_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -9,9 +9,9 @@ import (
"os"
"path/filepath"
"git.sr.ht/~kisom/goutils/ahash"
"git.sr.ht/~kisom/goutils/die"
"git.sr.ht/~kisom/goutils/lib"
"git.wntrmute.dev/kyle/goutils/ahash"
"git.wntrmute.dev/kyle/goutils/die"
"git.wntrmute.dev/kyle/goutils/lib"
)
func usage(w io.Writer) {

18
cmd/showimp/BUILD.bazel Normal file
View File

@@ -0,0 +1,18 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "showimp_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/showimp",
visibility = ["//visibility:private"],
deps = [
"//die",
"//logging",
],
)
go_binary(
name = "showimp",
embed = [":showimp_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -12,36 +12,23 @@ import (
"sort"
"strings"
"git.sr.ht/~kisom/goutils/die"
"git.sr.ht/~kisom/goutils/logging"
"git.wntrmute.dev/kyle/goutils/dbg"
"git.wntrmute.dev/kyle/goutils/die"
)
var (
gopath string
project string
debug bool
)
var (
stdLibRegexp = regexp.MustCompile(`^\w+(/\w+)*$`)
sourceRegexp = regexp.MustCompile(`^[^.].*\.go$`)
log = logging.NewConsole()
imports = map[string]bool{}
debug = dbg.New()
fset = &token.FileSet{}
imports = map[string]bool{}
sourceRegexp = regexp.MustCompile(`^[^.].*\.go$`)
stdLibRegexp = regexp.MustCompile(`^\w+(/\w+)*$`)
)
func debugf(format string, args ...interface{}) {
if debug {
fmt.Printf(format, args...)
}
}
func debugln(args ...interface{}) {
if debug {
fmt.Println(args...)
}
}
func init() {
gopath = os.Getenv("GOPATH")
if gopath == "" {
@@ -75,7 +62,7 @@ func walkFile(path string, info os.FileInfo, err error) error {
return nil
}
debugln(path)
debug.Println(path)
f, err := parser.ParseFile(fset, path, nil, parser.ImportsOnly)
if err != nil {
@@ -85,16 +72,16 @@ func walkFile(path string, info os.FileInfo, err error) error {
for _, importSpec := range f.Imports {
importPath := strings.Trim(importSpec.Path.Value, `"`)
if stdLibRegexp.MatchString(importPath) {
debugln("standard lib:", importPath)
debug.Println("standard lib:", importPath)
continue
} else if strings.HasPrefix(importPath, project) {
debugln("internal import:", importPath)
debug.Println("internal import:", importPath)
continue
} else if strings.HasPrefix(importPath, "golang.org/") {
debugln("extended lib:", importPath)
debug.Println("extended lib:", importPath)
continue
}
debugln("import:", importPath)
debug.Println("import:", importPath)
imports[importPath] = true
}
@@ -108,7 +95,7 @@ func main() {
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.Enabled, "v", false, "log debugging information")
flag.Parse()
if noVendor {

18
cmd/ski/BUILD.bazel Normal file
View File

@@ -0,0 +1,18 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "ski_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/ski",
visibility = ["//visibility:private"],
deps = [
"//die",
"//lib",
],
)
go_binary(
name = "ski",
embed = [":ski_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -17,8 +17,8 @@ import (
"os"
"strings"
"git.sr.ht/~kisom/goutils/die"
"git.sr.ht/~kisom/goutils/lib"
"git.wntrmute.dev/kyle/goutils/die"
"git.wntrmute.dev/kyle/goutils/lib"
)
func usage(w io.Writer) {

15
cmd/sprox/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "sprox_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/sprox",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "sprox",
embed = [":sprox_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -6,7 +6,7 @@ import (
"log"
"net"
"git.sr.ht/~kisom/goutils/die"
"git.wntrmute.dev/kyle/goutils/die"
)
func proxy(conn net.Conn, inside string) error {

View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "stealchain-server_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/stealchain-server",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "stealchain-server",
embed = [":stealchain-server_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -12,7 +12,7 @@ import (
"net"
"os"
"git.sr.ht/~kisom/goutils/die"
"git.wntrmute.dev/kyle/goutils/die"
)
func main() {

View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "stealchain_lib",
srcs = ["thief.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/stealchain",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "stealchain",
embed = [":stealchain_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -10,7 +10,7 @@ import (
"net"
"os"
"git.sr.ht/~kisom/goutils/die"
"git.wntrmute.dev/kyle/goutils/die"
)
func main() {

18
cmd/subjhash/BUILD.bazel Normal file
View File

@@ -0,0 +1,18 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "subjhash_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/subjhash",
visibility = ["//visibility:private"],
deps = [
"//die",
"//lib",
],
)
go_binary(
name = "subjhash",
embed = [":subjhash_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -9,8 +9,8 @@ import (
"io"
"os"
"git.sr.ht/~kisom/goutils/die"
"git.sr.ht/~kisom/goutils/lib"
"git.wntrmute.dev/kyle/goutils/die"
"git.wntrmute.dev/kyle/goutils/lib"
)
func init() {

View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "tlskeypair_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/tlskeypair",
visibility = ["//visibility:private"],
deps = ["//die"],
)
go_binary(
name = "tlskeypair",
embed = [":tlskeypair_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -15,7 +15,7 @@ import (
"log"
"os"
"git.sr.ht/~kisom/goutils/die"
"git.wntrmute.dev/kyle/goutils/die"
)
var validPEMs = map[string]bool{

14
cmd/utc/BUILD.bazel Normal file
View File

@@ -0,0 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "utc_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/utc",
visibility = ["//visibility:private"],
)
go_binary(
name = "utc",
embed = [":utc_lib"],
visibility = ["//visibility:public"],
)

15
cmd/yamll/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "yamll_lib",
srcs = ["main.go"],
importpath = "git.wntrmute.dev/kyle/goutils/cmd/yamll",
visibility = ["//visibility:private"],
deps = ["@in_gopkg_yaml_v2//:yaml_v2"],
)
go_binary(
name = "yamll",
embed = [":yamll_lib"],
visibility = ["//visibility:public"],
)

23
config/BUILD.bazel Normal file
View File

@@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "config",
srcs = [
"config.go",
"path_linux.go",
],
importpath = "git.wntrmute.dev/kyle/goutils/config",
visibility = ["//visibility:public"],
deps = ["//config/iniconf"],
)
go_test(
name = "config_test",
size = "small",
srcs = [
"config_test.go",
"path_test.go",
],
data = glob(["testdata/**"]),
embed = [":config"],
)

View File

@@ -15,7 +15,7 @@ import (
"os"
"strings"
"git.sr.ht/~kisom/goutils/config/iniconf"
"git.wntrmute.dev/kyle/goutils/config/iniconf"
)
// NB: Rather than define a singleton type, everything is defined at

View File

@@ -0,0 +1,16 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "iniconf",
srcs = ["iniconf.go"],
importpath = "git.wntrmute.dev/kyle/goutils/config/iniconf",
visibility = ["//visibility:public"],
)
go_test(
name = "iniconf_test",
size = "small",
srcs = ["iniconf_test.go"],
data = glob(["testdata/**"]),
embed = [":iniconf"],
)

19
dbg/BUILD.bazel Normal file
View File

@@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "dbg",
srcs = ["dbg.go"],
importpath = "git.wntrmute.dev/kyle/goutils/dbg",
visibility = ["//visibility:public"],
)
go_test(
name = "dbg_test",
size = "small",
srcs = ["dbg_test.go"],
embed = [":dbg"],
deps = [
"//testio",
"@com_github_stretchr_testify//require",
],
)

View File

@@ -55,21 +55,21 @@ func To(w io.WriteCloser) *DebugPrinter {
}
// Print calls fmt.Print if Enabled is true.
func (dbg DebugPrinter) Print(v ...interface{}) {
func (dbg *DebugPrinter) Print(v ...interface{}) {
if dbg.Enabled {
fmt.Fprint(dbg.out, v...)
}
}
// Println calls fmt.Println if Enabled is true.
func (dbg DebugPrinter) Println(v ...interface{}) {
func (dbg *DebugPrinter) Println(v ...interface{}) {
if dbg.Enabled {
fmt.Fprintln(dbg.out, v...)
}
}
// Printf calls fmt.Printf if Enabled is true.
func (dbg DebugPrinter) Printf(format string, v ...interface{}) {
func (dbg *DebugPrinter) Printf(format string, v ...interface{}) {
if dbg.Enabled {
fmt.Fprintf(dbg.out, format, v...)
}

View File

@@ -5,7 +5,7 @@ import (
"os"
"testing"
"git.sr.ht/~kisom/goutils/testio"
"git.wntrmute.dev/kyle/goutils/testio"
"github.com/stretchr/testify/require"
)

352
deps.bzl Normal file
View File

@@ -0,0 +1,352 @@
load("@bazel_gazelle//:deps.bzl", "go_repository")
def go_dependencies():
go_repository(
name = "com_github_akavel_rsrc",
importpath = "github.com/akavel/rsrc",
sum = "h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=",
version = "v0.8.0",
)
go_repository(
name = "com_github_certifi_gocertifi",
importpath = "github.com/certifi/gocertifi",
sum = "h1:6/yVvBsKeAw05IUj4AzvrxaCnDjN4nUqKjW9+w5wixg=",
version = "v0.0.0-20180118203423-deb3ae2ef261",
)
go_repository(
name = "com_github_cloudflare_backoff",
importpath = "github.com/cloudflare/backoff",
sum = "h1:8d1CEOF1xldesKds5tRG3tExBsMOgWYownMHNCsev54=",
version = "v0.0.0-20161212185259-647f3cdfc87a",
)
go_repository(
name = "com_github_cloudflare_cfssl",
importpath = "github.com/cloudflare/cfssl",
sum = "h1:vFJDAvQgFSRbCn9zg8KpSrrEZrBAQ4KO5oNK7SXEyb0=",
version = "v1.5.0",
)
go_repository(
name = "com_github_cloudflare_go_metrics",
importpath = "github.com/cloudflare/go-metrics",
sum = "h1:/8sZyuGTAU2+fYv0Sz9lBcipqX0b7i4eUl8pSStk/4g=",
version = "v0.0.0-20151117154305-6a9aea36fb41",
)
go_repository(
name = "com_github_cloudflare_redoctober",
importpath = "github.com/cloudflare/redoctober",
sum = "h1:p0Q1GvgWtVf46XpMMibupKiE7aQxPYUIb+/jLTTK2kM=",
version = "v0.0.0-20171127175943-746a508df14c",
)
go_repository(
name = "com_github_creack_pty",
importpath = "github.com/creack/pty",
sum = "h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=",
version = "v1.1.9",
)
go_repository(
name = "com_github_daaku_go_zipexe",
importpath = "github.com/daaku/go.zipexe",
sum = "h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=",
version = "v1.0.0",
)
go_repository(
name = "com_github_davecgh_go_spew",
importpath = "github.com/davecgh/go-spew",
sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=",
version = "v1.1.1",
)
go_repository(
name = "com_github_geertjohan_go_incremental",
importpath = "github.com/GeertJohan/go.incremental",
sum = "h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg=",
version = "v1.0.0",
)
go_repository(
name = "com_github_geertjohan_go_rice",
importpath = "github.com/GeertJohan/go.rice",
sum = "h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ=",
version = "v1.0.0",
)
go_repository(
name = "com_github_getsentry_raven_go",
importpath = "github.com/getsentry/raven-go",
sum = "h1:ELaJ1cjF2nEJeIlHXahGme22yG7TK+3jB6IGCq0Cdrc=",
version = "v0.0.0-20180121060056-563b81fc02b7",
)
go_repository(
name = "com_github_go_sql_driver_mysql",
importpath = "github.com/go-sql-driver/mysql",
sum = "h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=",
version = "v1.4.0",
)
go_repository(
name = "com_github_golang_protobuf",
importpath = "github.com/golang/protobuf",
sum = "h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=",
version = "v1.3.1",
)
go_repository(
name = "com_github_google_certificate_transparency_go",
importpath = "github.com/google/certificate-transparency-go",
sum = "h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=",
version = "v1.0.21",
)
go_repository(
name = "com_github_hashicorp_go_syslog",
importpath = "github.com/hashicorp/go-syslog",
sum = "h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=",
version = "v1.0.0",
)
go_repository(
name = "com_github_jessevdk_go_flags",
importpath = "github.com/jessevdk/go-flags",
sum = "h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=",
version = "v1.4.0",
)
go_repository(
name = "com_github_jmhodges_clock",
importpath = "github.com/jmhodges/clock",
sum = "h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4=",
version = "v0.0.0-20160418191101-880ee4c33548",
)
go_repository(
name = "com_github_jmoiron_sqlx",
importpath = "github.com/jmoiron/sqlx",
sum = "h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=",
version = "v1.2.0",
)
go_repository(
name = "com_github_kisielk_sqlstruct",
importpath = "github.com/kisielk/sqlstruct",
sum = "h1:o/c0aWEP/m6n61xlYW2QP4t9424qlJOsxugn5Zds2Rg=",
version = "v0.0.0-20150923205031-648daed35d49",
)
go_repository(
name = "com_github_kisom_goutils",
importpath = "github.com/kisom/goutils",
sum = "h1:z4HEOgAnFq+e1+O4QdVsyDPatJDu5Ei/7w7DRbYjsIA=",
version = "v1.1.0",
)
go_repository(
name = "com_github_konsorten_go_windows_terminal_sequences",
importpath = "github.com/konsorten/go-windows-terminal-sequences",
sum = "h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=",
version = "v1.0.1",
)
go_repository(
name = "com_github_kr_fs",
importpath = "github.com/kr/fs",
sum = "h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=",
version = "v0.1.0",
)
go_repository(
name = "com_github_kr_pretty",
importpath = "github.com/kr/pretty",
sum = "h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=",
version = "v0.1.0",
)
go_repository(
name = "com_github_kr_pty",
importpath = "github.com/kr/pty",
sum = "h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=",
version = "v1.1.1",
)
go_repository(
name = "com_github_kr_text",
importpath = "github.com/kr/text",
sum = "h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=",
version = "v0.2.0",
)
go_repository(
name = "com_github_kylelemons_go_gypsy",
importpath = "github.com/kylelemons/go-gypsy",
sum = "h1:mkl3tvPHIuPaWsLtmHTybJeoVEW7cbePK73Ir8VtruA=",
version = "v0.0.0-20160905020020-08cad365cd28",
)
go_repository(
name = "com_github_lib_pq",
importpath = "github.com/lib/pq",
sum = "h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=",
version = "v1.3.0",
)
go_repository(
name = "com_github_mattn_go_sqlite3",
importpath = "github.com/mattn/go-sqlite3",
sum = "h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=",
version = "v1.10.0",
)
go_repository(
name = "com_github_mreiferson_go_httpclient",
importpath = "github.com/mreiferson/go-httpclient",
sum = "h1:oKIteTqeSpenyTrOVj5zkiyCaflLa8B+CD0324otT+o=",
version = "v0.0.0-20160630210159-31f0106b4474",
)
go_repository(
name = "com_github_nkovacs_streamquote",
importpath = "github.com/nkovacs/streamquote",
sum = "h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg=",
version = "v0.0.0-20170412213628-49af9bddb229",
)
go_repository(
name = "com_github_op_go_logging",
importpath = "github.com/op/go-logging",
sum = "h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=",
version = "v0.0.0-20160315200505-970db520ece7",
)
go_repository(
name = "com_github_pkg_errors",
importpath = "github.com/pkg/errors",
sum = "h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=",
version = "v0.9.1",
)
go_repository(
name = "com_github_pkg_sftp",
importpath = "github.com/pkg/sftp",
sum = "h1:/f3b24xrDhkhddlaobPe2JgBqfdt+gC/NYl0QY9IOuI=",
version = "v1.12.0",
)
go_repository(
name = "com_github_pmezard_go_difflib",
importpath = "github.com/pmezard/go-difflib",
sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=",
version = "v1.0.0",
)
go_repository(
name = "com_github_sirupsen_logrus",
importpath = "github.com/sirupsen/logrus",
sum = "h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=",
version = "v1.3.0",
)
go_repository(
name = "com_github_stretchr_objx",
importpath = "github.com/stretchr/objx",
sum = "h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=",
version = "v0.1.1",
)
go_repository(
name = "com_github_stretchr_testify",
importpath = "github.com/stretchr/testify",
sum = "h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=",
version = "v1.6.1",
)
go_repository(
name = "com_github_valyala_bytebufferpool",
importpath = "github.com/valyala/bytebufferpool",
sum = "h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=",
version = "v1.0.0",
)
go_repository(
name = "com_github_valyala_fasttemplate",
importpath = "github.com/valyala/fasttemplate",
sum = "h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=",
version = "v1.0.1",
)
go_repository(
name = "com_github_weppos_publicsuffix_go",
importpath = "github.com/weppos/publicsuffix-go",
sum = "h1:0Tu1uzLBd1jPn4k6OnMmOPZH/l/9bj9kUOMMkoRs6Gg=",
version = "v0.13.0",
)
go_repository(
name = "com_github_ziutek_mymysql",
importpath = "github.com/ziutek/mymysql",
sum = "h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=",
version = "v1.5.4",
)
go_repository(
name = "com_github_zmap_rc2",
importpath = "github.com/zmap/rc2",
sum = "h1:kKCF7VX/wTmdg2ZjEaqlq99Bjsoiz7vH6sFniF/vI4M=",
version = "v0.0.0-20131011165748-24b9757f5521",
)
go_repository(
name = "com_github_zmap_zcertificate",
importpath = "github.com/zmap/zcertificate",
sum = "h1:17HHAgFKlLcZsDOjBOUrd5hDihb1ggf+1a5dTbkgkIY=",
version = "v0.0.0-20180516150559-0e3d58b1bac4",
)
go_repository(
name = "com_github_zmap_zcrypto",
importpath = "github.com/zmap/zcrypto",
sum = "h1:PIpcdSOg3pMdFJUBg5yR9xxcj5rm/SGAyaWT/wK6Kco=",
version = "v0.0.0-20200911161511-43ff0ea04f21",
)
go_repository(
name = "com_github_zmap_zlint_v2",
importpath = "github.com/zmap/zlint/v2",
sum = "h1:b2kI/ToXX16h2wjV2c6Da65eT6aTMtkLHKetXuM9EtI=",
version = "v2.2.1",
)
go_repository(
name = "in_gopkg_check_v1",
importpath = "gopkg.in/check.v1",
sum = "h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=",
version = "v1.0.0-20180628173108-788fd7840127",
)
go_repository(
name = "in_gopkg_yaml_v2",
importpath = "gopkg.in/yaml.v2",
sum = "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=",
version = "v2.4.0",
)
go_repository(
name = "in_gopkg_yaml_v3",
importpath = "gopkg.in/yaml.v3",
sum = "h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=",
version = "v3.0.0-20200313102051-9f266ea9e77c",
)
go_repository(
name = "org_bitbucket_liamstask_goose",
importpath = "bitbucket.org/liamstask/goose",
sum = "h1:bkb2NMGo3/Du52wvYj9Whth5KZfMV6d3O0Vbr3nz/UE=",
version = "v0.0.0-20150115234039-8488cc47d90c",
)
go_repository(
name = "org_golang_google_appengine",
importpath = "google.golang.org/appengine",
sum = "h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=",
version = "v1.6.6",
)
go_repository(
name = "org_golang_x_crypto",
importpath = "golang.org/x/crypto",
sum = "h1:Qwe1rC8PSniVfAFPFJeyUkB+zcysC3RgJBAGk7eqBEU=",
version = "v0.0.0-20220314234659-1baeb1ce4c0b",
)
go_repository(
name = "org_golang_x_lint",
importpath = "golang.org/x/lint",
sum = "h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=",
version = "v0.0.0-20190930215403-16217165b5de",
)
go_repository(
name = "org_golang_x_net",
importpath = "golang.org/x/net",
sum = "h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=",
version = "v0.0.0-20211112202133-69e39bad7dc2",
)
go_repository(
name = "org_golang_x_sys",
importpath = "golang.org/x/sys",
sum = "h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=",
version = "v0.0.0-20220412211240-33da011f77ad",
)
go_repository(
name = "org_golang_x_term",
importpath = "golang.org/x/term",
sum = "h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=",
version = "v0.0.0-20201126162022-7de9c90e9dd1",
)
go_repository(
name = "org_golang_x_text",
importpath = "golang.org/x/text",
sum = "h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=",
version = "v0.3.6",
)
go_repository(
name = "org_golang_x_tools",
importpath = "golang.org/x/tools",
sum = "h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ=",
version = "v0.0.0-20190311212946-11955173bddd",
)

8
die/BUILD.bazel Normal file
View File

@@ -0,0 +1,8 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "die",
srcs = ["die.go"],
importpath = "git.wntrmute.dev/kyle/goutils/die",
visibility = ["//visibility:public"],
)

9
fileutil/BUILD.bazel Normal file
View File

@@ -0,0 +1,9 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "fileutil",
srcs = ["fileutil.go"],
importpath = "git.wntrmute.dev/kyle/goutils/fileutil",
visibility = ["//visibility:public"],
deps = ["@org_golang_x_sys//unix"],
)

View File

@@ -1,3 +1,6 @@
//go:build !windows
// +build !windows
// Package fileutil contains common file functions.
package fileutil

View File

@@ -0,0 +1,49 @@
//go:build windows
// +build windows
// Package fileutil contains common file functions.
package fileutil
import (
"errors"
"os"
)
// FileDoesExist returns true if the file exists.
func FileDoesExist(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
// DirectoryDoesExist returns true if the file exists.
func DirectoryDoesExist(path string) bool {
fi, err := os.Stat(path)
if err != nil {
return false
}
return fi.Mode().IsDir()
}
const (
// AccessExists checks whether the file exists. This is invalid outside of
// Unix systems.
AccessExists = 0
// AccessRead checks whether the user has read permissions on
// the file. This is invalid outside of Unix systems.
AccessRead = 0
// AccessWrite checks whether the user has write permissions
// on the file. This is invalid outside of Unix systems.
AccessWrite = 0
// AccessExec checks whether the user has executable
// permissions on the file. This is invalid outside of Unix systems.
AccessExec = 0
)
// Access is a Unix-only call, and has no meaning on Windows.
func Access(path string, mode int) error {
return errors.New("fileutil: Access is meaningless on Windows")
}

16
fileutil/symlinks.go Normal file
View File

@@ -0,0 +1,16 @@
package fileutil
import (
"path/filepath"
"strings"
)
// ValidateSymlink checks to make sure a symlink exists in some top-level
// directory.
func ValidateSymlink(symlink, topLevel string) bool {
target, err := filepath.EvalSymlinks(symlink)
if err != nil {
return false
}
return strings.HasPrefix(target, topLevel)
}

14
gazelle.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
set -euxo pipefail
BAZEL="bazel"
if [ -z "$(command -v ${BAZEL})" ]
then
BAZEL="bazelisk"
fi
$BAZEL run //:gazelle
$BAZEL run //:gazelle -- update-repos -from_file=go.mod -to_macro=deps.bzl%go_dependencies
$BAZEL run //:gazelle

10
go.mod
View File

@@ -1,15 +1,15 @@
module git.sr.ht/~kisom/goutils
module git.wntrmute.dev/kyle/goutils
go 1.13
go 1.20
require (
github.com/cloudflare/cfssl v1.5.0
github.com/kisom/goutils v1.1.0
github.com/hashicorp/go-syslog v1.0.0
github.com/kr/text v0.2.0
github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.12.0
github.com/stretchr/testify v1.6.1
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392
golang.org/x/sys v0.0.0-20201126233918-771906719818
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
gopkg.in/yaml.v2 v2.4.0
)

21
go.sum
View File

@@ -18,11 +18,12 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/kisielk/sqlstruct v0.0.0-20150923205031-648daed35d49/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
github.com/kisom/goutils v1.1.0 h1:z4HEOgAnFq+e1+O4QdVsyDPatJDu5Ei/7w7DRbYjsIA=
github.com/kisom/goutils v1.1.0/go.mod h1:+UBTfd78habUYWFbNWTJNG+jNG/i/lGURakr4A/yNRw=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
@@ -72,26 +73,30 @@ golang.org/x/crypto v0.0.0-20200124225646-8b5121be2f68/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc=
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b h1:Qwe1rC8PSniVfAFPFJeyUkB+zcysC3RgJBAGk7eqBEU=
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818 h1:f1CIuDlJhwANEC2MM87MBEVMr3jl5bifgsfj90XAF9c=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=

117
lib/BUILD.bazel Normal file
View File

@@ -0,0 +1,117 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "lib",
srcs = [
"defs.go",
"ftime_bsd.go",
"ftime_unix.go",
"lib.go",
],
importpath = "git.wntrmute.dev/kyle/goutils/lib",
visibility = ["//visibility:public"],
deps = select({
"@io_bazel_rules_go//go/platform:android_386": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:android_amd64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:android_arm": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:android_arm64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:darwin_386": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:darwin_amd64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:freebsd_386": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:freebsd_amd64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:freebsd_arm": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:freebsd_arm64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:ios_amd64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_386": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_arm": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_arm64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_mips": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_mips64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_mips64le": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_mipsle": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_ppc64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_ppc64le": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_riscv64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:linux_s390x": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:netbsd_386": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:netbsd_amd64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:netbsd_arm": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:netbsd_arm64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:openbsd_386": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:openbsd_amd64": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:openbsd_arm": [
"@org_golang_x_sys//unix",
],
"@io_bazel_rules_go//go/platform:openbsd_arm64": [
"@org_golang_x_sys//unix",
],
"//conditions:default": [],
}),
)
go_test(
name = "lib_test",
size = "small",
srcs = ["lib_test.go"],
embed = [":lib"],
deps = ["//assert"],
)

View File

@@ -89,7 +89,7 @@ func Duration(d time.Duration) string {
if d >= yearDuration {
years := d / yearDuration
s += fmt.Sprintf("%dy", years)
d -= (years * yearDuration)
d -= years * yearDuration
}
if d >= dayDuration {
@@ -103,7 +103,7 @@ func Duration(d time.Duration) string {
d %= 1 * time.Second
hours := d / time.Hour
d -= (hours * time.Hour)
d -= hours * time.Hour
s += fmt.Sprintf("%dh%s", hours, d)
return s
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"testing"
"git.sr.ht/~kisom/goutils/assert"
"git.wntrmute.dev/kyle/goutils/assert"
)
// some CA certs I found on my computerbox.

24
logging/BUILD.bazel Normal file
View File

@@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "logging",
srcs = [
"console_logger.go",
"doc.go",
"file.go",
"levels.go",
"log.go",
],
importpath = "git.wntrmute.dev/kyle/goutils/logging",
visibility = ["//visibility:public"],
)
go_test(
name = "logging_test",
size = "small",
srcs = [
"example_test.go",
"log_test.go",
],
embed = [":logging"],
)

View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "example_lib",
srcs = ["example.go"],
importpath = "git.wntrmute.dev/kyle/goutils/logging/example",
visibility = ["//visibility:private"],
deps = ["//logging"],
)
go_binary(
name = "example",
embed = [":example_lib"],
visibility = ["//visibility:public"],
)

View File

@@ -4,7 +4,7 @@ import (
"os"
"time"
"git.sr.ht/~kisom/goutils/logging"
"git.wntrmute.dev/kyle/goutils/logging"
)
var log = logging.NewConsole()

View File

@@ -3,7 +3,7 @@ package logging_test
import (
"time"
"git.sr.ht/~kisom/goutils/logging"
"git.wntrmute.dev/kyle/goutils/logging"
)
var log = logging.NewConsole()

View File

@@ -8,6 +8,67 @@ import (
)
// Logger provides a standardised logging interface.
//
// Log messages consist of four components:
//
// 1. The **level** attaches a notion of priority to the log message.
// Several log levels are available:
//
// + FATAL (32): the system is in an unsuable state, and cannot
// continue to run. Most of the logging for this will cause the
// program to exit with an error code.
// + CRITICAL (16): critical conditions. The error, if uncorrected, is
// likely to cause a fatal condition shortly. An example is running
// out of disk space. This is something that the ops team should get
// paged for.
// + ERROR (8): error conditions. A single error doesn't require an
// ops team to be paged, but repeated errors should often trigger a
// page based on threshold triggers. An example is a network
// failure: it might be a transient failure (these do happen), but
// most of the time it's self-correcting.
// + WARNING (4): warning conditions. An example of this is a bad
// request sent to a server. This isn't an error on the part of the
// program, but it may be indicative of other things. Like errors,
// the ops team shouldn't be paged for errors, but a page might be
// triggered if a certain threshold of warnings is reached (which is
// typically much higher than errors). For example, repeated
// warnings might be a sign that the system is under attack.
// + INFO (2): informational message. This is a normal log message
// that is used to deliver information, such as recording
// requests. Ops teams are never paged for informational
// messages. This is the default log level.
// + DEBUG (1): debug-level message. These are only used during
// development or if a deployed system repeatedly sees abnormal
// errors.
//
// The numeric values indicate the priority of a given level.
//
// 2. The **actor** is used to specify which component is generating
// the log message. This could be the program name, or it could be
// a specific component inside the system.
//
// 3. The **event** is a short message indicating what happened. This is
// most like the traditional log message.
//
// 4. The **attributes** are an optional set of key-value string pairs that
// provide additional information.
//
// Additionally, each log message has an associated timestamp. For the
// text-based logs, this is "%FT%T%z"; for the binary logs, this is a
// 64-bit Unix timestamp. An example text-based timestamp might look like ::
//
// [2016-03-27T20:59:27-0700] [INFO] [actor:server event:request received] client=192.168.2.5 request-size=839
//
// Note that this is organised in a manner that facilitates parsing::
//
// /\[(\d{4}-\d{3}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4})\] \[(\w+\)]\) \[actor:(.+?) event:(.+?)\]/
//
// will cover the header:
//
// + ``$1`` contains the timestamp
// + ``$2`` contains the level
// + ``$3`` contains the actor
// + ``$4`` contains the event
type Logger interface {
// SetLevel sets the minimum log level.
SetLevel(Level)
@@ -23,66 +84,6 @@ type Logger interface {
// Close gives the Logger the opportunity to perform any cleanup.
Close() error
// Log messages consist of four components:
//
// 1. The **level** attaches a notion of priority to the log message.
// Several log levels are available:
//
// + FATAL (32): the system is in an unsuable state, and cannot
// continue to run. Most of the logging for this will cause the
// program to exit with an error code.
// + CRITICAL (16): critical conditions. The error, if uncorrected, is
// likely to cause a fatal condition shortly. An example is running
// out of disk space. This is something that the ops team should get
// paged for.
// + ERROR (8): error conditions. A single error doesn't require an
// ops team to be paged, but repeated errors should often trigger a
// page based on threshold triggers. An example is a network
// failure: it might be a transient failure (these do happen), but
// most of the time it's self-correcting.
// + WARNING (4): warning conditions. An example of this is a bad
// request sent to a server. This isn't an error on the part of the
// program, but it may be indicative of other things. Like errors,
// the ops team shouldn't be paged for errors, but a page might be
// triggered if a certain threshold of warnings is reached (which is
// typically much higher than errors). For example, repeated
// warnings might be a sign that the system is under attack.
// + INFO (2): informational message. This is a normal log message
// that is used to deliver information, such as recording
// requests. Ops teams are never paged for informational
// messages. This is the default log level.
// + DEBUG (1): debug-level message. These are only used during
// development or if a deployed system repeatedly sees abnormal
// errors.
//
// The numeric values indicate the priority of a given level.
//
// 2. The **actor** is used to specify which component is generating
// the log message. This could be the program name, or it could be
// a specific component inside the system.
//
// 3. The **event** is a short message indicating what happened. This is
// most like the traditional log message.
//
// 4. The **attributes** are an optional set of key-value string pairs that
// provide additional information.
//
// Additionally, each log message has an associated timestamp. For the
// text-based logs, this is "%FT%T%z"; for the binary logs, this is a
// 64-bit Unix timestamp. An example text-based timestamp might look like ::
//
// [2016-03-27T20:59:27-0700] [INFO] [actor:server event:request received] client=192.168.2.5 request-size=839
//
// Note that this is organised in a manner that facilitates parsing::
//
// /\[(\d{4}-\d{3}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4})\] \[(\w+\)]\) \[actor:(.+?) event:(.+?)\]/
//
// will cover the header:
//
// + ``$1`` contains the timestamp
// + ``$2`` contains the level
// + ``$3`` contains the actor
// + ``$4`` contains the event
Debug(actor, event string, attrs map[string]string)
Info(actor, event string, attrs map[string]string)
Warn(actor, event string, attrs map[string]string)

19
mwc/BUILD.bazel Normal file
View File

@@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "mwc",
srcs = ["mwc.go"],
importpath = "git.wntrmute.dev/kyle/goutils/mwc",
visibility = ["//visibility:public"],
)
go_test(
name = "mwc_test",
size = "small",
srcs = ["mwc_test.go"],
embed = [":mwc"],
deps = [
"//assert",
"//testio",
],
)

View File

@@ -4,8 +4,8 @@ import (
"bytes"
"testing"
"git.sr.ht/~kisom/goutils/assert"
"git.sr.ht/~kisom/goutils/testio"
"git.wntrmute.dev/kyle/goutils/assert"
"git.wntrmute.dev/kyle/goutils/testio"
)
func TestMWC(t *testing.T) {

15
rand/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "rand",
srcs = ["rand.go"],
importpath = "git.wntrmute.dev/kyle/goutils/rand",
visibility = ["//visibility:public"],
)
go_test(
name = "rand_test",
size = "small",
srcs = ["rand_test.go"],
embed = [":rand"],
)

16
sbuf/BUILD.bazel Normal file
View File

@@ -0,0 +1,16 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "sbuf",
srcs = ["sbuf.go"],
importpath = "git.wntrmute.dev/kyle/goutils/sbuf",
visibility = ["//visibility:public"],
)
go_test(
name = "sbuf_test",
size = "small",
srcs = ["sbuf_test.go"],
embed = [":sbuf"],
deps = ["@org_golang_x_crypto//nacl/box"],
)

16
seekbuf/BUILD.bazel Normal file
View File

@@ -0,0 +1,16 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "seekbuf",
srcs = ["seekbuf.go"],
importpath = "git.wntrmute.dev/kyle/goutils/seekbuf",
visibility = ["//visibility:public"],
)
go_test(
name = "seekbuf_test",
size = "small",
srcs = ["seekbuf_test.go"],
embed = [":seekbuf"],
deps = ["//assert"],
)

View File

@@ -1,3 +1,4 @@
// Package seekbuf implements a read-seekable buffer.
package seekbuf
import "io"
@@ -40,7 +41,7 @@ func (b *Buffer) Seek(pos int) {
// Rewind resets the read pointer to 0.
func (b *Buffer) Rewind() {
b.pos = 0
b.Seek(0)
}
// Close clears all the data out of the buffer and sets the read position to 0.
@@ -49,3 +50,8 @@ func (b *Buffer) Close() error {
b.pos = 0
return nil
}
// Len returns the length of data remaining to be read.
func (b *Buffer) Len() int {
return len(b.data[b.pos:])
}

39
seekbuf/seekbuf_test.go Normal file
View File

@@ -0,0 +1,39 @@
package seekbuf
import (
"fmt"
"testing"
"git.wntrmute.dev/kyle/goutils/assert"
)
func TestSeeking(t *testing.T) {
partA := []byte("hello, ")
partB := []byte("world!")
buf := New(partA)
assert.BoolT(t, buf.Len() == len(partA), fmt.Sprintf("on init: have length %d, want length %d", buf.Len(), len(partA)))
b := make([]byte, 32)
n, err := buf.Read(b)
assert.NoErrorT(t, err)
assert.BoolT(t, buf.Len() == 0, fmt.Sprintf("after reading 1: have length %d, want length 0", buf.Len()))
assert.BoolT(t, n == len(partA), fmt.Sprintf("after reading 2: have length %d, want length %d", n, len(partA)))
n, err = buf.Write(partB)
assert.NoErrorT(t, err)
assert.BoolT(t, n == len(partB), fmt.Sprintf("after writing: have length %d, want length %d", n, len(partB)))
n, err = buf.Read(b)
assert.NoErrorT(t, err)
assert.BoolT(t, buf.Len() == 0, fmt.Sprintf("after rereading 1: have length %d, want length 0", buf.Len()))
assert.BoolT(t, n == len(partB), fmt.Sprintf("after rereading 2: have length %d, want length %d", n, len(partB)))
partsLen := len(partA) + len(partB)
buf.Rewind()
assert.BoolT(t, buf.Len() == partsLen, fmt.Sprintf("after rewinding: have length %d, want length %d", buf.Len(), partsLen))
buf.Close()
assert.BoolT(t, buf.Len() == 0, fmt.Sprintf("after closing, have length %d, want length 0", buf.Len()))
}

17
syslog/BUILD.bazel Normal file
View File

@@ -0,0 +1,17 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "log",
srcs = ["logger.go"],
importpath = "git.wntrmute.dev/kyle/kdhcp/log",
visibility = ["//visibility:public"],
deps = ["@com_github_hashicorp_go_syslog//:go-syslog"],
)
go_library(
name = "syslog",
srcs = ["logger.go"],
importpath = "git.wntrmute.dev/kyle/goutils/syslog",
visibility = ["//visibility:public"],
deps = ["@com_github_hashicorp_go_syslog//:go-syslog"],
)

257
syslog/logger.go Normal file
View File

@@ -0,0 +1,257 @@
// Package syslog is a syslog-type facility for logging.
package syslog
import (
"fmt"
"os"
"strings"
"time"
gsyslog "github.com/hashicorp/go-syslog"
)
type logger struct {
l gsyslog.Syslogger
p gsyslog.Priority
}
func (log *logger) printf(p gsyslog.Priority, format string, args ...interface{}) {
if !strings.HasSuffix(format, "\n") {
format += "\n"
}
if p <= log.p {
fmt.Printf("%s [%s] ", prioritiev[p], timestamp())
fmt.Printf(format, args...)
}
if log.l != nil {
log.l.WriteLevel(p, []byte(fmt.Sprintf(format, args...)))
}
}
func (log *logger) print(p gsyslog.Priority, args ...interface{}) {
if p <= log.p {
fmt.Printf("%s [%s] ", prioritiev[p], timestamp())
fmt.Print(args...)
}
if log.l != nil {
log.l.WriteLevel(p, []byte(fmt.Sprint(args...)))
}
}
func (log *logger) println(p gsyslog.Priority, args ...interface{}) {
if p <= log.p {
fmt.Printf("%s [%s] ", prioritiev[p], timestamp())
fmt.Println(args...)
}
if log.l != nil {
log.l.WriteLevel(p, []byte(fmt.Sprintln(args...)))
}
}
func (log *logger) adjustPriority(level string) error {
priority, ok := priorities[level]
if !ok {
return fmt.Errorf("log: unknown priority %s", level)
}
log.p = priority
return nil
}
var log = &logger{p: gsyslog.LOG_WARNING}
var priorities = map[string]gsyslog.Priority{
"EMERG": gsyslog.LOG_EMERG,
"ALERT": gsyslog.LOG_ALERT,
"CRIT": gsyslog.LOG_CRIT,
"ERR": gsyslog.LOG_ERR,
"WARNING": gsyslog.LOG_WARNING,
"NOTICE": gsyslog.LOG_NOTICE,
"INFO": gsyslog.LOG_INFO,
"DEBUG": gsyslog.LOG_DEBUG,
}
var prioritiev = map[gsyslog.Priority]string{
gsyslog.LOG_EMERG: "EMERG",
gsyslog.LOG_ALERT: "ALERT",
gsyslog.LOG_CRIT: "CRIT",
gsyslog.LOG_ERR: "ERR",
gsyslog.LOG_WARNING: "WARNING",
gsyslog.LOG_NOTICE: "NOTICE",
gsyslog.LOG_INFO: "INFO",
gsyslog.LOG_DEBUG: "DEBUG",
}
func timestamp() string {
return time.Now().Format("2006-01-02 15:04:05 MST")
}
type Options struct {
Level string
Tag string
Facility string
WriteSyslog bool
}
// DefaultOptions returns a sane set of defaults for syslog, using the program
// name as the tag name. withSyslog controls whether logs should be sent to
// syslog, too.
func DefaultOptions(tag string, withSyslog bool) *Options {
if tag == "" {
tag = os.Args[0]
}
return &Options{
Level: "WARNING",
Tag: tag,
Facility: "daemon",
WriteSyslog: withSyslog,
}
}
// DefaultDebugOptions returns a sane set of debug defaults for syslog,
// using the program name as the tag name. withSyslog controls whether logs
// should be sent to syslog, too.
func DefaultDebugOptions(tag string, withSyslog bool) *Options {
if tag == "" {
tag = os.Args[0]
}
return &Options{
Level: "DEBUG",
Facility: "daemon",
WriteSyslog: withSyslog,
}
}
func Setup(opts *Options) error {
priority, ok := priorities[opts.Level]
if !ok {
return fmt.Errorf("log: unknown priority %s", opts.Level)
}
log.p = priority
var err error
log.l, err = gsyslog.NewLogger(priority, opts.Facility, opts.Tag)
if err != nil {
return err
}
return nil
}
func Debug(args ...interface{}) {
log.print(gsyslog.LOG_DEBUG, args...)
}
func Info(args ...interface{}) {
log.print(gsyslog.LOG_INFO, args...)
}
func Notice(args ...interface{}) {
log.print(gsyslog.LOG_NOTICE, args...)
}
func Warning(args ...interface{}) {
log.print(gsyslog.LOG_WARNING, args...)
}
func Err(args ...interface{}) {
log.print(gsyslog.LOG_ERR, args...)
}
func Crit(args ...interface{}) {
log.print(gsyslog.LOG_CRIT, args...)
}
func Alert(args ...interface{}) {
log.print(gsyslog.LOG_ALERT, args...)
}
func Emerg(args ...interface{}) {
log.print(gsyslog.LOG_EMERG, args...)
}
func Debugln(args ...interface{}) {
log.println(gsyslog.LOG_DEBUG, args...)
}
func Infoln(args ...interface{}) {
log.println(gsyslog.LOG_INFO, args...)
}
func Noticeln(args ...interface{}) {
log.println(gsyslog.LOG_NOTICE, args...)
}
func Warningln(args ...interface{}) {
log.print(gsyslog.LOG_WARNING, args...)
}
func Errln(args ...interface{}) {
log.println(gsyslog.LOG_ERR, args...)
}
func Critln(args ...interface{}) {
log.println(gsyslog.LOG_CRIT, args...)
}
func Alertln(args ...interface{}) {
log.println(gsyslog.LOG_ALERT, args...)
}
func Emergln(args ...interface{}) {
log.println(gsyslog.LOG_EMERG, args...)
}
func Debugf(format string, args ...interface{}) {
log.printf(gsyslog.LOG_DEBUG, format, args...)
}
func Infof(format string, args ...interface{}) {
log.printf(gsyslog.LOG_INFO, format, args...)
}
func Noticef(format string, args ...interface{}) {
log.printf(gsyslog.LOG_NOTICE, format, args...)
}
func Warningf(format string, args ...interface{}) {
log.printf(gsyslog.LOG_WARNING, format, args...)
}
func Errf(format string, args ...interface{}) {
log.printf(gsyslog.LOG_ERR, format, args...)
}
func Critf(format string, args ...interface{}) {
log.printf(gsyslog.LOG_CRIT, format, args...)
}
func Alertf(format string, args ...interface{}) {
log.printf(gsyslog.LOG_ALERT, format, args...)
}
func Emergf(format string, args ...interface{}) {
log.printf(gsyslog.LOG_EMERG, format, args...)
os.Exit(1)
}
func Fatal(args ...interface{}) {
log.println(gsyslog.LOG_ERR, args...)
os.Exit(1)
}
func Fatalf(format string, args ...interface{}) {
log.printf(gsyslog.LOG_ERR, format, args...)
os.Exit(1)
}
func ChangePriority(level string) error {
return log.adjustPriority(level)
}

8
tee/BUILD.bazel Normal file
View File

@@ -0,0 +1,8 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "tee",
srcs = ["tee.go"],
importpath = "git.wntrmute.dev/kyle/goutils/tee",
visibility = ["//visibility:public"],
)

15
testio/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "testio",
srcs = ["testio.go"],
importpath = "git.wntrmute.dev/kyle/goutils/testio",
visibility = ["//visibility:public"],
)
go_test(
name = "testio_test",
size = "small",
srcs = ["testio_test.go"],
embed = [":testio"],
)

View File

@@ -9,7 +9,7 @@ This is a collection of various utility io types:
* LoggingBuffer
You can check out the
[godoc](https://godoc.org/github.com/kisom/goutils/testio) for dtails.
[godoc](https://godoc.io/git.wntrmute.dev/kyle/goutils/testio) for dtails.
It was imported from [kisom/testio](https://github.com/kisom/testio/). The
original Git directory is preserved in git-hist.tar.xz.

8
testutil/BUILD.bazel Normal file
View File

@@ -0,0 +1,8 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "testutil",
srcs = ["testutil.go"],
importpath = "git.wntrmute.dev/kyle/goutils/testutil",
visibility = ["//visibility:public"],
)