Skip to content
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
17 changes: 11 additions & 6 deletions cmd/cm/repository/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func createDeleteCmd() *cobra.Command {
var force bool

deleteCmd := &cobra.Command{
Use: "delete <repository-name>",
Use: "delete [repository-name]",
Short: "Delete a repository and all associated resources",
Long: `Delete a repository from CM and remove all associated worktrees and files.

Expand All @@ -21,13 +21,16 @@ This command will:
• Remove the repository from the status file
• Delete the repository directory (if within base path)

If no repository name is provided, you will be prompted to select one interactively.

Use the --force flag to skip confirmation prompts.

Examples:
cm repository delete my-repo
cm repo delete https://github.com/user/repo.git
cm r delete my-repo --force`,
Args: cobra.ExactArgs(1),
cm r delete my-repo --force
cm r delete # Interactive selection`,
Args: cobra.MaximumNArgs(1),
RunE: func(_ *cobra.Command, args []string) error {
if err := cli.CheckInitialization(); err != nil {
return err
Expand All @@ -41,10 +44,12 @@ Examples:
cmManager.SetLogger(logger.NewVerboseLogger())
}

// Create delete parameters
// Create delete parameters (interactive selection handled in code-manager)
params := cm.DeleteRepositoryParams{
RepositoryName: args[0],
Force: force,
Force: force,
}
if len(args) > 0 {
params.RepositoryName = args[0]
}

return cmManager.DeleteRepository(params)
Expand Down
7 changes: 3 additions & 4 deletions cmd/cm/repository/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ func createListCmd() *cobra.Command {
Short: "List all repositories in CM",
Long: `List all repositories tracked by CM with visual indicators.

Repositories are displayed in a numbered list format. An asterisk (*) indicates
repositories that are not within the configured base path.
An asterisk (*) indicates repositories that are not within the configured base path.

Examples:
cm repository list
Expand Down Expand Up @@ -48,12 +47,12 @@ Examples:
return nil
}

for i, repo := range repositories {
for _, repo := range repositories {
indicator := ""
if !repo.InRepositoriesDir {
indicator = "*"
}
fmt.Printf(" %d. %s%s\n", i+1, indicator, repo.Name)
fmt.Printf(" %s%s\n", indicator, repo.Name)
}

return nil
Expand Down
23 changes: 15 additions & 8 deletions cmd/cm/workspace/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import (

func createDeleteCmd() *cobra.Command {
deleteCmd := &cobra.Command{
Use: "delete <workspace-name>",
Use: "delete [workspace-name]",
Short: "Delete a workspace and all associated resources",
Long: getDeleteCommandLongDescription(),
Args: cobra.ExactArgs(1),
Args: cobra.MaximumNArgs(1),
RunE: createDeleteCmdRunE,
}

Expand All @@ -40,6 +40,8 @@ The deletion process includes:
- Removing the workspace entry from status.yaml
- Preserving individual repository entries (they may be used by other workspaces)

If no workspace name is provided, you will be prompted to select one interactively.

By default, the command will show a confirmation prompt with a detailed summary
of what will be deleted. Use the --force flag to skip confirmation prompts.

Expand All @@ -48,13 +50,14 @@ Examples:
cm workspace delete my-workspace

# Delete workspace without confirmation
cm workspace delete my-workspace --force`
cm workspace delete my-workspace --force

# Interactive selection
cm ws delete`
}

// createDeleteCmdRunE creates the RunE function for the delete command.
func createDeleteCmdRunE(cmd *cobra.Command, args []string) error {
workspaceName := args[0]

// Get force flag
force, err := cmd.Flags().GetBool("force")
if err != nil {
Expand All @@ -72,19 +75,23 @@ func createDeleteCmdRunE(cmd *cobra.Command, args []string) error {
cmManager.SetLogger(logger.NewVerboseLogger())
}

// Delete workspace
// Create delete parameters (interactive selection handled in code-manager)
params := cm.DeleteWorkspaceParams{
WorkspaceName: workspaceName,
WorkspaceName: "",
Force: force,
}
if len(args) > 0 {
params.WorkspaceName = args[0]
}

// Delete workspace (interactive selection handled in code-manager)
if err := cmManager.DeleteWorkspace(params); err != nil {
return err
}

// Print success message
if !cli.Quiet {
fmt.Printf("✓ Workspace '%s' deleted successfully\n", workspaceName)
fmt.Printf("✓ Workspace '%s' deleted successfully\n", params.WorkspaceName)
}

return nil
Expand Down
10 changes: 5 additions & 5 deletions cmd/cm/worktree/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ func createCreateCmd() *cobra.Command {
createCmd.Flags().StringVar(&fromIssue, "from-issue", "",
"Create worktree from GitHub issue (URL, number, or owner/repo#issue format)")
createCmd.Flags().StringVarP(&workspaceName, "workspace", "w", "",
"Create worktrees from workspace definition in status.yaml")
"Create worktrees from workspace definition in status.yaml (interactive selection if not provided)")
createCmd.Flags().StringVarP(&repositoryName, "repository", "r", "",
"Create worktree for the specified repository (name from status.yaml or path)")
"Create worktree for the specified repository (name from status.yaml or path, interactive selection if not provided)")

return createCmd
}
Expand All @@ -59,7 +59,7 @@ Issue Reference Formats:
- Owner/repo#issue format: owner/repo#123

Examples:
cm worktree create feature-branch
cm worktree create feature-branch # Interactive selection of workspace/repository
cm wt create feature-branch --ide ` + ide.DefaultIDE + `
cm w create feature-branch --ide cursor
cm worktree create --from-issue https://github.com/owner/repo/issues/123
Expand Down Expand Up @@ -93,8 +93,8 @@ func createCreateCmdArgsValidator(
if *workspaceName != "" || *repositoryName != "" {
return cobra.ExactArgs(1)(cmd, args)
}
// Otherwise, branch name is required
return cobra.ExactArgs(1)(cmd, args)
// Otherwise, branch name is optional (interactive selection will handle target selection)
return cobra.MaximumNArgs(1)(cmd, args)
}
}

Expand Down
32 changes: 22 additions & 10 deletions cmd/cm/worktree/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ func createDeleteCmd() *cobra.Command {
var all bool

deleteCmd := &cobra.Command{
Use: "delete <branch> [branch2] [branch3] ... [--force/-f] [--workspace/-w] [--repository/-r] [--all/-a]",
Short: "Delete worktrees for the specified branches or all worktrees",
Long: getDeleteCmdLongDescription(),
Args: createDeleteCmdArgsValidator(&all, &workspaceName, &repositoryName),
RunE: createDeleteCmdRunE(&all, &force, &workspaceName, &repositoryName),
Use: "delete [branch] [branch2] [branch3] ... [--force/-f] [--workspace/-w] [--repository/-r] [--all/-a]",
Short: "Delete worktrees for the specified branches or all worktrees " +
"(two-step interactive selection if no branch provided)",
Long: getDeleteCmdLongDescription(),
Args: createDeleteCmdArgsValidator(&all, &workspaceName, &repositoryName),
RunE: createDeleteCmdRunE(&all, &force, &workspaceName, &repositoryName),
}

addDeleteCmdFlags(deleteCmd, &force, &workspaceName, &repositoryName, &all)
Expand All @@ -31,10 +32,13 @@ func getDeleteCmdLongDescription() string {
return `Delete worktrees for the specified branches or all worktrees.

You can delete multiple worktrees at once by providing multiple branch names,
or delete all worktrees using the --all flag.
or delete all worktrees using the --all flag. If no branch is specified,
interactive selection will prompt you to choose a repository/workspace first,
then select a specific worktree from that target.

Examples:
cm worktree delete feature-branch
cm worktree delete # Two-step: select repository/workspace, then worktree
cm worktree delete feature-branch # One-step: select repository/workspace only
cm wt delete feature-branch --force
cm w delete feature-branch --force
cm wt delete feature-branch --workspace my-workspace
Expand All @@ -61,8 +65,10 @@ func createDeleteCmdArgsValidator(
if *all && len(args) > 0 {
return fmt.Errorf("cannot specify both --all flag and branch names")
}
// Allow no arguments for interactive selection
if !*all && len(args) == 0 {
return fmt.Errorf("must specify either branch names or --all flag")
// This will trigger interactive selection in the code-manager
return nil
}
return nil
}
Expand Down Expand Up @@ -90,16 +96,17 @@ func createDeleteCmdRunE(
if *all {
return cmManager.DeleteAllWorktrees(*force)
}

return runDeleteWorktree(args, *force, *workspaceName, *repositoryName)
}
}

func addDeleteCmdFlags(cmd *cobra.Command, force *bool, workspaceName *string, repositoryName *string, all *bool) {
cmd.Flags().BoolVarP(force, "force", "f", false, "Skip confirmation prompts")
cmd.Flags().StringVarP(workspaceName, "workspace", "w", "",
"Name of the workspace to delete worktree from (optional)")
"Name of the workspace to delete worktree from (interactive selection if not provided)")
cmd.Flags().StringVarP(repositoryName, "repository", "r", "",
"Name of the repository to delete worktree from (optional)")
"Name of the repository to delete worktree from (interactive selection if not provided)")
cmd.Flags().BoolVarP(all, "all", "a", false, "Delete all worktrees")
}

Expand All @@ -116,6 +123,11 @@ func runDeleteWorktree(args []string, force bool, workspaceName string, reposito
return deleteWorktreesIndividually(cmManager, args, force, opts)
}

// If no arguments provided, use single worktree deletion with interactive selection
if len(args) == 0 {
return cmManager.DeleteWorkTree("", force, opts...)
}

// Otherwise use bulk deletion
return cmManager.DeleteWorkTrees(args, force)
}
Expand Down
7 changes: 4 additions & 3 deletions cmd/cm/worktree/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ func createListCmd() *cobra.Command {

// Add workspace and repository flags to list command (optional)
listCmd.Flags().StringVarP(&workspaceName, "workspace", "w", "",
"Name of the workspace to list worktrees for (optional)")
"Name of the workspace to list worktrees for (interactive selection if not provided)")
listCmd.Flags().StringVarP(&repositoryName, "repository", "r", "",
"Name of the repository to list worktrees for (optional)")
"Name of the repository to list worktrees for (interactive selection if not provided)")

