fix: Use FatalErrorRespectJSON across all commands (bd-28sq)
Convert all fmt.Fprintf(os.Stderr, ...) + os.Exit(1) patterns to use FatalErrorRespectJSON for consistent JSON error output: - dep.go: dependency commands (add, remove, tree, cycles) - label.go: label commands (add, remove, list, list-all) - comments.go: comment commands (list, add) - epic.go: epic commands (status, close-eligible) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -42,17 +42,14 @@ Examples:
|
||||
if err != nil {
|
||||
if isUnknownOperationError(err) {
|
||||
if err := fallbackToDirectMode("daemon does not support comment_list RPC"); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting comments: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("getting comments: %v", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "Error getting comments: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("getting comments: %v", err)
|
||||
}
|
||||
} else {
|
||||
if err := json.Unmarshal(resp.Data, &comments); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error decoding comments: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("decoding comments: %v", err)
|
||||
}
|
||||
usedDaemon = true
|
||||
}
|
||||
@@ -60,21 +57,18 @@ Examples:
|
||||
|
||||
if !usedDaemon {
|
||||
if err := ensureStoreActive(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting comments: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("getting comments: %v", err)
|
||||
}
|
||||
ctx := rootCtx
|
||||
fullID, err := utils.ResolvePartialID(ctx, store, issueID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving %s: %v\n", issueID, err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving %s: %v", issueID, err)
|
||||
}
|
||||
issueID = fullID
|
||||
|
||||
|
||||
result, err := store.GetIssueComments(ctx, issueID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting comments: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("getting comments: %v", err)
|
||||
}
|
||||
comments = result
|
||||
}
|
||||
@@ -87,8 +81,7 @@ Examples:
|
||||
if jsonOutput {
|
||||
data, err := json.MarshalIndent(comments, "", " ")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error encoding JSON: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("encoding JSON: %v", err)
|
||||
}
|
||||
fmt.Println(string(data))
|
||||
return
|
||||
@@ -130,13 +123,11 @@ Examples:
|
||||
// Read from file
|
||||
data, err := os.ReadFile(commentText) // #nosec G304 - user-provided file path is intentional
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error reading file: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("reading file: %v", err)
|
||||
}
|
||||
commentText = string(data)
|
||||
} else if len(args) < 2 {
|
||||
fmt.Fprintf(os.Stderr, "Error: comment text required (use -f to read from file)\n")
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("comment text required (use -f to read from file)")
|
||||
} else {
|
||||
commentText = args[1]
|
||||
}
|
||||
@@ -167,18 +158,15 @@ Examples:
|
||||
if err != nil {
|
||||
if isUnknownOperationError(err) {
|
||||
if err := fallbackToDirectMode("daemon does not support comment_add RPC"); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding comment: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("adding comment: %v", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "Error adding comment: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("adding comment: %v", err)
|
||||
}
|
||||
} else {
|
||||
var parsed types.Comment
|
||||
if err := json.Unmarshal(resp.Data, &parsed); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error decoding comment: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("decoding comment: %v", err)
|
||||
}
|
||||
comment = &parsed
|
||||
}
|
||||
@@ -186,30 +174,26 @@ Examples:
|
||||
|
||||
if comment == nil {
|
||||
if err := ensureStoreActive(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding comment: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("adding comment: %v", err)
|
||||
}
|
||||
ctx := rootCtx
|
||||
|
||||
|
||||
fullID, err := utils.ResolvePartialID(ctx, store, issueID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving %s: %v\n", issueID, err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving %s: %v", issueID, err)
|
||||
}
|
||||
issueID = fullID
|
||||
|
||||
|
||||
comment, err = store.AddIssueComment(ctx, issueID, author, commentText)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding comment: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("adding comment: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if jsonOutput {
|
||||
data, err := json.MarshalIndent(comment, "", " ")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error encoding JSON: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("encoding JSON: %v", err)
|
||||
}
|
||||
fmt.Println(string(data))
|
||||
return
|
||||
|
||||
@@ -71,12 +71,10 @@ Examples:
|
||||
resolveArgs := &rpc.ResolveIDArgs{ID: args[0]}
|
||||
resp, err := daemonClient.ResolveID(resolveArgs)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving issue ID %s: %v\n", args[0], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving issue ID %s: %v", args[0], err)
|
||||
}
|
||||
if err := json.Unmarshal(resp.Data, &fromID); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error unmarshaling resolved ID: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("unmarshaling resolved ID: %v", err)
|
||||
}
|
||||
|
||||
if isExternalRef {
|
||||
@@ -84,27 +82,23 @@ Examples:
|
||||
toID = args[1]
|
||||
// Validate format: external:<project>:<capability>
|
||||
if err := validateExternalRef(toID); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
} else {
|
||||
resolveArgs = &rpc.ResolveIDArgs{ID: args[1]}
|
||||
resp, err = daemonClient.ResolveID(resolveArgs)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving dependency ID %s: %v\n", args[1], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving dependency ID %s: %v", args[1], err)
|
||||
}
|
||||
if err := json.Unmarshal(resp.Data, &toID); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error unmarshaling resolved ID: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("unmarshaling resolved ID: %v", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
fromID, err = utils.ResolvePartialID(ctx, store, args[0])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving issue ID %s: %v\n", args[0], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving issue ID %s: %v", args[0], err)
|
||||
}
|
||||
|
||||
if isExternalRef {
|
||||
@@ -112,14 +106,12 @@ Examples:
|
||||
toID = args[1]
|
||||
// Validate format: external:<project>:<capability>
|
||||
if err := validateExternalRef(toID); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
} else {
|
||||
toID, err = utils.ResolvePartialID(ctx, store, args[1])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving dependency ID %s: %v\n", args[1], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving dependency ID %s: %v", args[1], err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,10 +119,7 @@ Examples:
|
||||
// Check for child→parent dependency anti-pattern (bd-nim5)
|
||||
// This creates a deadlock: child can't start (parent open), parent can't close (children not done)
|
||||
if isChildOf(fromID, toID) {
|
||||
fmt.Fprintf(os.Stderr, "Error: Cannot add dependency: %s is already a child of %s.\n", fromID, toID)
|
||||
fmt.Fprintf(os.Stderr, "Children inherit dependency on parent completion via hierarchy.\n")
|
||||
fmt.Fprintf(os.Stderr, "Adding an explicit dependency would create a deadlock.\n")
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("cannot add dependency: %s is already a child of %s. Children inherit dependency on parent completion via hierarchy. Adding an explicit dependency would create a deadlock", fromID, toID)
|
||||
}
|
||||
|
||||
// If daemon is running, use RPC
|
||||
@@ -143,8 +132,7 @@ Examples:
|
||||
|
||||
resp, err := daemonClient.AddDependency(depArgs)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
|
||||
if jsonOutput {
|
||||
@@ -165,8 +153,7 @@ Examples:
|
||||
}
|
||||
|
||||
if err := store.AddDependency(ctx, dep, actor); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
|
||||
// Schedule auto-flush
|
||||
@@ -225,36 +212,30 @@ var depRemoveCmd = &cobra.Command{
|
||||
resolveArgs := &rpc.ResolveIDArgs{ID: args[0]}
|
||||
resp, err := daemonClient.ResolveID(resolveArgs)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving issue ID %s: %v\n", args[0], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving issue ID %s: %v", args[0], err)
|
||||
}
|
||||
if err := json.Unmarshal(resp.Data, &fromID); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error unmarshaling resolved ID: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("unmarshaling resolved ID: %v", err)
|
||||
}
|
||||
|
||||
|
||||
resolveArgs = &rpc.ResolveIDArgs{ID: args[1]}
|
||||
resp, err = daemonClient.ResolveID(resolveArgs)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving dependency ID %s: %v\n", args[1], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving dependency ID %s: %v", args[1], err)
|
||||
}
|
||||
if err := json.Unmarshal(resp.Data, &toID); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error unmarshaling resolved ID: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("unmarshaling resolved ID: %v", err)
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
fromID, err = utils.ResolvePartialID(ctx, store, args[0])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving issue ID %s: %v\n", args[0], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving issue ID %s: %v", args[0], err)
|
||||
}
|
||||
|
||||
|
||||
toID, err = utils.ResolvePartialID(ctx, store, args[1])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving dependency ID %s: %v\n", args[1], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving dependency ID %s: %v", args[1], err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,8 +248,7 @@ var depRemoveCmd = &cobra.Command{
|
||||
|
||||
resp, err := daemonClient.RemoveDependency(depArgs)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
|
||||
if jsonOutput {
|
||||
@@ -286,8 +266,7 @@ var depRemoveCmd = &cobra.Command{
|
||||
fullToID := toID
|
||||
|
||||
if err := store.RemoveDependency(ctx, fullFromID, fullToID, actor); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
|
||||
// Schedule auto-flush
|
||||
@@ -332,19 +311,16 @@ Examples:
|
||||
resolveArgs := &rpc.ResolveIDArgs{ID: args[0]}
|
||||
resp, err := daemonClient.ResolveID(resolveArgs)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving issue ID %s: %v\n", args[0], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving issue ID %s: %v", args[0], err)
|
||||
}
|
||||
if err := json.Unmarshal(resp.Data, &fullID); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error unmarshaling resolved ID: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("unmarshaling resolved ID: %v", err)
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
fullID, err = utils.ResolvePartialID(ctx, store, args[0])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving %s: %v\n", args[0], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving %s: %v", args[0], err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,8 +329,7 @@ Examples:
|
||||
var err error
|
||||
store, err = sqlite.New(rootCtx, dbPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: failed to open database: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("failed to open database: %v", err)
|
||||
}
|
||||
defer func() { _ = store.Close() }()
|
||||
}
|
||||
@@ -375,13 +350,11 @@ Examples:
|
||||
|
||||
// Validate direction
|
||||
if direction != "down" && direction != "up" && direction != "both" {
|
||||
fmt.Fprintf(os.Stderr, "Error: --direction must be 'down', 'up', or 'both'\n")
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("--direction must be 'down', 'up', or 'both'")
|
||||
}
|
||||
|
||||
if maxDepth < 1 {
|
||||
fmt.Fprintf(os.Stderr, "Error: --max-depth must be >= 1\n")
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("--max-depth must be >= 1")
|
||||
}
|
||||
|
||||
// For "both" direction, we need to fetch both trees and merge them
|
||||
@@ -392,15 +365,13 @@ Examples:
|
||||
// Get dependencies (down) - what blocks this issue
|
||||
downTree, err := store.GetDependencyTree(ctx, fullID, maxDepth, showAllPaths, false)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
|
||||
// Get dependents (up) - what this issue blocks
|
||||
upTree, err := store.GetDependencyTree(ctx, fullID, maxDepth, showAllPaths, true)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
|
||||
// Merge: root appears once, dependencies below, dependents above
|
||||
@@ -410,8 +381,7 @@ Examples:
|
||||
} else {
|
||||
tree, err = store.GetDependencyTree(ctx, fullID, maxDepth, showAllPaths, direction == "up")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,8 +441,7 @@ var depCyclesCmd = &cobra.Command{
|
||||
var err error
|
||||
store, err = sqlite.New(rootCtx, dbPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: failed to open database: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("failed to open database: %v", err)
|
||||
}
|
||||
defer func() { _ = store.Close() }()
|
||||
}
|
||||
@@ -480,8 +449,7 @@ var depCyclesCmd = &cobra.Command{
|
||||
ctx := rootCtx
|
||||
cycles, err := store.DetectCycles(ctx)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
|
||||
if jsonOutput {
|
||||
|
||||
@@ -26,23 +26,19 @@ var epicStatusCmd = &cobra.Command{
|
||||
EligibleOnly: eligibleOnly,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error communicating with daemon: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("communicating with daemon: %v", err)
|
||||
}
|
||||
if !resp.Success {
|
||||
fmt.Fprintf(os.Stderr, "Error getting epic status: %s\n", resp.Error)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("getting epic status: %s", resp.Error)
|
||||
}
|
||||
if err := json.Unmarshal(resp.Data, &epics); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("parsing response: %v", err)
|
||||
}
|
||||
} else {
|
||||
ctx := rootCtx
|
||||
epics, err = store.GetEpicsEligibleForClosure(ctx)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting epic status: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("getting epic status: %v", err)
|
||||
}
|
||||
if eligibleOnly {
|
||||
filtered := []*types.EpicStatus{}
|
||||
@@ -58,8 +54,7 @@ var epicStatusCmd = &cobra.Command{
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
if err := enc.Encode(epics); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error encoding JSON: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("encoding JSON: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -108,23 +103,19 @@ var closeEligibleEpicsCmd = &cobra.Command{
|
||||
EligibleOnly: true,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error communicating with daemon: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("communicating with daemon: %v", err)
|
||||
}
|
||||
if !resp.Success {
|
||||
fmt.Fprintf(os.Stderr, "Error getting eligible epics: %s\n", resp.Error)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("getting eligible epics: %s", resp.Error)
|
||||
}
|
||||
if err := json.Unmarshal(resp.Data, &eligibleEpics); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("parsing response: %v", err)
|
||||
}
|
||||
} else {
|
||||
ctx := rootCtx
|
||||
epics, err := store.GetEpicsEligibleForClosure(ctx)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting eligible epics: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("getting eligible epics: %v", err)
|
||||
}
|
||||
for _, epic := range epics {
|
||||
if epic.EligibleForClose {
|
||||
@@ -145,8 +136,7 @@ var closeEligibleEpicsCmd = &cobra.Command{
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
if err := enc.Encode(eligibleEpics); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error encoding JSON: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("encoding JSON: %v", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("Would close %d epic(s):\n", len(eligibleEpics))
|
||||
@@ -191,8 +181,7 @@ var closeEligibleEpicsCmd = &cobra.Command{
|
||||
"closed": closedIDs,
|
||||
"count": len(closedIDs),
|
||||
}); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error encoding JSON: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("encoding JSON: %v", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("✓ Closed %d epic(s)\n", len(closedIDs))
|
||||
|
||||
@@ -102,9 +102,7 @@ var labelAddCmd = &cobra.Command{
|
||||
// Protect reserved label namespaces (bd-eijl)
|
||||
// provides:* labels can only be added via 'bd ship' command
|
||||
if strings.HasPrefix(label, "provides:") {
|
||||
fmt.Fprintf(os.Stderr, "Error: 'provides:' labels are reserved for cross-project capabilities\n")
|
||||
fmt.Fprintf(os.Stderr, "Hint: use 'bd ship %s' instead\n", strings.TrimPrefix(label, "provides:"))
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("'provides:' labels are reserved for cross-project capabilities. Hint: use 'bd ship %s' instead", strings.TrimPrefix(label, "provides:"))
|
||||
}
|
||||
|
||||
processBatchLabelOperation(issueIDs, label, "added", jsonOutput,
|
||||
@@ -176,19 +174,16 @@ var labelListCmd = &cobra.Command{
|
||||
resolveArgs := &rpc.ResolveIDArgs{ID: args[0]}
|
||||
resp, err := daemonClient.ResolveID(resolveArgs)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving issue ID %s: %v\n", args[0], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving issue ID %s: %v", args[0], err)
|
||||
}
|
||||
if err := json.Unmarshal(resp.Data, &issueID); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error unmarshaling resolved ID: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("unmarshaling resolved ID: %v", err)
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
issueID, err = utils.ResolvePartialID(ctx, store, args[0])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error resolving %s: %v\n", args[0], err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("resolving %s: %v", args[0], err)
|
||||
}
|
||||
}
|
||||
var labels []string
|
||||
@@ -196,13 +191,11 @@ var labelListCmd = &cobra.Command{
|
||||
if daemonClient != nil {
|
||||
resp, err := daemonClient.Show(&rpc.ShowArgs{ID: issueID})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
var issue types.Issue
|
||||
if err := json.Unmarshal(resp.Data, &issue); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("parsing response: %v", err)
|
||||
}
|
||||
labels = issue.Labels
|
||||
} else {
|
||||
@@ -210,8 +203,7 @@ var labelListCmd = &cobra.Command{
|
||||
var err error
|
||||
labels, err = store.GetLabels(ctx, issueID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
}
|
||||
if jsonOutput {
|
||||
@@ -245,19 +237,16 @@ var labelListAllCmd = &cobra.Command{
|
||||
if daemonClient != nil {
|
||||
resp, err := daemonClient.List(&rpc.ListArgs{})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
if err := json.Unmarshal(resp.Data, &issues); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("parsing response: %v", err)
|
||||
}
|
||||
} else {
|
||||
// Direct mode
|
||||
issues, err = store.SearchIssues(ctx, "", types.IssueFilter{})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("%v", err)
|
||||
}
|
||||
}
|
||||
// Collect unique labels with counts
|
||||
@@ -272,8 +261,7 @@ var labelListAllCmd = &cobra.Command{
|
||||
// Direct mode - need to fetch labels
|
||||
labels, err := store.GetLabels(ctx, issue.ID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting labels for %s: %v\n", issue.ID, err)
|
||||
os.Exit(1)
|
||||
FatalErrorRespectJSON("getting labels for %s: %v", issue.ID, err)
|
||||
}
|
||||
for _, label := range labels {
|
||||
labelCounts[label]++
|
||||
|
||||
Reference in New Issue
Block a user