Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9091cc7682 | |||
| 74ce7bc58a | |||
| 8b2d10209e | |||
| 770100b688 | |||
| 29630c55a9 | |||
| 3c2ec896f8 | |||
| 7828726ba4 | |||
| 458f3ceaed | |||
| 2c45ae7b4e | |||
| c1b8b72cf1 | |||
| bfc7fedbf9 | |||
| 965312f48e | |||
| 237aa46ddd | |||
| f8c64d3be5 |
10
BUILD.bazel
10
BUILD.bazel
@@ -10,3 +10,13 @@ go_library(
|
||||
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",
|
||||
)
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -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
|
||||
|
||||
31
README.md
31
README.md
@@ -1,10 +1,12 @@
|
||||
GOUTILS
|
||||
|
||||
### Note: this repo is archived and not being maintained here anymore.
|
||||
|
||||
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:
|
||||
|
||||
@@ -25,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.
|
||||
@@ -60,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.
|
||||
|
||||
13
WORKSPACE
13
WORKSPACE
@@ -1,5 +1,7 @@
|
||||
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",
|
||||
@@ -20,20 +22,11 @@ http_archive(
|
||||
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
|
||||
|
||||
############################################################
|
||||
# Define your own dependencies here using go_repository.
|
||||
# Else, dependencies declared by rules_go/gazelle will be used.
|
||||
# The first declaration of an external repository "wins".
|
||||
############################################################
|
||||
|
||||
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()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/ahash",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@ht_sr_git_kisom_goutils//assert:go_default_library",
|
||||
"//assert",
|
||||
"@org_golang_x_crypto//blake2b",
|
||||
"@org_golang_x_crypto//blake2s",
|
||||
"@org_golang_x_crypto//md4",
|
||||
@@ -17,7 +17,8 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "ahash_test",
|
||||
size = "small",
|
||||
srcs = ["ahash_test.go"],
|
||||
embed = [":ahash"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//assert:go_default_library"],
|
||||
deps = ["//assert"],
|
||||
)
|
||||
|
||||
@@ -45,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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["certchain.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/certchain",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -6,9 +6,9 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/certexpiry",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//die",
|
||||
"//lib",
|
||||
"@com_github_cloudflare_cfssl//helpers",
|
||||
"@ht_sr_git_kisom_goutils//die:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//lib:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"git.wntrmute.dev/kyle/goutils/die"
|
||||
"git.wntrmute.dev/kyle/goutils/lib"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
)
|
||||
|
||||
var warnOnly bool
|
||||
|
||||
@@ -6,10 +6,10 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/certverify",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//die",
|
||||
"//lib",
|
||||
"@com_github_cloudflare_cfssl//helpers",
|
||||
"@com_github_cloudflare_cfssl//revoke",
|
||||
"@ht_sr_git_kisom_goutils//die:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//lib:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/revoke"
|
||||
"git.wntrmute.dev/kyle/goutils/die"
|
||||
"git.wntrmute.dev/kyle/goutils/lib"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/revoke"
|
||||
)
|
||||
|
||||
func printRevocation(cert *x509.Certificate) {
|
||||
|
||||
@@ -6,8 +6,8 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/clustersh",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//lib",
|
||||
"@com_github_pkg_sftp//:sftp",
|
||||
"@ht_sr_git_kisom_goutils//lib:go_default_library",
|
||||
"@org_golang_x_crypto//ssh",
|
||||
"@org_golang_x_crypto//ssh/agent",
|
||||
],
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["main.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/cruntar",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"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
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["pubdump.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/csrpubdump",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
19
cmd/diskimg/BUILD.bazel
Normal file
19
cmd/diskimg/BUILD.bazel
Normal 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
34
cmd/diskimg/README
Normal 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
116
cmd/diskimg/main.go
Normal 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)
|
||||
}
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["main.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/eig",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["fragment.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/fragment",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["jlp.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/jlp",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//lib:go_default_library"],
|
||||
deps = ["//lib"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["main.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/parts",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["pembody.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/pembody",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//lib:go_default_library"],
|
||||
deps = ["//lib"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -6,9 +6,9 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/pemit",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"@ht_sr_git_kisom_goutils//assert:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//die:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//lib:go_default_library",
|
||||
"//assert",
|
||||
"//die",
|
||||
"//lib",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/renfnv",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"@ht_sr_git_kisom_goutils//fileutil:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//lib:go_default_library",
|
||||
"//fileutil",
|
||||
"//lib",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/rhash",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"@ht_sr_git_kisom_goutils//ahash:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//die:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//lib:go_default_library",
|
||||
"//ahash",
|
||||
"//die",
|
||||
"//lib",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/showimp",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"@ht_sr_git_kisom_goutils//die:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//logging:go_default_library",
|
||||
"//die",
|
||||
"//logging",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -12,36 +12,23 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"git.wntrmute.dev/kyle/goutils/dbg"
|
||||
"git.wntrmute.dev/kyle/goutils/die"
|
||||
"git.wntrmute.dev/kyle/goutils/logging"
|
||||
)
|
||||
|
||||
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 {
|
||||
|
||||
@@ -6,8 +6,8 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/ski",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"@ht_sr_git_kisom_goutils//die:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//lib:go_default_library",
|
||||
"//die",
|
||||
"//lib",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["main.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/sprox",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["main.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/stealchain-server",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["thief.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/stealchain",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -6,8 +6,8 @@ go_library(
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/subjhash",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"@ht_sr_git_kisom_goutils//die:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//lib:go_default_library",
|
||||
"//die",
|
||||
"//lib",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["main.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/cmd/tlskeypair",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//die:go_default_library"],
|
||||
deps = ["//die"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
@@ -8,11 +8,12 @@ go_library(
|
||||
],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/config",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//config/iniconf:go_default_library"],
|
||||
deps = ["//config/iniconf"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "config_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"config_test.go",
|
||||
"path_test.go",
|
||||
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "iniconf_test",
|
||||
size = "small",
|
||||
srcs = ["iniconf_test.go"],
|
||||
data = glob(["testdata/**"]),
|
||||
embed = [":iniconf"],
|
||||
|
||||
@@ -9,10 +9,11 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "dbg_test",
|
||||
size = "small",
|
||||
srcs = ["dbg_test.go"],
|
||||
embed = [":dbg"],
|
||||
deps = [
|
||||
"//testio",
|
||||
"@com_github_stretchr_testify//require",
|
||||
"@ht_sr_git_kisom_goutils//testio:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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...)
|
||||
}
|
||||
|
||||
27
deps.bzl
27
deps.bzl
@@ -91,6 +91,13 @@ def go_dependencies():
|
||||
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",
|
||||
@@ -304,8 +311,8 @@ def go_dependencies():
|
||||
go_repository(
|
||||
name = "org_golang_x_crypto",
|
||||
importpath = "golang.org/x/crypto",
|
||||
sum = "h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc=",
|
||||
version = "v0.0.0-20201124201722-c8d3bf9c5392",
|
||||
sum = "h1:Qwe1rC8PSniVfAFPFJeyUkB+zcysC3RgJBAGk7eqBEU=",
|
||||
version = "v0.0.0-20220314234659-1baeb1ce4c0b",
|
||||
)
|
||||
go_repository(
|
||||
name = "org_golang_x_lint",
|
||||
@@ -316,26 +323,26 @@ def go_dependencies():
|
||||
go_repository(
|
||||
name = "org_golang_x_net",
|
||||
importpath = "golang.org/x/net",
|
||||
sum = "h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=",
|
||||
version = "v0.0.0-20201010224723-4f7140c49acb",
|
||||
sum = "h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=",
|
||||
version = "v0.0.0-20211112202133-69e39bad7dc2",
|
||||
)
|
||||
go_repository(
|
||||
name = "org_golang_x_sys",
|
||||
importpath = "golang.org/x/sys",
|
||||
sum = "h1:f1CIuDlJhwANEC2MM87MBEVMr3jl5bifgsfj90XAF9c=",
|
||||
version = "v0.0.0-20201126233918-771906719818",
|
||||
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:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=",
|
||||
version = "v0.0.0-20201117132131-f5c789dd3221",
|
||||
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:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=",
|
||||
version = "v0.3.3",
|
||||
sum = "h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=",
|
||||
version = "v0.3.6",
|
||||
)
|
||||
go_repository(
|
||||
name = "org_golang_x_tools",
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
// Package fileutil contains common file functions.
|
||||
package fileutil
|
||||
|
||||
|
||||
49
fileutil/fileutil_windows.go
Normal file
49
fileutil/fileutil_windows.go
Normal 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
16
fileutil/symlinks.go
Normal 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)
|
||||
}
|
||||
8
go.mod
8
go.mod
@@ -1,15 +1,15 @@
|
||||
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
21
go.sum
@@ -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=
|
||||
|
||||
@@ -110,7 +110,8 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "lib_test",
|
||||
size = "small",
|
||||
srcs = ["lib_test.go"],
|
||||
embed = [":lib"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//assert:go_default_library"],
|
||||
deps = ["//assert"],
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -15,10 +15,10 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "logging_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"example_test.go",
|
||||
"log_test.go",
|
||||
],
|
||||
embed = [":logging"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//logging:go_default_library"],
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ go_library(
|
||||
srcs = ["example.go"],
|
||||
importpath = "git.wntrmute.dev/kyle/goutils/logging/example",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@ht_sr_git_kisom_goutils//logging:go_default_library"],
|
||||
deps = ["//logging"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
||||
121
logging/log.go
121
logging/log.go
@@ -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)
|
||||
|
||||
@@ -9,10 +9,11 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "mwc_test",
|
||||
size = "small",
|
||||
srcs = ["mwc_test.go"],
|
||||
embed = [":mwc"],
|
||||
deps = [
|
||||
"@ht_sr_git_kisom_goutils//assert:go_default_library",
|
||||
"@ht_sr_git_kisom_goutils//testio:go_default_library",
|
||||
"//assert",
|
||||
"//testio",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "rand_test",
|
||||
size = "small",
|
||||
srcs = ["rand_test.go"],
|
||||
embed = [":rand"],
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "sbuf_test",
|
||||
size = "small",
|
||||
srcs = ["sbuf_test.go"],
|
||||
embed = [":sbuf"],
|
||||
deps = ["@org_golang_x_crypto//nacl/box"],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "seekbuf",
|
||||
@@ -6,3 +6,11 @@ go_library(
|
||||
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"],
|
||||
)
|
||||
|
||||
@@ -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
39
seekbuf/seekbuf_test.go
Normal 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
17
syslog/BUILD.bazel
Normal 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"],
|
||||
)
|
||||
269
syslog/logger.go
Normal file
269
syslog/logger.go
Normal file
@@ -0,0 +1,269 @@
|
||||
// Package syslog is a syslog-type facility for logging.
|
||||
package syslog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
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) spew(args ...interface{}) {
|
||||
if log.p == gsyslog.LOG_DEBUG {
|
||||
spew.Dump(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)
|
||||
}
|
||||
|
||||
// Spew will pretty print the args if the logger is set to DEBUG priority.
|
||||
func Spew(args ...interface{}) {
|
||||
log.spew(args...)
|
||||
}
|
||||
|
||||
func ChangePriority(level string) error {
|
||||
return log.adjustPriority(level)
|
||||
}
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "testio_test",
|
||||
size = "small",
|
||||
srcs = ["testio_test.go"],
|
||||
embed = [":testio"],
|
||||
)
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user