From cd65ec614b5506013c86e02236ce6267d22fc77e Mon Sep 17 00:00:00 2001 From: Juan Batiz-Benet Date: Tue, 6 Jan 2015 13:07:28 -0800 Subject: [PATCH 1/3] merkledag: keep links sorted by name May not be necessary to sort when adding each link-- doing so would be unnecessarily expensive O(n^2) when constructing nodes -- though n wont be big. --- merkledag/coding.go | 5 +++++ merkledag/merkledag.go | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/merkledag/coding.go b/merkledag/coding.go index 81cc1fc7c..cbd2de74a 100644 --- a/merkledag/coding.go +++ b/merkledag/coding.go @@ -2,6 +2,7 @@ package merkledag import ( "fmt" + "sort" mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" @@ -30,6 +31,7 @@ func (n *Node) Unmarshal(encoded []byte) error { } n.Links[i].Hash = h } + sort.Stable(LinkSlice(n.Links)) // keep links sorted n.Data = pbn.GetData() return nil @@ -59,6 +61,8 @@ func (n *Node) Marshal() ([]byte, error) { func (n *Node) getPBNode() *pb.PBNode { pbn := &pb.PBNode{} pbn.Links = make([]*pb.PBLink, len(n.Links)) + + sort.Stable(LinkSlice(n.Links)) // keep links sorted for i, l := range n.Links { pbn.Links[i] = &pb.PBLink{} pbn.Links[i].Name = &l.Name @@ -73,6 +77,7 @@ func (n *Node) getPBNode() *pb.PBNode { // Encoded returns the encoded raw data version of a Node instance. // It may use a cached encoded version, unless the force flag is given. func (n *Node) Encoded(force bool) ([]byte, error) { + sort.Stable(LinkSlice(n.Links)) // keep links sorted if n.encoded == nil || force { var err error n.encoded, err = n.Marshal() diff --git a/merkledag/merkledag.go b/merkledag/merkledag.go index 007b5d055..cd50d9e5b 100644 --- a/merkledag/merkledag.go +++ b/merkledag/merkledag.go @@ -66,6 +66,12 @@ type Link struct { Node *Node } +type LinkSlice []*Link + +func (ls LinkSlice) Len() int { return len(ls) } +func (ls LinkSlice) Swap(a, b int) { ls[a], ls[b] = ls[b], ls[a] } +func (ls LinkSlice) Less(a, b int) bool { return ls[a].Name < ls[b].Name } + // MakeLink creates a link to the given node func MakeLink(n *Node) (*Link, error) { s, err := n.Size() From d490a8570648f4d471db227f70d0408c7e84813d Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 20 Dec 2014 16:39:37 +0100 Subject: [PATCH 2/3] Make sure ipfs add output is sorted by name License: MIT Signed-off-by: Christian Couder --- core/commands/add.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/commands/add.go b/core/commands/add.go index 176824a9f..3ab27ad8f 100644 --- a/core/commands/add.go +++ b/core/commands/add.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "path" + "sort" cmds "github.com/jbenet/go-ipfs/commands" core "github.com/jbenet/go-ipfs/core" @@ -82,6 +83,8 @@ remains to be implemented. return nil, u.ErrCast() } + sort.Stable(val) + var buf bytes.Buffer for i, obj := range val.Objects { if val.Quiet { @@ -197,3 +200,16 @@ func addDagnode(output *AddOutput, name string, dn *dag.Node) error { output.Names = append(output.Names, name) return nil } + +// Sort interface implementation to sort add output by name + +func (a AddOutput) Len() int { + return len(a.Names) +} +func (a AddOutput) Swap(i, j int) { + a.Names[i], a.Names[j] = a.Names[j], a.Names[i] + a.Objects[i], a.Objects[j] = a.Objects[j], a.Objects[i] +} +func (a AddOutput) Less(i, j int) bool { + return a.Names[i] < a.Names[j] +} From 3b65f1a507693f8cf75b9c0ba6ec078e3dea74d3 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 28 Nov 2014 22:05:07 +0100 Subject: [PATCH 3/3] Add sharness tests for recursive add License: MIT Signed-off-by: Christian Couder --- test/t0040-add-and-cat.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/t0040-add-and-cat.sh b/test/t0040-add-and-cat.sh index a95ed9a61..b6aae632d 100755 --- a/test/t0040-add-and-cat.sh +++ b/test/t0040-add-and-cat.sh @@ -67,6 +67,23 @@ test_expect_success "'ipfs add -q' output looks good" ' test_cmp expected actual ' +test_expect_success "'ipfs add -r' succeeds" ' + mkdir mountdir/planets && + echo "Hello Mars!" >mountdir/planets/mars.txt && + echo "Hello Venus!" >mountdir/planets/venus.txt && + ipfs add -r mountdir/planets >actual +' + +test_expect_success "'ipfs add -r' output looks good" ' + PLANETS="QmWSgS32xQEcXMeqd3YPJLrNBLSdsfYCep2U7CFkyrjXwY" && + MARS="QmPrrHqJzto9m7SyiRzarwkqPcCSsKR2EB1AyqJfe8L8tN" && + VENUS="QmU5kp3BH3B8tnWUU2Pikdb2maksBNkb92FHRr56hyghh4" && + echo "added $PLANETS mountdir/planets" >expected && + echo "added $MARS mountdir/planets/mars.txt" >>expected && + echo "added $VENUS mountdir/planets/venus.txt" >>expected && + test_cmp expected actual +' + test_expect_success "go-random is installed" ' type random '