Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate kpm command to kcl cli #8

Merged
merged 1 commit into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cmd/kcl/commands/args.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package cmd

func argsGet(a []string, n int) string {
if len(a) > n {
return a[n]
}
return ""
}
2 changes: 2 additions & 0 deletions cmd/kcl/commands/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ func appendLangFlags(o *options.RunOptions, flags *pflag.FlagSet) {
"Run in vendor mode")
flags.BoolVar(&o.NoStyle, "no_style", false,
"Set to prohibit output of command line waiting styles, including colors, etc.")
flags.BoolVarP(&o.Quiet, "quiet", "q", false,
"quiet (no output)")
}
73 changes: 29 additions & 44 deletions cmd/kcl/commands/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@ package cmd

import (
"github.com/spf13/cobra"
cli "github.com/urfave/cli/v2"
"kcl-lang.io/cli/pkg/version"
"kcl-lang.io/kpm/pkg/client"
kpmcmd "kcl-lang.io/kpm/pkg/cmd"
"kcl-lang.io/kpm/pkg/reporter"
)

const (
modDesc = `
This command manages the kcl module
`
modExample = ` # Init one kcl module
modExample = ` kcl mod <command> [arguments]...
# Init one kcl module
kcl mod init

# Add dependencies for the current module
Expand All @@ -26,55 +24,42 @@ This command manages the kcl module
kcl mod push`
)

var (
quiet bool
vendor bool
update bool
git string
tag string
target string
)

// NewModCmd returns the mod command.
func NewModCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "mod",
Short: "KCL module management",
Long: modDesc,
Example: modExample,
RunE: func(_ *cobra.Command, args []string) error {
return RunWithKpmMod("mod", args)
},
Use: "mod",
Short: "KCL module management",
Long: modDesc,
Example: modExample,
SilenceUsage: true,
}

return cmd
}
cmd.Flags().BoolVarP(&quiet, "quiet", "q", false, "quiet (no output)")

func RunWithKpmMod(cmd string, args []string) error {
reporter.InitReporter()
kpmcli, err := client.NewKpmClient()
cli, err := client.NewKpmClient()
if err != nil {
return err
}
app := cli.NewApp()
app.Usage = "module related functions"
app.Name = "kcl mod"
app.Version = version.GetVersionString()
app.UsageText = "kcl mod <command> [arguments]..."
app.Commands = []*cli.Command{
kpmcmd.NewInitCmd(kpmcli),
kpmcmd.NewAddCmd(kpmcli),
kpmcmd.NewPkgCmd(kpmcli),
kpmcmd.NewMetadataCmd(kpmcli),
kpmcmd.NewRunCmd(kpmcli),
kpmcmd.NewPushCmd(kpmcli),
kpmcmd.NewPullCmd(kpmcli),
panic(err)
}
app.Flags = []cli.Flag{
&cli.BoolFlag{
Name: kpmcmd.FLAG_QUIET,
Usage: "push in vendor mode",
},
if quiet {
cli.SetLogWriter(nil)
}
app.Before = func(c *cli.Context) error {
if c.Bool(kpmcmd.FLAG_QUIET) {
kpmcli.SetLogWriter(nil)
}
return nil
}
argsWithCmd := []string{cmd}
argsWithCmd = append(argsWithCmd, args...)
return app.Run(argsWithCmd)

cmd.AddCommand(NewModInitCmd(cli))
cmd.AddCommand(NewModAddCmd(cli))
cmd.AddCommand(NewModPkgCmd(cli))
cmd.AddCommand(NewModMetadataCmd(cli))
cmd.AddCommand(NewModPushCmd(cli))
cmd.AddCommand(NewModPullCmd(cli))

return cmd
}
204 changes: 204 additions & 0 deletions cmd/kcl/commands/mod_add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package cmd

import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/spf13/cobra"
"kcl-lang.io/kpm/pkg/client"
"kcl-lang.io/kpm/pkg/env"
"kcl-lang.io/kpm/pkg/errors"
"kcl-lang.io/kpm/pkg/opt"
pkg "kcl-lang.io/kpm/pkg/package"
"kcl-lang.io/kpm/pkg/reporter"
)

const (
modAddDesc = `
This command adds new dependency
`
modAddExample = ` # Add the module dependency named "k8s"
kcl mod add k8s

# Add the module dependency named "k8s" with the version "1.28"
kcl mod add k8s:1.28

# Add a local dependency
kcl mod add /path/to/another_module`
)

// NewModAddCmd returns the mod add command.
func NewModAddCmd(cli *client.KpmClient) *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Short: "add new dependency",
Long: modAddDesc,
Example: modAddExample,
RunE: func(_ *cobra.Command, args []string) error {
return ModAdd(cli, args)
},
SilenceUsage: true,
}

cmd.Flags().StringVar(&git, "git", "", "git repository location")
cmd.Flags().StringVar(&tag, "tag", "", "git repository tag")

return cmd
}

func ModAdd(cli *client.KpmClient, args []string) error {
// acquire the lock of the package cache.
err := cli.AcquirePackageCacheLock()
if err != nil {
return err
}

defer func() {
// release the lock of the package cache after the function returns.
releaseErr := cli.ReleasePackageCacheLock()
if releaseErr != nil && err == nil {
err = releaseErr
}
}()

pwd, err := os.Getwd()

if err != nil {
return reporter.NewErrorEvent(reporter.Bug, err, "internal bugs, please contact us to fix it.")
}

globalPkgPath, err := env.GetAbsPkgPath()
if err != nil {
return err
}

kclPkg, err := pkg.LoadKclPkg(pwd)
if err != nil {
return err
}

err = kclPkg.ValidateKpmHome(globalPkgPath)
if err != (*reporter.KpmEvent)(nil) {
return err
}

addOpts, err := parseAddOptions(cli, globalPkgPath, args)
if err != nil {
return err
}

if addOpts.RegistryOpts.Local != nil {
absAddPath, err := filepath.Abs(addOpts.RegistryOpts.Local.Path)
if err != nil {
return reporter.NewErrorEvent(reporter.Bug, err, "internal bugs, please contact us to fix it.")
}
if absAddPath == kclPkg.HomePath {
return reporter.NewErrorEvent(
reporter.AddItselfAsDep,
fmt.Errorf("cannot add '%s' as a dependency to itself", kclPkg.GetPkgName()),
)
}
}

err = addOpts.Validate()
if err != nil {
return err
}

_, err = cli.AddDepWithOpts(kclPkg, addOpts)
if err != nil {
return err
}
return nil
}

// parseAddOptions will parse the user cli inputs.
func parseAddOptions(cli *client.KpmClient, localPath string, args []string) (*opt.AddOptions, error) {
// parse from 'kpm add -git https://xxx/xxx.git -tag v0.0.1'.
if len(args) == 0 {
return &opt.AddOptions{
LocalPath: localPath,
RegistryOpts: opt.RegistryOptions{
Git: &opt.GitOptions{
Url: git,
Tag: tag,
},
},
}, nil
} else {
localPkg, err := parseLocalPathOptions(args)
if err != (*reporter.KpmEvent)(nil) {
// parse from 'kpm add xxx:0.0.1'.
ociReg, err := parseOciRegistryOptions(cli, args)
if err != nil {
return nil, err
}
return &opt.AddOptions{
LocalPath: localPath,
RegistryOpts: *ociReg,
}, nil
} else {
return &opt.AddOptions{
LocalPath: localPath,
RegistryOpts: *localPkg,
}, nil
}
}
}

// parseOciRegistryOptions will parse the oci registry information from user cli inputs.
func parseOciRegistryOptions(cli *client.KpmClient, args []string) (*opt.RegistryOptions, error) {
ociPkgRef := argsGet(args, 0)
name, version, err := parseOciPkgNameAndVersion(ociPkgRef)
if err != nil {
return nil, err
}

return &opt.RegistryOptions{
Oci: &opt.OciOptions{
Reg: cli.GetSettings().DefaultOciRegistry(),
Repo: cli.GetSettings().DefaultOciRepo(),
PkgName: name,
Tag: version,
},
}, nil
}

// parseLocalPathOptions will parse the local path information from user cli inputs.
func parseLocalPathOptions(args []string) (*opt.RegistryOptions, *reporter.KpmEvent) {
localPath := argsGet(args, 0)
if localPath == "" {
return nil, reporter.NewErrorEvent(reporter.PathIsEmpty, errors.PathIsEmpty)
}
// check if the local path exists.
if _, err := os.Stat(localPath); os.IsNotExist(err) {
return nil, reporter.NewErrorEvent(reporter.LocalPathNotExist, err)
} else {
return &opt.RegistryOptions{
Local: &opt.LocalOptions{
Path: localPath,
},
}, nil
}
}

// parseOciPkgNameAndVersion will parse package name and version
// from string "<pkg_name>:<pkg_version>".
func parseOciPkgNameAndVersion(s string) (string, string, error) {
parts := strings.Split(s, ":")
if len(parts) == 1 {
return parts[0], "", nil
}

if len(parts) > 2 {
return "", "", reporter.NewErrorEvent(reporter.InvalidPkgRef, fmt.Errorf("invalid oci package reference '%s'", s))
}

if parts[1] == "" {
return "", "", reporter.NewErrorEvent(reporter.InvalidPkgRef, fmt.Errorf("invalid oci package reference '%s'", s))
}

return parts[0], parts[1], nil
}
Loading