transplant

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 23, 2020 License: MPL-2.0 Imports: 48 Imported by: 0

Documentation

Overview

Package transplant defines the core types used by both egress and ingress logic.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AllImportPathReplacer

func AllImportPathReplacer(op Op) *cage_strings.ReplaceSet

AllImportPathReplacer returns a replacer covering Ops.From.LocalImportPath and all Ops.Dep.From.ImportPath values.

func DepImportPathReplacer

func DepImportPathReplacer(op Op) *cage_strings.ReplaceSet

DepImportPathReplacer returns a replacer covering all Ops.Dep.From.ImportPath values.

func FilepathClean

func FilepathClean(p string) string

FilepathClean prevents empty config paths from being converted to ".".

func FromAbs

func FromAbs(op Op, parts ...string) string

FromAbs resolves the relative path parts to the origin module's root directory.

func MatchAnyDirRelPath

func MatchAnyDirRelPath(prefix string, config cage_filepath.MatchAnyInput) cage_file.DirMatcher

MatchAnyDirRelPath requires candidate paths to contain the input prefix, and only matches input patterns against the variable, relative suffixes. If the prefix itself is a candidate path, it will be included in the matched results.

For example, "**/dirname/*" would normally match any directory under a "dirname" directory regardless of the prefix before the "dirname" path part.

This function only returns candidates which contain the input prefix, and only matches patterns against the remaining suffix.

func MatchAnyFileRelPath

func MatchAnyFileRelPath(prefix string, config cage_filepath.MatchAnyInput) cage_file.FileMatcher

MatchAnyFileRelPath requires candidate paths to contain the input prefix, and only matches input patterns against the variable, relative suffixes. If the prefix itself is a candidate path, it will be included in the matched results.

For example, "**/dirname/*" would normally match any file under a "dirname" directory regardless of the prefix before the "dirname" path part.

This function only returns candidates which contain the input prefix, and only matches patterns against the remaining suffix.

func ToAbs

func ToAbs(op Op, parts ...string) string

ToAbs resolves the relative path parts to the destination module's root directory.

Types

type Audit

