pkg/scan/producer/reproducer.go   A
last analyzed

Size/Duplication

Total Lines 63
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 36
dl 0
loc 63
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A producer.NewReProducer 0 4 1
A producer.*ReProducer.Reproduce 0 2 1
B producer.*ReProducer.buildReproducer 0 36 7
1
package producer
2
3
import (
4
	"context"
5
	"sync"
6
7
	"github.com/stefanoj3/dirstalk/pkg/common/urlpath"
8
	"github.com/stefanoj3/dirstalk/pkg/scan"
9
)
10
11
const defaultChannelBuffer = 25
12
13
func NewReProducer(
14
	producer scan.Producer,
15
) *ReProducer {
16
	return &ReProducer{producer: producer}
17
}
18
19
type ReProducer struct {
20
	producer scan.Producer
21
}
22
23
// Reproduce will check if it is possible to go deeper on the result provided, if so will.
24
func (r *ReProducer) Reproduce(ctx context.Context) func(r scan.Result) <-chan scan.Target {
25
	return r.buildReproducer(ctx)
26
}
27
28
func (r *ReProducer) buildReproducer(ctx context.Context) func(result scan.Result) <-chan scan.Target {
29
	resultRegistry := sync.Map{}
30
31
	return func(result scan.Result) <-chan scan.Target {
32
		resultChannel := make(chan scan.Target, defaultChannelBuffer)
33
34
		go func() {
35
			defer close(resultChannel)
36
37
			if result.Target.Depth <= 0 {
38
				return
39
			}
40
41
			// no point in appending to a filename
42
			if urlpath.HasExtension(result.Target.Path) {
43
				return
44
			}
45
46
			_, inRegistry := resultRegistry.Load(result.Target.Path)
47
			if inRegistry {
48
				return
49
			}
50
51
			resultRegistry.Store(result.Target.Path, nil)
52
53
			for target := range r.producer.Produce(ctx) {
54
				newTarget := result.Target
55
				newTarget.Depth--
56
				newTarget.Path = urlpath.Join(newTarget.Path, target.Path)
57
				newTarget.Method = target.Method
58
59
				resultChannel <- newTarget
60
			}
61
		}()
62
63
		return resultChannel
64
	}
65
}
66