return listCmd
}
Expand All @@ -37,7 +37,7 @@ func getListCmdLongDescription() string {
return `List all worktrees for a specific workspace, repository, or current repository.

Examples:
cm worktree list # List worktrees for current repository
cm worktree list # Interactive selection of workspace/repository
cm worktree list --workspace my-workspace # List worktrees for specific workspace
cm worktree list --repository my-repo # List worktrees for specific repository
cm wt list -w my-workspace
Expand All @@ -59,6 +59,7 @@ func createListCmdRunE(workspaceName, repositoryName *string) func(*cobra.Comman

opts := buildListWorktreesOptions(*workspaceName, *repositoryName)

// List worktrees (interactive selection handled in code-manager)
worktrees, err := cmManager.ListWorktrees(opts...)
if err != nil {
return fmt.Errorf("failed to list worktrees: %w", err)
Expand Down
16 changes: 10 additions & 6 deletions cmd/cm/worktree/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ func createLoadCmd() *cobra.Command {
The remote part is optional and defaults to "origin" if not specified.

Examples:
cm worktree load feature-branch # Uses origin:feature-branch
cm worktree load feature-branch # Interactive repository selection, uses origin:feature-branch
cm wt load origin:feature-branch # Explicitly specify remote
cm w load upstream:main # Use different remote
cm worktree load feature-branch --ide ` + ide.DefaultIDE + `
cm worktree load feature-branch --repository my-repo
cm wt load origin:main --repository /path/to/repo --ide cursor`,
Args: cobra.ExactArgs(1),
Args: cobra.MaximumNArgs(1),
RunE: func(_ *cobra.Command, args []string) error {
if err := cli.CheckInitialization(); err != nil {
return err
Expand All @@ -40,7 +40,7 @@ Examples:
cmManager.SetLogger(logger.NewVerboseLogger())
}

// Prepare options for LoadWorktree
// Prepare options for LoadWorktree (interactive selection handled in code-manager)
var opts cm.LoadWorktreeOpts
if ideName != "" {
opts.IDEName = ideName
Expand All @@ -49,15 +49,19 @@ Examples:
opts.RepositoryName = repositoryName
}

// Load the worktree (parsing is handled by CM manager)
return cmManager.LoadWorktree(args[0], opts)
// Load the worktree (interactive selection handled in code-manager, parsing is handled by CM manager)
branchRef := ""
if len(args) > 0 {
branchRef = args[0]
}
return cmManager.LoadWorktree(branchRef, opts)
},
}

