Skip to content

Commit

Permalink
feat: remove globals from stats package
Browse files Browse the repository at this point in the history
Signed-off-by: Brian McGee <[email protected]>
  • Loading branch information
brianmcgee committed Oct 8, 2024
1 parent 3ee8d07 commit aa0dc25
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 175 deletions.
12 changes: 6 additions & 6 deletions cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ type Entry struct {
}

var (
db *bolt.DB
logger *log.Logger
db *bolt.DB //nolint:gochecknoglobals
logger *log.Logger //nolint:gochecknoglobals

ReadBatchSize = 1024 * runtime.NumCPU()
ReadBatchSize = 1024 * runtime.NumCPU() //nolint:gochecknoglobals
)

// Open creates an instance of bolt.DB for a given treeRoot path.
Expand Down Expand Up @@ -187,7 +187,7 @@ func putEntry(bucket *bolt.Bucket, path string, entry *Entry) error {

// ChangeSet is used to walk a filesystem, starting at root, and outputting any new or changed paths using pathsCh.
// It determines if a path is new or has changed by comparing against cache entries.
func ChangeSet(ctx context.Context, walker walk.Walker, filesCh chan<- *walk.File) error {
func ChangeSet(ctx context.Context, statz *stats.Stats, walker walk.Walker, filesCh chan<- *walk.File) error {
start := time.Now()

defer func() {
Expand Down Expand Up @@ -238,14 +238,14 @@ func ChangeSet(ctx context.Context, walker walk.Walker, filesCh chan<- *walk.Fil

changedOrNew := cached == nil || !(cached.Modified == file.Info.ModTime() && cached.Size == file.Info.Size())

stats.Add(stats.Traversed, 1)
statz.Add(stats.Traversed, 1)

if !changedOrNew {
// no change
return nil
}

stats.Add(stats.Emitted, 1)
statz.Add(stats.Emitted, 1)

// pass on the path
select {
Expand Down
38 changes: 22 additions & 16 deletions cmd/format/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,14 @@ const (

var ErrFailOnChange = errors.New("unexpected changes detected, --fail-on-change is enabled")

func Run(v *viper.Viper, cmd *cobra.Command, paths []string) error {
func Run(v *viper.Viper, statz *stats.Stats, cmd *cobra.Command, paths []string) error {
cmd.SilenceUsage = true

cfg, err := config.FromViper(v)
if err != nil {
return fmt.Errorf("failed to load config: %w", err)
}

// initialise stats collection
stats.Init()

if cfg.CI {
log.Info("ci mode enabled")

Expand All @@ -69,6 +66,7 @@ func Run(v *viper.Viper, cmd *cobra.Command, paths []string) error {
return fmt.Errorf("exactly one path should be specified when using the --stdin flag")
}

//nolint:nestif
if cfg.Stdin {
// read stdin into a temporary file with the same file extension
pattern := fmt.Sprintf("*%s", filepath.Ext(paths[0]))
Expand Down Expand Up @@ -194,10 +192,10 @@ func Run(v *viper.Viper, cmd *cobra.Command, paths []string) error {
processedCh := make(chan *format.Task, cap(filesCh))

// start concurrent processing tasks in reverse order
eg.Go(updateCache(ctx, cfg, processedCh))
eg.Go(detectFormatted(ctx, cfg, formattedCh, processedCh))
eg.Go(applyFormatters(ctx, cfg, globalExcludes, formatters, filesCh, formattedCh))
eg.Go(walkFilesystem(ctx, cfg, paths, filesCh))
eg.Go(updateCache(ctx, cfg, statz, processedCh))
eg.Go(detectFormatted(ctx, cfg, statz, formattedCh, processedCh))
eg.Go(applyFormatters(ctx, cfg, statz, globalExcludes, formatters, filesCh, formattedCh))
eg.Go(walkFilesystem(ctx, cfg, statz, paths, filesCh))

// wait for everything to complete
return eg.Wait()
Expand All @@ -206,6 +204,7 @@ func Run(v *viper.Viper, cmd *cobra.Command, paths []string) error {
func walkFilesystem(
ctx context.Context,
cfg *config.Config,
statz *stats.Stats,
paths []string,
filesCh chan *walk.File,
) func() error {
Expand Down Expand Up @@ -262,8 +261,8 @@ func walkFilesystem(
case <-ctx.Done():
return ctx.Err()
default:
stats.Add(stats.Traversed, 1)
stats.Add(stats.Emitted, 1)
statz.Add(stats.Traversed, 1)
statz.Add(stats.Emitted, 1)
filesCh <- file

return nil
Expand All @@ -273,7 +272,7 @@ func walkFilesystem(

// otherwise we pass the walker to the cache and have it generate files for processing based on whether or not
// they have been added/changed since the last invocation
if err = cache.ChangeSet(ctx, walker, filesCh); err != nil {
if err = cache.ChangeSet(ctx, statz, walker, filesCh); err != nil {
return fmt.Errorf("failed to generate change set: %w", err)
}

Expand All @@ -285,6 +284,7 @@ func walkFilesystem(
func applyFormatters(
ctx context.Context,
cfg *config.Config,
statz *stats.Stats,
globalExcludes []glob.Glob,
formatters map[string]*format.Formatter,
filesCh chan *walk.File,
Expand Down Expand Up @@ -397,7 +397,7 @@ func applyFormatters(
}
} else {
// record the match
stats.Add(stats.Matched, 1)
statz.Add(stats.Matched, 1)
// create a new format task, add it to a batch based on its batch key and try to apply if the batch is full
task := format.NewTask(file, matches)
tryApply(&task)
Expand All @@ -421,6 +421,7 @@ func applyFormatters(
func detectFormatted(
ctx context.Context,
cfg *config.Config,
statz *stats.Stats,
formattedCh chan *format.Task,
processedCh chan *format.Task,
) func() error {
Expand Down Expand Up @@ -452,7 +453,7 @@ func detectFormatted(

if changed {
// record the change
stats.Add(stats.Formatted, 1)
statz.Add(stats.Formatted, 1)

logMethod := log.Debug
if cfg.FailOnChange {
Expand Down Expand Up @@ -480,7 +481,12 @@ func detectFormatted(
}
}

func updateCache(ctx context.Context, cfg *config.Config, processedCh chan *format.Task) func() error {
func updateCache(
ctx context.Context,
cfg *config.Config,
statz *stats.Stats,
processedCh chan *format.Task,
) func() error {
return func() error {
// used to batch updates for more efficient txs
batch := make([]*format.Task, 0, BatchSize)
Expand Down Expand Up @@ -561,13 +567,13 @@ func updateCache(ctx context.Context, cfg *config.Config, processedCh chan *form
}

// if fail on change has been enabled, check that no files were actually formatted, throwing an error if so
if cfg.FailOnChange && stats.Value(stats.Formatted) != 0 {
if cfg.FailOnChange && statz.Value(stats.Formatted) != 0 {
return ErrFailOnChange
}

// print stats to stdout unless we are processing stdin and printing the results to stdout
if !cfg.Stdin {
stats.Print()
statz.Print()
}

return nil
Expand Down
14 changes: 9 additions & 5 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import (
"github.com/numtide/treefmt/cmd/format"
_init "github.com/numtide/treefmt/cmd/init"
"github.com/numtide/treefmt/config"
"github.com/numtide/treefmt/stats"
"github.com/numtide/treefmt/walk"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

func NewRoot() *cobra.Command {
func NewRoot() (*cobra.Command, *stats.Stats) {
var (
treefmtInit bool
configFile string
Expand All @@ -24,13 +25,16 @@ func NewRoot() *cobra.Command {
// create a viper instance for reading in config
v := config.NewViper()

// create a new stats instance
statz := stats.New()

// create out root command
cmd := &cobra.Command{
Use: fmt.Sprintf("%s <paths...>", build.Name),
Short: "One CLI to format your repo",
Version: build.Version,
RunE: func(cmd *cobra.Command, args []string) error {
return runE(v, cmd, args)
return runE(v, statz, cmd, args)
},
}

Expand Down Expand Up @@ -60,10 +64,10 @@ func NewRoot() *cobra.Command {
cobra.CheckErr(fmt.Errorf("failed to bind global config to viper: %w", err))
}

return cmd
return cmd, statz
}

func runE(v *viper.Viper, cmd *cobra.Command, args []string) error {
func runE(v *viper.Viper, statz *stats.Stats, cmd *cobra.Command, args []string) error {
flags := cmd.Flags()

// change working directory if required
Expand Down Expand Up @@ -122,5 +126,5 @@ func runE(v *viper.Viper, cmd *cobra.Command, args []string) error {
}

// format
return format.Run(v, cmd, args)
return format.Run(v, statz, cmd, args)
}
Loading

0 comments on commit aa0dc25

Please sign in to comment.