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

     1  // Copyright 2024 The KCL Authors. All rights reserved.
     2  
     3  package cmd
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  
     9  	"github.com/dominikbraun/graph"
    10  	"github.com/urfave/cli/v2"
    11  	"golang.org/x/mod/module"
    12  	"kcl-lang.io/kpm/pkg/client"
    13  	"kcl-lang.io/kpm/pkg/env"
    14  	pkg "kcl-lang.io/kpm/pkg/package"
    15  	"kcl-lang.io/kpm/pkg/reporter"
    16  )
    17  
    18  // NewGraphCmd new a Command for `kpm graph`.
    19  func NewGraphCmd(kpmcli *client.KpmClient) *cli.Command {
    20  	return &cli.Command{
    21  		Hidden: false,
    22  		Name:   "graph",
    23  		Usage:  "prints the module dependency graph",
    24  		Action: func(c *cli.Context) error {
    25  			return KpmGraph(c, kpmcli)
    26  		},
    27  	}
    28  }
    29  
    30  func KpmGraph(c *cli.Context, kpmcli *client.KpmClient) error {
    31  	// acquire the lock of the package cache.
    32  	err := kpmcli.AcquirePackageCacheLock()
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	defer func() {
    38  		// release the lock of the package cache after the function returns.
    39  		releaseErr := kpmcli.ReleasePackageCacheLock()
    40  		if releaseErr != nil && err == nil {
    41  			err = releaseErr
    42  		}
    43  	}()
    44  
    45  	pwd, err := os.Getwd()
    46  
    47  	if err != nil {
    48  		return reporter.NewErrorEvent(reporter.Bug, err, "internal bugs, please contact us to fix it.")
    49  	}
    50  
    51  	globalPkgPath, err := env.GetAbsPkgPath()
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	kclPkg, err := pkg.LoadKclPkg(pwd)
    57  	if err != nil {
    58  		return err
    59  	}
    60  
    61  	err = kclPkg.ValidateKpmHome(globalPkgPath)
    62  	if err != (*reporter.KpmEvent)(nil) {
    63  		return err
    64  	}
    65  
    66  	_, depGraph, err := kpmcli.InitGraphAndDownloadDeps(kclPkg)
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	adjMap, err := depGraph.AdjacencyMap()
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	format := func(m module.Version) string {
    77  		formattedMsg := m.Path
    78  		if m.Version != "" {
    79  			formattedMsg += "@" + m.Version
    80  		}
    81  		return formattedMsg
    82  	}
    83  
    84  	// print the dependency graph to stdout.
    85  	root := module.Version{Path: kclPkg.GetPkgName(), Version: kclPkg.GetPkgVersion()}
    86  	err = graph.BFS(depGraph, root, func(source module.Version) bool {
    87  		for target := range adjMap[source] {
    88  			reporter.ReportMsgTo(
    89  				fmt.Sprint(format(source), " ", format(target)),
    90  				kpmcli.GetLogWriter(),
    91  			)
    92  		}
    93  		return false
    94  	})
    95  	if err != nil {
    96  		return err
    97  	}
    98  	return nil
    99  }