@@ -83,20 +83,38 @@ func (p *Pkg) adjustByPath(path string) {
8383 if p .Name != "" && p .Version != "" {
8484 return
8585 }
86- var underscore = strings .LastIndex (path , "_" )
87- if underscore > - 1 {
88- path = path [:underscore ]
89- }
90- var i = strings .LastIndex (path , "/" )
91- if i == - 1 {
86+ name , version , ok := parseNameVersionFromPackagePath (path )
87+ if ! ok {
9288 return
9389 }
9490 if p .Name == "" {
95- p .Name = strings . Trim ( path [: i ], "/" )
91+ p .Name = name
9692 }
9793 if p .Version == "" {
98- p .Version = strings .Trim (path [i :], "/" )
94+ p .Version = version
95+ }
96+ }
97+
98+ func parseNameVersionFromPackagePath (path string ) (name , version string , ok bool ) {
99+ trimmed := strings .Trim (path , "/" )
100+ if trimmed == "" {
101+ return "" , "" , false
102+ }
103+ slash := strings .LastIndex (trimmed , "/" )
104+ if slash <= 0 || slash == len (trimmed )- 1 {
105+ return "" , "" , false
106+ }
107+
108+ name = trimmed [:slash ]
109+ versionWithSuffix := trimmed [slash + 1 :]
110+ underscore := strings .Index (versionWithSuffix , "_" )
111+ if underscore >= 0 {
112+ versionWithSuffix = versionWithSuffix [:underscore ]
113+ }
114+ if name == "" || versionWithSuffix == "" {
115+ return "" , "" , false
99116 }
117+ return name , versionWithSuffix , true
100118}
101119
102120func (l * Lockfile ) buildIndexes () {
@@ -111,34 +129,51 @@ func (l *Lockfile) buildIndexes() {
111129 pkg .adjustByPath (path )
112130 }
113131 l .pkgIndexes = make (map [[2 ]string ]* Pkg , len (l .Packages ))
114- indexPaths := make (map [[2 ]string ]string , len (l .Packages ))
115132 for _ , path := range paths {
116133 pkg := l .Packages [path ]
117134 var name , version = pkg .Name , pkg .Version
118135 if name == "" {
119136 continue
120137 }
121138 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
139+ if merged , ok := l . pkgIndexes [key ]; ok {
140+ mergePkg ( merged , pkg )
141+ } else {
142+ l .pkgIndexes [key ] = clonePkg ( pkg )
126143 }
127144 }
128145}
129146
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
147+ func clonePkg ( pkg * Pkg ) * Pkg {
148+ out := & Pkg {
149+ Name : pkg . Name ,
150+ Version : pkg . Version ,
151+ Dev : pkg . Dev ,
135152 }
136- return candidatePath < currentPath
153+ if len (pkg .Dependencies ) == 0 {
154+ return out
155+ }
156+ out .Dependencies = make (map [string ]string , len (pkg .Dependencies ))
157+ for n , v := range pkg .Dependencies {
158+ out .Dependencies [n ] = v
159+ }
160+ return out
137161}
138162
139- func isCanonicalPath (path , name , version string ) bool {
140- canonical := "/" + name + "/" + version
141- return path == canonical || strings .TrimPrefix (path , "/" ) == strings .TrimPrefix (canonical , "/" )
163+ func mergePkg (merged , pkg * Pkg ) {
164+ // If any context is non-dev, keep the merged node as non-dev.
165+ merged .Dev = merged .Dev && pkg .Dev
166+ if len (pkg .Dependencies ) == 0 {
167+ return
168+ }
169+ if merged .Dependencies == nil {
170+ merged .Dependencies = make (map [string ]string , len (pkg .Dependencies ))
171+ }
172+ for n , v := range pkg .Dependencies {
173+ if _ , exists := merged .Dependencies [n ]; ! exists {
174+ merged .Dependencies [n ] = v
175+ }
176+ }
142177}
143178
144179func (l * Lockfile ) findPkg (name , version string ) (p * Pkg ) {
0 commit comments