-
Notifications
You must be signed in to change notification settings - Fork 1
/
parse.go
149 lines (125 loc) · 3.3 KB
/
parse.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package parse
import (
"errors"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"github.com/rstudio/python-distribution-parser/internal/packages"
"github.com/rstudio/python-distribution-parser/types"
)
func endsWith(str, suffix string) bool {
return len(str) >= len(suffix) && str[len(str)-len(suffix):] == suffix
}
func groupWheelFilesFirst(files []string) []string {
// Check if there's any wheel file
hasWheel := false
for _, fname := range files {
if endsWith(fname, ".whl") {
hasWheel = true
break
}
}
if !hasWheel {
return files
}
sort.Slice(files, func(i, j int) bool {
return endsWith(files[i], ".whl") && !endsWith(files[j], ".whl")
})
return files
}
func findDistributions(dists []string) ([]string, error) {
var packages []string
for _, filename := range dists {
if _, err := os.Stat(filename); err == nil {
packages = append(packages, filename)
continue
}
files, err := filepath.Glob(filename)
if err != nil {
return nil, err
}
if len(files) == 0 {
return nil, fmt.Errorf("cannot find file (or expand pattern): %s", filename)
}
packages = append(packages, files...)
}
return groupWheelFilesFirst(packages), nil
}
func makePackage(filename string, signatures map[string]string) (*types.PackageFile, error) {
packageFile, err := packages.NewPackageFile(filename)
if err != nil {
return nil, fmt.Errorf("unable to parse %s, path may not point to a valid Python package: %v\n", filename, err)
}
signedName := packageFile.SignedBaseFilename
if signature, exists := signatures[signedName]; exists {
err := packageFile.AddGPGSignature(signature, signedName)
if err != nil {
return nil, err
}
}
_, err = packages.GetFileSize(packageFile.Filename)
if err != nil {
return nil, fmt.Errorf("%s is not a real file\n", packageFile.Filename)
}
return packageFile, nil
}
func parse(dists []string) ([]*types.PackageFile, error) {
dists, err := findDistributions(dists)
if err != nil {
return nil, fmt.Errorf("error finding distributions: %v\n", err)
}
// Initialize maps for signatures and a slice for distributions
signatures := make(map[string]string)
var distributions []string
// Separate signatures and distributions
for _, d := range dists {
base := filepath.Base(d)
if strings.HasSuffix(d, ".asc") {
signatures[base] = d
} else {
distributions = append(distributions, d)
}
}
var packages []*types.PackageFile
for _, filename := range distributions {
p, err := makePackage(filename, signatures)
if err != nil {
return nil, err
}
packages = append(packages, p)
}
return packages, nil
}
func Parse(paths ...string) ([]*types.PackageFile, error) {
var files []string
for _, path := range paths {
info, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("%s does not exist: %v\n", path, err)
}
return nil, err
}
if info.IsDir() {
dirFiles, err := os.ReadDir(path)
if err != nil {
return nil, err
}
for _, entry := range dirFiles {
// Don't recursively go in directories, only go one level deep.
if !entry.IsDir() {
fullPath := filepath.Join(path, entry.Name())
files = append(files, fullPath)
}
}
} else {
files = append(files, path)
}
}
if len(files) == 0 {
return nil, errors.New("no files to parse")
}
return parse(files)
}