diff --git a/cmd/lk/app.go b/cmd/lk/app.go index 754991e7..316ed233 100644 --- a/cmd/lk/app.go +++ b/cmd/lk/app.go @@ -267,22 +267,32 @@ func setupTemplate(ctx context.Context, cmd *cli.Command) error { } func cloneTemplate(_ context.Context, cmd *cli.Command, url, appName string) error { + var out []byte var cmdErr error + + tempName, relocate, cleanup := useTempPath(appName) + defer cleanup() + if err := spinner.New(). Title("Cloning template from " + url). Action(func() { - c := exec.Command("git", "clone", "--depth=1", url, appName) - var out []byte - if out, cmdErr = c.CombinedOutput(); len(out) > 0 && cmd.Bool("verbose") { - fmt.Println(string(out)) - } - os.RemoveAll(path.Join(appName, ".git")) + c := exec.Command("git", "clone", "--depth=1", url, tempName) + out, cmdErr = c.CombinedOutput() + os.RemoveAll(path.Join(tempName, ".git")) }). Style(theme.Focused.Title). Run(); err != nil { return err } - return cmdErr + + if len(out) > 0 && (cmdErr != nil || cmd.Bool("verbose")) { + fmt.Println(string(out)) + } + + if cmdErr != nil { + return cmdErr + } + return relocate() } func instantiateEnv(ctx context.Context, cmd *cli.Command, rootPath string, addlEnv *map[string]string) error { diff --git a/cmd/lk/utils.go b/cmd/lk/utils.go index b1faa244..41b5974a 100644 --- a/cmd/lk/utils.go +++ b/cmd/lk/utils.go @@ -22,6 +22,7 @@ import ( "fmt" "net/url" "os" + "path" "path/filepath" "strings" @@ -30,6 +31,7 @@ import ( "github.com/twitchtv/twirp" "github.com/urfave/cli/v3" + "github.com/livekit/protocol/utils/guid" "github.com/livekit/protocol/utils/interceptors" "github.com/livekit/livekit-cli/pkg/config" @@ -153,6 +155,20 @@ func wrapWith(wrap string) func(string) string { } } +// Provides a temporary path, a function to relocate it to a permanent path, +// and a function to clean up the temporary path that should always be deferred +// in the case of a failure to relocate. +func useTempPath(permanentPath string) (string, func() error, func() error) { + tempPath := path.Join(os.TempDir(), guid.New("LK_")) + relocate := func() error { + return os.Rename(tempPath, permanentPath) + } + cleanup := func() error { + return os.RemoveAll(tempPath) + } + return tempPath, relocate, cleanup +} + func hashString(str string) (string, error) { hash := sha256.New() if _, err := hash.Write([]byte(str)); err != nil {