// Add IDE and repository flags to load command
loadCmd.Flags().StringVarP(&ideName, "ide", "i", ide.DefaultIDE, "Open in specified IDE after loading")
loadCmd.Flags().StringVarP(&repositoryName, "repository", "r", "",
"Load worktree for the specified repository (name from status.yaml or path)")
"Load worktree for the specified repository (name from status.yaml or path, interactive selection if not provided)")

return loadCmd
}
20 changes: 12 additions & 8 deletions cmd/cm/worktree/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,34 @@ func createOpenCmd() *cobra.Command {
var workspaceName string

openCmd := &cobra.Command{
Use: "open <branch> [--ide <ide-name>] [--workspace <workspace-name>] [--repository <repository-name>]",
Use: "open [branch] [--ide <ide-name>] [--workspace <workspace-name>] [--repository <repository-name>]",
Short: "Open a worktree in the specified IDE",
Long: `Open a worktree for the specified branch in the specified IDE.

Examples:
cm worktree open feature-branch
cm worktree open feature-branch # Interactive selection of workspace/repository
cm wt open main
cm w open feature-branch -i cursor
cm worktree open main --ide ` + ide.DefaultIDE + `
cm worktree open feature-branch --workspace my-workspace
cm worktree open feature-branch --repository my-repo
cm wt open main --repository /path/to/repo --ide cursor`,
Args: cobra.ExactArgs(1),
Args: cobra.MaximumNArgs(1),
RunE: func(_ *cobra.Command, args []string) error {
return openWorktree(args[0], ideName, workspaceName, repositoryName)
branchName := ""
if len(args) > 0 {
branchName = args[0]
}
return openWorktree(branchName, ideName, workspaceName, repositoryName)
},
}

// Add IDE, workspace, and repository flags to open command
openCmd.Flags().StringVarP(&ideName, "ide", "i", "", "Open in specified IDE")
openCmd.Flags().StringVarP(&workspaceName, "workspace", "w", "",
"Open worktree for the specified workspace (name from status.yaml)")
"Open worktree for the specified workspace (name from status.yaml, interactive selection if not provided)")
openCmd.Flags().StringVarP(&repositoryName, "repository", "r", "",
"Open worktree for the specified repository (name from status.yaml or path)")
"Open worktree for the specified repository (name from status.yaml or path, interactive selection if not provided)")

return openCmd
}
Expand All @@ -65,7 +69,7 @@ func openWorktree(branchName, ideName, workspaceName, repositoryName string) err
ideToUse = ideName
}

// Prepare options for OpenWorktree
// Prepare options for OpenWorktree (interactive selection handled in code-manager)
var opts []cm.OpenWorktreeOpts
if workspaceName != "" {
opts = append(opts, cm.OpenWorktreeOpts{
Expand All @@ -78,7 +82,7 @@ func openWorktree(branchName, ideName, workspaceName, repositoryName string) err
})
}

// Open the worktree
// Open the worktree (interactive selection handled in code-manager)
if err := cmManager.OpenWorktree(branchName, ideToUse, opts...); err != nil {
return fmt.Errorf("failed to open worktree: %w", err)
}
Expand Down
Loading