Completed
Push — master ( 015fff...2fb069 )
by Valentin
02:25
created

cmd.scanHandler   D

Complexity

Conditions 13

Size

Total Lines 57
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 38
nop 2
dl 0
loc 57
rs 4.2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like cmd.scanHandler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package cmd
2
3
import (
4
	"fmt"
5
	"github.com/spf13/cobra"
6
	"github.com/vvval/go-metadata-scanner/cmd/scancmd"
7
	"github.com/vvval/go-metadata-scanner/cmd/scancmd/writers"
8
	"github.com/vvval/go-metadata-scanner/config"
9
	"github.com/vvval/go-metadata-scanner/etool"
10
	"github.com/vvval/go-metadata-scanner/util"
11
	"github.com/vvval/go-metadata-scanner/util/log"
12
	"github.com/vvval/go-metadata-scanner/util/rand"
13
	"github.com/vvval/go-metadata-scanner/util/scan"
14
	"github.com/vvval/go-metadata-scanner/vars"
15
	"os"
16
	"path/filepath"
17
	"sync"
18
)
19
20
var (
21
	scanFlags    scancmd.Flags
22
	PoolSize     = 10
23
	MinChunkSize = 5
24
)
25
26
func init() {
27
	// cmd represents the scan command
28
	var cmd = &cobra.Command{
29
		Use:   "scan",
30
		Short: "Scan folder and write metadata into the output file.",
31
		Long: `Scan folder and write metadata into the output file.
32
By default output file is a "csv" file.`,
33
		Run: scanHandler,
34
	}
35
36
	rootCmd.AddCommand(cmd)
37
	scanFlags.Fill(cmd)
38
}
39
40
func scanHandler(cmd *cobra.Command, args []string) {
41
	log.Log("Scanning", util.Abs(scanFlags.Directory()))
42
43
	var files = scan.MustDir(scanFlags.Directory(), config.App.Extensions())
44
	poolSize, chunkSize := util.AdjustSizes(len(files), PoolSize, MinChunkSize)
45
46
	var chunks = make(chan vars.Chunk)
47
	var scannedFiles = make(chan vars.File)
48
	var wg sync.WaitGroup
49
	scancmd.CreatePool(
50
		&wg,
51
		poolSize,
52
		chunks,
53
		func(files vars.Chunk) ([]byte, error) {
54
			return etool.Read(files, config.App.Fields())
55
		},
56
		func(data []byte) {
57
			for _, parsed := range etool.Parse(data) {
58
				scannedFiles <- parsed
59
			}
60
		},
61
	)
62
63
	for _, chunk := range files.Split(chunkSize) {
64
		wg.Add(1)
65
		chunks <- chunk
66
	}
67
68
	go func() {
69
		wg.Wait()
70
		close(chunks)
71
		close(scannedFiles)
72
	}()
73
74
	outputFilename := randomizeOutputFilename(scanFlags.Filename())
75
76
	headers := packHeaders(config.App.Fields())
77
	wr, err := writers.Get(scanFlags.Format())
78
	if err != nil {
79
		logWriterFatal(err)
80
	}
81
82
	err = wr.Open(outputFilename, headers)
83
	if err != nil {
84
		logWriterFatal(err)
85
	}
86
	defer wr.Close()
87
88
	for file := range scannedFiles {
89
		file.WithRelPath(scanFlags.Directory())
90
		err := wr.Write(&file)
91
		if err != nil {
92
			log.Failure("CSV write", fmt.Sprintf("failed writing data for \"%s\" file", file.RelPath()))
93
		}
94
	}
95
96
	log.Log("Scanned", fmt.Sprintf("Scan results are in the \"%s\" file", outputFilename))
97
}
98
99
func randomizeOutputFilename(path string) string {
100
	ext := filepath.Ext(path)
101
	dir := filepath.Dir(path)
102
	base := filepath.Base(path)
103
	hash := rand.Strings(10)
104
105
	return filepath.Join(dir, base[0:len(base)-len(ext)]+"-"+hash+ext)
106
}
107
108
func packHeaders(fields []string) []string {
109
	headers := []string{"filename"}
110
111
	for _, field := range fields {
112
		headers = append(headers, field)
113
	}
114
115
	return headers
116
}
117
118
func logWriterFatal(err error) {
119
	log.Failure("Output writer", err.Error())
120
	os.Exit(1)
121
}
122