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: uniform kcl cli #90

Merged
merged 1 commit into from
Jun 5, 2024
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ build/
_kcl_test.k

.DS_store

# e2e test cases dir
scripts/e2e/pkg_in_reg/*
scripts/e2e/registry_auth/*
2 changes: 2 additions & 0 deletions cmd/kcl/commands/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ var (
vendor bool
update bool
git string
oci string
path string
tag string
commit string
branch string
Expand Down
155 changes: 98 additions & 57 deletions cmd/kcl/commands/mod_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package cmd

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

"github.com/spf13/cobra"
"kcl-lang.io/kpm/pkg/client"
Expand All @@ -24,11 +24,23 @@ const (
# Add the module dependency named "k8s" with the version "1.28"
kcl mod add k8s:1.28

# Add the module dependency from the GitHub
# Add the module dependency from the GitHub by git url
kcl mod add git://github.com/kcl-lang/konfig --tag v0.4.0

# Add the module dependency from the OCI Registry by oci url
kcl mod add oci://github.com/kcl-lang/konfig --tag v0.4.0

# Add the module dependency from the local file system by file url
kcl mod add /path/to/another_module

# Add the module dependency from the GitHub by flag
kcl mod add --git https://github.com/kcl-lang/konfig --tag v0.4.0

# Add a local dependency
kcl mod add /path/to/another_module`
# Add the module dependency from the OCI Registry by flag
kcl mod add --oci https://ghcr.io/kcl-lang/helloworld --tag 0.1.0

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

// NewModAddCmd returns the mod add command.
Expand All @@ -45,7 +57,8 @@ func NewModAddCmd(cli *client.KpmClient) *cobra.Command {
}

cmd.Flags().StringVar(&git, "git", "", "git repository url")
cmd.Flags().StringVar(&tag, "tag", "", "git repository tag")
cmd.Flags().StringVar(&oci, "oci", "", "oci repository url")
cmd.Flags().StringVar(&tag, "tag", "", "git or oci repository tag")
cmd.Flags().StringVar(&commit, "commit", "", "git repository commit")
cmd.Flags().StringVar(&branch, "branch", "", "git repository branch")
cmd.Flags().StringVar(&rename, "rename", "", "rename the dependency")
Expand Down Expand Up @@ -122,31 +135,94 @@ func ModAdd(cli *client.KpmClient, args []string) error {

// parseAddOptions will parse the user cli inputs.
func parseAddOptions(cli *client.KpmClient, localPath string, args []string) (*opt.AddOptions, error) {
// parse the CLI command with the following style
// kcl mod add --git https://xxx/xxx --tag 0.0.1
// kcl mod add --oci https://xxx/xxx --tag 0.0.1
// kcl mod add --path /path/to/xxx
if len(args) == 0 {
return &opt.AddOptions{
LocalPath: localPath,
RegistryOpts: opt.RegistryOptions{
Git: &opt.GitOptions{
Url: git,
Tag: tag,
Commit: commit,
Branch: branch,
},
},
NoSumCheck: noSumCheck,
NewPkgName: rename,
}, nil
if len(git) != 0 {
gitUrl, err := url.Parse(git)
if err != nil {
return nil, err
}
gitOpt := opt.NewGitOptionsFromUrl(gitUrl)
if gitOpt == nil {
return nil, fmt.Errorf("invalid git url '%s'", git)
}

gitOpt.Tag = tag
gitOpt.Commit = commit
gitOpt.Branch = branch

return &opt.AddOptions{
LocalPath: localPath,
RegistryOpts: opt.RegistryOptions{Git: gitOpt},
NoSumCheck: noSumCheck,
NewPkgName: rename,
}, nil
} else if len(oci) != 0 {
ociUrl, err := url.Parse(oci)
if err != nil {
return nil, err
}
ociOpt := opt.NewOciOptionsFromUrl(ociUrl)
if ociOpt == nil {
return nil, fmt.Errorf("invalid oci url '%s'", oci)
}
ociOpt.Tag = tag

return &opt.AddOptions{
LocalPath: localPath,
RegistryOpts: opt.RegistryOptions{Oci: ociOpt},
NoSumCheck: noSumCheck,
NewPkgName: rename,
}, nil
} else if len(path) != 0 {
pathUrl, err := url.Parse(path)
if err != nil {
return nil, err
}

pathOpt, err := opt.NewLocalOptionsFromUrl(pathUrl)
if err != (*reporter.KpmEvent)(nil) {
return nil, err
}

return &opt.AddOptions{
LocalPath: localPath,
RegistryOpts: opt.RegistryOptions{Local: pathOpt},
NoSumCheck: noSumCheck,
NewPkgName: rename,
}, nil
}
} else {
// parse the CLI command with the following style
// kcl mod add k8s
// kcl mod add k8s:0.0.1
// kcl mod add /path/to/xxx
// kcl mod add https://xxx/xxx --tag 0.0.1
// kcl mod add oci://xxx/xxx --tag 0.0.1

localPkg, err := parseLocalPathOptions(args)
pkgSource := argsGet(args, 0)
if err != (*reporter.KpmEvent)(nil) {
// parse from 'kpm add xxx:0.0.1'.
ociReg, err := parseOciRegistryOptions(cli, args)
// parse url and ref
regOpt, err := opt.NewRegistryOptionsFrom(pkgSource, cli.GetSettings())
if err != nil {
return nil, err
}

if regOpt.Git != nil {
regOpt.Git.Tag = tag
regOpt.Git.Commit = commit
regOpt.Git.Branch = branch
} else if regOpt.Oci != nil && len(tag) != 0 {
regOpt.Oci.Tag = tag
}

return &opt.AddOptions{
LocalPath: localPath,
RegistryOpts: *ociReg,
RegistryOpts: *regOpt,
NoSumCheck: noSumCheck,
NewPkgName: rename,
}, nil
Expand All @@ -159,24 +235,8 @@ func parseAddOptions(cli *client.KpmClient, localPath string, args []string) (*o
}, 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
return nil, fmt.Errorf("invalid add options")
}

// parseLocalPathOptions will parse the local path information from user cli inputs.
Expand All @@ -196,22 +256,3 @@ func parseLocalPathOptions(args []string) (*opt.RegistryOptions, *reporter.KpmEv
}, 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
}
6 changes: 3 additions & 3 deletions cmd/kcl/commands/mod_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/spf13/cobra"
"kcl-lang.io/kpm/pkg/client"
"kcl-lang.io/kpm/pkg/errors"
"kcl-lang.io/kpm/pkg/oci"
kpmoci "kcl-lang.io/kpm/pkg/oci"
"kcl-lang.io/kpm/pkg/opt"
pkg "kcl-lang.io/kpm/pkg/package"
"kcl-lang.io/kpm/pkg/reporter"
Expand Down Expand Up @@ -72,7 +72,7 @@ func genDefaultOciUrlForKclPkg(pkg *pkg.KclPkg, cli *client.KpmClient) (string,
urlPath := utils.JoinPath(cli.GetSettings().DefaultOciRepo(), pkg.GetPkgName())

u := &url.URL{
Scheme: oci.OCI_SCHEME,
Scheme: kpmoci.OCI_SCHEME,
Host: cli.GetSettings().DefaultOciRegistry(),
Path: urlPath,
}
Expand Down Expand Up @@ -169,7 +169,7 @@ func pushPackage(ociUrl string, kclPkg *pkg.KclPkg, vendorMode bool, cli *client
"only support url scheme 'oci://'.",
)
}
ociOpts.Annotations, err = oci.GenOciManifestFromPkg(kclPkg)
ociOpts.Annotations, err = kpmoci.GenOciManifestFromPkg(kclPkg)
if err != nil {
return err
}
Expand Down
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
kcl-lang.io/kcl-go v0.9.0-beta.1
kcl-lang.io/kcl-openapi v0.6.1
kcl-lang.io/kcl-playground v0.5.1
kcl-lang.io/kpm v0.9.0-beta.1
kcl-lang.io/kpm v0.9.0-beta.1.0.20240605035613-c5c5085800b4
)

require (
Expand All @@ -29,6 +29,7 @@ require (
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
github.com/containers/ocicrypt v1.1.10 // indirect
github.com/containers/storage v1.54.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/emicklei/proto v1.13.2 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
Expand All @@ -52,9 +53,12 @@ require (
github.com/moby/sys/user v0.1.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
github.com/urfave/cli/v2 v2.25.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
Expand Down
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
Expand Down Expand Up @@ -867,7 +868,9 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
Expand Down Expand Up @@ -934,13 +937,18 @@ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk=
github.com/urfave/cli/v2 v2.25.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8=
github.com/urfave/cli/v2 v2.25.0/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down Expand Up @@ -1685,6 +1693,14 @@ kcl-lang.io/kcl-playground v0.5.1 h1:MKQQUHgt4+2QyU2NVwa73oksOaBJGDi4keGoggA0MiU
kcl-lang.io/kcl-playground v0.5.1/go.mod h1:IFmnlw7m011ccX8OidMUfnnN2u/TWdtQGxyABRTbmow=
kcl-lang.io/kpm v0.9.0-beta.1 h1:buc7yp6RR3MJPG0Un6IkkCpQaVPF8LnwgZtluY0a6dA=
kcl-lang.io/kpm v0.9.0-beta.1/go.mod h1:QJNbc1+go6OXAhiiBHJ7GAjYJ1AC5wLmKAmDS9o5n+k=
kcl-lang.io/kpm v0.9.0-beta.1.0.20240530104317-7a35562e78a2 h1:c/xCUaE/5rnN4FQjgh+Hd0QGl2KmeWxuibgtsjr+y40=
kcl-lang.io/kpm v0.9.0-beta.1.0.20240530104317-7a35562e78a2/go.mod h1:QJNbc1+go6OXAhiiBHJ7GAjYJ1AC5wLmKAmDS9o5n+k=
kcl-lang.io/kpm v0.9.0-beta.1.0.20240604083117-d7258bd4bbf0 h1:t5Z8qa9DzZVG8yLR95rYTOeWhFjUZi+aa06Oxw27jk0=
kcl-lang.io/kpm v0.9.0-beta.1.0.20240604083117-d7258bd4bbf0/go.mod h1:QJNbc1+go6OXAhiiBHJ7GAjYJ1AC5wLmKAmDS9o5n+k=
kcl-lang.io/kpm v0.9.0-beta.1.0.20240604093242-4244558de99a h1:2Y/Ek+TgDFMzq2dlbiRNAc2LXgeOByzWRPSzTSasFjE=
kcl-lang.io/kpm v0.9.0-beta.1.0.20240604093242-4244558de99a/go.mod h1:QJNbc1+go6OXAhiiBHJ7GAjYJ1AC5wLmKAmDS9o5n+k=
kcl-lang.io/kpm v0.9.0-beta.1.0.20240605035613-c5c5085800b4 h1:G4hkxgAQcxYt5vOIfma944KFLcMi6da7b8SnDRw9Cmg=
kcl-lang.io/kpm v0.9.0-beta.1.0.20240605035613-c5c5085800b4/go.mod h1:QJNbc1+go6OXAhiiBHJ7GAjYJ1AC5wLmKAmDS9o5n+k=
kcl-lang.io/lib v0.9.0-beta.1 h1:oO/3h5Ubk61LKVnE7A9xlV4FfSfKa6Jv+KNsoHMcnNc=
kcl-lang.io/lib v0.9.0-beta.1/go.mod h1:ubsalGXxJaa5II/EsHmsI/tL2EluYHIcW+BwzQPt+uY=
oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo=
Expand Down
2 changes: 1 addition & 1 deletion scripts/e2e/push_pkg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $current_dir/bin/kcl mod push
cd "$current_dir"

# Push the package helloworld/0.1.1 to the registry
cd ./scripts/pkg_in_reg/ghcr.io/kcl-lang/helloworld/0.1.1
cd ./scripts/e2e/pkg_in_reg/ghcr.io/kcl-lang/helloworld/0.1.1
$current_dir/bin/kcl mod push

cd "$current_dir"
Expand Down
2 changes: 0 additions & 2 deletions scripts/e2e/registry_auth/htpasswd

This file was deleted.

5 changes: 1 addition & 4 deletions test/e2e/test_suites/test_kcl_mod_add_git/stdout
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
adding dependency 'konfig'
cloning 'https://github.com/kcl-lang/konfig' with tag 'v0.4.0'
downloading 'test/k8s:1.28' from 'localhost:5001/test/k8s:1.28'
add dependency 'konfig:v0.4.0' successfully
add dependency 'konfig:v0.4.0' successfully
1 change: 1 addition & 0 deletions test/e2e/test_suites/test_kcl_mod_add_git_1/input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
kcl mod add --git https://github.com/kcl-lang/konfig --branch main
Empty file.
1 change: 1 addition & 0 deletions test/e2e/test_suites/test_kcl_mod_add_git_1/stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add dependency 'konfig:main' successfully
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
name = "test_space"
edition = "v0.9.0"
version = "0.0.1"

Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The_first_kcl_program = 'Hello World!'
1 change: 1 addition & 0 deletions test/e2e/test_suites/test_kcl_mod_add_git_2/input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
kcl mod add --git https://github.com/kcl-lang/konfig --commit 01ca24c
Empty file.
1 change: 1 addition & 0 deletions test/e2e/test_suites/test_kcl_mod_add_git_2/stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add dependency 'konfig:01ca24c' successfully
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
name = "test_space"
edition = "v0.9.0"
version = "0.0.1"

Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The_first_kcl_program = 'Hello World!'
1 change: 1 addition & 0 deletions test/e2e/test_suites/test_kcl_mod_add_git_3/input
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
kcl mod add --git ssh://github.com/kcl-lang/konfig --commit 01ca24c
Empty file.
1 change: 1 addition & 0 deletions test/e2e/test_suites/test_kcl_mod_add_git_3/stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add dependency 'konfig:01ca24c' successfully
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
name = "test_space"
edition = "v0.9.0"
version = "0.0.1"

Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The_first_kcl_program = 'Hello World!'
Loading
Loading