type Audit struct {
	// AllDepGoFiles holds absolute paths to all files found recursively in all Dep.From.FilePath.
	AllDepGoFiles *cage_strings.Set

	// UsedDepGoFiles holds absolute paths to files directly/transitively depended on by LocalGoFiles
	// by examining the global identifier usage into the latter.
	//
	// All package files will be included even if LocalGoFiles only depends on one file. This excess
	// is currently used to ensure all init functions are included.
	//
	// When a filename is added, its path should be added to UsedDepImportPaths (depDirToImportPath may help).
	UsedDepGoFiles *cage_strings.Set

	// UsedDepImportPaths holds the import paths of packages directly/transitively depended on by LocalGoFiles.
	UsedDepImportPaths *cage_strings.Set

	// LocalGoFiles holds absolute paths of Ops.From.FilePath Go files.
	LocalGoFiles *cage_strings.Set

	// LocalGoTestFiles holds absolute paths of Ops.From.FilePath Go test files.
	LocalGoTestFiles *cage_strings.Set

	// LocalCopyOnlyFiles include all Ops.From.FilePath contents matching Ops.From.CopyOnlyFilePath.
	LocalCopyOnlyFiles *cage_strings.Set

	// LocalGoDescendantFiles include Ops.From.FilePath contents matching Ops.From.GoDescendantFilePath.
	//
	// They are filtered based on having an ancestor Go directory during the copy operation.
	LocalGoDescendantFiles *cage_strings.Set

	// LocalIncludeDirs holds absolute paths of Ops.From.FilePath dirs/files which are/match an
	// Ops.From.* inclusion pattern (that was not invalidated by a related exclusion pattern).
	LocalIncludeDirs *cage_strings.Set

	// AllDepDirs holds absolute paths of directories which match Ops.Dep.From.GoFilePath queries.
	//
	// It differs from the narrower scope of UsedDepGoFiles and covers directories which may include
	// packages which are not dependencies of LocalGoFiles.
	AllDepDirs *cage_strings.Set

	// UnconfiguredDirs holds absolute paths of directories whose packages were imported into Ops.From
	// or Ops.Dep.From packages but were not covered by those configuration.
	//
	// It is indexed by the import path of the packages which perform the imports.
	UnconfiguredDirs map[string]*cage_strings.Set

	// UnconfiguredDirImporters holds the import path keys of UnconfiguredDirs.
	UnconfiguredDirImporters *cage_strings.Set

	// DepCopyOnlyFiles include all Ops.Dep.From.FilePath contents matching Ops.Dep.From.CopyOnlyFilePath.
	DepCopyOnlyFiles *cage_strings.Set

	// DepGoDescendantFiles include Ops.Dep.From.FilePath contents matching Ops.Dep.From.GoDescendantFilePath.
	//
	// They are filtered based on having an ancestor Go directory during the copy operation.
	DepGoDescendantFiles *cage_strings.Set

	// DirectDepImportsIntoLocal enumerates the Ops.Dep.From packages directly imported into Ops.From packages.
	DirectDepImportsIntoLocal *cage_pkgs.ImportList

	// AllDepImportsIntoLocal enumerates the Ops.Dep.From packages directly or transitively imported into
	// Ops.From packages. It includes all elements of DirectDepImportsIntoLocal.
	AllDepImportsIntoLocal *cage_pkgs.ImportList

	// DepGlobalIdUsageDag graphs usage of global identifiers in Ops.Dep packages (except for their
	// init functions) to support pruning the latter during a refactor operation.
	//
	// It graphs connections between LocalGoFiles (as LocalGoFilesDagRoot) and all identifiers observed during
	// a recursive walk of global functions/methods in the Ops.Dep packages.
	DepGlobalIdUsageDag cage_dag.Graph

	// LocalGoFilesDagRoot represents all LocalGoFiles in the DepGlobalIdUsageDag.
	//
	// A Ops.Dep global can be pruned if there is no path from this root to the global in either DAG.
	LocalGoFilesDagRoot cage_pkgs.GlobalId

	// DepGoTestFiles holds absolute paths to files which were found in the same directory as a
	// Ops.Dep package which is directly/transitively used by Ops.Dep packages that are
	// directly/transitively used by LocalGoFiles.
	DepGoTestFiles *cage_strings.Set

	// LocalInspectDirs holds the Ops.From.FilePath directories provided to Inspector for
	// loading by x/tools/go/packages.
	LocalInspectDirs *cage_strings.Set

	// DepInspectDirs holds the Ops.Dep.From.FilePath directories provided to Inspector for
	// loading by x/tools/go/packages.
	DepInspectDirs *cage_strings.Set

	// UsedDepExports indexes used Ops.Dep global identifiers first by import path, then global name.
	UsedDepExports map[string]map[string]cage_pkgs.GlobalId

	// IngressRemovableDirs holds (egress) Ops.From.FilePath dirs which may be removed during ingress because
	// they match config patterns of the egress operation.
	IngressRemovableDirs *cage_strings.Set

	// IngressRemovableFiles holds (egress) Ops.From.FilePath files which may be removed during ingress because
	// they match config patterns of the egress operation.
	IngressRemovableFiles *cage_strings.Set

	// LocalReplaceStringFiles holds Ops.From.ReplaceString matches.
	LocalReplaceStringFiles *ReplaceStringFiles

	// DepReplaceStringFiles holds Ops.Dep.From.ReplaceString matches.
	DepReplaceStringFiles *ReplaceStringFiles

	// Progress receives messages describing analysis steps and runtimes.
	Progress io.Writer

	// WhyLog if non-nil will receive updates which support `{egress,ingress} file` queries.
	WhyLog why.Log

	// AllImportPathReplacer replaces Ops.From.LocalImportPath and all Ops.Dep.From.ImportPath substrings
	// with their To counterparts.
	AllImportPathReplacer *cage_strings.ReplaceSet

	// DepImportPathReplacer replaces Ops.Dep.From.ImportPath substrings with its To counterpart.
	DepImportPathReplacer *cage_strings.ReplaceSet
	// contains filtered or unexported fields
}

Audit provides detail about the origin module collected during an initial analysis-only walk.

