github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-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  	"sort"
    11  	"strings"
    12  	"sync"
    13  
    14  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/base"
    15  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/modfetch"
    16  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/par"
    17  
    18  	"golang.org/x/mod/modfile"
    19  	"golang.org/x/mod/module"
    20  	"golang.org/x/mod/semver"
    21  )
    22  
    23  // ConvertLegacyConfig converts legacy config to modfile.
    24  // The file argument is slash-delimited.
    25  func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error {
    26  	i := strings.LastIndex(file, "/")
    27  	j := -2
    28  	if i >= 0 {
    29  		j = strings.LastIndex(file[:i], "/")
    30  	}
    31  	convert := Converters[file[i+1:]]
    32  	if convert == nil && j != -2 {
    33  		convert = Converters[file[j+1:]]
    34  	}
    35  	if convert == nil {
    36  		return fmt.Errorf("unknown legacy config file %s", file)
    37  	}
    38  	mf, err := convert(file, data)
    39  	if err != nil {
    40  		return fmt.Errorf("parsing %s: %v", file, err)
    41  	}
    42  
    43  	// Convert requirements block, which may use raw SHA1 hashes as versions,
    44  	// to valid semver requirement list, respecting major versions.
    45  	var (
    46  		work    par.Work
    47  		mu      sync.Mutex
    48  		need    = make(map[string]string)
    49  		replace = make(map[string]*modfile.Replace)
    50  	)
    51  
    52  	for _, r := range mf.Replace {
    53  		replace[r.New.Path] = r
    54  		replace[r.Old.Path] = r
    55  	}
    56  	for _, r := range mf.Require {
    57  		m := r.Mod
    58  		if m.Path == "" {
    59  			continue
    60  		}
    61  		if re, ok := replace[m.Path]; ok {
    62  			work.Add(re.New)
    63  			continue
    64  		}
    65  		work.Add(r.Mod)
    66  	}
    67  
    68  	work.Do(10, func(item interface{}) {
    69  		r := item.(module.Version)
    70  		repo, info, err := modfetch.ImportRepoRev(r.Path, r.Version)
    71  		if err != nil {
    72  			fmt.Fprintf(os.Stderr, "go: converting %s: stat %s@%s: %v\n", base.ShortPath(file), r.Path, r.Version, err)
    73  			return
    74  		}
    75  		mu.Lock()
    76  		path := repo.ModulePath()
    77  		// Don't use semver.Max here; need to preserve +incompatible suffix.
    78  		if v, ok := need[path]; !ok || semver.Compare(v, info.Version) < 0 {
    79  			need[path] = info.Version
    80  		}
    81  		mu.Unlock()
    82  	})
    83  
    84  	var paths []string
    85  	for path := range need {
    86  		paths = append(paths, path)
    87  	}
    88  	sort.Strings(paths)
    89  	for _, path := range paths {
    90  		if re, ok := replace[path]; ok {
    91  			err := f.AddReplace(re.Old.Path, re.Old.Version, path, need[path])
    92  			if err != nil {
    93  				return fmt.Errorf("add replace: %v", err)
    94  			}
    95  		}
    96  		f.AddNewRequire(path, need[path], false)
    97  	}
    98  
    99  	f.Cleanup()
   100  	return nil
   101  }