mirror of
https://github.com/numtide/treefmt.git
synced 2024-10-05 13:07:17 +03:00
cli: search for the tree root by default
Restore the treefmt 1.x behaviour where it would search for the tree
root by recursively searching for the treefmt.toml file up the
filesystem, starting from the current directory.
The `--tree-root-file` option will be useful to remove this bash wrapper: 2fba33a182/module-options.nix (L116-L135)
Fixes #308
This commit is contained in:
parent
022398399f
commit
bd32d36a33
@ -13,10 +13,11 @@ type Format struct {
|
||||
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" help:"The config file to use."`
|
||||
ConfigFile string `type:"path" help:"Load the config file from the given path (defaults to finding treefmt.toml up)."`
|
||||
FailOnChange bool `help:"Exit with error if any changes were made. Useful for CI."`
|
||||
Formatters []string `short:"f" help:"Specify formatters to apply. Defaults to all formatters."`
|
||||
TreeRoot string `type:"existingdir" default:"." help:"The root directory from which treefmt will start walking the filesystem."`
|
||||
TreeRoot string `type:"path" help:"The root directory from which treefmt will start walking the filesystem (defaults to the directory containing the config file)."`
|
||||
TreeRootFile string `type:"path" help:"File to search for to find the project root (if --tree-root is not passed)."`
|
||||
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."`
|
||||
|
@ -69,6 +69,40 @@ func (f *Format) Run() (err error) {
|
||||
}
|
||||
}()
|
||||
|
||||
// find the config file unless specified
|
||||
if Cli.ConfigFile == "" {
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
Cli.ConfigFile, _, err = findUp(pwd, "treefmt.toml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// search for the project root unless specified
|
||||
if Cli.TreeRoot == "" {
|
||||
// use the location of the treefmt.toml file by default
|
||||
dir := filepath.Dir(Cli.ConfigFile)
|
||||
|
||||
// search using the --tree-root-file if specified
|
||||
if Cli.TreeRootFile != "" {
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, dir, err = findUp(pwd, Cli.TreeRootFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
Cli.TreeRoot = dir
|
||||
}
|
||||
|
||||
log.Debugf("config-file=%s tree-root=%s", Cli.ConfigFile, Cli.TreeRoot)
|
||||
|
||||
// read config
|
||||
cfg, err := config.ReadFile(Cli.ConfigFile, Cli.Formatters)
|
||||
if err != nil {
|
||||
@ -384,3 +418,56 @@ func applyFormatters(ctx context.Context) func() error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func findUp(searchDir string, fileName string) (path string, dir string, err error) {
|
||||
for _, dir := range eachDir(searchDir) {
|
||||
path := filepath.Join(dir, fileName)
|
||||
if fileExists(path) {
|
||||
return path, dir, nil
|
||||
}
|
||||
}
|
||||
return "", "", fmt.Errorf("could not find %s in %s", fileName, searchDir)
|
||||
}
|
||||
|
||||
func eachDir(path string) (paths []string) {
|
||||
path, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
paths = []string{path}
|
||||
|
||||
if path == "/" {
|
||||
return
|
||||
}
|
||||
|
||||
for i := len(path) - 1; i >= 0; i-- {
|
||||
if path[i] == os.PathSeparator {
|
||||
path = path[:i]
|
||||
if path == "" {
|
||||
path = "/"
|
||||
}
|
||||
paths = append(paths, path)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func fileExists(path string) bool {
|
||||
// Some broken filesystems like SSHFS return file information on stat() but
|
||||
// then cannot open the file. So we use os.Open.
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Next, check that the file is a regular file.
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return fi.Mode().IsRegular()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user