103 lines
2.1 KiB
Go
103 lines
2.1 KiB
Go
package logging
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"code.icb4dc0.de/buildr/buildr/internal/ioutils"
|
|
)
|
|
|
|
type OutputSource string
|
|
|
|
const (
|
|
OutputSourceStdout OutputSource = "stdout"
|
|
OutputSourceStderr OutputSource = "stderr"
|
|
)
|
|
|
|
type LogFileNameFormatter interface {
|
|
LogFileName(src OutputSource) string
|
|
}
|
|
|
|
type LogFileNameFormatterFunc func(src OutputSource) string
|
|
|
|
func (f LogFileNameFormatterFunc) LogFileName(src OutputSource) string {
|
|
return f(src)
|
|
}
|
|
|
|
func NewTaskOutputSink(logsDirectory string, logToStdErr bool, formatter LogFileNameFormatter) (sink TaskOutputSink, err error) {
|
|
fileSink := fileOutputSink{
|
|
logToStdErr: logToStdErr,
|
|
}
|
|
|
|
if logToStdErr {
|
|
if fileSink.stdOut, err = os.CreateTemp(os.TempDir(), "buildr-*.stdout.log"); err != nil {
|
|
return nil, err
|
|
}
|
|
if fileSink.stdErr, err = os.CreateTemp(os.TempDir(), "buildr-*.stderr.log"); err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if fileSink.stdOut, err = os.Create(filepath.Join(logsDirectory, formatter.LogFileName(OutputSourceStdout))); err != nil {
|
|
return nil, err
|
|
}
|
|
if fileSink.stdErr, err = os.Create(filepath.Join(logsDirectory, formatter.LogFileName(OutputSourceStderr))); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return fileSink, nil
|
|
}
|
|
|
|
var _ TaskOutputSink = (*fileOutputSink)(nil)
|
|
|
|
type file interface {
|
|
Name() string
|
|
io.ReadWriter
|
|
io.Seeker
|
|
io.Closer
|
|
}
|
|
|
|
type fileOutputSink struct {
|
|
stdOut file
|
|
stdErr file
|
|
logToStdErr bool
|
|
}
|
|
|
|
func (f fileOutputSink) StdOut() io.Writer {
|
|
return f.stdOut
|
|
}
|
|
|
|
func (f fileOutputSink) StdErr() io.Writer {
|
|
return f.stdErr
|
|
}
|
|
|
|
func (f fileOutputSink) Close() error {
|
|
if f.logToStdErr {
|
|
return errors.Join(
|
|
f.copyToStdErrAndClose(f.stdOut),
|
|
f.copyToStdErrAndClose(f.stdErr),
|
|
)
|
|
}
|
|
|
|
return errors.Join(
|
|
f.stdOut.Close(),
|
|
f.stdErr.Close(),
|
|
)
|
|
}
|
|
|
|
func (f fileOutputSink) copyToStdErrAndClose(src file) error {
|
|
return AcquireStdErr(func(stdErr io.Writer) error {
|
|
if _, err := src.Seek(0, 0); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := ioutils.CopyWithPooledBuffer(stdErr, src); err != nil {
|
|
return err
|
|
}
|
|
|
|
return errors.Join(src.Close(), os.Remove(src.Name()))
|
|
})
|
|
}
|