Skip to content

Commit 30c41ca

Browse files
authored
Merge pull request #144 from zong-zhe/kpm-add-local
feat: 'kpm add' supports local path.
2 parents e104bef + 1a6d48c commit 30c41ca

File tree

266 files changed

+587
-141
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

266 files changed

+587
-141
lines changed

pkg/cmd/cmd_add.go

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package cmd
55
import (
66
"fmt"
77
"os"
8+
"path/filepath"
89
"strings"
910

1011
"github.com/urfave/cli/v2"
@@ -86,6 +87,19 @@ func KpmAdd(c *cli.Context) error {
8687
return err
8788
}
8889

90+
if addOpts.RegistryOpts.Local != nil {
91+
absAddPath, err := filepath.Abs(addOpts.RegistryOpts.Local.Path)
92+
if err != nil {
93+
return reporter.NewErrorEvent(reporter.Bug, err, "internal bugs, please contact us to fix it.")
94+
}
95+
if absAddPath == kclPkg.HomePath {
96+
return reporter.NewErrorEvent(
97+
reporter.AddItselfAsDep,
98+
fmt.Errorf("cannot add '%s' as a dependency to itself", kclPkg.GetPkgName()),
99+
)
100+
}
101+
}
102+
89103
err = addOpts.Validate()
90104
if err != nil {
91105
return err
@@ -126,15 +140,23 @@ func parseAddOptions(c *cli.Context, localPath string) (*opt.AddOptions, error)
126140
RegistryOpts: *gitOpts,
127141
}, nil
128142
} else {
129-
// parse from 'kpm add xxx:0.0.1'.
130-
ociReg, err := parseOciRegistryOptions(c)
131-
if err != nil {
132-
return nil, err
143+
localPkg, err := parseLocalPathOptions(c)
144+
if err != (*reporter.KpmEvent)(nil) {
145+
// parse from 'kpm add xxx:0.0.1'.
146+
ociReg, err := parseOciRegistryOptions(c)
147+
if err != nil {
148+
return nil, err
149+
}
150+
return &opt.AddOptions{
151+
LocalPath: localPath,
152+
RegistryOpts: *ociReg,
153+
}, nil
154+
} else {
155+
return &opt.AddOptions{
156+
LocalPath: localPath,
157+
RegistryOpts: *localPkg,
158+
}, nil
133159
}
134-
return &opt.AddOptions{
135-
LocalPath: localPath,
136-
RegistryOpts: *ociReg,
137-
}, nil
138160
}
139161
}
140162

@@ -191,6 +213,24 @@ func parseOciRegistryOptions(c *cli.Context) (*opt.RegistryOptions, error) {
191213
}, nil
192214
}
193215

