bldr/util/gocompiler/mod-relocate.go
Rama master · réplica de lectura del repositorio original.
package gocompiler
import (
"os"
"path"
"path/filepath"
"strings"
"golang.org/x/mod/modfile"
)
// dotSlash is ./
var dotSlash = string([]rune{'.', os.PathSeparator})
// RelocateGoModFile transforms all references to a new path.
//
// expects the modfile to have been parsed with an absolute path.
func RelocateGoModFile(
modf *modfile.File,
nextModPath string,
) error {
// Identify the original module path for relative replacements.
prevGoModPath := modf.Syntax.Name
// has no effect if the path is already absolute.
modPathAbs, err := filepath.Abs(path.Dir(prevGoModPath))
if err != nil {
return err
}
// Resolve the destination directory for the relocated module.
nextGoModDir := path.Dir(nextModPath)
codegenModDir, err := filepath.Abs(nextGoModDir)
if err != nil {
return err
}
// Collect relative replacements using the destination module directory.
var adjOps [](func() error)
for _, srcReplace := range modf.Replace {
newPath := srcReplace.New.Path
// if the path replacement has a ./ or ../ prefix, update the relative path
if strings.HasPrefix(newPath, "./") || strings.HasPrefix(newPath, "../") {
// join the absolute path to the module with the relative replacement
// prevNewPathAbs is the absolute path to the replacement module.
prevNewPathAbs := filepath.Join(modPathAbs, newPath)
// newPathRelative is the relative path from the new module to the replacement.
newPathRelative, err := filepath.Rel(codegenModDir, prevNewPathAbs)
if err != nil {
return err
}
// ensure starts with ./
newPathRelative = ensureStartsWithDotSlash(newPathRelative)
// add a new replacement to override the old
oldSrcReplacePath := srcReplace.Old.Path
oldSrcReplaceVersion := srcReplace.Old.Version
oldSrcReplaceNewVersion := srcReplace.New.Version
adjOps = append(adjOps, func() error {
return modf.AddReplace(
oldSrcReplacePath,
oldSrcReplaceVersion,
newPathRelative,
oldSrcReplaceNewVersion,
)
})
}
}
// Apply the replacement paths after inspecting the original module.
for _, op := range adjOps {
if err := op(); err != nil {
return err
}
}
// Remove obsolete module syntax after replacing the paths.
modf.Cleanup()
return nil
}
// ensureStartsWithDotSlash returns the string with a ./ or ../ prefix
func ensureStartsWithDotSlash(p string) string {
// ensure starts with ./ or ../ - check simply for '.'
if !strings.HasPrefix(p, dotSlash[:1]) {
p = dotSlash + p
}
return p
}