kcl-lang.io/kpm@v0.8.7-0.20240520061008-9fc4c5efc8c7/pkg/mvs/mvs.go (about)

     1  package mvs
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/dominikbraun/graph"
     7  	"github.com/hashicorp/go-version"
     8  	"golang.org/x/mod/module"
     9  	"kcl-lang.io/kpm/pkg/3rdparty/mvs"
    10  	"kcl-lang.io/kpm/pkg/client"
    11  	errInt "kcl-lang.io/kpm/pkg/errors"
    12  	pkg "kcl-lang.io/kpm/pkg/package"
    13  	"kcl-lang.io/kpm/pkg/reporter"
    14  	"kcl-lang.io/kpm/pkg/semver"
    15  )
    16  
    17  type ReqsGraph struct {
    18  	graph.Graph[module.Version, module.Version]
    19  	KpmClient *client.KpmClient
    20  	KpmPkg    *pkg.KclPkg
    21  }
    22  
    23  func (r ReqsGraph) Max(path, v1, v2 string) string {
    24  	if v1 == "none" || v2 == "" {
    25  		return v2
    26  	}
    27  	if v2 == "none" || v1 == "" {
    28  		return v1
    29  	}
    30  	version1, err := version.NewVersion(v1)
    31  	if err != nil {
    32  		reporter.Fatal(reporter.FailedParseVersion, err, fmt.Sprintf("failed to parse version %s for module %s", v1, path))
    33  		return ""
    34  	}
    35  	version2, err := version.NewVersion(v2)
    36  	if err != nil {
    37  		reporter.Fatal(reporter.FailedParseVersion, err, fmt.Sprintf("failed to parse version %s for module %s", v2, path))
    38  		return ""
    39  	}
    40  	if version1.GreaterThan(version2) {
    41  		return v1
    42  	}
    43  	return v2
    44  }
    45  
    46  func (r ReqsGraph) Upgrade(m module.Version) (module.Version, error) {
    47  	_, properties, err := r.VertexWithProperties(m)
    48  	if err != nil {
    49  		return module.Version{}, err
    50  	}
    51  
    52  	// there must be only one property depending on the download source type
    53  	if len(properties.Attributes) != 1 {
    54  		return module.Version{}, errInt.MultipleSources
    55  	}
    56  
    57  	var releases []string
    58  	for sourceType, uri := range properties.Attributes {
    59  		releases, err = client.GetReleasesFromSource(sourceType, uri)
    60  		if err != nil {
    61  			return module.Version{}, err
    62  		}
    63  	}
    64  
    65  	if releases == nil {
    66  		return m, nil
    67  	}
    68  
    69  	m.Version, err = semver.LatestCompatibleVersion(releases, m.Version)
    70  	if err != nil {
    71  		return module.Version{}, err
    72  	}
    73  	_, err = r.Vertex(m)
    74  	if err == graph.ErrVertexNotFound {
    75  		d := pkg.Dependency{
    76  			Name:    m.Path,
    77  			Version: m.Version,
    78  		}
    79  		d.FullName = d.GenDepFullName()
    80  		for sourceType, uri := range properties.Attributes {
    81  			d.Source, err = pkg.GenSource(sourceType, uri, m.Version)
    82  			if err != nil {
    83  				return module.Version{}, err
    84  			}
    85  		}
    86  		deps := pkg.Dependencies{
    87  			Deps: map[string]pkg.Dependency{
    88  				m.Path: d,
    89  			},
    90  		}
    91  		lockDeps := pkg.Dependencies{
    92  			Deps: make(map[string]pkg.Dependency),
    93  		}
    94  		_, err = r.KpmClient.DownloadDeps(&deps, &lockDeps, r.Graph, r.KpmPkg.HomePath, module.Version{})
    95  		if err != nil {
    96  			return module.Version{}, err
    97  		}
    98  	}
    99  	return m, nil
   100  }
   101  
   102  func (r ReqsGraph) Previous(m module.Version) (module.Version, error) {
   103  	_, properties, err := r.VertexWithProperties(m)
   104  	if err != nil {
   105  		return module.Version{}, err
   106  	}
   107  
   108  	// there must be only one property depending on the download source type
   109  	if len(properties.Attributes) != 1 {
   110  		return module.Version{}, errInt.MultipleSources
   111  	}
   112  
   113  	var releases []string
   114  	for sourceType, uri := range properties.Attributes {
   115  		releases, err = client.GetReleasesFromSource(sourceType, uri)
   116  		if err != nil {
   117  			return module.Version{}, err
   118  		}
   119  	}
   120  
   121  	if releases == nil {
   122  		return m, nil
   123  	}
   124  
   125  	// copy the version to compare it later
   126  	v := m.Version
   127  
   128  	m.Version, err = semver.LeastOldCompatibleVersion(releases, m.Version)
   129  	if err != nil && err != errInt.InvalidVersionFormat {
   130  		return module.Version{}, err
   131  	}
   132  
   133  	if v == m.Version {
   134  		return module.Version{Path: m.Path, Version: "none"}, nil
   135  	}
   136  
   137  	_, err = r.Vertex(m)
   138  	if err == graph.ErrVertexNotFound {
   139  		d := pkg.Dependency{
   140  			Name:    m.Path,
   141  			Version: m.Version,
   142  		}
   143  		d.FullName = d.GenDepFullName()
   144  		for sourceType, uri := range properties.Attributes {
   145  			d.Source, err = pkg.GenSource(sourceType, uri, m.Version)
   146  			if err != nil {
   147  				return module.Version{}, err
   148  			}
   149  		}
   150  		deps := pkg.Dependencies{
   151  			Deps: map[string]pkg.Dependency{
   152  				m.Path: d,
   153  			},
   154  		}
   155  		lockDeps := pkg.Dependencies{
   156  			Deps: make(map[string]pkg.Dependency),
   157  		}
   158  		_, err = r.KpmClient.DownloadDeps(&deps, &lockDeps, r.Graph, r.KpmPkg.HomePath, module.Version{})
   159  		if err != nil {
   160  			return module.Version{}, err
   161  		}
   162  	}
   163  	return m, nil
   164  }
   165  
   166  func (r ReqsGraph) Required(m module.Version) ([]module.Version, error) {
   167  	adjMap, err := r.AdjacencyMap()
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  	var reqs []module.Version
   172  	for v := range adjMap[m] {
   173  		reqs = append(reqs, v)
   174  	}
   175  	return reqs, nil
   176  }
   177  
   178  // UpdateBuildList decides whether to upgrade or downgrade based on modulesToUpgrade and modulesToDowngrade.
   179  // if modulesToUpgrade is empty, upgrade all dependencies. if modulesToUpgrade is not empty, upgrade the dependencies.
   180  // if modulesToDowngrade is not empty, downgrade the dependencies.
   181  // if modulesToUpgrade and modulesToDowngrade are both empty, first apply upgrade operation and
   182  // then downgrade the build list returned from previous operation.
   183  func UpdateBuildList(target module.Version, modulesToUpgrade []module.Version, modulesToDowngrade []module.Version, reqs *ReqsGraph) ([]module.Version, error) {
   184  	var (
   185  		UpdBuildLists []module.Version
   186  		err           error
   187  	)
   188  
   189  	if len(modulesToUpgrade) == 0 {
   190  		UpdBuildLists, err = mvs.UpgradeAll(target, reqs)
   191  	} else {
   192  		UpdBuildLists, err = mvs.Upgrade(target, reqs, modulesToUpgrade...)
   193  	}
   194  	if err != nil {
   195  		return []module.Version{}, err
   196  	}
   197  
   198  	if len(modulesToDowngrade) != 0 {
   199  		UpdBuildLists, err = mvs.Downgrade(target, reqs, modulesToDowngrade...)
   200  	}
   201  	if err != nil {
   202  		return []module.Version{}, err
   203  	}
   204  
   205  	return UpdBuildLists, nil
   206  }