It is used in the later replication pass to inform/limit copy operations.

func NewEgressAudit

func NewEgressAudit(op Op) *Audit

func NewIngressAudit

func NewIngressAudit(op Op) *Audit

func (*Audit) Generate

func (a *Audit) Generate() (errs []error)

Multiple errors may be returned due to accumulation during operations like ast.Inspect, or in cases where a full report of all detected problems might assist bulk remediation instead of one-at-a-time.

func (*Audit) IsDepGlobalUsedInLocal

func (a *Audit) IsDepGlobalUsedInLocal(g cage_pkgs.GlobalId) bool

func (*Audit) Op

func (a *Audit) Op() Op

func (*Audit) PrintUnconfiguredDirs

func (a *Audit) PrintUnconfiguredDirs(w io.Writer)

type Config

type Config struct {
	// Ops holds all refactor operation definitions indexed by a user-defined ID.
	Ops map[string]Op

	// Template holds key/value pairs which can be used in some string fields via {{.key_name}} syntax.
	//
	// Key names must use lowercase due to viper(/mapstructure?) limitation. Convention: "some_key_name".
	// https://github.com/spf13/viper/issues/411
	// https://github.com/spf13/viper/pull/635
	Template map[string]string
}

Config is the unmarshaled structure of the YAML config file.

func (*Config) ReadFile

func (c *Config) ReadFile(name string, _opIds ...string) (errs []error)

ReadFile populates Config fields with values from the named file.

If the name is empty, it checks if transplant.* files in the working directory are present (in order: *.yml, *.yaml, *.json, *.toml) and defaults to the first match. If none of the default names exist, an error is returned.

It also validates the fields expected to be user-defined and computes others which are derived from the former.

type ConfigMatcher

type ConfigMatcher struct {
	// BaseFilePath is the original base path selected when creating the full-path matchers
	BaseFilePath string

	CopyOnlyFilesFull   cage_file.FileMatcher
	CopyOnlyFilesSuffix cage_file.FileMatcher

	GoDescendantFilesFull   cage_file.FileMatcher
	GoDescendantFilesSuffix cage_file.FileMatcher

	InspectDirsFull   cage_file.DirMatcher
	InspectDirsSuffix cage_file.DirMatcher
}

ConfigMatcher holds the file/dir matchers computed from FilePathQuery config patterns.

func NewConfigMatcher

func NewConfigMatcher(baseFilePath string) *ConfigMatcher

type Copier

type Copier struct {
	// Audit results inform the copier operation by providing data such as the file lists and globals found in the AST.
	Audit *Audit

	// Ctx is applied to context-aware operations to support externally-defined cancellation.
	Ctx context.Context

	// Op is the configuration data used by both the Audit and copy operation to determine their scope, modes, etc.
	Op Op

	// OverwriteMin is true if the copy should only populate the staging dir, and overwrite files in the
	// destination dir, if the inbound content is different. Files with the same content will be added to
	// CopyPlan.OverwriteSkip.
	OverwriteMin bool

	// ModuleRequire is true if the Go modules step should be performed where the module is initialized
	// and receives requirements from the origin module.
	ModuleRequire bool

	// Plan enumerates the copy actions which would run, to support dry-run mode.
	Plan CopyPlan

	// ProgressCore receives messages describing core copy steps and runtimes.
	ProgressCore io.Writer

	// ProgressModule receives stdout messages from module-related Go commands.
	ProgressModule io.Writer

	// Stderr receives messages about errors which are printed but considered serious enough to be
	// collected and cause the operation to exit early.
	Stderr io.Writer

	// Stage abstracts a temporary directory which is populated fully before the actual copy operation
	// in order to minimize side-effects if an error is encountered.
	Stage *cage_file_stage.Stage

	// WhyLog if non-nil will receive updates which support `{egress,ingress} file` queries.
	WhyLog why.Log
}

Copier performs both egress and ingress copy operations.

func NewCopier

func NewCopier(ctx context.Context, audit *Audit) (c *Copier, err error)

NewCopier returns an initialized instance.

func (*Copier) Run

func (c *Copier) Run() (_ CopyPlan, errs []error)

