|
1 | 1 | package v5 |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "github.com/murphysecurity/murphysec/model" |
5 | | - "github.com/murphysecurity/murphysec/module/pnpm/shared" |
6 | 4 | "sort" |
7 | 5 | "strings" |
| 6 | + |
| 7 | + "github.com/murphysecurity/murphysec/model" |
| 8 | + "github.com/murphysecurity/murphysec/module/pnpm/shared" |
8 | 9 | ) |
9 | 10 |
|
10 | 11 | type Pkg struct { |
@@ -99,17 +100,45 @@ func (p *Pkg) adjustByPath(path string) { |
99 | 100 | } |
100 | 101 |
|
101 | 102 | func (l *Lockfile) buildIndexes() { |
102 | | - for path, pkg := range l.Packages { |
| 103 | + paths := make([]string, 0, len(l.Packages)) |
| 104 | + for path := range l.Packages { |
| 105 | + paths = append(paths, path) |
| 106 | + } |
| 107 | + sort.Strings(paths) |
| 108 | + |
| 109 | + for _, path := range paths { |
| 110 | + pkg := l.Packages[path] |
103 | 111 | pkg.adjustByPath(path) |
104 | 112 | } |
105 | 113 | l.pkgIndexes = make(map[[2]string]*Pkg, len(l.Packages)) |
106 | | - for _, pkg := range l.Packages { |
| 114 | + indexPaths := make(map[[2]string]string, len(l.Packages)) |
| 115 | + for _, path := range paths { |
| 116 | + pkg := l.Packages[path] |
107 | 117 | var name, version = pkg.Name, pkg.Version |
108 | 118 | if name == "" { |
109 | 119 | continue |
110 | 120 | } |
111 | | - l.pkgIndexes[[2]string{name, version}] = pkg |
| 121 | + key := [2]string{name, version} |
| 122 | + prevPath, exists := indexPaths[key] |
| 123 | + if !exists || preferPkgPath(prevPath, path, name, version) { |
| 124 | + indexPaths[key] = path |
| 125 | + l.pkgIndexes[key] = pkg |
| 126 | + } |
| 127 | + } |
| 128 | +} |
| 129 | + |
| 130 | +func preferPkgPath(currentPath, candidatePath, name, version string) bool { |
| 131 | + currentCanonical := isCanonicalPath(currentPath, name, version) |
| 132 | + candidateCanonical := isCanonicalPath(candidatePath, name, version) |
| 133 | + if currentCanonical != candidateCanonical { |
| 134 | + return candidateCanonical |
112 | 135 | } |
| 136 | + return candidatePath < currentPath |
| 137 | +} |
| 138 | + |
| 139 | +func isCanonicalPath(path, name, version string) bool { |
| 140 | + canonical := "/" + name + "/" + version |
| 141 | + return path == canonical || strings.TrimPrefix(path, "/") == strings.TrimPrefix(canonical, "/") |
113 | 142 | } |
114 | 143 |
|
115 | 144 | func (l *Lockfile) findPkg(name, version string) (p *Pkg) { |
|
0 commit comments