diff --git a/cmd/migrate/migration/init.go b/cmd/migrate/migration/init.go index 08e61160..669bec65 100644 --- a/cmd/migrate/migration/init.go +++ b/cmd/migrate/migration/init.go @@ -3,7 +3,6 @@ package migration import ( "fmt" "log" - "path/filepath" "sort" "strings" "sync" @@ -363,7 +362,10 @@ func (e *Migration) run(appCode string) { // from the empty app code, which selects the framework's own migrations. const allApps = "\x00all" +// GetFilename derives a migration's version from its file name. The rule +// lives in contract/migration, because an application registering through +// that package names its files by the same convention and must land on the +// same version string; a second copy here is a second thing to keep in step. func GetFilename(s string) string { - s = filepath.Base(s) - return s[:13] + return contractmigration.GetFilename(s) } diff --git a/cmd/migrate/migration/init_test.go b/cmd/migrate/migration/init_test.go index c4c8db6f..13d8c6a6 100644 --- a/cmd/migrate/migration/init_test.go +++ b/cmd/migrate/migration/init_test.go @@ -561,3 +561,22 @@ func TestMergedEntriesHostRegistrationWinsOnKeyCollision(t *testing.T) { t.Error("contract registration ran; host registration should have won the collision") } } + +// GetFilename must stay the same rule the contract package applies, since an +// application registering through contract/migration names its files by that +// convention and has to land on the same version string. Pinning the reject +// case is what catches a re-divergence: a local copy that only sliced would +// return "add_orders.go" here and register a migration under a key that never +// matches anything. +func TestGetFilenameDelegatesToTheContractRule(t *testing.T) { + if got := GetFilename("version/1786700001000_demo_menu.go"); got != "1786700001000" { + t.Fatalf("GetFilename = %q, want %q", got, "1786700001000") + } + + defer func() { + if recover() == nil { + t.Fatal("a file name carrying no version did not panic") + } + }() + GetFilename("version/add_orders.go") +}