package commands import ( "fmt" "os" "path/filepath" "git.dws.rip/DWS/onyx/internal/core" gogit "github.com/go-git/go-git/v5" "github.com/spf13/cobra" ) // NewCloneCmd creates the clone command func NewCloneCmd() *cobra.Command { cmd := &cobra.Command{ Use: "clone [directory]", Short: "Clone a repository and initialize Onyx", Long: `Clone a repository from a remote URL and initialize Onyx. This command combines Git's clone functionality with automatic Onyx setup. The cloned URL is automatically configured as the primary remote. Examples: onx clone https://github.com/user/repo.git onx clone git@github.com:user/repo.git my-project`, Args: cobra.RangeArgs(1, 2), RunE: func(cmd *cobra.Command, args []string) error { url := args[0] var directory string if len(args) == 2 { directory = args[1] } return runClone(url, directory) }, } return cmd } // runClone executes the clone command func runClone(url, directory string) error { // If no directory specified, derive from URL if directory == "" { directory = deriveDirectoryFromURL(url) } // Check if directory already exists if _, err := os.Stat(directory); err == nil { return fmt.Errorf("directory '%s' already exists", directory) } // Clone the repository using go-git fmt.Printf("Cloning into '%s'...\n", directory) _, err := gogit.PlainClone(directory, false, &gogit.CloneOptions{ URL: url, Progress: os.Stdout, }) if err != nil { return fmt.Errorf("failed to clone repository: %w", err) } fmt.Println("āœ“ Clone completed") // Change to the cloned directory originalDir, err := os.Getwd() if err != nil { return fmt.Errorf("failed to get current directory: %w", err) } absDir, err := filepath.Abs(directory) if err != nil { return fmt.Errorf("failed to get absolute path: %w", err) } if err := os.Chdir(absDir); err != nil { return fmt.Errorf("failed to change directory: %w", err) } defer os.Chdir(originalDir) // Initialize Onyx in the cloned repository fmt.Println("Initializing Onyx...") // Check if .git exists (it should, since we just cloned) gitDir := filepath.Join(absDir, ".git") if _, err := os.Stat(gitDir); os.IsNotExist(err) { return fmt.Errorf("no .git directory found after clone") } // Initialize Onyx repository structure (this will create .onx directory) onyxRepo := &core.OnyxRepository{} if err := onyxRepo.Init(absDir); err != nil { return fmt.Errorf("failed to initialize Onyx: %w", err) } defer onyxRepo.Close() // Create default workstream matching the cloned branch wsManager := core.NewWorkstreamManager(onyxRepo) if err := wsManager.CreateDefaultWorkstream(); err != nil { // Don't fail clone if workstream creation fails, just warn fmt.Fprintf(os.Stderr, "Warning: failed to create default workstream: %v\n", err) } // Get the workstream name to display to the user currentWs, _ := wsManager.GetCurrentWorkstreamName() if currentWs == "" { currentWs = "main" // fallback } // The remote 'origin' is automatically configured by git clone // We don't need to do anything extra - it's already the primary remote fmt.Printf("\nāœ“ Successfully cloned and initialized Onyx repository in '%s'\n", directory) fmt.Printf("\nāœ“ Created workstream '%s' tracking branch '%s'\n", currentWs, currentWs) fmt.Printf("\nThe remote 'origin' (%s) is configured as your primary remote.\n", url) fmt.Printf("\nNext steps:\n") fmt.Printf(" cd %s\n", directory) fmt.Printf(" onx save -m \"message\" # Save your work\n") fmt.Printf(" onx new # Create a new workstream\n") return nil } // deriveDirectoryFromURL extracts a directory name from a Git URL func deriveDirectoryFromURL(url string) string { // Remove .git suffix if present name := url if filepath.Ext(name) == ".git" { name = name[:len(name)-4] } // Extract the last component of the path name = filepath.Base(name) // Handle edge cases if name == "/" || name == "." { name = "repository" } return name }