/
csv.go
117 lines (93 loc) · 2.3 KB
/
csv.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package lockfile
import (
"encoding/csv"
"errors"
"fmt"
"io"
"os"
"sort"
"strings"
)
var errCSVRecordNotEnoughFields = errors.New("not enough fields (expected at least four)")
var errCSVRecordMissingPackageField = errors.New("field 3 is empty (must be the name of a package)")
var errCSVRecordMissingCommitField = errors.New("field 4 is empty (must be a commit)")
func fromCSVRecord(lines []string) (PackageDetails, error) {
if len(lines) < 4 {
return PackageDetails{}, errCSVRecordNotEnoughFields
}
ecosystem := Ecosystem(lines[0])
compareAs := Ecosystem(lines[1])
name := lines[2]
version := lines[3]
commit := ""
if compareAs == "" {
compareAs = ecosystem
}
if ecosystem == "" {
if version == "" {
return PackageDetails{}, errCSVRecordMissingCommitField
}
commit = version
version = ""
}
if name == "" {
return PackageDetails{}, errCSVRecordMissingPackageField
}
return PackageDetails{
Name: name,
Version: version,
Ecosystem: ecosystem,
CompareAs: compareAs,
Commit: commit,
}, nil
}
func fromCSV(reader io.Reader) ([]PackageDetails, error) {
var packages []PackageDetails
i := 0
r := csv.NewReader(reader)
for {
i++
record, err := r.Read()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return packages, fmt.Errorf("%w", err)
}
details, err := fromCSVRecord(record)
if err != nil {
return packages, fmt.Errorf("row %d: %w", i, err)
}
packages = append(packages, details)
}
sort.Slice(packages, func(i, j int) bool {
if packages[i].Name == packages[j].Name {
return packages[i].Version < packages[j].Version
}
return packages[i].Name < packages[j].Name
})
return packages, nil
}
func FromCSVRows(filePath string, parseAs string, rows []string) (Lockfile, error) {
packages, err := fromCSV(strings.NewReader(strings.Join(rows, "\n")))
return Lockfile{
FilePath: filePath,
ParsedAs: parseAs,
Packages: packages,
}, err
}
func FromCSVFile(pathToCSV string, parseAs string) (Lockfile, error) {
reader, err := os.Open(pathToCSV)
if err != nil {
return Lockfile{}, fmt.Errorf("could not read %s: %w", pathToCSV, err)
}
packages, err := fromCSV(reader)
if err != nil {
err = fmt.Errorf("%s: %w", pathToCSV, err)
}
return Lockfile{
FilePath: pathToCSV,
ParsedAs: parseAs,
Packages: packages,
}, err
}