Skip to content

Commit

Permalink
feat: git clone recursive submodules option
Browse files Browse the repository at this point in the history
  • Loading branch information
charlysotelo committed Dec 18, 2024
1 parent 11b7590 commit ffb9327
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 82 deletions.
1 change: 1 addition & 0 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func NewBuildCmd(flags *flags.GlobalFlags) *cobra.Command {
buildCmd.Flags().StringSliceVar(&cmd.Platform, "platform", []string{}, "Set target platform for build")
buildCmd.Flags().BoolVar(&cmd.SkipPush, "skip-push", false, "If true will not push the image to the repository, useful for testing")
buildCmd.Flags().Var(&cmd.GitCloneStrategy, "git-clone-strategy", "The git clone strategy DevPod uses to checkout git based workspaces. Can be full (default), blobless, treeless or shallow")
buildCmd.Flags().BoolVar(&cmd.GitCloneRecursiveSubmodules, "git-clone-recursive-submodules", false, "If true will clone git submodule repositories recursively")

// TESTING
buildCmd.Flags().BoolVar(&cmd.ForceBuild, "force-build", false, "TESTING ONLY")
Expand Down
1 change: 1 addition & 0 deletions cmd/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ func NewUpCmd(f *flags.GlobalFlags) *cobra.Command {
upCmd.Flags().StringVar(&cmd.IDE, "ide", "", "The IDE to open the workspace in. If empty will use vscode locally or in browser")
upCmd.Flags().BoolVar(&cmd.OpenIDE, "open-ide", true, "If this is false and an IDE is configured, DevPod will only install the IDE server backend, but not open it")
upCmd.Flags().Var(&cmd.GitCloneStrategy, "git-clone-strategy", "The git clone strategy DevPod uses to checkout git based workspaces. Can be full (default), blobless, treeless or shallow")
upCmd.Flags().BoolVar(&cmd.GitCloneRecursiveSubmodules, "git-clone-recursive-submodules", false, "If true will clone git submodule repositories recursively")
upCmd.Flags().StringVar(&cmd.GitSSHSigningKey, "git-ssh-signing-key", "", "The ssh key to use when signing git commits. Used to explicitly setup DevPod's ssh signature forwarding with given key. Should be same format as value of `git config user.signingkey`")
upCmd.Flags().StringVar(&cmd.FallbackImage, "fallback-image", "", "The fallback image to use if no devcontainer configuration has been detected")

Expand Down
10 changes: 9 additions & 1 deletion pkg/agent/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ func CloneRepositoryForWorkspace(
}

// run git command
cloner := git.NewCloner(options.GitCloneStrategy)
cloner := git.NewClonerWithOpts(getGitOptions(options)...)
gitInfo := git.NewGitInfo(source.GitRepository, source.GitBranch, source.GitCommit, source.GitPRReference, source.GitSubPath)
err := git.CloneRepositoryWithEnv(ctx, gitInfo, extraEnv, workspaceDir, helper, cloner, log)
if err != nil {
Expand Down Expand Up @@ -323,6 +323,14 @@ func CloneRepositoryForWorkspace(
return nil
}

func getGitOptions(options provider2.CLIOptions) []git.Option {
gitOpts := []git.Option{git.WithCloneStrategy(options.GitCloneStrategy)}
if options.GitCloneRecursiveSubmodules {
gitOpts = append(gitOpts, git.WithRecursiveSubmodules())
}
return gitOpts
}

func setupSSHKey(key string, agentPath string) ([]string, func(), error) {
keyFile, err := os.CreateTemp("", "")
if err != nil {
Expand Down
103 changes: 44 additions & 59 deletions pkg/git/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,32 @@ type Cloner interface {
Clone(ctx context.Context, repository string, targetDir string, extraArgs, extraEnv []string, log log.Logger) error
}

func NewCloner(strategy CloneStrategy) Cloner {
switch strategy {
case BloblessCloneStrategy:
return &bloblessClone{}
case TreelessCloneStrategy:
return &treelessClone{}
case ShallowCloneStrategy:
return &shallowClone{}
case BareCloneStrategy:
return &bareClone{}
case FullCloneStrategy:
return &fullClone{}
default:
return &fullClone{}
type Option func(*cloner)

func WithCloneStrategy(strategy CloneStrategy) Option {
return func(c *cloner) {
c.cloneStrategy = strategy
}
}

func WithRecursiveSubmodules() Option {
return func(c *cloner) {
c.extraArgs = append(c.extraArgs, "--recurse-submodules")
}
}

func NewClonerWithOpts(options ...Option) Cloner {
cloner := &cloner{}
for _, opt := range options {
opt(cloner)
}
return cloner
}

func NewCloner(strategy CloneStrategy) Cloner {
return NewClonerWithOpts(WithCloneStrategy(strategy))
}

var _ pflag.Value = (*CloneStrategy)(nil)

func (s *CloneStrategy) Set(v string) error {
Expand All @@ -68,57 +77,33 @@ func (s *CloneStrategy) String() string {
return string(*s)
}

type fullClone struct{}

var _ Cloner = &fullClone{}

func (c *fullClone) Clone(ctx context.Context, repository string, targetDir string, extraArgs, extraEnv []string, log log.Logger) error {
args := []string{"clone"}
args = append(args, extraArgs...)
args = append(args, repository, targetDir)
return run(ctx, args, extraEnv, log)
type cloner struct {
extraArgs []string
cloneStrategy CloneStrategy
}

type bloblessClone struct{}
var _ Cloner = &cloner{}

var _ Cloner = &bloblessClone{}

func (c *bloblessClone) Clone(ctx context.Context, repository string, targetDir string, extraArgs, extraEnv []string, log log.Logger) error {
args := []string{"clone", "--filter=blob:none"}
args = append(args, extraArgs...)
args = append(args, repository, targetDir)
return run(ctx, args, extraEnv, log)
}

type treelessClone struct{}

var _ Cloner = treelessClone{}

func (c treelessClone) Clone(ctx context.Context, repository string, targetDir string, extraArgs, extraEnv []string, log log.Logger) error {
args := []string{"clone", "--filter=tree:0"}
args = append(args, extraArgs...)
args = append(args, repository, targetDir)
return run(ctx, args, extraEnv, log)
}

type shallowClone struct{}

var _ Cloner = shallowClone{}

func (c shallowClone) Clone(ctx context.Context, repository string, targetDir string, extraArgs, extraEnv []string, log log.Logger) error {
args := []string{"clone", "--depth=1"}
args = append(args, extraArgs...)
args = append(args, repository, targetDir)
return run(ctx, args, extraEnv, log)
func (c *cloner) initialArgs() []string {
switch c.cloneStrategy {
case BloblessCloneStrategy:
return []string{"clone", "--filter=blob:none"}
case TreelessCloneStrategy:
return []string{"clone", "--filter=tree:0"}
case ShallowCloneStrategy:
return []string{"clone", "--depth=1"}
case BareCloneStrategy:
return []string{"clone", "bare", "--depth=1"}
case FullCloneStrategy:
default:
}
return []string{"clone"}
}

type bareClone struct{}

var _ Cloner = bareClone{}

func (c bareClone) Clone(ctx context.Context, repository string, targetDir string, extraArgs, extraEnv []string, log log.Logger) error {
args := []string{"clone", "bare", "--depth=1"}
func (c *cloner) Clone(ctx context.Context, repository string, targetDir string, extraArgs, extraEnv []string, log log.Logger) error {
args := c.initialArgs()
args = append(args, extraArgs...)
args = append(args, c.extraArgs...)
args = append(args, repository, targetDir)
return run(ctx, args, extraEnv, log)
}
Expand Down
45 changes: 23 additions & 22 deletions pkg/provider/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,28 +195,29 @@ type AgentWorkspaceInfo struct {

type CLIOptions struct {
// up options
flags.GitCredentialsFlags `json:",inline"`
ID string `json:"id,omitempty"`
Source string `json:"source,omitempty"`
IDE string `json:"ide,omitempty"`
IDEOptions []string `json:"ideOptions,omitempty"`
PrebuildRepositories []string `json:"prebuildRepositories,omitempty"`
DevContainerImage string `json:"devContainerImage,omitempty"`
DevContainerPath string `json:"devContainerPath,omitempty"`
EnvironmentTemplate string `json:"environmentTemplate,omitempty"`
EnvironmentTemplateVersion string `json:"environmentTemplateVersion,omitempty"`
WorkspaceEnv []string `json:"workspaceEnv,omitempty"`
WorkspaceEnvFile []string `json:"workspaceEnvFile,omitempty"`
InitEnv []string `json:"initEnv,omitempty"`
Recreate bool `json:"recreate,omitempty"`
Reset bool `json:"reset,omitempty"`
Proxy bool `json:"proxy,omitempty"`
DisableDaemon bool `json:"disableDaemon,omitempty"`
DaemonInterval string `json:"daemonInterval,omitempty"`
ForceCredentials bool `json:"forceCredentials,omitempty"`
GitCloneStrategy git.CloneStrategy `json:"gitCloneStrategy,omitempty"`
FallbackImage string `json:"fallbackImage,omitempty"`
GitSSHSigningKey string `json:"gitSshSigningKey,omitempty"`
flags.GitCredentialsFlags `json:",inline"`
ID string `json:"id,omitempty"`
Source string `json:"source,omitempty"`
IDE string `json:"ide,omitempty"`
IDEOptions []string `json:"ideOptions,omitempty"`
PrebuildRepositories []string `json:"prebuildRepositories,omitempty"`
DevContainerImage string `json:"devContainerImage,omitempty"`
DevContainerPath string `json:"devContainerPath,omitempty"`
EnvironmentTemplate string `json:"environmentTemplate,omitempty"`
EnvironmentTemplateVersion string `json:"environmentTemplateVersion,omitempty"`
WorkspaceEnv []string `json:"workspaceEnv,omitempty"`
WorkspaceEnvFile []string `json:"workspaceEnvFile,omitempty"`
InitEnv []string `json:"initEnv,omitempty"`
Recreate bool `json:"recreate,omitempty"`
Reset bool `json:"reset,omitempty"`
Proxy bool `json:"proxy,omitempty"`
DisableDaemon bool `json:"disableDaemon,omitempty"`
DaemonInterval string `json:"daemonInterval,omitempty"`
ForceCredentials bool `json:"forceCredentials,omitempty"`
GitCloneStrategy git.CloneStrategy `json:"gitCloneStrategy,omitempty"`
GitCloneRecursiveSubmodules bool `json:"gitCloneRecursive,omitempty"`
FallbackImage string `json:"fallbackImage,omitempty"`
GitSSHSigningKey string `json:"gitSshSigningKey,omitempty"`

// build options
Repository string `json:"repository,omitempty"`
Expand Down

0 comments on commit ffb9327

Please sign in to comment.