Ctrl K
ComunidadGuías…

bldr/util/gocompiler/mod-relocate.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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
}