Documentation ¶
Overview ¶
Package upgrade implements template upgrading: taking a directory containing a rendered template and updating it with the latest version of the template.
Index ¶
Constants ¶
const ( // These are appended to files that need manual merge conflict resolution. SuffixLocallyAdded = ".abcmerge_locally_added" SuffixLocallyEdited = ".abcmerge_locally_edited" SuffixFromNewTemplate = ".abcmerge_from_new_template" SuffixFromNewTemplateLocallyDeleted = ".abcmerge_locally_deleted_vs_new_template_version" SuffixWantToDelete = ".abcmerge_template_wants_to_delete" // This is the beginning of all the above suffixes. ConflictSuffixBegins = ".abcmerge_" )
Variables ¶
var ErrNoManifests error = fmt.Errorf("found no template manifests to upgrade")
ErrNoManifests is returned when upgrade is called with a directory that contains no manifest, or a filename that is not a manifest. Nothing could be found to be upgraded.
Functions ¶
This section is empty.
Types ¶
type Action ¶ added in v0.8.0
type Action string
An Action is an action to take for a given output file. This may involve conflicts between upgraded template output files and files that were locally customized by the user.
For the mergeActions named e.g. "editDelete", the first thing is what the user did locally ("edit") and the second thing is want the template wants to do ("delete").
const ( // Just write the contents of the file from the new template. WriteNew Action = "writeNew" // Just DeleteAction the preexisting file in the template output directory. // We can't just call this "delete" because that's a Go builtin. DeleteAction Action = "delete" // Take no action, the current contents of the output directory are correct. Noop Action = "noop" // The user manually created a file, and the template also wants to create // that file. This is a conflict requiring the user to resolve. AddAddConflict Action = "addAddConflict" // The template originally outputted a file, which the user then edited. Now // the template wants to change the file, but we don't want to clobber the // user's edits, so we have to ask them to manually resolve the differences. EditEditConflict Action = "editEditConflict" // The template originally outputted a file, which the user then edited. Now // the template wants to delete the file, but we don't want to clobber the // user's edits, so we have to ask them to manually resolve the differences. EditDeleteConflict Action = "editDeleteConflict" // The template originally outputted a file, which the user then deleted. // Now the template wants to change the file. The user might want the newly // changed file despite having deleted the previous version of the file, so // we'll require them to manually resolve. DeleteEditConflict Action = "deleteEditConflict" )
func (Action) IsConflict ¶ added in v0.8.0
type ActionTaken ¶ added in v0.8.0
type ActionTaken struct { Action Action // Explanation is a human-readable reason why the given Action was chosen // for this path. Explanation string // This is the Path to the single file that this ActionTaken is about. It is // always set. // // This is a relative path, starting from the directory where the template // is installed. Path string // OursPath is only set for certain types of merge conflict. This is the // path that the local file was renamed to that needs manual merge // resolution. // // This is a relative path, starting from the directory where the template // is installed. OursPath string // IncomingTemplatePath is only set for certain types of merge conflict. // This is the path to the incoming template file that needs merge // resolution. // // This is a relative path, starting from the directory where the template // is installed. IncomingTemplatePath string }
ActionTaken represents an output of the merge operation. Every file that's part of the template output will have an ActionTaken that explains what the merge algorithm decided to do for this file (e.g. Noop, EditEditConflict, or other), and why.
If there was a merge conflict, then files may have been renamed. See OursPath and IncomingTemplatePath.
type ManifestResult ¶ added in v0.9.2
type ManifestResult struct { // MergeConflicts is the set of files that require manual intervention by the // user to resolve a merge conflict. For example, there may be a file that // was edited by the user and that edit conflicts with changes to that same // file by the upgraded version of the template. // // This field should only be used when Type==MergeConflict. MergeConflicts []ActionTaken // If this template installation needed to wait to be upgraded before // another template installation, this will be the ManifestPath of the other // ManifestResult that happened first. These dependencies arise when the // output of one template is itself a template. // // This is mainly useful for debugging and testing. DependedOn []string // The metadata returned by the template downloader. DLMeta *templatesource.DownloadMetadata // The relative path to the manifest file of this template installation // that's being upgraded. It's relative to the path that the user provided // to the "upgrade" commnd. If the user provided a path to a manifest file, // this will just be "." (a single dot). ManifestPath string // The paths to files where abc tried to apply the reversal // patches from the manifest to included-from-destination files, and the // patches could not be applied cleanly. Manual resolution is needed. // // This field should only be used when Type==PatchReversalConflict. ReversalConflicts []*ReversalConflict // NonConflicts is the set of template output files that do NOT require any // action by the user. Callers are free to ignore this. // // This is mutually exclusive with "Conflicts". Each file is in at most one // of the two lists. // // This field should only be used when Type is Success or MergeConflict. NonConflicts []ActionTaken // If no upgrade was done because this installation of the template is // already on the latest version, then this will be true and all other // fields in this struct will have zero values. Type ResultType }
ManifestResult is the result of upgrading a single template installation (potentially one of many that may be found underneath a given directory).
type Params ¶
type Params struct { // Relative paths where patch reversal has already happened. This is a flag // supplied by the user. This will be set if there were merge conflicts // during patch reversal that were manually resolved by the user. // TODO(upgrade): implement this, should only apply to first upgrade AlreadyResolved []string Clock clock.Clock // The directory that relative paths are interpreted as being relative to. // In testing, this is a temp directory. If empty, the value of os.Getwd() // will be used. CWD string // The value of --debug-scratch-contents. DebugScratchContents bool // The value of --debug-step-diffs. DebugStepDiffs bool // FS abstracts filesystem operations for error injection testing. FS common.FS // The value of --git-protocol. GitProtocol string // The value of --input-file. InputFiles []string // The value of --input. Inputs map[string]string // The value of --keep-temp-dirs. KeepTempDirs bool // The path to either a directory or file. If a directory, it will be // crawled looking for manifests to upgrade. If a single manifest file, // that single template will be upgraded. Location string // The value of --prompt. Prompt bool Prompter input.Prompter // The value of --resume-from. Used after a patch reversal conflict to // continue upgrading at the point where the conflict occurred. ResumeFrom string // The value of --skip-input-validation. SkipInputValidation bool // Used in tests to do prompting for inputs even though the input is not a // TTY. SkipPromptTTYCheck bool // The output stream used to print prompts when Prompt==true. Stdout io.Writer // Empty string, except in tests. Will be used as the parent of temp dirs. TempDirBase string // An optional version to update to, overriding the upgrade_channel field in // the manifest. // // For the case of remote git templates, this may be a branch, tag, SHA, or // the special string "latest", which means "the vX.Y.Z tag that is largest // by semver ordering." In the case of a template on the local filesystem, // it's ignored because we only have the one version that's on the // filesystem. Version string // contains filtered or unexported fields }
Params contains all the arguments to Upgrade().
type Result ¶ added in v0.8.0
type Result struct { // The "most severe" or "most interesting" upgrade result out of all the // upgrades attempted. The ascending order of severity is None -> // AlreadyUpToDate -> Success -> PatchReversalConflict -> MergeConflict // // For example, if we ran an upgrade on a directory containing three // installed templates, and the results of the upgrades were Success, // AlreadyUpToDate, and MergeConflict (in any order), then the overall // result would be MergeConflict since that's the must severe. Overall ResultType // A map from manifestPath to the result of non-erroring upgrade attempts. // Merge conflicts are included in this map. There are potentially multiple // results per manifest because we loop and upgrade repeatedly. // // Since we stop the upgrade operation when encountering an error or // conflict, it's guaranteed that at most 1 of the entries in this map are // a conflict (Type equals MergeConflict or PatchReversalConflict). // // All slices in this map will have length at least one. Results []*ManifestResult // Err is any error encountered during the upgrade operation. A merge // conflict during upgrade is not considered an error. // // If Err is set, then ErrManifestPath may also be set. No other fields will // be set. Err error ErrManifestPath string // The optional path to the manifest whose upgrade resulted in error }
Result is the return value from an upgrade operation. It will be returned even if there's an error, to report any partial progress. It contains an error field to report an error that may have happened.
func UpgradeAll ¶ added in v0.9.2
UpgradeAll crawls the given directory looking for manifest files to upgrade, then calls Upgrade() for each one, until no more upgrades are possible. Stops if any errors are encountered.
If no manifests could be found, then ErrNoManifests is returned.
type ResultType ¶ added in v0.8.0
type ResultType int
ResultType is the outcome of attempting an upgrade. It may succeed, may be unnecessary, or may have some sort of merge conflict.
const ( // This is the value of Result.Type when the upgrade was vacuously // successful because the template is already on the latest version. AlreadyUpToDate ResultType = iota // This is the value of Result.Type when there was an upgrade and it was // successful, and no user intervention is needed. Success ResultType = iota // This is the value of Result.Type when abc tried to apply the reversal // patches from the manifest to included-from-destination files, and the // patches could not be applied cleanly. User intervention is needed, and // the ReversalConflicts field should be used. PatchReversalConflict ResultType = iota // The new version of the template conflicted with local modifications and // manual resolution is required. The Conflicts field should be used. MergeConflict ResultType = iota )
func (ResultType) RequiresUserAttention ¶ added in v0.9.2
func (r ResultType) RequiresUserAttention() bool
func (ResultType) String ¶ added in v0.9.2
func (r ResultType) String() string
type ReversalConflict ¶ added in v0.8.0
type ReversalConflict struct { // The paths to the file that needs manual resolution. RelPath string AbsPath string // Absolute path to the .rej file where the "patch" command saved the hunks // that failed to apply. RejectedHunks string }
ReversalConflict happens when abc tried to apply the reversal patches from the manifest to included-from-destination files, and the patches could not be applied cleanly.