mirror of
https://github.com/stashapp/stash.git
synced 2025-12-11 10:54:14 +01:00
* Upgrade gqlgen to v0.17.2 This enables builds on Go 1.18. github.com/vektah/gqlparser is upgraded to the newest version too. Getting this to work is a bit of a hazzle. I had to first remove vendoring from the repository, perform the upgrade and then re-introduce the vendor directory. I think gqlgens analysis went wrong for some reason on the upgrade. It would seem a clean-room installation fixed it. * Bump project to 1.18 * Update all packages, address gqlgenc breaking changes * Let `go mod tidy` handle the go.mod file * Upgrade linter to 1.45.2 * Introduce v1.45.2 of the linter The linter now correctly warns on `strings.Title` because it isn't unicode-aware. Fix this by using the suggested fix from x/text/cases to produce unicode-aware strings. The mapping isn't entirely 1-1 as this new approach has a larger iface: it spans all of unicode rather than just ASCII. It coincides for ASCII however, so things should be largely the same. * Ready ourselves for errchkjson and contextcheck. * Revert dockerfile golang version changes for now Co-authored-by: Kermie <kermie@isinthe.house> Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
154 lines
3.7 KiB
Go
154 lines
3.7 KiB
Go
package zerolog
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"path"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// LevelWriter defines as interface a writer may implement in order
|
|
// to receive level information with payload.
|
|
type LevelWriter interface {
|
|
io.Writer
|
|
WriteLevel(level Level, p []byte) (n int, err error)
|
|
}
|
|
|
|
type levelWriterAdapter struct {
|
|
io.Writer
|
|
}
|
|
|
|
func (lw levelWriterAdapter) WriteLevel(l Level, p []byte) (n int, err error) {
|
|
return lw.Write(p)
|
|
}
|
|
|
|
type syncWriter struct {
|
|
mu sync.Mutex
|
|
lw LevelWriter
|
|
}
|
|
|
|
// SyncWriter wraps w so that each call to Write is synchronized with a mutex.
|
|
// This syncer can be used to wrap the call to writer's Write method if it is
|
|
// not thread safe. Note that you do not need this wrapper for os.File Write
|
|
// operations on POSIX and Windows systems as they are already thread-safe.
|
|
func SyncWriter(w io.Writer) io.Writer {
|
|
if lw, ok := w.(LevelWriter); ok {
|
|
return &syncWriter{lw: lw}
|
|
}
|
|
return &syncWriter{lw: levelWriterAdapter{w}}
|
|
}
|
|
|
|
// Write implements the io.Writer interface.
|
|
func (s *syncWriter) Write(p []byte) (n int, err error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
return s.lw.Write(p)
|
|
}
|
|
|
|
// WriteLevel implements the LevelWriter interface.
|
|
func (s *syncWriter) WriteLevel(l Level, p []byte) (n int, err error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
return s.lw.WriteLevel(l, p)
|
|
}
|
|
|
|
type multiLevelWriter struct {
|
|
writers []LevelWriter
|
|
}
|
|
|
|
func (t multiLevelWriter) Write(p []byte) (n int, err error) {
|
|
for _, w := range t.writers {
|
|
if _n, _err := w.Write(p); err == nil {
|
|
n = _n
|
|
if _err != nil {
|
|
err = _err
|
|
} else if _n != len(p) {
|
|
err = io.ErrShortWrite
|
|
}
|
|
}
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
func (t multiLevelWriter) WriteLevel(l Level, p []byte) (n int, err error) {
|
|
for _, w := range t.writers {
|
|
if _n, _err := w.WriteLevel(l, p); err == nil {
|
|
n = _n
|
|
if _err != nil {
|
|
err = _err
|
|
} else if _n != len(p) {
|
|
err = io.ErrShortWrite
|
|
}
|
|
}
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
// MultiLevelWriter creates a writer that duplicates its writes to all the
|
|
// provided writers, similar to the Unix tee(1) command. If some writers
|
|
// implement LevelWriter, their WriteLevel method will be used instead of Write.
|
|
func MultiLevelWriter(writers ...io.Writer) LevelWriter {
|
|
lwriters := make([]LevelWriter, 0, len(writers))
|
|
for _, w := range writers {
|
|
if lw, ok := w.(LevelWriter); ok {
|
|
lwriters = append(lwriters, lw)
|
|
} else {
|
|
lwriters = append(lwriters, levelWriterAdapter{w})
|
|
}
|
|
}
|
|
return multiLevelWriter{lwriters}
|
|
}
|
|
|
|
// TestingLog is the logging interface of testing.TB.
|
|
type TestingLog interface {
|
|
Log(args ...interface{})
|
|
Logf(format string, args ...interface{})
|
|
Helper()
|
|
}
|
|
|
|
// TestWriter is a writer that writes to testing.TB.
|
|
type TestWriter struct {
|
|
T TestingLog
|
|
|
|
// Frame skips caller frames to capture the original file and line numbers.
|
|
Frame int
|
|
}
|
|
|
|
// NewTestWriter creates a writer that logs to the testing.TB.
|
|
func NewTestWriter(t TestingLog) TestWriter {
|
|
return TestWriter{T: t}
|
|
}
|
|
|
|
// Write to testing.TB.
|
|
func (t TestWriter) Write(p []byte) (n int, err error) {
|
|
t.T.Helper()
|
|
|
|
n = len(p)
|
|
|
|
// Strip trailing newline because t.Log always adds one.
|
|
p = bytes.TrimRight(p, "\n")
|
|
|
|
// Try to correct the log file and line number to the caller.
|
|
if t.Frame > 0 {
|
|
_, origFile, origLine, _ := runtime.Caller(1)
|
|
_, frameFile, frameLine, ok := runtime.Caller(1 + t.Frame)
|
|
if ok {
|
|
erase := strings.Repeat("\b", len(path.Base(origFile))+len(strconv.Itoa(origLine))+3)
|
|
t.T.Logf("%s%s:%d: %s", erase, path.Base(frameFile), frameLine, p)
|
|
return n, err
|
|
}
|
|
}
|
|
t.T.Log(string(p))
|
|
|
|
return n, err
|
|
}
|
|
|
|
// ConsoleTestWriter creates an option that correctly sets the file frame depth for testing.TB log.
|
|
func ConsoleTestWriter(t TestingLog) func(w *ConsoleWriter) {
|
|
return func(w *ConsoleWriter) {
|
|
w.Out = TestWriter{T: t, Frame: 6}
|
|
}
|
|
}
|