refactor: add tag and relation methods to node to enforce integrity

This commit is contained in:
2026-03-29 23:16:44 +02:00
parent 4ebcb88628
commit dadd3d9e13
15 changed files with 313 additions and 179 deletions

View File

@@ -7,7 +7,6 @@ import (
"fmt"
"os"
"slices"
"strings"
"github.com/spf13/cobra"
)
@@ -33,15 +32,16 @@ var updateCmd = &cobra.Command{
return
}
// parse relations
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)
rel, err := parseRelFlag(svc, r)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return false
}
dst[rt] = append(dst[rt], tgt)
dst[rel.Type] = append(dst[rel.Type], rel.Target)
}
return true
}
@@ -49,6 +49,8 @@ var updateCmd = &cobra.Command{
return
}
// enforce blocking of tasks
//TODO: mabye part of the backend?
if slices.Contains(uAddTags, "_status::done") {
ok, blockers, err := svc.CanClose(args[0])
if err != nil {
@@ -59,21 +61,9 @@ var updateCmd = &cobra.Command{
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")
}
for _, prefix := range []string{"_type::", "_status::", "_prio::", "_namespace::"} {
if slices.ContainsFunc(uAddTags, func(e string) bool { return strings.HasPrefix(e, prefix) }) {
for _, existing := range node.Tags {
if strings.HasPrefix(existing, prefix) {
uRmTags = append(uRmTags, existing)
}
}
}
}
// update main fields
if cmd.Flags().Changed("title") {
node.Title = uTitle
}
@@ -87,28 +77,33 @@ var updateCmd = &cobra.Command{
node.DueDate = ""
}
// udpate tags
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)
if err := node.RemoveTag(t); err != nil {
fmt.Fprintln(os.Stderr, "failed to remove tag:", err)
return
}
}
for _, t := range uAddTags {
node.AddTag(t)
}
// update relations
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 })
if err := node.RemoveRelation(rt, tgt); err != nil {
fmt.Fprintln(os.Stderr, "failed to remove relation:", err)
return
}
}
}
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)
}
node.AddRelation(rt, tgt)
}
}
// persist update
if err := svc.Update(node); err != nil {
fmt.Fprintln(os.Stderr, "failed to update:", err)
return