Run performs the copy operation in stages, calling out to separate methods which implement them. The separation of methods is for both readability and to simplfy logic which determines which stages execute based on configuration.

type CopyFileError

type CopyFileError struct {
	// Name is an absolute path.
	Name string

	// Err is an Error() string.
	Err string
}

CopyFileError describes an error encountered while processing a specific file, but the error is collected for inclusion in CopyPlan instead of propagating down the stack.

type CopyPlan

type CopyPlan struct {
	// Add holds the absolute paths of all files to be added to Ops.To.FilePath.
	Add []string `json:",omitempty" toml:",omitempty" yaml:"Add,omitempty" `

	// Overwrite holds the absolute paths of all files to be overwritten in Ops.To.FilePath.
	Overwrite []string `json:",omitempty" toml:",omitempty" yaml:"Overwrite,omitempty"`

	// Remove holds the absolute paths of all files to be removed from Ops.To.FilePath.
	Remove []string `json:",omitempty" toml:",omitempty" yaml:"Remove,omitempty"`

	// PruneGlobalIds describes the global identifiers omitted from Ops.Dep packages because they were not
	// direct/transitive dependencies of packages under Ops.From.FilePath.
	//
	// Global identifier name format: <absolute path to package directory>.<package name>.<identifier name>
	// Files are identified by their absolute paths.
	PruneGlobalIds []string `json:",omitempty" toml:",omitempty" yaml:"PruneGlobalIds,omitempty"`

	// PruneGoFiles holds files which were omitted from the copy because they did not contain a
	// direct/transitive dependency of packages under Ops.From.FilePath.
	PruneGoFiles []string `json:",omitempty" toml:",omitempty" yaml:"PruneGoFiles,omitempty"`

	// GoFormatErr describes Ops.From.CopyOnlyFilePath Go files which could not be automatically
	// formatted by go/format.Source, e.g. due to a syntax error.
	//
	// Those errors are collected here, instead of causing the overall copy operation to fail, to support
	// fixtures with intentional defects. It also supports the general distinction between CopyOnlyFilePath
	// patterns and others like GoFilePath which require error-free parsing.
	GoFormatErr []CopyFileError `json:",omitempty" toml:",omitempty" yaml:"GoFormatErr,omitempty"`

	// RenameNotFound holds absolute paths of RenameFilePath targets which were not found.
	//
	// Paths are collected instead of causing the copy operation to fail to support cases where the
	// target file is not always present.
	RenameNotFound []string `json:",omitempty" toml:",omitempty" yaml:"RenameNotFound,omitempty"`

	// GoModVendor is true if `go mod vendor` is called.
	GoModVendor bool `yaml:"GoModVendor"`

	// Env holds environment details which affect Copier behavior.
	Env map[string]string `yaml:"Env"`

	// StagePath holds the absolute path to the staging file tree where the copy is generated as a whole and then
	// copied at the end of the process.
	StagePath string `yaml:"StagePath"`

	// OverwriteSkip holds the absolute paths of all files not overwritten in Ops.To.FilePath
	// because the destination's content is the same.
	OverwriteSkip []string `json:"-" toml:"-" yaml:"-"`
}

CopyPlan is written to a file selected by the --plan CLI flag.

func (*CopyPlan) String

func (p *CopyPlan) String() string

func (*CopyPlan) WriteFile

func (p *CopyPlan) WriteFile(name string, optFields *cage_strings.Set) (err error)

type Dep

type Dep struct {
	From DepFrom
	To   DepTo
}

Dep describes a specific dependency included in the copy operation.

type DepFrom

