Add testable CLI with dependency injection and new scanner/checker packages
Major changes: - Refactor CLI to accept injected I/O streams and filesystem (afero.Fs) for testing without touching the real filesystem - Add RunOptions struct and RunWithOptions() for configurable CLI execution - Add internal/scanner package with two-phase manifest generation: - Phase 1 (Enumeration): walk directories, collect metadata - Phase 2 (Scan): read contents, compute hashes, write manifest - Add internal/checker package for manifest verification with progress reporting and channel-based result streaming - Add mfer/builder.go for incremental manifest construction - Add --no-extra-files flag to check command to detect files not in manifest - Add timing summaries showing file count, size, elapsed time, and throughput - Add comprehensive tests using afero.MemMapFs (no real filesystem access) - Add contrib/usage.sh integration test script - Fix banner ASCII art alignment (consistent spacing) - Fix verbosity levels so summaries display at default log level - Update internal/log to support configurable output writers
This commit is contained in:
@@ -2,7 +2,10 @@ package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"github.com/apex/log"
|
||||
acli "github.com/apex/log/handlers/cli"
|
||||
@@ -12,6 +15,39 @@ import (
|
||||
|
||||
type Level = log.Level
|
||||
|
||||
var (
|
||||
// mu protects the output writers
|
||||
mu sync.RWMutex
|
||||
// stdout is the writer for progress output
|
||||
stdout io.Writer = os.Stdout
|
||||
// stderr is the writer for log output
|
||||
stderr io.Writer = os.Stderr
|
||||
)
|
||||
|
||||
// SetOutput configures the output writers for the log package.
|
||||
// stdout is used for progress output, stderr is used for log messages.
|
||||
func SetOutput(out, err io.Writer) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
stdout = out
|
||||
stderr = err
|
||||
pterm.SetDefaultOutput(out)
|
||||
}
|
||||
|
||||
// GetStdout returns the configured stdout writer.
|
||||
func GetStdout() io.Writer {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
return stdout
|
||||
}
|
||||
|
||||
// GetStderr returns the configured stderr writer.
|
||||
func GetStderr() io.Writer {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
return stderr
|
||||
}
|
||||
|
||||
func DisableStyling() {
|
||||
pterm.DisableColor()
|
||||
pterm.DisableStyling()
|
||||
@@ -24,10 +60,21 @@ func DisableStyling() {
|
||||
}
|
||||
|
||||
func Init() {
|
||||
log.SetHandler(acli.Default)
|
||||
mu.RLock()
|
||||
w := stderr
|
||||
mu.RUnlock()
|
||||
log.SetHandler(acli.New(w))
|
||||
log.SetLevel(log.InfoLevel)
|
||||
}
|
||||
|
||||
func Infof(format string, args ...interface{}) {
|
||||
log.Infof(format, args...)
|
||||
}
|
||||
|
||||
func Info(arg string) {
|
||||
log.Info(arg)
|
||||
}
|
||||
|
||||
func Debugf(format string, args ...interface{}) {
|
||||
DebugReal(fmt.Sprintf(format, args...), 2)
|
||||
}
|
||||
@@ -55,14 +102,13 @@ func EnableDebugLogging() {
|
||||
|
||||
func VerbosityStepsToLogLevel(l int) log.Level {
|
||||
switch l {
|
||||
case 1:
|
||||
return log.WarnLevel
|
||||
case 2:
|
||||
case 0:
|
||||
return log.InfoLevel
|
||||
case 3:
|
||||
case 1:
|
||||
return log.DebugLevel
|
||||
}
|
||||
return log.ErrorLevel
|
||||
// -vv or more
|
||||
return log.DebugLevel
|
||||
}
|
||||
|
||||
func SetLevelFromVerbosity(l int) {
|
||||
@@ -87,3 +133,14 @@ func GetLevel() log.Level {
|
||||
func WithError(e error) *log.Entry {
|
||||
return GetLogger().WithError(e)
|
||||
}
|
||||
|
||||
// Progressf prints a progress message that overwrites the current line.
|
||||
// Use ProgressDone() when progress is complete to move to the next line.
|
||||
func Progressf(format string, args ...interface{}) {
|
||||
pterm.Printf("\r"+format, args...)
|
||||
}
|
||||
|
||||
// ProgressDone completes a progress line by printing a newline.
|
||||
func ProgressDone() {
|
||||
pterm.Println()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user