mukan-ignite/ignite/internal/tools/gen-mig-diffs/pkg/diff/compute.go
Mukan Erkin Törük c32551b6f7
Some checks failed
Docs Deploy / build_and_deploy (push) Has been cancelled
Generate Docs / cli (push) Has been cancelled
Generate Config Doc / cli (push) Has been cancelled
Go formatting / go-formatting (push) Has been cancelled
Check links / markdown-link-check (push) Has been cancelled
Integration / pre-test (push) Has been cancelled
Integration / test on (push) Has been cancelled
Integration / status (push) Has been cancelled
Lint / Lint Go code (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
refactor: replace all github.com upstream refs with git.cw.tr/mukan-network
2026-05-11 03:36:24 +03:00

119 lines
2.8 KiB
Go

package diff
import (
"fmt"
"io/fs"
"os"
"path/filepath"
"github.com/gobwas/glob"
"github.com/hexops/gotextdiff"
"github.com/hexops/gotextdiff/myers"
"github.com/hexops/gotextdiff/span"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/errors"
)
// computeFS computes the unified diffs between the origin and modified filesystems.
// but ignores files that match the given globs.
func computeFS(origin, modified fs.FS, ignoreGlobs ...string) ([]gotextdiff.Unified, error) {
compiledGlobs, err := compileGlobs(ignoreGlobs)
if err != nil {
return nil, err
}
marked := make(map[string]struct{})
unified := make([]gotextdiff.Unified, 0)
err = fs.WalkDir(origin, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return errors.Errorf("failed to walk origin: %w", err)
}
if d.IsDir() {
return nil
}
if matchGlobs(compiledGlobs, path) {
return nil
}
marked[path] = struct{}{}
data, err := fs.ReadFile(origin, path)
if err != nil {
return errors.Errorf("failed to read file %q from origin: %w", path, err)
}
originFile := string(data)
data, err = fs.ReadFile(modified, path)
if !os.IsNotExist(err) && err != nil {
return errors.Errorf("failed to read file %q from modified: %w", path, err)
}
modifiedFile := string(data)
edits := myers.ComputeEdits(span.URIFromURI(fmt.Sprintf("file://%s", path)), originFile, modifiedFile)
if len(edits) > 0 {
unified = append(unified, gotextdiff.ToUnified(path, path, originFile, edits))
}
return nil
})
if err != nil {
return nil, err
}
err = fs.WalkDir(modified, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return errors.Errorf("failed to walk modified: %w", err)
}
if d.IsDir() {
return nil
}
if _, ok := marked[path]; ok {
return nil
}
if matchGlobs(compiledGlobs, path) {
return nil
}
originFile := ""
data, err := fs.ReadFile(modified, path)
if err != nil {
return errors.Errorf("failed to read file %q from modified: %w", path, err)
}
modifiedFile := string(data)
edits := myers.ComputeEdits(span.URIFromURI(fmt.Sprintf("file://%s", path)), originFile, modifiedFile)
if len(edits) > 0 {
unified = append(unified, gotextdiff.ToUnified(path, path, originFile, edits))
}
return nil
})
if err != nil {
return nil, err
}
return unified, nil
}
func compileGlobs(globs []string) ([]glob.Glob, error) {
var compiledGlobs []glob.Glob
for _, g := range globs {
compiledGlob, err := glob.Compile(g, filepath.Separator)
if err != nil {
return nil, errors.Errorf("failed to compile glob %q: %w", g, err)
}
compiledGlobs = append(compiledGlobs, compiledGlob)
}
return compiledGlobs, nil
}
func matchGlobs(globs []glob.Glob, path string) bool {
for _, g := range globs {
if g.Match(path) {
return true
}
}
return false
}