type DepFrom struct {
	// FilePath is a path relative to Ops.From.ModuleFilePath.
	//
	// It is used as the base path for all *FilePath patterns.
	FilePath string

	// ImportPath is the prefix of all packages under FilePath.
	//
	// It is computed based on Ops.From.ModuleImportPath and this type's FilePath.
	ImportPath string `mapstructure:"-"`

	// GoFilePath matches directories in which implementation (and optionally test) packages should
	// be copied and analyzed for their dependencies.
	//
	// Implementation packages will only be included if they're direct/transitive dependencies
	// of the target project. Tests will only be included if enabled by the Tests config field
	// and they share a directory with an already included implementation packages.
	//
	// Matching directories will be inspected.
	// If Tests is true, test packages will be auto-discovered.
	// Only Go files will be copied.
	GoFilePath FilePathQuery

	// CopyOnlyFilePath matches files which should be copied but not inspected/refactored.
	//
	// Each pattern is relative to FilePath.
	CopyOnlyFilePath FilePathQuery

	// GoDescendantFilePath first matches files which should be copied but not inspected or refactored
	// (except for basic string replacement of source file/import paths), same as CopyOnlyFilePath.
	// It also requires that each file is a descendant of directory which provides a Go package to the copy
	// (i.e. a dependency of a project matched by GoFilePath).
	//
	// For example, it supports the need to exclude files such as test fixtures whose only dependents are in
	// ancestor directories which will not be part of the copy.
	GoDescendantFilePath FilePathQuery

	// ReplaceString defines the scope of string replacements to perform during copy operations.
	//
	// Replacements occur on the intersection between its matches and those of all other config patterns,
	// such as GoFilePath and CopyOnlyFilePath, which control the scope of the copy operation itself.
	ReplaceString ReplaceStringSpec

	// Tests is true if a GoFilePath-matched test packages and their dependencies should be included.
	Tests bool
}

DepFrom describes the origin of a specific dependency included in the copy operation.

type DepTo

type DepTo struct {
	// FilePath is a path relative to Ops.To.ModuleFilePath.
	FilePath string

	// ImportPath is the prefix of all packages under FilePath.
	//
	// It is computed based on Ops.To.ModuleImportPath and this type's FilePath.
	ImportPath string `mapstructure:"-"`
}

DepTo describes the destination of a specific included in the copy operation.

type File

type File struct {
	// AbsPath is the absolute path to the file being copied.
	AbsPath string

	// Dir is the parent directory of the file.
	Dir string

	// Go is true of the file is a Go file.
	Go bool

	// Node is the inspection data about the associated ast.File.
	Node cage_pkgs.Node

	// FileSet contains the subject file if it is of Go type.
	FileSet *token.FileSet

	// Pkg is the inspection data about the file's package.
	Pkg *cage_pkgs.Package

	// Mode represents the file's mode/permission bits.
	Mode os.FileMode
}

File stores details about a single-file which will be copied to the stage and final destination, supporting copy-related tasks such as content updates and renaming.

For files which require node pruning, use PrunableFile instead.

func NewFile

func NewFile(audit *Audit, newFilePath string) (f *File, err error)

NewFile returns a new File instance.

All file path parameters must be absolute.

func (*File) Apply

func (f *File) Apply(fn func(cursor *astutil.Cursor) bool) ast.Node

func (*File) DepDestPaths

func (f *File) DepDestPaths(op Op, dep Dep) (absPath, relPath string)

DepDestPaths returns a Ops.Dep.From file's copy-destination (Ops.To) paths.

func (*File) GetNodeBytes

func (f *File) GetNodeBytes(node ast.Node) ([]byte, error)

GetNodeBytes converts the input node into a []byte using the file's decorator.

func (*File) LocalDestPaths

func (f *File) LocalDestPaths(op Op) (absPath, relPath string)

LocalDestPaths returns a Ops.From file's copy-destination (Ops.To) paths.

func (*File) RenameIfGoFileNamedAfterRootPackage

func (f *File) RenameIfGoFileNamedAfterRootPackage(fromImportPath, toImportPath string, allAbsPaths *cage_strings.Set)

RenameIfGoFileNamedAfterRootPackage alters the file's base name to match the package name of its destination directory if: the file's base name currently matches its package, the parent directory is the local/dep root dir, and a file with the new name does not conflict.

Example: Ops.From.ImportPath is "path/to/proj", Ops.To.ImportPath is "path/to/other", and the file's path relative to Ops.From.FilePath is "proj.go". "proj.go" is renamed to "other.go". However if the file's relative path is deep in the tree, e.g. "subdir/proj.go", then the file would not be renamed because the attempt to persist the naming convention should only happen at the top of the tree.

