@@ -109,6 +109,7 @@ type resolved struct {
109109 arch string
110110 packages sets.Set [string ]
111111 versions map [string ]string
112+ pinned map [string ]string
112113 provided map [string ]sets.Set [string ]
113114}
114115
@@ -124,21 +125,37 @@ func unify(originals []string, inputs []resolved) (map[string][]string, map[stri
124125 originalPackages := resolved {
125126 packages : make (sets.Set [string ], len (originals )),
126127 versions : make (map [string ]string , len (originals )),
128+ pinned : make (map [string ]string , len (originals )),
127129 }
128130
129131 byArch := map [string ][]string {}
130132
131133 for _ , orig := range originals {
132134 name := orig
135+ version := ""
136+ pinned := ""
137+
133138 // The function we want from go-apk is private, but these are all the
134139 // special characters that delimit the package name from the cosntraint
135140 // so lop off the package name and stick the rest of the constraint into
136141 // the versions map.
137142 if idx := strings .IndexAny (orig , "=<>~" ); idx >= 0 {
138143 name = orig [:idx ]
144+ version = orig [idx :]
145+ }
146+
147+ // Extract pinned version if present
148+ if idx := strings .IndexAny (orig , "@" ); idx >= 0 {
149+ pinned = orig [idx :]
139150 }
151+
152+ // Remove pinned suffix from name and version
153+ name = strings .TrimSuffix (name , pinned )
154+ version = strings .TrimSuffix (version , pinned )
155+
140156 originalPackages .packages .Insert (name )
141- originalPackages .versions [name ] = strings .TrimPrefix (orig , name )
157+ originalPackages .versions [name ] = version
158+ originalPackages .pinned [name ] = pinned
142159 }
143160
144161 // Start accumulating using the first entry, and unify it with the other
@@ -226,7 +243,11 @@ func unify(originals []string, inputs []resolved) (map[string][]string, map[stri
226243 // package constraint including the operator.
227244 for _ , pkg := range sets .List (missing ) {
228245 if ver := originalPackages .versions [pkg ]; ver != "" {
229- pl = append (pl , fmt .Sprintf ("%s%s" , pkg , ver ))
246+ if pin := originalPackages .versions [pkg ]; pin != "" {
247+ pl = append (pl , fmt .Sprintf ("%s%s%s" , pkg , ver , pin ))
248+ } else {
249+ pl = append (pl , fmt .Sprintf ("%s%s" , pkg , ver ))
250+ }
230251 } else {
231252 pl = append (pl , pkg )
232253 }
@@ -235,7 +256,11 @@ func unify(originals []string, inputs []resolved) (map[string][]string, map[stri
235256 // Append all of the resolved and unified packages with an exact match
236257 // based on the resolved version we found.
237258 for _ , pkg := range sets .List (acc .packages ) {
238- pl = append (pl , fmt .Sprintf ("%s=%s" , pkg , acc .versions [pkg ]))
259+ pkgName := fmt .Sprintf ("%s=%s" , pkg , acc .versions [pkg ])
260+ if pin := originalPackages .pinned [pkg ]; pin != "" {
261+ pkgName = fmt .Sprintf ("%s%s" , pkgName , pin )
262+ }
263+ pl = append (pl , pkgName )
239264 }
240265 // Sort the package list explicitly with the `=` included.
241266 // This is because (foo, foo-bar) sorts differently than (foo=1, foo-bar=1)
@@ -249,7 +274,11 @@ func unify(originals []string, inputs []resolved) (map[string][]string, map[stri
249274 for _ , input := range inputs {
250275 pl := make ([]string , 0 , len (input .packages ))
251276 for _ , pkg := range sets .List (input .packages ) {
252- pl = append (pl , fmt .Sprintf ("%s=%s" , pkg , input .versions [pkg ]))
277+ pkgName := fmt .Sprintf ("%s=%s" , pkg , input .versions [pkg ])
278+ if pin := originalPackages .pinned [pkg ]; pin != "" {
279+ pkgName = fmt .Sprintf ("%s%s" , pkgName , pin )
280+ }
281+ pl = append (pl , pkgName )
253282 }
254283 // Sort the package list explicitly with the `=` included.
255284 // This is because (foo, foo-bar) sorts differently than (foo=1, foo-bar=1)
0 commit comments