github.com/KusionStack/kpm@v0.8.4-0.20240326033734-dc72298a30e5/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  	"kcl-lang.io/kpm/pkg/client"
    12  	"kcl-lang.io/kpm/pkg/env"
    13  	pkg "kcl-lang.io/kpm/pkg/package"
    14  	"kcl-lang.io/kpm/pkg/reporter"
    15  )
    16  
    17  // NewGraphCmd new a Command for `kpm graph`.
    18  func NewGraphCmd(kpmcli *client.KpmClient) *cli.Command {
    19  	return &cli.Command{
    20  		Hidden: false,
    21  		Name:   "graph",
    22  		Usage:  "prints the module dependency graph",
    23  		Action: func(c *cli.Context) error {
    24  			return KpmGraph(c, kpmcli)
    25  		},
    26  	}
    27  }
    28  
    29  func KpmGraph(c *cli.Context, kpmcli *client.KpmClient) error {
    30  	// acquire the lock of the package cache.
    31  	err := kpmcli.AcquirePackageCacheLock()
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	defer func() {
    37  		// release the lock of the package cache after the function returns.
    38  		releaseErr := kpmcli.ReleasePackageCacheLock()
    39  		if releaseErr != nil && err == nil {
    40  			err = releaseErr
    41  		}
    42  	}()
    43  
    44  	pwd, err := os.Getwd()
    45  
    46  	if err != nil {
    47  		return reporter.NewErrorEvent(reporter.Bug, err, "internal bugs, please contact us to fix it.")
    48  	}
    49  
    50  	globalPkgPath, err := env.GetAbsPkgPath()
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	kclPkg, err := pkg.LoadKclPkg(pwd)
    56  	if err != nil {
    57  		return err
    58  	}
    59  
    60  	err = kclPkg.ValidateKpmHome(globalPkgPath)
    61  	if err != (*reporter.KpmEvent)(nil) {
    62  		return err
    63  	}
    64  
    65  	_, depGraph, err := kpmcli.InitGraphAndDownloadDeps(kclPkg)
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	adjMap, err := depGraph.AdjacencyMap()
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	// print the dependency graph to stdout.
    76  	root := fmt.Sprintf("%s@%s", kclPkg.GetPkgName(), kclPkg.GetPkgVersion()) 
    77  	err = graph.BFS(depGraph, root, func(source string) bool {
    78  		for target := range adjMap[source] {
    79  			reporter.ReportMsgTo(
    80  				fmt.Sprint(source, " ", target),
    81  				kpmcli.GetLogWriter(),
    82  			)
    83  		}
    84  		return false
    85  	})
    86  	if err != nil {
    87  		return err
    88  	}
    89  	return nil
    90  }