func (*File) RenamePackageClause

func (f *File) RenamePackageClause(topLevelFilePath, fromImportPath, toImportPath string, fileText []byte) []byte

RenamePackageClause alters the `package X` line if the file is at the top level of the origin file path by renaming the package to match the destination import path's base name.

It allows files which are named after parent, top-level directory to continue being named after the parent, e.g. files in Op.From.LocalFilePath or Op.Dep.From.FilePath.

E.g. if origin file "from1" and the destination import base is "f1", then the new package clause will contain the name "f1".

func (*File) RewriteImportPath

func (f *File) RewriteImportPath(audit *Audit, op Op, importPath string, isLocal bool) string

RewriteImportPath detects Op.From.LocalImportPath/Op.Dep.From.ImportPath prefixes and replaces them with Op.To.LocalImportPath/Op.Dep.To.ImportPath.

func (*File) RewriteImportsInNode

func (f *File) RewriteImportsInNode(audit *Audit, op Op, cursor *astutil.Cursor, isLocal bool) (err error)

RewriteImportsInNode updates an AST node if it imports or references a package whose location will change in the copy operation.

Import declarations and identifiers which include an import name of a Op.From.LocalFilePath/Op.Dep.From.FilePath package will be updated to the associated Op.To.LocalFilePath/Op.Dep.To.FilePath path/name.

type FileConfig

type FileConfig struct {
	Audit            *Audit
	ToFilePathPrefix string
}

type FilePathQuery

type FilePathQuery struct {
	// Include holds github.com/bmatcuk/doublestar glob patterns which validate a candidate path.
	//
	// If any matches, the candidate path is accepted.
	Include []string

	// Exclude holds github.com/bmatcuk/doublestar glob patterns which invalidate a candidate path.
	//
	// If any matches, the candidate path is rejected.
	Exclude []string
}

FilePathQuery defines file selection criteria.

func (FilePathQuery) Copy

func (q FilePathQuery) Copy() (cpy FilePathQuery)

func (*FilePathQuery) ResolveTo

func (q *FilePathQuery) ResolveTo(basePath string)

ResolveTo updates all patterns to absolute path form.

func (FilePathQuery) Validate

func (q FilePathQuery) Validate() (errs []error)

type FromFinderInput

type FromFinderInput struct {
	// BaseFilePath is the base path of Include/Exclude suffix-targeting matchers.
	BaseFilePath string

	// Include holds the file/dir matchers computed from Ops.From or Ops.Dep.From config.
	Include *ConfigMatcher

	// Exclude allows the search to avoid overlapping result sets.
	// When Include defines an Ops.From search, Exclude holds Ops.Dep.From matchers.
	// When Include defines an Ops.Dep.From search, it holds a Ops.From matcher.
	Exclude []*ConfigMatcher

	// ReplaceString specs match subsets of Include matches which are targeted for string replacements.
	ReplaceString ReplaceStringSpec
}

FromFinderInput holds config patterns for finding Ops.From.*FilePath/Ops.Dep.From.*FilePath matches.

type FromFinderOutput

type FromFinderOutput struct {
	AllFiles cage_file.DirToFinderMatchFiles

	CopyOnlyFiles     *cage_strings.Set
	GoDescendantFiles *cage_strings.Set

	InspectDirs       *cage_strings.Set
	InspectIgnoreDirs *cage_strings.Set

	ReplaceStringFiles *ReplaceStringFiles
}

FromFinderOutput holds file/directory absolute paths found via Ops.From.*FilePath/Ops.Dep.From.*FilePath config patterns.

func NewFromFinderOutput

func NewFromFinderOutput() *FromFinderOutput

type Op

type Op struct {
	// Id is a copy of the Config.Ops key selected by the user in the config file.
	//
	// It supports cases such as error messages in parts of the code that only receive the Op
	// and not the whole Config from which it belongs.
	Id string

	// From describes the origin module location.
	From RootFrom

	// To describes the standalone-repo location.
	To RootTo

	// Dep describes dependencies of code in From that exists elsewhere in the origin module and is not vendored,
	// e.g. first-party packages/modules centrally shared in the repo.
	Dep []Dep

	// DryRun is true if the operation should perform all steps except creating/modifying Ops.To.FilePath.
	DryRun bool `mapstructure:"-"`

	// Ingress is true if the copy mode/direction is from a standalone module to the origin source tree.
	Ingress bool `mapstructure:"-"`
}

