93 lines
2.2 KiB
Go
93 lines
2.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"io/fs"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"regexp"
|
||
|
"strings"
|
||
|
|
||
|
"golang.org/x/tools/imports"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
// groupByPrefixes is the list of import prefixes that should _each_ be grouped separately.
|
||
|
// See: imports.LocalPrefix.
|
||
|
groupByPrefixes = []string{
|
||
|
"github.com/filecoin-project",
|
||
|
"github.com/filecoin-project/lotus",
|
||
|
}
|
||
|
newline = []byte("\n")
|
||
|
importBlockRegex = regexp.MustCompile(`(?s)import\s*\((.*?)\)`)
|
||
|
consecutiveNewlinesRegex = regexp.MustCompile(`\n\s*\n`)
|
||
|
)
|
||
|
|
||
|
func main() {
|
||
|
if err := filepath.Walk(".", func(path string, info fs.FileInfo, err error) error {
|
||
|
switch {
|
||
|
case err != nil:
|
||
|
return err
|
||
|
case // Skip the entire "./extern/..." directory and its contents.
|
||
|
strings.HasPrefix(path, "extern/"):
|
||
|
return filepath.SkipDir
|
||
|
case // Skip directories, generated cborgen go files and any other non-go files.
|
||
|
info.IsDir(),
|
||
|
strings.HasSuffix(info.Name(), "_cbor_gen.go"),
|
||
|
!strings.HasSuffix(info.Name(), ".go"):
|
||
|
return nil
|
||
|
}
|
||
|
return fixGoImports(path)
|
||
|
}); err != nil {
|
||
|
fmt.Printf("Error fixing go imports: %v\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func fixGoImports(path string) error {
|
||
|
sourceFile, err := os.OpenFile(path, os.O_RDWR, 0666)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer func() { _ = sourceFile.Close() }()
|
||
|
|
||
|
source, err := io.ReadAll(sourceFile)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
formatted := collapseImportNewlines(source)
|
||
|
for _, prefix := range groupByPrefixes {
|
||
|
imports.LocalPrefix = prefix
|
||
|
formatted, err = imports.Process(path, formatted, nil)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
if !bytes.Equal(source, formatted) {
|
||
|
if err := replaceFileContent(sourceFile, formatted); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func replaceFileContent(target *os.File, replacement []byte) error {
|
||
|
if _, err := target.Seek(0, io.SeekStart); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
written, err := target.Write(replacement)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return target.Truncate(int64(written))
|
||
|
}
|
||
|
|
||
|
func collapseImportNewlines(content []byte) []byte {
|
||
|
return importBlockRegex.ReplaceAllFunc(content, func(importBlock []byte) []byte {
|
||
|
// Replace consecutive newlines with a single newline within the import block
|
||
|
return consecutiveNewlinesRegex.ReplaceAll(importBlock, newline)
|
||
|
})
|
||
|
}
|