192 lines
4.6 KiB
Go
192 lines
4.6 KiB
Go
package commands
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
|
|
"git.dws.rip/DWS/onyx/internal/core"
|
|
"git.dws.rip/DWS/onyx/internal/models"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// ANSI color codes
|
|
const (
|
|
colorReset = "\033[0m"
|
|
colorGreen = "\033[32m"
|
|
colorYellow = "\033[33m"
|
|
colorBlue = "\033[34m"
|
|
colorGray = "\033[90m"
|
|
colorBold = "\033[1m"
|
|
)
|
|
|
|
// NewListCmd creates the list command
|
|
func NewListCmd() *cobra.Command {
|
|
var showAll bool
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "list",
|
|
Short: "List all workstreams",
|
|
Long: `List all workstreams in the repository.
|
|
|
|
Shows the current workstream (marked with *), the number of commits in each
|
|
workstream, and the workstream status.
|
|
|
|
Status indicators:
|
|
* active - Currently being worked on (green)
|
|
* merged - Has been merged (gray)
|
|
* abandoned - No longer being worked on (gray)
|
|
* archived - Archived for historical purposes (gray)`,
|
|
Aliases: []string{"ls"},
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return runList(showAll)
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolVarP(&showAll, "all", "a", false, "Show all workstreams including merged and archived")
|
|
|
|
return cmd
|
|
}
|
|
|
|
// runList executes the list command
|
|
func runList(showAll bool) error {
|
|
// Get current directory
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get current directory: %w", err)
|
|
}
|
|
|
|
// Check if this is an Onyx repository
|
|
if !core.IsOnyxRepo(cwd) {
|
|
return fmt.Errorf("not an Onyx repository")
|
|
}
|
|
|
|
// Open the repository
|
|
repo, err := core.Open(cwd)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to open repository: %w", err)
|
|
}
|
|
defer repo.Close()
|
|
|
|
// Create workstream manager
|
|
wsManager := core.NewWorkstreamManager(repo)
|
|
|
|
// Get all workstreams
|
|
workstreams, err := wsManager.ListWorkstreams()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list workstreams: %w", err)
|
|
}
|
|
|
|
// Get current workstream name
|
|
currentName, err := wsManager.GetCurrentWorkstreamName()
|
|
if err != nil {
|
|
currentName = "" // No current workstream
|
|
}
|
|
|
|
// Filter workstreams if not showing all
|
|
var displayWorkstreams []*models.Workstream
|
|
for _, ws := range workstreams {
|
|
if showAll || ws.Status == models.WorkstreamStatusActive {
|
|
displayWorkstreams = append(displayWorkstreams, ws)
|
|
}
|
|
}
|
|
|
|
// Check if there are any workstreams
|
|
if len(displayWorkstreams) == 0 {
|
|
if showAll {
|
|
fmt.Println("No workstreams found.")
|
|
} else {
|
|
fmt.Println("No active workstreams found.")
|
|
fmt.Println("Use 'onx new <name>' to create a new workstream.")
|
|
fmt.Println("Use 'onx list --all' to see all workstreams including merged and archived.")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Sort workstreams by name for consistent output
|
|
sort.Slice(displayWorkstreams, func(i, j int) bool {
|
|
return displayWorkstreams[i].Name < displayWorkstreams[j].Name
|
|
})
|
|
|
|
// Display workstreams
|
|
fmt.Println("Workstreams:")
|
|
for _, ws := range displayWorkstreams {
|
|
displayWorkstream(ws, ws.Name == currentName)
|
|
}
|
|
|
|
// Show helpful footer
|
|
fmt.Println()
|
|
fmt.Printf("Use 'onx switch <name>' to switch to a different workstream\n")
|
|
if !showAll {
|
|
fmt.Printf("Use 'onx list --all' to see all workstreams\n")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// displayWorkstream displays a single workstream with formatting
|
|
func displayWorkstream(ws *models.Workstream, isCurrent bool) {
|
|
// Determine the indicator
|
|
indicator := " "
|
|
if isCurrent {
|
|
indicator = "*"
|
|
}
|
|
|
|
// Determine the color based on status
|
|
color := colorReset
|
|
switch ws.Status {
|
|
case models.WorkstreamStatusActive:
|
|
color = colorGreen
|
|
case models.WorkstreamStatusMerged:
|
|
color = colorGray
|
|
case models.WorkstreamStatusAbandoned:
|
|
color = colorGray
|
|
case models.WorkstreamStatusArchived:
|
|
color = colorGray
|
|
}
|
|
|
|
// Format the output
|
|
name := ws.Name
|
|
if isCurrent {
|
|
name = colorBold + name + colorReset
|
|
}
|
|
|
|
commitCount := ws.GetCommitCount()
|
|
commitText := "commit"
|
|
if commitCount != 1 {
|
|
commitText = "commits"
|
|
}
|
|
|
|
// Build status string
|
|
statusStr := string(ws.Status)
|
|
if ws.Status != models.WorkstreamStatusActive {
|
|
statusStr = colorGray + statusStr + colorReset
|
|
}
|
|
|
|
// Build the line
|
|
line := fmt.Sprintf("%s %s%s%s", indicator, color, name, colorReset)
|
|
|
|
// Add base branch info
|
|
baseBranchInfo := fmt.Sprintf(" (based on %s)", ws.BaseBranch)
|
|
line += colorGray + baseBranchInfo + colorReset
|
|
|
|
// Add commit count
|
|
commitInfo := fmt.Sprintf(" - %d %s", commitCount, commitText)
|
|
line += commitInfo
|
|
|
|
// Add status if not active
|
|
if ws.Status != models.WorkstreamStatusActive {
|
|
line += fmt.Sprintf(" [%s]", statusStr)
|
|
}
|
|
|
|
fmt.Println(line)
|
|
|
|
// Add description if present
|
|
if ws.Description != "" {
|
|
description := strings.TrimSpace(ws.Description)
|
|
fmt.Printf(" %s%s%s\n", colorGray, description, colorReset)
|
|
}
|
|
}
|