Op describes a package/project copy operation.

type PrunableFile

type PrunableFile struct {
	*File

	// DecoratedFile is a converted ast.File that contains additional information which supports
	// such things as AST editing w/ comment position retention.
	DecoratedFile *dst.File

	// Decorator converts the ast.File to Decorated file, maps dst.Node values to ast.Node values, etc.
	Decorator *decorator.Decorator
}

PrunableFile stores details about a single-file which will be copied to the stage and final destination, supporting copy-related tasks such as content updates and renaming.

It serves the same purpose as File but only for files which require may have its nodes pruned and printed by github.com/dave/dst for improved comment handling.

func NewPrunableFile

func NewPrunableFile(audit *Audit, newFilePath string) (f *PrunableFile, err error)

NewPrunableFile returns an instance representing a file in the tree which will be copied.

It performs the same role as File except for supporting github.com/dave/dst ASTs which provides improved comment handling when nodes are removed.

All file path parameters must be absolute.

func (*PrunableFile) Apply

func (f *PrunableFile) Apply(fn func(cursor *dstutil.Cursor) bool) dst.Node

Apply is an astutil.Apply alternative that retains comment position after AST mutation.

func (*PrunableFile) GetImportedPaths

func (f *PrunableFile) GetImportedPaths(audit *Audit, op Op, isLocal bool) (paths *cage_strings.Set, errs []error)

GetImportedPaths returns the import paths used in the file based on inspection data.

func (*PrunableFile) GetNodeBytes

func (f *PrunableFile) GetNodeBytes(node dst.Node) ([]byte, error)

GetNodeBytes converts the input node into a []byte using the file's decorator.

func (*PrunableFile) RewriteImportsInNode

func (f *PrunableFile) RewriteImportsInNode(audit *Audit, op Op, cursor *dstutil.Cursor, astNode ast.Node, isLocal bool) (err error)

RewriteImportsInNode updates an AST node if it imports or references a package whose location will change in the copy operation.

Import declarations and identifiers which include an import name of a Op.From.LocalFilePath/Op.Dep.From.FilePath package will be updated to the associated Op.To.LocalFilePath/Op.Dep.To.FilePath path/name.

func (*PrunableFile) UpdateDepAst

func (f *PrunableFile) UpdateDepAst(audit *Audit, op Op) (prunedGlobalIds *cage_strings.Set, errs []error)

UpdateDepAst modifies import paths/names to point to destination paths, prunes declarations of unused globals, and removes unused import declarations.

type RenameSpec

type RenameSpec struct {
	// Old is a relative path.
	//
	// It is a source path during egress and destination path during ingress.
	//
	// It must identify a file already selected in the operation, e.g. via CopyOnlyFilePath
	// or other *FilePath query.
	Old string

	// New is a relative path.
	//
	// It is a destination path during egress and source path during ingress.
	//
	// It must identify a file already selected in the operation, e.g. via CopyOnlyFilePath
	// or other *FilePath query.
	New string
}

RenameSpec defines a file/directory path change.

Definitions are currently restricted to single file/directory changes in order for them to be reverisble in an egress/ingress cycle. For example, if a glob pattern was used to select files to move during egress, the same pattern might be insufficient during ingress because it matches on additional files that were there before the egress operation.

type ReplaceStringFiles

type ReplaceStringFiles struct {
	// ImportPath holds Ops.From.ReplaceString.ImportPath/Ops.Dep.From.ReplaceString.ImportPath matches.
	ImportPath *cage_strings.Set
}

ReplaceStringFiles holds file absolute paths found via Ops.From.ReplaceString/Ops.Dep.From.ReplaceString config patterns.

func NewReplaceStringFiles

func NewReplaceStringFiles() *ReplaceStringFiles

type ReplaceStringSpec

