Skip to content

Commit

Permalink
Merge pull request 'Feature parity with treefmt.rs' (#22) from feat/e…
Browse files Browse the repository at this point in the history
…xplicit-paths-and-stdin into main

Reviewed-on: https://git.numtide.com/numtide/treefmt/pulls/22
Reviewed-by: Jonas Chevalier <[email protected]>
  • Loading branch information
Jonas Chevalier committed Feb 19, 2024
2 parents 4dd4c55 + 2b49923 commit 9de4fd4
Show file tree
Hide file tree
Showing 27 changed files with 450 additions and 177 deletions.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Treefmt Contributors
Copyright (c) 2024 Treefmt Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
6 changes: 6 additions & 0 deletions build/build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package build

var (
Name = "treefmt"
Version = "v0.0.1+dev"
)
13 changes: 4 additions & 9 deletions internal/cache/cache.go → cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"os"
"time"

"git.numtide.com/numtide/treefmt/internal/walk"
"git.numtide.com/numtide/treefmt/format"
"git.numtide.com/numtide/treefmt/walk"

"git.numtide.com/numtide/treefmt/internal/format"
"github.com/charmbracelet/log"

"github.com/adrg/xdg"
Expand Down Expand Up @@ -173,7 +173,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, root string, walkerType walk.Type, pathsCh chan<- string) error {
func ChangeSet(ctx context.Context, walker walk.Walker, pathsCh chan<- string) error {
var tx *bolt.Tx
var bucket *bolt.Bucket
var processed int
Expand All @@ -185,12 +185,7 @@ func ChangeSet(ctx context.Context, root string, walkerType walk.Type, pathsCh c
}
}()

w, err := walk.New(walkerType, root)
if err != nil {
return fmt.Errorf("%w: failed to create walker", err)
}

return w.Walk(ctx, func(path string, info fs.FileInfo, err error) error {
return walker.Walk(ctx, func(path string, info fs.FileInfo, err error) error {
select {
case <-ctx.Done():
return ctx.Err()
Expand Down
25 changes: 14 additions & 11 deletions internal/cli/cli.go → cli/cli.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
package cli

import (
"git.numtide.com/numtide/treefmt/internal/walk"
"git.numtide.com/numtide/treefmt/walk"
"github.com/alecthomas/kong"
"github.com/charmbracelet/log"
)

var Cli = Options{}
var Cli = Format{}

type Options struct {
AllowMissingFormatter bool `default:"false" help:"Do not exit with error if a configured formatter is missing."`
WorkingDirectory kong.ChangeDirFlag `default:"." short:"C" help:"Run as if treefmt was started in the specified working directory instead of the current working directory."`
ClearCache bool `short:"c" help:"Reset the evaluation cache. Use in case the cache is not precise enough."`
type Format struct {
AllowMissingFormatter bool `default:"false" help:"Do not exit with error if a configured formatter is missing"`
WorkingDirectory kong.ChangeDirFlag `default:"." short:"C" help:"Run as if treefmt was started in the specified working directory instead of the current working directory"`
NoCache bool `help:"Ignore the evaluation cache entirely. Useful for CI"`
ClearCache bool `short:"c" help:"Reset the evaluation cache. Use in case the cache is not precise enough"`
ConfigFile string `type:"existingfile" default:"./treefmt.toml"`
FailOnChange bool `help:"Exit with error if any changes were made. Useful for CI."`
Formatters []string `help:"Specify formatters to apply. Defaults to all formatters."`
TreeRoot string `type:"existingdir" default:"."`
Walk walk.Type `enum:"auto,git,filesystem" default:"auto" help:"The method used to traverse the files within --tree-root. Currently supports 'auto', 'git' or 'filesystem'."`
Verbosity int `name:"verbose" short:"v" type:"counter" default:"0" env:"LOG_LEVEL" help:"Set the verbosity of logs e.g. -vv."`
Version bool `name:"version" short:"V" help:"Print version"`

Format Format `cmd:"" default:"."`
Paths []string `name:"paths" arg:"" type:"path" optional:"" help:"Paths to format. Defaults to formatting the whole tree."`
Stdin bool `help:"Format the context passed in via stdin"`
}

func (c *Options) Configure() {
func (f *Format) Configure() {
log.SetReportTimestamp(false)

if c.Verbosity == 0 {
if f.Verbosity == 0 {
log.SetLevel(log.WarnLevel)
} else if c.Verbosity == 1 {
} else if f.Verbosity == 1 {
log.SetLevel(log.InfoLevel)
} else if c.Verbosity >= 2 {
} else if f.Verbosity > 1 {
log.SetLevel(log.DebugLevel)
}
}
85 changes: 62 additions & 23 deletions internal/cli/format.go → cli/format.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
package cli

import (
"bufio"
"context"
"errors"
"fmt"
"io/fs"
"os"
"os/signal"
"strings"
"syscall"
"time"

"git.numtide.com/numtide/treefmt/internal/config"

"git.numtide.com/numtide/treefmt/internal/cache"
"git.numtide.com/numtide/treefmt/internal/format"
"git.numtide.com/numtide/treefmt/cache"
"git.numtide.com/numtide/treefmt/config"
format2 "git.numtide.com/numtide/treefmt/format"
"git.numtide.com/numtide/treefmt/walk"

"github.com/charmbracelet/log"
"golang.org/x/sync/errgroup"
)

type Format struct{}

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

func (f *Format) Run() error {
Expand All @@ -46,7 +46,7 @@ func (f *Format) Run() error {
return fmt.Errorf("%w: failed to read config file", err)
}

globalExcludes, err := format.CompileGlobs(cfg.Global.Excludes)
globalExcludes, err := format2.CompileGlobs(cfg.Global.Excludes)

// create optional formatter filter set
formatterSet := make(map[string]bool)
Expand All @@ -67,7 +67,7 @@ func (f *Format) Run() error {
}
}

formatters := make(map[string]*format.Formatter)
formatters := make(map[string]*format2.Formatter)

// detect broken dependencies
for name, formatterCfg := range cfg.Formatters {
Expand Down Expand Up @@ -114,8 +114,8 @@ func (f *Format) Run() error {
continue
}

formatter, err := format.NewFormatter(name, formatterCfg, globalExcludes)
if errors.Is(err, format.ErrCommandNotFound) && Cli.AllowMissingFormatter {
formatter, err := format2.NewFormatter(name, formatterCfg, globalExcludes)
if errors.Is(err, format2.ErrCommandNotFound) && Cli.AllowMissingFormatter {
l.Debugf("formatter not found: %v", name)
continue
} else if err != nil {
Expand Down Expand Up @@ -146,7 +146,7 @@ func (f *Format) Run() error {
//
completedCh := make(chan string, 1024)

ctx = format.SetCompletedChannel(ctx, completedCh)
ctx = format2.SetCompletedChannel(ctx, completedCh)

//
eg, ctx := errgroup.WithContext(ctx)
Expand All @@ -169,6 +169,20 @@ func (f *Format) Run() error {

var changes int

processBatch := func() error {
if Cli.NoCache {
changes += len(batch)
} else {
count, err := cache.Update(batch)
if err != nil {
return err
}
changes += count
}
batch = batch[:0]
return nil
}

LOOP:
for {
select {
Expand All @@ -180,28 +194,23 @@ func (f *Format) Run() error {
}
batch = append(batch, path)
if len(batch) == batchSize {
count, err := cache.Update(batch)
if err != nil {
if err = processBatch(); err != nil {
return err
}
changes += count
batch = batch[:0]
}
}
}

// final flush
count, err := cache.Update(batch)
if err != nil {
if err = processBatch(); err != nil {
return err
}
changes += count

if Cli.FailOnChange && changes != 0 {
return ErrFailOnChange
}

fmt.Printf("%v files changed in %v", changes, time.Now().Sub(start))
fmt.Printf("%v files changed in %v\n", changes, time.Now().Sub(start))
return nil
})

Expand Down Expand Up @@ -235,10 +244,40 @@ func (f *Format) Run() error {
return nil
})

eg.Go(func() error {
err := cache.ChangeSet(ctx, Cli.TreeRoot, Cli.Walk, pathsCh)
close(pathsCh)
return err
eg.Go(func() (err error) {
paths := Cli.Paths

if len(paths) == 0 && Cli.Stdin {
// read in all the paths
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
paths = append(paths, scanner.Text())
}
}

walker, err := walk.New(Cli.Walk, Cli.TreeRoot, paths)
if err != nil {
return fmt.Errorf("%w: failed to create walker", err)
}

defer close(pathsCh)

if Cli.NoCache {
return walker.Walk(ctx, func(path string, info fs.FileInfo, err error) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
// ignore symlinks and directories
if !(info.IsDir() || info.Mode()&os.ModeSymlink == os.ModeSymlink) {
pathsCh <- path
}
return nil
}
})
}

return cache.ChangeSet(ctx, walker, pathsCh)
})

// listen for shutdown and call cancel if required
Expand Down
Loading

0 comments on commit 9de4fd4

Please sign in to comment.