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: create some APIs for command 'kpm run'. #146

Merged
merged 1 commit into from
Aug 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
188 changes: 188 additions & 0 deletions pkg/api/kpm_run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
package api

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

"kcl-lang.io/kpm/pkg/env"
"kcl-lang.io/kpm/pkg/errors"
"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"
"kcl-lang.io/kpm/pkg/runner"
"kcl-lang.io/kpm/pkg/utils"
)

// RunTar will compile the kcl package from a kcl package tar.
func RunTar(tarPath string, entryFiles []string, vendorMode bool, kclArgs string) (string, error) {
absTarPath, err := absTarPath(tarPath)
if err != nil {
return "", err
}
// Extract the tar package to a directory with the same name.
// e.g.
// 'xxx/xxx/xxx/test.tar' will be extracted to the directory 'xxx/xxx/xxx/test'.
destDir := strings.TrimSuffix(absTarPath, filepath.Ext(absTarPath))
err = utils.UnTarDir(absTarPath, destDir)
if err != nil {
return "", err
}

// The directory after extracting the tar package is taken as the root directory of the package,
// and kclvm is called to compile the kcl program under the 'destDir'.
// e.g.
// if the tar path is 'xxx/xxx/xxx/test.tar',
// the 'xxx/xxx/xxx/test' will be taken as the root path of the kcl package to compile.
compileResult, compileErr := RunPkgInPath(destDir, entryFiles, vendorMode, kclArgs)

if compileErr != nil {
return "", compileErr
}
return compileResult, nil
}

const KCL_PKG_TAR = "*.tar"

// RunOci will compile the kcl package from an OCI reference.
func RunOci(ociRef, version string, entryFiles []string, vendorMode bool, kclArgs string) (string, error) {
ociOpts, err := opt.ParseOciOptionFromString(ociRef, version)

if err != nil {
return "", err
}

// 1. Create the temporary directory to pull the tar.
tmpDir, err := os.MkdirTemp("", "")
if err != nil {
return "", errors.InternalBug
}
// clean the temp dir.
defer os.RemoveAll(tmpDir)

localPath := ociOpts.AddStoragePathSuffix(tmpDir)

// 2. Pull the tar.
err = oci.Pull(localPath, ociOpts.Reg, ociOpts.Repo, ociOpts.Tag)

if err != nil {
return "", err
}

// 3.Get the (*.tar) file path.
matches, err := filepath.Glob(filepath.Join(localPath, KCL_PKG_TAR))
if err != nil || len(matches) != 1 {
return "", errors.FailedPull
}

return RunTar(matches[0], entryFiles, vendorMode, kclArgs)
}

// RunPkg will compile current kcl package.
func RunPkg(entryFiles []string, vendorMode bool, kclArgs string) (string, error) {

// If no tar packages specified by "--tar" to run
// kpm will take the current directory ($PWD) as the root of the kcl package and compile.
pwd, err := os.Getwd()

if err != nil {
reporter.ExitWithReport("kpm: internal bug: failed to load working directory")
}

compileResult, err := RunPkgInPath(pwd, entryFiles, vendorMode, kclArgs)
if err != nil {
return "", err
}

return compileResult, nil
}

// RunPkgInPath will load the 'KclPkg' from path 'pkgPath'.
// And run the kcl package with entry file in 'entryFilePath' in 'vendorMode'.
func RunPkgInPath(pkgPath string, entryFilePaths []string, vendorMode bool, kclArgs string) (string, error) {

pkgPath, err := filepath.Abs(pkgPath)
if err != nil {
return "", errors.InternalBug
}

kclPkg, err := pkg.LoadKclPkg(pkgPath)
if err != nil {
return "", errors.FailedToLoadPackage
}

kclPkg.SetVendorMode(vendorMode)

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

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

// Calculate the absolute path of entry file described by '--input'.
compiler := runner.DefaultCompiler()
compiler.SetKclCliArgs(kclArgs)
for _, entryFilePath := range entryFilePaths {
entryFilePath, err = getAbsInputPath(pkgPath, entryFilePath)
if err != nil {
return "", err
}
compiler.AddKFile(entryFilePath)
}

if len(entryFilePaths) == 0 && len(kclPkg.GetEntryKclFilesFromModFile()) == 0 {
compiler.AddKFile(kclPkg.HomePath)
}

// Call the kcl compiler.
compileResult, err := kclPkg.Compile(
globalPkgPath,
compiler,
)

if err != nil {
return "", err
}

return compileResult.GetRawYamlResult(), nil
}

