From c334a23bff46a2d9981c3a009dce599a21475555 Mon Sep 17 00:00:00 2001 From: Oleg Olivson Date: Fri, 19 Jan 2024 16:07:53 +0100 Subject: [PATCH] call OnEndEdit always(!) if OnBeginEdit called successfully --- node/edit.go | 14 ++++++++------ node/edit_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ node/selection.go | 9 +++++---- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/node/edit.go b/node/edit.go index 69df34e..a323071 100644 --- a/node/edit.go +++ b/node/edit.go @@ -31,10 +31,15 @@ func (e editor) edit(from *Selection, to *Selection, s editStrategy) (err error) return nil } -func (e editor) enter(from *Selection, to *Selection, new bool, strategy editStrategy, root bool, bubble bool) error { - if err := to.beginEdit(NodeRequest{New: new, Source: to, EditRoot: root}, bubble); err != nil { - return err +func (e editor) enter(from *Selection, to *Selection, new bool, strategy editStrategy, root bool, bubble bool) (err error) { + if err = to.beginEdit(NodeRequest{New: new, Source: to, EditRoot: root}, bubble); err != nil { + return } + defer func() { + if endErr := to.endEdit(NodeRequest{New: new, Source: to, EditRoot: root}, bubble); endErr != nil { + err = fmt.Errorf("error during endEdit: %v, previous error: %w", endErr, err) + } + }() if meta.IsList(from.Meta()) && !from.InsideList { if err := e.list(from, to, from.Meta().(*meta.List), new, strategy); err != nil { return err @@ -61,9 +66,6 @@ func (e editor) enter(from *Selection, to *Selection, new bool, strategy editStr } //fmt.Printf("Ended %s\n", meta.SchemaPath(from.Meta())) } - if err := to.endEdit(NodeRequest{New: new, Source: to, EditRoot: root}, bubble); err != nil { - return err - } return nil } diff --git a/node/edit_test.go b/node/edit_test.go index 316245b..4c8f94f 100644 --- a/node/edit_test.go +++ b/node/edit_test.go @@ -530,3 +530,44 @@ func testDataRoot() map[string]interface{} { }, } } + +func TestNodeEndEditOnFailure(t *testing.T) { + mstr := `module m { prefix ""; namespace ""; revision 0; + container c { + leaf x { + type string; + } + } + }` + json, _ := nodeutil.ReadJSON(`{"x":4}`) + m, err := parser.LoadModuleFromString(nil, mstr) + if err != nil { + t.Fatal(err) + } + n := &nodeutil.Basic{} + n.OnChild = func(r node.ChildRequest) (node.Node, error) { + return n, nil + } + var actual bytes.Buffer + n.OnBeginEdit = func(r node.NodeRequest) error { + fmt.Fprintf(&actual, "begin %s\n", r.Selection.Meta().Ident()) + return nil + } + n.OnEndEdit = func(r node.NodeRequest) error { + fmt.Fprintf(&actual, "end %s\n", r.Selection.Meta().Ident()) + return nil + } + root := node.NewBrowser(m, n).Root() + sel, err := root.Find("c") + fc.RequireEqual(t, nil, err) + err = sel.UpdateFrom(json) + if err == nil { + t.Error("Expected sel.UpdateFrom() to fail due to wrong argument") + } + + fc.AssertEqual(t, `begin c +begin m +end c +end m +`, actual.String()) +} diff --git a/node/selection.go b/node/selection.go index 8d14085..df0d37d 100644 --- a/node/selection.go +++ b/node/selection.go @@ -379,6 +379,11 @@ func (sel *Selection) Delete() (err error) { if err := sel.beginEdit(NodeRequest{Source: sel, Delete: true, EditRoot: true}, true); err != nil { return err } + defer func() { + if endErr := sel.endEdit(NodeRequest{Source: sel, Delete: true, EditRoot: true}, true); endErr != nil { + err = fmt.Errorf("error during endEdit: %v, previous error: %w", endErr, err) + } + }() if sel.InsideList { r := ListRequest{ @@ -404,10 +409,6 @@ func (sel *Selection) Delete() (err error) { return err } } - - if err := sel.endEdit(NodeRequest{Source: sel, Delete: true, EditRoot: true}, true); err != nil { - return err - } return }