Skip to content

Commit

Permalink
feat: mod push add examples dir also mark generator executable (#964)
Browse files Browse the repository at this point in the history
  • Loading branch information
adohe authored Mar 26, 2024
1 parent 5c65438 commit 7642064
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 62 deletions.
10 changes: 5 additions & 5 deletions pkg/cmd/generate/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package generator

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

Expand All @@ -18,10 +19,6 @@ import (
"kusionstack.io/kusion/pkg/util/kfile"
)

const (
IncludeSchemaTypePath = "include_schema_type_path"
)

// Generator is an interface for things that can generate versioned Intent from
// configuration code under current working directory and given input parameters.
type Generator interface {
Expand Down Expand Up @@ -50,7 +47,6 @@ func (g *DefaultGenerator) Generate(workDir string, params map[string]string) (*
}

// Copy dependent modules before call builder
// fixme
err = copyDependentModules(workDir)
if err != nil {
return nil, err
Expand Down Expand Up @@ -96,6 +92,10 @@ func copyDependentModules(workDir string) error {
dest = fmt.Sprintf("%s.exe", dest)
}
err = io.CopyFile(source, dest)
if err == nil {
// mark the dest file executable
err = os.Chmod(dest, 0o755)
}
allErrs = append(allErrs, err)
}
}
Expand Down
60 changes: 4 additions & 56 deletions pkg/cmd/mod/mod_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"context"
"encoding/base64"
"fmt"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
Expand All @@ -24,6 +22,7 @@ import (
"kusionstack.io/kusion/pkg/util/executable"
"kusionstack.io/kusion/pkg/util/gitutil"
"kusionstack.io/kusion/pkg/util/i18n"
ioutil "kusionstack.io/kusion/pkg/util/io"
"kusionstack.io/kusion/pkg/util/pretty"
)

Expand Down Expand Up @@ -235,7 +234,9 @@ func (o *PushModOptions) Run() error {
defer cancel()

// Copy to temp module dir and push artifact to OCI repository
err = copyWithoutGeneratorSrc(o.ModulePath, tempModuleDir)
err = ioutil.CopyDir(tempModuleDir, o.ModulePath, func(path string) bool {
return strings.Contains(path, "src")
})
if err != nil {
return err
}
Expand Down Expand Up @@ -366,56 +367,3 @@ func detectGitRepository(path string) (string, error) {
}
return path, nil
}

// copyWithoutGeneratorSrc copies module contents except for generator source code to dest dir.
func copyWithoutGeneratorSrc(modulePath, dstDir string) error {
return filepath.WalkDir(modulePath, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if path == modulePath || strings.Contains(path, "src") {
return nil
}
srcStat, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return nil
} else {
return err
}
}

if !srcStat.Mode().IsRegular() && !srcStat.Mode().IsDir() {
return fmt.Errorf("%s is not a regular file or directory", path)
}

relPath, err := filepath.Rel(modulePath, path)
if err != nil {
return err
}

dst := filepath.Join(dstDir, relPath)
if srcStat.IsDir() {
err = os.MkdirAll(dst, os.ModePerm)
if err != nil {
return err
}
return nil
}

source, err := os.Open(path)
if err != nil {
return err
}
defer source.Close()

destination, err := os.Create(dst)
if err != nil {
return err
}
defer destination.Close()

_, err = io.Copy(destination, source)
return err
})
}
90 changes: 89 additions & 1 deletion pkg/util/io/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package io

import (
"fmt"
"io"
"os"
"path/filepath"
)

// Create dir recursively if not exist
// CreateDirIfNotExist creates dir recursively if not exist
// Note: input argument must be a dirPath
func CreateDirIfNotExist(dirPath string) error {
_, err := os.Stat(dirPath)
Expand Down Expand Up @@ -38,3 +39,90 @@ func OutDir(path string) (string, error) {
outDir += "/"
return outDir, nil
}

// CopyDir recursively copies all the files within the directory given in
// src to the directory given in dst.
//
// Both directories should already exist. If the destination directory is
// non-empty then the new files will merge in with the old, overwriting any
// files that have a relative path in common between source and destination.
func CopyDir(dst, src string, skip func(path string) bool) error {
src, err := filepath.EvalSymlinks(src)
if err != nil {
return err
}

walkFn := func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if path == src {
return nil
}

// Skip specific files if required
if skip != nil && skip(path) {
return nil
}

// The "path" has the src prefixed to it. We need to join our
// destination with the path without the src on it.
dstPath := filepath.Join(dst, path[len(src):])

// we don't want to try and copy the same file over itself.
if eq, err := SameFile(path, dstPath); eq {
return nil
} else if err != nil {
return err
}

// If we have a directory, make that subdirectory, then continue
// the walk.
if info.IsDir() {
if path == filepath.Join(src, dst) {
// dst is in src; don't walk it.
return nil
}

if err := os.MkdirAll(dstPath, 0o755); err != nil {
return err
}

return nil
}

// If the current path is a symlink, recreate the symlink relative to
// the dst directory
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
target, err := os.Readlink(path)
if err != nil {
return err
}

return os.Symlink(target, dstPath)
}

// If we have a file, copy the contents.
srcF, err := os.Open(path)
if err != nil {
return err
}
defer srcF.Close()

dstF, err := os.Create(dstPath)
if err != nil {
return err
}
defer dstF.Close()

if _, err := io.Copy(dstF, srcF); err != nil {
return err
}

// Chmod it
return os.Chmod(dstPath, info.Mode())
}

return filepath.Walk(src, walkFn)
}
28 changes: 28 additions & 0 deletions pkg/util/io/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,31 @@ func CopyFile(source, dest string) error {
}
return nil
}

// SameFile returns true if the two given paths refer to the same physical
// file on disk, using the unique file identifiers from the underlying
// operating system. For example, on Unix systems this checks whether the
// two files are on the same device and have the same inode.
func SameFile(a, b string) (bool, error) {
if a == b {
return true, nil
}

aInfo, err := os.Lstat(a)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}

bInfo, err := os.Lstat(b)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}

return os.SameFile(aInfo, bInfo), nil
}

0 comments on commit 7642064

Please sign in to comment.