// absTarPath checks whether path 'tarPath' exists and whether path 'tarPath' ends with '.tar'
// And after checking, absTarPath return the abs path for 'tarPath'.
func absTarPath(tarPath string) (string, error) {
absTarPath, err := filepath.Abs(tarPath)
if err != nil {
return "", errors.InternalBug
}

if filepath.Ext(absTarPath) != ".tar" {
return "", errors.InvalidKclPacakgeTar
} else if !utils.DirExists(absTarPath) {
return "", errors.KclPacakgeTarNotFound
}

return absTarPath, nil
}

// getAbsInputPath will return the abs path of the file path described by '--input'.
// If the path exists after 'inputPath' is computed as a full path, it will be returned.
// If not, the kpm checks whether the full path of 'pkgPath/inputPath' exists,
// If the full path of 'pkgPath/inputPath' exists, it will be returned.
// If not, getAbsInputPath returns 'entry file not found' error.
func getAbsInputPath(pkgPath string, inputPath string) (string, error) {
absPath, err := filepath.Abs(filepath.Join(pkgPath, inputPath))
if err != nil {
return "", err
}

if utils.DirExists(absPath) {
return absPath, nil
}

return "", errors.EntryFileNotFound
}
10 changes: 5 additions & 5 deletions pkg/cmd/cmd_run_test.go → pkg/api/kpm_run_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cmd
package api

import (
"os"
Expand Down Expand Up @@ -58,23 +58,23 @@ func TestAbsTarPath(t *testing.T) {

func TestRunPkgInPath(t *testing.T) {
pkgPath := getTestDir("test_run_pkg_in_path")
result, err := runPkgInPath(filepath.Join(pkgPath, "test_kcl"), []string{"main.k"}, false, "")
result, err := RunPkgInPath(filepath.Join(pkgPath, "test_kcl"), []string{"main.k"}, false, "")
assert.Equal(t, err, nil)
expected, _ := os.ReadFile(filepath.Join(pkgPath, "expected"))
assert.Equal(t, utils.RmNewline(string(result)), utils.RmNewline(string(expected)))
}

func TestRunPkgInPathInvalidPath(t *testing.T) {
pkgPath := getTestDir("test_run_pkg_in_path")
result, err := runPkgInPath(filepath.Join(pkgPath, "test_kcl"), []string{"not_exist.k"}, false, "")
result, err := RunPkgInPath(filepath.Join(pkgPath, "test_kcl"), []string{"not_exist.k"}, false, "")
assert.NotEqual(t, err, nil)
assert.Equal(t, err, errors.EntryFileNotFound)
assert.Equal(t, result, "")
}

func TestRunPkgInPathInvalidPkg(t *testing.T) {
pkgPath := getTestDir("test_run_pkg_in_path")
result, err := runPkgInPath(filepath.Join(pkgPath, "invalid_pkg"), []string{"not_exist.k"}, false, "")
result, err := RunPkgInPath(filepath.Join(pkgPath, "invalid_pkg"), []string{"not_exist.k"}, false, "")
assert.NotEqual(t, err, nil)
assert.Equal(t, err, errors.FailedToLoadPackage)
assert.Equal(t, result, "")
Expand All @@ -91,7 +91,7 @@ func TestRunTar(t *testing.T) {
}

expectedResult, _ := os.ReadFile(expectPath)
gotResult, err := runTar(tarPath, []string{""}, true, "")
gotResult, err := RunTar(tarPath, []string{""}, true, "")
assert.Equal(t, err, nil)
assert.Equal(t, utils.RmNewline(string(expectedResult)), utils.RmNewline(gotResult))
assert.Equal(t, utils.DirExists(untarPath), true)
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/cmd_pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path/filepath"

"github.com/urfave/cli/v2"
"kcl-lang.io/kpm/pkg/api"
"kcl-lang.io/kpm/pkg/errors"
"kcl-lang.io/kpm/pkg/oci"
"kcl-lang.io/kpm/pkg/opt"
Expand Down Expand Up @@ -104,7 +105,7 @@ func KpmPull(c *cli.Context) error {
}

// 3. Get the (*.tar) file path.
tarPath := filepath.Join(localPath, KCL_PKG_TAR)
tarPath := filepath.Join(localPath, api.KCL_PKG_TAR)
matches, err := filepath.Glob(tarPath)
if err != nil || len(matches) != 1 {
if err == nil {
Expand Down
12 changes: 12 additions & 0 deletions pkg/cmd/cmd_push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,24 @@
package cmd

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
pkg "kcl-lang.io/kpm/pkg/package"
)

const testDataDir = "test_data"

func getTestDir(subDir string) string {
pwd, _ := os.Getwd()
testDir := filepath.Join(pwd, testDataDir)
testDir = filepath.Join(testDir, subDir)

return testDir
}

func TestGenDefaultOciUrlForKclPkg(t *testing.T) {
pkgPath := getTestDir("test_gen_oci_url")
kclPkg, err := pkg.LoadKclPkg(pkgPath)
Expand Down
Loading