216+
// parseLocalPathOptions will parse the local path information from user cli inputs.
217+
func parseLocalPathOptions(c *cli.Context) (*opt.RegistryOptions, *reporter.KpmEvent) {
218+
localPath := c.Args().First()
219+
if localPath == "" {
220+
return nil, reporter.NewErrorEvent(reporter.PathIsEmpty, errors.PathIsEmpty)
221+
}
222+
// check if the local path exists.
223+
if _, err := os.Stat(localPath); os.IsNotExist(err) {
224+
return nil, reporter.NewErrorEvent(reporter.LocalPathNotExist, err)
225+
} else {
226+
return &opt.RegistryOptions{
227+
Local: &opt.LocalOptions{
228+
Path: localPath,
229+
},
230+
}, nil
231+
}
232+
}
233+
194234
// parseOciPkgNameAndVersion will parse package name and version
195235
// from string "<pkg_name>:<pkg_version>".
196236
func parseOciPkgNameAndVersion(s string) (string, string, error) {

pkg/errors/errors.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ var IsOciRef = errors.New("kpm: oci ref is not an url.")
4747

4848
// Invalid Version
4949
var InvalidVersionFormat = errors.New("kpm: failed to parse version.")
50-
50+
var PathNotFound = errors.New("path not found.")
51+
var PathIsEmpty = errors.New("path is empty.")
5152
var InvalidPkg = errors.New("invalid kcl package.")
5253
var InvalidOciUrl = errors.New("invalid oci url.")
5354
var UnknownEnv = errors.New("invalid environment variable.")

pkg/oci/oci.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ type OciClient struct {
8080
func NewOciClient(regName, repoName string) (*OciClient, error) {
8181
repoPath := utils.JoinPath(regName, repoName)
8282
repo, err := remote.NewRepository(repoPath)
83+
8384
if err != nil {
8485
return nil, reporter.NewErrorEvent(
8586
reporter.RepoNotFound,

pkg/opt/opt.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package opt
44

55
import (
66
"net/url"
7+
"os"
78
"path/filepath"
89
"strings"
910

@@ -39,13 +40,16 @@ func (opts *AddOptions) Validate() error {
3940
return opts.RegistryOpts.Git.Validate()
4041
} else if opts.RegistryOpts.Oci != nil {
4142
return opts.RegistryOpts.Oci.Validate()
43+
} else if opts.RegistryOpts.Local != nil {
44+
return opts.RegistryOpts.Local.Validate()
4245
}
4346
return nil
4447
}
4548

4649
type RegistryOptions struct {
47-
Git *GitOptions
48-
Oci *OciOptions
50+
Git *GitOptions
51+
Oci *OciOptions
52+
Local *LocalOptions
4953
}
5054

5155
type GitOptions struct {
@@ -78,6 +82,22 @@ func (opts *OciOptions) Validate() error {
7882
return nil
7983
}
8084

85+
// LocalOptions for local packages.
86+
// kpm will find packages from local path.
87+
type LocalOptions struct {
88+
Path string
89+
}
90+
91+
func (opts *LocalOptions) Validate() error {
92+
if len(opts.Path) == 0 {
93+
return errors.PathIsEmpty
94+
}
95+
if _, err := os.Stat(opts.Path); err != nil {
96+
return err
97+
}
98+
return nil
99+
}
100+
81101
const OCI_SEPARATOR = ":"
82102

83103
// ParseOciOptionFromString will parser '<repo_name>:<repo_tag>' into an 'OciOptions' with an OCI registry.

pkg/mod/modfile.go renamed to pkg/package/modfile.go

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright 2022 The KCL Authors. All rights reserved.
2-
package modfile
2+
package pkg
33

44
import (
55
"fmt"
@@ -101,6 +101,10 @@ type Dependency struct {
101101
Source `json:"-"`
102102
}
103103

104+
func (dep *Dependency) isFromLocal() bool {
105+
return dep.Source.Oci == nil && dep.Source.Git == nil && dep.Source.Local != nil
106+
}
107+
104108
// FillDepInfo will fill registry information for a dependency.
105109
func (dep *Dependency) FillDepInfo() error {
106110
if dep.Source.Oci != nil {
@@ -144,6 +148,10 @@ func (dep *Dependency) Download(localPath string) (*Dependency, error) {
144148
dep.FullName = dep.GenDepFullName()
145149
}
146150

151+
if dep.Source.Local != nil {
152+
dep.LocalFullPath = dep.Source.Local.Path
153+
}
154+
147155
var err error
148156
dep.Sum, err = utils.HashDir(dep.LocalFullPath)
149157
if err != nil {
@@ -259,6 +267,11 @@ func (dep *Oci) Download(localPath string) (string, error) {
259267
type Source struct {
260268
*Git
261269
*Oci
270+
*Local
271+
}
272+
273+
type Local struct {
274+
Path string `toml:"path,omitempty"`
262275
}
263276

264277
type Oci struct {
@@ -396,7 +409,7 @@ func (deps *Dependencies) loadLockFile(filepath string) error {
396409
}
397410

398411
// Parse out some information for a Dependency from registry url.
399-
func ParseOpt(opt *opt.RegistryOptions) *Dependency {
412+
func ParseOpt(opt *opt.RegistryOptions) (*Dependency, error) {
400413
if opt.Git != nil {
401414
gitSource := Git{
402415
Url: opt.Git.Url,
@@ -412,7 +425,7 @@ func ParseOpt(opt *opt.RegistryOptions) *Dependency {
412425
Git: &gitSource,
413426
},
414427
Version: gitSource.Tag,
415-
}
428+
}, nil
416429
}
417430
if opt.Oci != nil {
418431
repoPath := utils.JoinPath(opt.Oci.Repo, opt.Oci.PkgName)
@@ -429,9 +442,27 @@ func ParseOpt(opt *opt.RegistryOptions) *Dependency {
429442
Oci: &ociSource,
430443
},
431444
Version: opt.Oci.Tag,
445+
}, nil
446+
}
447+
if opt.Local != nil {
448+
depPkg, err := LoadKclPkg(opt.Local.Path)
449+
if err != nil {
450+
return nil, err
432451
}
452+
return &Dependency{
453+
Name: depPkg.modFile.Pkg.Name,
454+
FullName: depPkg.modFile.Pkg.Name + "_" + depPkg.modFile.Pkg.Version,
455+
LocalFullPath: opt.Local.Path,
456+
Source: Source{
457+
Local: &Local{
458+
Path: opt.Local.Path,
459+
},
460+
},
461+
Version: depPkg.modFile.Pkg.Version,
462+
}, nil
463+
433464
}
434-
return nil
465+
return nil, nil
435466
}
436467

437468
const PKG_NAME_PATTERN = "%s_%s"

pkg/mod/modfile_test.go renamed to pkg/package/modfile_test.go

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package modfile
1+
package pkg
22

33
import (
44
"os"
@@ -11,25 +11,6 @@ import (
1111
"kcl-lang.io/kpm/pkg/utils"
1212
)
1313

14-
const testDataDir = "test_data"
15-
16-
func getTestDir(subDir string) string {
17-
pwd, _ := os.Getwd()
18-
testDir := filepath.Join(pwd, testDataDir)
19-
testDir = filepath.Join(testDir, subDir)
20-
21-
return testDir
22-
}
23-
24-
func initTestDir(subDir string) string {
25-
testDir := getTestDir(subDir)
26-
// clean the test data
27-
_ = os.RemoveAll(testDir)
28-
_ = os.Mkdir(testDir, 0755)
29-
30-
return testDir
31-
}
32-
3314
func TestModFileExists(t *testing.T) {
3415
testDir := initTestDir("test_data_modfile")
3516
// there is no 'kcl.mod' and 'kcl.mod.lock'.
@@ -74,15 +55,15 @@ func TestModFileExists(t *testing.T) {
7455

7556
func TestParseOpt(t *testing.T) {
7657

77-
dep := ParseOpt(&opt.RegistryOptions{
58+
dep, err := ParseOpt(&opt.RegistryOptions{
7859
Git: &opt.GitOptions{
7960
Url: "test.git",
8061
Branch: "test_branch",
8162
Commit: "test_commit",
8263
Tag: "test_tag",
8364
},
8465
})
85-
66+
assert.Equal(t, err, nil)
8667
assert.Equal(t, dep.Name, "test")
8768
assert.Equal(t, dep.FullName, "test_test_tag")
8869
assert.Equal(t, dep.Url, "test.git")

0 commit comments

Comments
 (0)