github.com/bir3/gocompiler@v0.3.205/src/cmd/gocmd/internal/modconv/convert.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package modconv 6 7 import ( 8 "fmt" 9 "os" 10 "runtime" 11 "sort" 12 "strings" 13 14 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/base" 15 16 "github.com/bir3/gocompiler/src/xvendor/golang.org/x/mod/modfile" 17 "github.com/bir3/gocompiler/src/xvendor/golang.org/x/mod/module" 18 "github.com/bir3/gocompiler/src/xvendor/golang.org/x/mod/semver" 19 ) 20 21 // ConvertLegacyConfig converts legacy config to modfile. 22 // The file argument is slash-delimited. 23 func ConvertLegacyConfig(f *modfile.File, file string, data []byte, queryPackage func(path, rev string) (module.Version, error)) error { 24 i := strings.LastIndex(file, "/") 25 j := -2 26 if i >= 0 { 27 j = strings.LastIndex(file[:i], "/") 28 } 29 convert := Converters[file[i+1:]] 30 if convert == nil && j != -2 { 31 convert = Converters[file[j+1:]] 32 } 33 if convert == nil { 34 return fmt.Errorf("unknown legacy config file %s", file) 35 } 36 mf, err := convert(file, data) 37 if err != nil { 38 return fmt.Errorf("parsing %s: %v", file, err) 39 } 40 41 // Convert requirements block, which may use raw SHA1 hashes as versions, 42 // to valid semver requirement list, respecting major versions. 43 versions := make([]module.Version, len(mf.Require)) 44 replace := make(map[string]*modfile.Replace) 45 46 for _, r := range mf.Replace { 47 replace[r.New.Path] = r 48 replace[r.Old.Path] = r 49 } 50 51 type token struct{} 52 sem := make(chan token, runtime.GOMAXPROCS(0)) 53 for i, r := range mf.Require { 54 m := r.Mod 55 if m.Path == "" { 56 continue 57 } 58 if re, ok := replace[m.Path]; ok { 59 m = re.New 60 } 61 sem <- token{} 62 go func(i int, m module.Version) { 63 defer func() { <-sem }() 64 version, err := queryPackage(m.Path, m.Version) 65 if err != nil { 66 fmt.Fprintf(os.Stderr, "go: converting %s: stat %s@%s: %v\n", base.ShortPath(file), m.Path, m.Version, err) 67 return 68 } 69 70 versions[i] = version 71 }(i, m) 72 } 73 // Fill semaphore channel to wait for all tasks to finish. 74 for n := cap(sem); n > 0; n-- { 75 sem <- token{} 76 } 77 78 need := map[string]string{} 79 for _, v := range versions { 80 if v.Path == "" { 81 continue 82 } 83 // Don't use semver.Max here; need to preserve +incompatible suffix. 84 if needv, ok := need[v.Path]; !ok || semver.Compare(needv, v.Version) < 0 { 85 need[v.Path] = v.Version 86 } 87 } 88 paths := make([]string, 0, len(need)) 89 for path := range need { 90 paths = append(paths, path) 91 } 92 sort.Strings(paths) 93 for _, path := range paths { 94 if re, ok := replace[path]; ok { 95 err := f.AddReplace(re.Old.Path, re.Old.Version, path, need[path]) 96 if err != nil { 97 return fmt.Errorf("add replace: %v", err) 98 } 99 } 100 f.AddNewRequire(path, need[path], false) 101 } 102 103 f.Cleanup() 104 return nil 105 }