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 ", 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, "") }