134 lines
2.5 KiB
Go
134 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"go.jolheiser.com/imp/format"
|
|
|
|
"gitea.com/jolheiser/globber"
|
|
gofumptFormat "mvdan.cc/gofumpt/format"
|
|
)
|
|
|
|
func runImp(root, ignore string, write, gofumpt, gofumptExtra bool) error {
|
|
mod, err := modInfo()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
globs, err := globber.ParseFile(ignore)
|
|
if err != nil {
|
|
if !errors.Is(err, fs.ErrNotExist) {
|
|
return err
|
|
}
|
|
globs = globber.New()
|
|
}
|
|
|
|
var failed bool
|
|
if err := filepath.Walk(root, func(walkPath string, walkInfo os.FileInfo, walkErr error) error {
|
|
if walkErr != nil {
|
|
return walkErr
|
|
}
|
|
|
|
walkPath = filepath.ToSlash(walkPath)
|
|
|
|
if s := checkSkip(walkPath, walkInfo, globs); s != CHECK {
|
|
if s == SKIPDIR {
|
|
return filepath.SkipDir
|
|
}
|
|
return nil
|
|
}
|
|
|
|
data, err := os.ReadFile(walkPath)
|
|
if err != nil {
|
|
return fmt.Errorf("could not read file %q: %w", walkPath, err)
|
|
}
|
|
|
|
formatted, err := impFormat(data, mod, gofumpt, gofumptExtra)
|
|
if err != nil {
|
|
return fmt.Errorf("could not format file %q: %w", walkPath, err)
|
|
}
|
|
|
|
if write {
|
|
if err := os.WriteFile(walkPath, formatted, walkInfo.Mode()); err != nil {
|
|
return fmt.Errorf("could not write file %q: %w", walkPath, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
if !bytes.Equal(data, formatted) {
|
|
failed = true
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
if failed {
|
|
return errors.New("imports are formatted incorrectly; this can be fixed with the `--write` flag")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func impFormat(src []byte, mod module, gofumpt, gofumptExtra bool) ([]byte, error) {
|
|
formatted, err := format.Source(src, mod.Path)
|
|
if err != nil {
|
|
return src, err
|
|
}
|
|
if gofumpt {
|
|
formatted, err = gofumptFormat.Source(formatted, gofumptFormat.Options{
|
|
LangVersion: mod.GoVersion,
|
|
ModulePath: mod.Path,
|
|
ExtraRules: gofumptExtra,
|
|
})
|
|
if err != nil {
|
|
return src, err
|
|
}
|
|
}
|
|
return formatted, nil
|
|
}
|
|
|
|
func checkSkip(walkPath string, walkInfo os.FileInfo, globs *globber.GlobSet) walkStatus {
|
|
// Skip current directory
|
|
if strings.EqualFold(walkPath, ".") {
|
|
return SKIP
|
|
}
|
|
|
|
// Skip hidden paths (starting with ".")
|
|
if strings.HasPrefix(walkPath, ".") {
|
|
if walkInfo.IsDir() {
|
|
return SKIPDIR
|
|
}
|
|
return SKIP
|
|
}
|
|
|
|
// Skip directories
|
|
if walkInfo.IsDir() {
|
|
return SKIP
|
|
}
|
|
|
|
// Skip non-Go files
|
|
if !strings.HasSuffix(walkInfo.Name(), ".go") {
|
|
return SKIP
|
|
}
|
|
|
|
// Skip included (ignored) globs
|
|
i, e := globs.Explain(walkPath)
|
|
if len(i) > 0 && len(e) == 0 {
|
|
return SKIP
|
|
}
|
|
|
|
return CHECK
|
|
}
|
|
|
|
type walkStatus int
|
|
|
|
const (
|
|
SKIP walkStatus = iota
|
|
SKIPDIR
|
|
CHECK
|
|
)
|