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