files2.0: return errors from ufsIterator properly
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
Łukasz Magiera committed
Dec 14, 2018 at 12:37 UTC
a92a174526583a305f84f78b0bba0f2485ba1dfa
2 files changed
+78
-4
core/coreapi/unixfile.go
+31
-4
@@ -31,7 +31,8 @@ type ufsIterator struct {
31
curName string
32
curFile files.Node
33
34
- err error
34
+ err error
35
+ errCh chan error
36
}
37
38
func (it *ufsIterator) Name() string {
@@ -43,11 +44,31 @@ func (it *ufsIterator) Node() files.Node {
44
}
45
46
func (it *ufsIterator) Next() bool {
46
- l, ok := <-it.files
47
- if !ok {
47
+ if it.err != nil {
48
return false
49
}
50
51
+ var l *ipld.Link
52
+ var ok bool
53
+ for !ok {
54
+ if it.files == nil && it.errCh == nil {
55
+ return false
56
+ }
57
+ select {
58
+ case l, ok = <-it.files:
59
+ if !ok {
60
+ it.files = nil
61
+ }
62
+ case err := <-it.errCh:
63
+ it.errCh = nil
64
+ it.err = err
65
+
66
+ if err != nil {
67
+ return false
68
+ }
69
+ }
70
+ }
71
+
72
it.curFile = nil
73
74
nd, err := l.GetNode(it.ctx, it.dserv)
@@ -71,8 +92,12 @@ func (d *ufsDirectory) Close() error {
92
93
func (d *ufsDirectory) Entries() files.DirIterator {
94
fileCh := make(chan *ipld.Link, prefetchFiles)
95
+ errCh := make(chan error, 1)
96
go func() {
75
- d.dir.ForEachLink(d.ctx, func(link *ipld.Link) error {
97
+ errCh <- d.dir.ForEachLink(d.ctx, func(link *ipld.Link) error {
98
+ if d.ctx.Err() != nil {
99
+ return d.ctx.Err()
100
+ }
101
select {
102
case fileCh <- link:
103
case <-d.ctx.Done():
@@ -81,12 +106,14 @@ func (d *ufsDirectory) Entries() files.DirIterator {
106
return nil
107
})
108
109
+ close(errCh)
110
close(fileCh)
111
}()
112
113
return &ufsIterator{
114
ctx: d.ctx,
115
files: fileCh,
116
+ errCh: errCh,
117
dserv: d.dserv,
118
}
119
}
core/coreapi/unixfs_test.go
+47
@@ -776,6 +776,53 @@ func TestLs(t *testing.T) {
776
}
777
}
778
779
+func TestEntriesExpired(t *testing.T) {
780
+ ctx := context.Background()
781
+ node, api, err := makeAPI(ctx)
782
+ if err != nil {
783
+ t.Error(err)
784
+ }
785
+
786
+ r := strings.NewReader("content-of-file")
787
+ k, _, err := coreunix.AddWrapped(node, r, "name-of-file")
788
+ if err != nil {
789
+ t.Error(err)
790
+ }
791
+ parts := strings.Split(k, "/")
792
+ if len(parts) != 2 {
793
+ t.Errorf("unexpected path: %s", k)
794
+ }
795
+ p, err := coreiface.ParsePath("/ipfs/" + parts[0])
796
+ if err != nil {
797
+ t.Error(err)
798
+ }
799
+
800
+ ctx, cancel := context.WithCancel(ctx)
801
+
802
+ nd, err := api.Unixfs().Get(ctx, p)
803
+ if err != nil {
804
+ t.Error(err)
805
+ }
806
+ cancel()
807
+
808
+ it := files.ToDir(nd).Entries()
809
+ if it == nil {
810
+ t.Fatal("it was nil")
811
+ }
812
+
813
+ if it.Next() {
814
+ t.Fatal("Next succeeded")
815
+ }
816
+
817
+ if it.Err() != context.Canceled {
818
+ t.Fatalf("unexpected error %s", it.Err())
819
+ }
820
+
821
+ if it.Next() {
822
+ t.Fatal("Next succeeded")
823
+ }
824
+}
825
+
826
func TestLsEmptyDir(t *testing.T) {
827
ctx := context.Background()
828
node, api, err := makeAPI(ctx)