133 lines
3.4 KiB
Go
133 lines
3.4 KiB
Go
package cmd
|
|
|
|
import (
|
|
"axolotl/db"
|
|
"axolotl/models"
|
|
"axolotl/output"
|
|
"axolotl/service"
|
|
"fmt"
|
|
"os"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
uTitle, uContent, uDue, dummy string
|
|
uClearDue bool
|
|
uAddTags, uRmTags, uAddRels, uRmRels []string
|
|
)
|
|
|
|
var updateCmd = &cobra.Command{
|
|
Use: "update <id>", Short: "Update a node", Args: cobra.ExactArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
d, err := db.GetDB()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
return
|
|
}
|
|
svc := service.NewSQLiteNodeService(d.DB, cfg.GetUser())
|
|
|
|
node, err := svc.GetByID(args[0])
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "node not found:", args[0])
|
|
return
|
|
}
|
|
|
|
addRels, rmRels := make(map[models.RelType][]string), make(map[models.RelType][]string)
|
|
parseRel := func(src []string, dst map[models.RelType][]string) bool {
|
|
for _, r := range src {
|
|
rt, tgt, err := parseRelFlag(r)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
return false
|
|
}
|
|
dst[rt] = append(dst[rt], tgt)
|
|
}
|
|
return true
|
|
}
|
|
if !parseRel(uAddRels, addRels) || !parseRel(uRmRels, rmRels) {
|
|
return
|
|
}
|
|
|
|
if slices.Contains(uAddTags, "_status::done") {
|
|
ok, blockers, err := svc.CanClose(args[0])
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "failed to check blockers:", err)
|
|
return
|
|
}
|
|
if !ok {
|
|
fmt.Fprintf(os.Stderr, "cannot close: blocked by %v\n", blockers)
|
|
return
|
|
}
|
|
uRmTags = append(uRmTags, "_status::open")
|
|
} else if slices.Contains(uAddTags, "_status::open") {
|
|
uRmTags = append(uRmTags, "_status::done")
|
|
}
|
|
if slices.ContainsFunc(uAddTags, func(e string) bool { return strings.HasPrefix(e, "_prio") }) {
|
|
uRmTags = append(uRmTags, "_prio::low", "_prio::medium", "_prio::high")
|
|
}
|
|
|
|
if cmd.Flags().Changed("title") {
|
|
node.Title = uTitle
|
|
}
|
|
if cmd.Flags().Changed("content") {
|
|
node.Content = uContent
|
|
}
|
|
if cmd.Flags().Changed("due") {
|
|
node.DueDate = uDue
|
|
}
|
|
if uClearDue {
|
|
node.DueDate = ""
|
|
}
|
|
|
|
for _, t := range uRmTags {
|
|
node.Tags = slices.DeleteFunc(node.Tags, func(e string) bool { return e == t })
|
|
}
|
|
for _, t := range uAddTags {
|
|
if !slices.Contains(node.Tags, t) {
|
|
node.Tags = append(node.Tags, t)
|
|
}
|
|
}
|
|
|
|
for rt, tgts := range rmRels {
|
|
for _, tgt := range tgts {
|
|
node.Relations[string(rt)] = slices.DeleteFunc(node.Relations[string(rt)], func(e string) bool { return e == tgt })
|
|
}
|
|
}
|
|
for rt, tgts := range addRels {
|
|
for _, tgt := range tgts {
|
|
if !slices.Contains(node.Relations[string(rt)], tgt) {
|
|
node.Relations[string(rt)] = append(node.Relations[string(rt)], tgt)
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := svc.Update(node); err != nil {
|
|
fmt.Fprintln(os.Stderr, "failed to update:", err)
|
|
return
|
|
}
|
|
if n, err := svc.GetByID(args[0]); err == nil {
|
|
output.PrintNode(cmd.OutOrStdout(), n, jsonFlag)
|
|
} else {
|
|
fmt.Fprintln(os.Stderr, "failed to fetch node:", err)
|
|
}
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(updateCmd)
|
|
f := updateCmd.Flags()
|
|
f.StringVar(&uTitle, "title", "", "")
|
|
f.StringVar(&uContent, "content", "", "")
|
|
f.StringVar(&uDue, "due", "", "")
|
|
f.BoolVar(&uClearDue, "clear-due", false, "")
|
|
f.StringVar(&dummy, "status", "", "")
|
|
f.StringVar(&dummy, "prio", "", "")
|
|
f.StringArrayVar(&uAddTags, "tag", nil, "")
|
|
f.StringArrayVar(&uRmTags, "tag-remove", nil, "")
|
|
f.StringArrayVar(&uAddRels, "rel", nil, "")
|
|
f.StringArrayVar(&uRmRels, "rel-remove", nil, "")
|
|
}
|