this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

mod/modfile: add FixLegacy function

This implements the core functionality required
to migrate legacy module.cue files to the new syntax.

For #3137

Signed-off-by: Roger Peppe <rogpeppe@gmail.com>
Change-Id: I27cf3e7241d64d56398289c1400d51ef79b0f813
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1194769
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>

+128
+69
mod/modfile/modfile.go
··· 262 262 return parse(modfile, filename, false) 263 263 } 264 264 265 + // FixLegacy converts a legacy module.cue file as parsed by [ParseLegacy] 266 + // into a format suitable for parsing with [Parse]. It adds a language.version 267 + // field and moves all unrecognized fields into custom.legacy. 268 + // 269 + // If there is no module field or it is empty, it is set to "test.example@v0". 270 + // 271 + // If the file already parses OK with [ParseNonStrict], it returns the 272 + // result of that. 273 + func FixLegacy(modfile []byte, filename string) (*File, error) { 274 + f, err := ParseNonStrict(modfile, filename) 275 + if err == nil { 276 + // It parses OK so it doesn't need fixing. 277 + return f, nil 278 + } 279 + ctx := cuecontext.New() 280 + file, err := parseDataOnlyCUE(ctx, modfile, filename) 281 + if err != nil { 282 + return nil, errors.Wrapf(err, token.NoPos, "invalid module.cue file syntax") 283 + } 284 + v := ctx.BuildFile(file) 285 + if err := v.Validate(cue.Concrete(true)); err != nil { 286 + return nil, errors.Wrapf(err, token.NoPos, "invalid module.cue file value") 287 + } 288 + var allFields map[string]any 289 + if err := v.Decode(&allFields); err != nil { 290 + return nil, err 291 + } 292 + mpath := "test.example@v0" 293 + if m, ok := allFields["module"]; ok { 294 + if mpath1, ok := m.(string); ok && mpath1 != "" { 295 + mpath = mpath1 296 + } else if !ok { 297 + return nil, fmt.Errorf("module field has unexpected type %T", m) 298 + } 299 + // TODO decide what to do if the module path isn't OK according to the new rules. 300 + } 301 + customLegacy := make(map[string]any) 302 + for k, v := range allFields { 303 + if k != "module" { 304 + customLegacy[k] = v 305 + } 306 + } 307 + var custom map[string]map[string]any 308 + if len(customLegacy) > 0 { 309 + custom = map[string]map[string]any{ 310 + "legacy": customLegacy, 311 + } 312 + } 313 + f = &File{ 314 + Module: mpath, 315 + Language: &Language{ 316 + Version: cueversion.LanguageVersion(), 317 + }, 318 + Custom: custom, 319 + } 320 + // Round-trip through [Parse] so that we get exactly the same 321 + // result as a later parse of the same data will. This also 322 + // adds a major version to the module path if needed. 323 + data, err := f.Format() 324 + if err != nil { 325 + return nil, fmt.Errorf("cannot format fixed file: %v", err) 326 + } 327 + f, err = ParseNonStrict(data, "fixed-"+filename) 328 + if err != nil { 329 + return nil, fmt.Errorf("cannot round-trip fixed module file %q: %v", data, err) 330 + } 331 + return f, nil 332 + } 333 + 265 334 func parse(modfile []byte, filename string, strict bool) (*File, error) { 266 335 // Unfortunately we need a new context. See the note inside [moduleSchemaDo]. 267 336 ctx := cuecontext.New()
+59
mod/modfile/modfile_test.go
··· 342 342 wantDefaults: map[string]string{ 343 343 "foo.com/bar": "v0", 344 344 }, 345 + }, { 346 + testName: "FixLegacyWithModulePath", 347 + parse: FixLegacy, 348 + data: ` 349 + module: "foo.com/bar" 350 + `, 351 + want: &File{ 352 + Module: "foo.com/bar@v0", 353 + Language: &Language{Version: "v0.9.0"}, 354 + }, 355 + wantDefaults: map[string]string{ 356 + "foo.com/bar": "v0", 357 + }, 358 + }, { 359 + testName: "FixLegacyWithoutModulePath", 360 + parse: FixLegacy, 361 + data: ` 362 + `, 363 + want: &File{ 364 + Module: "test.example@v0", 365 + Language: &Language{Version: "v0.9.0"}, 366 + }, 367 + wantDefaults: map[string]string{ 368 + "test.example": "v0", 369 + }, 370 + }, { 371 + testName: "FixLegacyWithEmptyModulePath", 372 + parse: FixLegacy, 373 + data: ` 374 + module: "" 375 + `, 376 + want: &File{ 377 + Module: "test.example@v0", 378 + Language: &Language{Version: "v0.9.0"}, 379 + }, 380 + wantDefaults: map[string]string{ 381 + "test.example": "v0", 382 + }, 383 + }, { 384 + testName: "FixLegacyWithCustomFields", 385 + parse: FixLegacy, 386 + data: ` 387 + module: "foo.com" 388 + some: true 389 + other: field: 123 390 + `, 391 + want: &File{ 392 + Module: "foo.com@v0", 393 + Language: &Language{Version: "v0.9.0"}, 394 + Custom: map[string]map[string]any{ 395 + "legacy": { 396 + "some": true, 397 + "other": map[string]any{"field": 123}, 398 + }, 399 + }, 400 + }, 401 + wantDefaults: map[string]string{ 402 + "foo.com": "v0", 403 + }, 345 404 }} 346 405 347 406 func TestParse(t *testing.T) {