type ReplaceStringSpec struct {
	// ImportPath matches files which should have Ops.From/Ops.To import paths converted
	// when found outside import statements of parsed files identified via GoFilePath:
	// e.g. CopyOnlyFilePath and GoDescendantFilePath matches
	//
	// Each pattern is relative to the FilePath field in the parent RootFrom/DepFrom.
	ImportPath FilePathQuery
}

ReplaceStringSpec defines the scope of string replacements to perform during copy operations.

type RootFrom

type RootFrom struct {
	// ModuleFilePath is the absolute path to the root of the origin module where the go.mod can be found.
	//
	// It is the base directory for all *FilePath patterns.
	//
	// If it contains a go.sum, and `go mod tidy` execution in the destination during egress also
	// creates one, the destination's hashes will be verified against the origin's.
	//
	// If it contains a vendor/modules.txt file, `go mod vendor` will be used to create one in the destination.
	ModuleFilePath string

	// ModuleImportPath is the import path of the module rooted in ModuleFilePath.
	//
	// It is a copy of Module.Path and present for consistency with RootTo.ModuleImportPath.
	ModuleImportPath string `mapstructure:"-"`

	// LocalFilePath is a path relative to ModuleFilePath which declares the root of all project-local files.
	//
	// It is read from the config file, resolved to an absolute path, and then used as the base path for
	// all Ops.From.*FilePath patterns.
	LocalFilePath string

	// LocalImportPath is the prefix of all packages under LocalFilePath.
	//
	// It is computed based on ModuleImportPath and LocalFilePath.
	LocalImportPath string `mapstructure:"-"`

	// GoFilePath matches directories in which implementation (and optionally test) packages should
	// be copied and analyzed for their dependencies.
	//
	// Matching directories will be inspected.
	// If Tests is true, test packages will be auto-discovered.
	// Only Go files will be copied.
	GoFilePath FilePathQuery

	// CopyOnlyFilePath matches files which should be copied but not inspected or refactored
	// (except for basic string replacement of source file/import paths).
	//
	// Each pattern is relative to FilePath.
	CopyOnlyFilePath FilePathQuery

	// GoDescendantFilePath first matches files which should be copied but not inspected or refactored
	// (except for basic string replacement of source file/import paths), same as CopyOnlyFilePath.
	// It also requires that each file is a descendant of directory which provides a Go package to the copy
	// (i.e. a dependency of a project matched by GoFilePath).
	//
	// For example, it supports the need to exclude files such as test fixtures whose only dependents are in
	// ancestor directories which will not be part of the copy.
	GoDescendantFilePath FilePathQuery

	// Rename defines file/directory path changes to perform during the copy operation.
	RenameFilePath []RenameSpec

	// ReplaceString defines the scope of string replacements to perform during copy operations.
	//
	// Replacements occur on the intersection between its matches and those of all other config patterns,
	// such as GoFilePath and CopyOnlyFilePath, which control the scope of the copy operation itself.
	ReplaceString ReplaceStringSpec

	// ModuleSum is true if <ModuleFilePath>/go.sum was found during config validation/finalization.
	ModuleSum bool `mapstructure:"-"`

	// Tests is true if GoFilePath-matched test packages and their dependencies should be included.
	Tests bool

	// Vendor is true if GOFLAGS contains "-mod=vendor" and <ModuleFilePath>/{go.sum,vendor/modules.txt} exists
	// (as indication that the origin is using the same vendoring tool as we are).
	//
	// go.sum is required because a prior `go mod vendor` run should have created one.
	Vendor bool `mapstructure:"-"`
}

RootFrom describes the origin of a copy operation.

type RootTo

type RootTo struct {
	// ModuleFilePath is the absolute path to the root of the copy's tree.
	ModuleFilePath string

	// ModuleImportPath is the import path of the module copied to ModuleFilePath.
	ModuleImportPath string

	// LocalFilePath is a path relative to ModuleFilePath which declares the root of all copied project-local files.
	LocalFilePath string

	// LocalImportPath is the prefix of all packages under LocalFilePath.
	//
	// It is computed based on ModuleImportPath and LocalFilePath.
	LocalImportPath string `mapstructure:"-"`
}

RootTo describes the destination of a copy operation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL