Skip to content

Commit 5bc2b5f

Browse files
committed
fix(pnpm/v5): make package index selection deterministic
1 parent ec44f44 commit 5bc2b5f

File tree

1 file changed

+34
-5
lines changed

1 file changed

+34
-5
lines changed

module/pnpm/v5/v5.go

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package v5
22

33
import (
4-
"github.com/murphysecurity/murphysec/model"
5-
"github.com/murphysecurity/murphysec/module/pnpm/shared"
64
"sort"
75
"strings"
6+
7+
"github.com/murphysecurity/murphysec/model"
8+
"github.com/murphysecurity/murphysec/module/pnpm/shared"
89
)
910

1011
type Pkg struct {
@@ -99,17 +100,45 @@ func (p *Pkg) adjustByPath(path string) {
99100
}
100101

101102
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]
103111
pkg.adjustByPath(path)
104112
}
105113
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]
107117
var name, version = pkg.Name, pkg.Version
108118
if name == "" {
109119
continue
110120
}
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
112135
}
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, "/")
113142
}
114143

115144
func (l *Lockfile) findPkg(name, version string) (p *Pkg) {

0 commit comments

Comments
 (0)