Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions content/docs/migration/easyp-v0.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,58 @@ Modified legacy policy and manifest files receive byte-identical <code>.v0.bak</

## What is preserved

The converter preserves the effective selected lint rules, exceptions, rule settings, and explicit legacy comment-suppression setting. It converts literal ignores and rule-specific prefix ignores to the corresponding v1 exclusions. Generation preserves plugin sources, argv, options, <code>with_imports</code>, and supported managed settings. Relative paths remain relative to the configuration directory.
The converter preserves the effective selected lint rules, exceptions, rule settings, and explicit legacy comment-suppression setting. It converts literal ignores and rule-specific prefix ignores to the corresponding v1 exclusions. Generation preserves plugin sources, argv, options, <code>with_imports</code>, and supported managed settings. Plugin output paths remain relative to the configuration directory.

Legacy <code>direct</code> and <code>indirect</code> requirements are converted to native <code>require</code> directives. The tool checks that whole v1 source roots would select the same local protobuf files with the same import paths. It does not silently expand a sliced input into an entire module.
Legacy <code>direct</code> and <code>indirect</code> requirements are converted to native <code>require</code> directives. The tool proves that local generation keeps the same protobuf files and import paths, using whole roots, literal generation paths or exact package selectors.

## Keep default roots and source locations

An omitted or empty legacy root means <code>.</code>. Native <code>protobuf.mod</code> has the same default when <code>roots</code> is omitted; there is no need to move proto files into a new directory.

For example, an input selecting <code>mcp</code> under root <code>.</code> can become the following generation selection without including copies elsewhere in the repository:

~~~yaml
version: v1
generate:
paths: [mcp]
plugins:
- name: go
out: .
opts:
paths: source_relative
~~~

Import roots stay unchanged and generated files keep their source-relative paths. The wizard first tries whole-root equality, then literal directory paths, then complete package selectors for mixed-root cases. Each choice must select exactly the same physical files with the same import names. Paths can preserve part of a package: ignored Gradle build copies outside `mcp` stay out of generation. Hidden/vendor/nested-module boundary changes and inferred local filters mixed with whole-module Git inputs remain blocked. Sources and fixed paths/packages are checked again before apply.

`generate.paths` matches literal module-directory-relative files or directory subtrees, with `.` meaning all sources; `mcp` does not select `mcp-copy`. Paths intersect optional package selectors, and every selector must match a resulting source across the selected modules. Unknown selectors fail before plugins or descriptor writes, even without plugins or under `--all`. Required imports outside these paths remain available. These paths are separate from plugin `opts.paths`, which controls output layout.

Path selection requires an updated v1 build; the initial <code>v1.0.0-nightly.20261005.1</code> and commit <code>8be79c7</code> do not provide it. When migration uses the complete-package fallback, the preview still warns that future files in those packages become targets regardless of their directory.

Variable placeholders are not expanded into saved values. If a placeholder or selector prevents safe analysis, conversion fails rather than persisting credentials or guessing its meaning.

For a sole local input, migration does not repeat its module in `generate.modules`: it is inferred from the generator location. With `root: api, path: easyp`, the output is `generate.paths: [api/easyp]` and protobuf import names stay unchanged. Global filters remain available without listing modules; each module object can also add its own `paths`/`packages`, intersected with global filters.

Migration does not create an empty `options.go.package_prefix`. This field is optional: omission allows normal v1 inheritance, while an explicitly empty value blocks prefix inheritance.

## Historical lock integrity

A full commit SHA is preserved, including a full SHA embedded in an old pseudo-version. For a legacy lock entry containing a tag but no SHA, conversion resolves that tag and verifies the historical installed-tree hash before accepting the revision. A moved tag or mismatched historical hash is an error.

The v1 content hash is then calculated independently over the tracked repository files. Old and new hashes cover different path layouts and cannot be copied or compared as interchangeable values. A missing historical dependency pin is not replaced with current HEAD.
Git's annotated-tag spelling, such as `v0.4.0^{}`, is accepted for a full SemVer tag in the historical lock. The tag, commit and original hash are still verified, and the old lock stays byte-identical. Peeled branches, abbreviated refs, repeated suffixes and pseudo-version-shaped peeled tags are rejected.

Released v0 installers archived Git's <code>*.proto</code> pathspec and stripped legacy root prefixes before hashing. Migration reproduces that archive at the pinned revision; it also retains verification of the existing whole-tree hash format. Git archive attributes that omit or alter proto files require manual migration because a native checkout would change the contract.

The v1 content hash is then calculated independently over the materialized logical snapshot. Old and new hashes cover different path layouts and cannot be copied or compared as interchangeable values. A missing historical dependency pin is not replaced with current HEAD.

Internal symlinks to files, directories, import roots and metadata are supported. Protobuf import names follow the logical path of the alias. Local targets must remain inside their owning source boundary; Git targets must be relative and resolve entirely from the pinned tree. Selected dangling links, cycles, submodule crossings and undeclared nested repositories fail. Invalid unused auxiliary links are omitted. Git snapshots contain regular resolved bytes, including safe non-proto aliases, regardless of `core.symlinks`.

If the legacy configuration file itself is a symlink, migration replaces that logical file with regular v1 content and creates a regular backup of its original contents. The former target stays unchanged; rollback restores the original link. Inputs and link topology are checked again before applying.

Historical v0 archive verification remains a separate migration step. A valid historical file alias must preserve both its installed import name and resolved contents. Its target must exist in the archived inputs; the verifier cannot use current files or unarchived Git blobs. The v1 hash is calculated independently from the materialized snapshot.

## Explicit limitations

Unknown fields, invalid or multi-document YAML, ambiguous source selection, unsupported references, and conflicting native outputs are rejected. Custom Git-input roots/subdirectories, external or sliced local inputs whose exact selection cannot be preserved, unsafe managed selectors, and full lock conversion with local replacements may require manual migration. Buf configurations are not inputs to this v0 converter.
Invalid known fields, invalid or multi-document YAML, ambiguous source selection, unsupported references, and conflicting native outputs are rejected. Keys ignored by v0 are omitted with warnings and remain in the legacy backup. Custom Git-input roots/subdirectories, external or sliced local inputs whose exact selection cannot be preserved, unsafe managed selectors, and full lock conversion with local replacements may require manual migration. Buf configurations are not inputs to this v0 converter.

The command stages all outputs and checks observed inputs again before applying. Ordinary application failures are rolled back. Several file replacements are not one process-crash-atomic transaction: after a machine or process failure, inspect the preserved backups and Git state before continuing. Uncooperative concurrent writers cannot be made safe by this command.

Expand Down
Loading
Loading