feat(src): copy merge-base fiximports optimisation from curio

Ref: https://github.com/filecoin-project/curio/pull/1010
This commit is contained in:
Rod Vagg
2026-02-17 22:40:08 +11:00
parent e718b4c2f6
commit 79a1d8d768

View File

@@ -4,7 +4,9 @@ import (
"bytes"
"fmt"
"io/fs"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
@@ -37,30 +39,19 @@ type fileContent struct {
func main() {
numWorkers := runtime.NumCPU()
// Collect all the filenames that we want to process
var files []string
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
}
files = append(files, path)
return nil
}); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Error walking directory: %v\n", err)
os.Exit(1)
// Get files changed since merge-base with master
// Files already on master have had fiximports run, so we only need to process changes
changedFiles := getChangedFilesSinceMergeBase()
if len(changedFiles) == 0 {
fmt.Println("No Go files changed since merge-base with master")
return
}
fmt.Printf("Processing %d changed Go file(s)\n", len(changedFiles))
// Read all file contents in parallel
fileContents, err := readFilesParallel(files, numWorkers)
fileContents, err := readFilesParallel(changedFiles, numWorkers)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Error reading files: %v\n", err)
os.Exit(1)
@@ -84,6 +75,86 @@ func main() {
}
}
// getChangedFilesSinceMergeBase returns Go files that have changed since the merge-base with master.
// This includes committed changes on the branch, uncommitted changes, and untracked files.
func getChangedFilesSinceMergeBase() []string {
// Find the merge-base between master and HEAD
mergeBase, err := exec.Command("git", "merge-base", "master", "HEAD").Output()
if err != nil {
// If we can't find merge-base (e.g., not on a branch), fall back to all files
fmt.Println("Could not determine merge-base, processing all files")
return getAllGoFiles()
}
base := strings.TrimSpace(string(mergeBase))
// Get files changed between merge-base and HEAD (committed changes)
committed, _ := exec.Command("git", "diff", "--name-only", base, "HEAD").Output()
// Get uncommitted changes (staged + unstaged)
staged, _ := exec.Command("git", "diff", "--name-only", "--cached").Output()
unstaged, _ := exec.Command("git", "diff", "--name-only").Output()
// Get untracked files (new files not yet added to git)
untracked, _ := exec.Command("git", "ls-files", "--others", "--exclude-standard").Output()
// Combine all changes
allChanges := string(committed) + string(staged) + string(unstaged) + string(untracked)
// Filter to Go files, excluding extern/ and generated files
seen := make(map[string]bool)
var goFiles []string
for _, line := range strings.Split(allChanges, "\n") {
path := strings.TrimSpace(line)
if path == "" || seen[path] {
continue
}
if !strings.HasSuffix(path, ".go") {
continue
}
if strings.HasPrefix(path, "extern/") {
continue
}
if strings.HasSuffix(path, "_cbor_gen.go") {
continue
}
// Verify file exists (might have been deleted)
if _, err := os.Stat(path); err != nil {
continue
}
seen[path] = true
goFiles = append(goFiles, path)
}
return goFiles
}
// getAllGoFiles returns all Go files in the repo (fallback when merge-base fails)
func getAllGoFiles() []string {
var files []string
err := filepath.Walk(".", func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
if strings.HasPrefix(path, "extern/") {
return filepath.SkipDir
}
if info.IsDir() {
return nil
}
if !strings.HasSuffix(path, ".go") {
return nil
}
if strings.HasSuffix(path, "_cbor_gen.go") {
return nil
}
files = append(files, path)
return nil
})
if err != nil {
log.Fatalf("Failed to walk directory: %v", err)
}
return files
}
func readFilesParallel(files []string, numWorkers int) ([]*fileContent, error) {
fileContents := make([]*fileContent, len(files))