Skip to content
rlsbl.commands.rewrite.go_module_path
On this page

Renames a Go module path across a repository: every go.mod token and every import site, line-scoped, with containment asked of the module-prefix rule.

#rlsbl.commands.rewrite.go_module_path

#rlsbl.commands.rewrite.go_module_path

Rename a Go module path across a repository.

rlsbl rewrite go-module-path --from-module <old> --to-module <new> moves a module and everything under it onto a new path:

  • every go.mod in the repository has its module-path TOKENS rewritten --

the module directive itself, and any require / replace / exclude / retract reference to the old path from a nested module;

  • every Go import site under the old path is rewritten, located by the

tree-sitter import scanner (:func:rlsbl.lint.go_ast.scan_imports) and rewritten line-scoped -- only on the exact line the parser reported an import spec, and only inside that spec's quoted literal.

Containment is never a bare startswith. Both halves ask :mod:rlsbl.module_paths, so a neighbouring module whose path merely begins with the same letters (github.com/o/foobar beside github.com/o/foo) is left alone.

What is deliberately NOT rewritten ----------------------------------

  • Comments. // text in a go.mod and anything outside an import

spec in a .go file are prose; rewriting them would make the occurrence counts describe something other than the code being moved. Grep for the old path after the rename to catch documentation.

  • **Any file that is not a go.mod or a .go.** READMEs, CI workflows

and generated code are outside this command's scope, on purpose: it renames a module, it does not sweep a repository for a string.

  • **vendor/ and .git/, and nothing else.** A vendored tree is a

third-party copy, not this module, and .git is the repository's own storage. Every other directory is visited, INCLUDING build, dist, static, public, assets and node_modules: those are a linter's build-output exclusions, and each of them is also a perfectly ordinary Go package directory (internal/assets, cmd/build, web/static). Pruning them here skipped real packages silently and left a tree that does not compile, so this command passes its own exclusion set to the shared walker rather than inheriting the linters' one.

#GoModuleRewriteError

A hard error in the module-path rewrite (bad input, count mismatch).

#FileRewrite

One file's pending rewrite, as observed.

#validate_module_paths

python
def validate_module_paths(old, new)

Reject module paths that cannot be renamed between.

A supplied-but-empty path is not refused here: that is one class with one message, and the CLI boundary owns it (rlsbl._refuse_empty_flags), so --from-module "" reads the same as every other empty flag value in rlsbl rather than a message only this command uses.

#_excluded

python
def _excluded(path, root)

True when path sits under an excluded path component.

#find_go_mod_files

python
def find_go_mod_files(root)

Every go.mod in the tree, absolute, sorted.

#rewrite_go_mod_text

python
def rewrite_go_mod_text(text, old, new)

Rewrite module-path tokens in go.mod text.

Returns (new_text, occurrences, sites). Only the code portion of each line is touched: anything after // is a comment and is left verbatim.

#_token_at

python
def _token_at(text, start)

The whole module-path token beginning at start in text.

#declared_modules

python
def declared_modules(go_mod_paths)

{abs go.mod path: declared module path} for every readable go.mod.

#_literal_on_line

python
def _literal_on_line(line, import_path)

The quoted literal for import_path as it appears on line, or None.

#rewrite_go_source_text

python
def rewrite_go_source_text(text, sites, old, new)

Rewrite the import literals sites names, line-scoped.

Args:

  • text: the file's full contents.
  • sites: [(import_path, line_number)] as the tree-sitter scanner

reported them, restricted to imports under old.

Returns (new_text, occurrences, descriptions). An import spec whose quoted literal is not present on the reported line -- in EITHER of Go's two string forms -- is a hard error: the parser and the text disagree, and guessing where to write is exactly the failure this command must not have. The form the file used is preserved: a raw-string import stays a raw string.

#scan_go_source

python
def scan_go_source(path, old)

Import sites in path that are under module old.

#observe_file

python
def observe_file(path, root, old, new)

Observe one file, returning a :class:FileRewrite or None.

#recompute

python
def recompute(rewrite, old, new)

Re-derive a file's rewrite from disk. Returns (new_text, count).

#observe

python
def observe(root, old, new)

Build the whole preview: one item per file that would change.

A sweep that finds NOTHING is a hard error, not an empty plan. The overwhelmingly likely cause is a mistyped --from-module, and a command that answers a typo with "nothing to do, exit 0" teaches the operator to believe a rename happened when none did.

A repository that does not itself DECLARE the module is fine and is reported as such: renaming a dependency's module path across a consumer (upstream moved, the imports must follow) is the same sweep with no module directive in it.

#apply_item

python
def apply_item(item, old, new, applied=None)

Write one file, refusing when its count moved since the preview.

applied is an optional list the caller passes through every item; each successful write appends its key, so an abort can name what is already on disk.

#cmd_go_module_path

python
def cmd_go_module_path(flags, project_root)

rlsbl rewrite go-module-path -- rename a Go module across the repo.

flags["from-module"] / flags["to-module"] -- the module paths. flags["dry-run"] -- plan only.

Search