aboutsummaryrefslogtreecommitdiff
path: root/gui/internal/model/plan.go
diff options
context:
space:
mode:
Diffstat (limited to 'gui/internal/model/plan.go')
-rw-r--r--gui/internal/model/plan.go18
1 files changed, 18 insertions, 0 deletions
diff --git a/gui/internal/model/plan.go b/gui/internal/model/plan.go
index c3e9654..31a783b 100644
--- a/gui/internal/model/plan.go
+++ b/gui/internal/model/plan.go
@@ -16,6 +16,7 @@ import (
"git.labunix.xyz/krino/internal/lock"
"git.labunix.xyz/krino/internal/plan"
"git.labunix.xyz/krino/internal/scan"
+ "git.labunix.xyz/krino/internal/xdg"
)
// Row is one line of the Plan tab: a file krino would act on, or one it
@@ -292,6 +293,23 @@ func (t *PlanTab) KeepThisCopy(i int) error {
if row.Path == "" {
return fmt.Errorf("model: %s has no path", row.Rel)
}
+ // Only the first step to reach a path may displace it: once another
+ // step of this same plan is going to put its own file there, displacing
+ // it again would destroy that file. internal/plan refuses to build such
+ // a pair; the window writes its step by hand, so it must refuse too.
+ for _, c := range t.dp.Chains {
+ if c.File.Rel == row.Rel {
+ continue
+ }
+ for _, st := range c.Steps {
+ if st.Skip != "" {
+ continue
+ }
+ if st.Dst == row.DuplicateOf || st.Displaces == row.DuplicateOf {
+ return fmt.Errorf("model: %s is already spoken for by %s in this plan", xdg.Abbrev(row.DuplicateOf), c.File.Rel)
+ }
+ }
+ }
for j, c := range t.dp.Chains {
if c.File.Rel != row.Rel {
continue