2025-03-03 20:00:50 +00:00
|
|
|
package patchwheel
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2025-03-05 14:49:15 +00:00
|
|
|
"strconv"
|
2025-03-03 20:00:50 +00:00
|
|
|
"strings"
|
2025-03-04 12:08:28 +00:00
|
|
|
"time"
|
2025-03-03 20:00:50 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// WheelInfo contains information extracted from a wheel filename
|
|
|
|
type WheelInfo struct {
|
|
|
|
Distribution string // Package distribution name
|
|
|
|
Version string // Package version
|
2025-03-05 15:20:20 +00:00
|
|
|
Tags []string // [optional build tag,] python_tag, abi_tag, platform_tag
|
2025-03-03 20:00:50 +00:00
|
|
|
}
|
|
|
|
|
2025-03-05 09:51:56 +00:00
|
|
|
// calculateNewVersion generates a new version string and filename based on the wheel info and modification time.
|
2025-03-04 11:27:20 +00:00
|
|
|
// The version is updated according to the following rules:
|
|
|
|
// - if there is an existing part after + it is dropped
|
|
|
|
// - append +<mtime of the original wheel> to version
|
2025-03-05 10:47:20 +00:00
|
|
|
//
|
2025-03-05 15:14:09 +00:00
|
|
|
// Example version transform: "1.2.3" -> "1.2.3+1741091696780123321"
|
2025-03-05 09:51:56 +00:00
|
|
|
func calculateNewVersion(info WheelInfo, mtime time.Time) (newVersion, newFilename string) {
|
2025-03-05 10:45:51 +00:00
|
|
|
baseVersion, _, _ := strings.Cut(info.Version, "+")
|
2025-03-04 12:08:28 +00:00
|
|
|
|
2025-03-05 14:49:15 +00:00
|
|
|
newVersion = baseVersion + "+" + strconv.FormatInt(mtime.UnixNano(), 10)
|
2025-03-04 12:08:28 +00:00
|
|
|
|
2025-03-04 11:27:20 +00:00
|
|
|
newFilename = fmt.Sprintf("%s-%s-%s.whl",
|
|
|
|
info.Distribution,
|
|
|
|
newVersion,
|
|
|
|
strings.Join(info.Tags, "-"))
|
2025-03-04 12:08:28 +00:00
|
|
|
|
2025-03-04 11:27:20 +00:00
|
|
|
return newVersion, newFilename
|
|
|
|
}
|
|
|
|
|
2025-03-03 20:00:50 +00:00
|
|
|
// ParseWheelFilename parses a wheel filename and extracts its components.
|
2025-03-04 16:45:02 +00:00
|
|
|
// Wheel filenames follow the pattern: {distribution}-{version}(-{build tag})?-{python_tag}-{abi_tag}-{platform_tag}.whl
|
2025-03-05 10:50:09 +00:00
|
|
|
// https://peps.python.org/pep-0491
|
2025-03-04 17:07:01 +00:00
|
|
|
func ParseWheelFilename(filename string) (WheelInfo, error) {
|
2025-03-04 10:34:45 +00:00
|
|
|
parts := strings.Split(filename, "-")
|
2025-03-04 10:52:45 +00:00
|
|
|
if len(parts) < 5 {
|
2025-03-04 17:07:01 +00:00
|
|
|
return WheelInfo{}, fmt.Errorf("invalid wheel filename format: not enough parts in %s", filename)
|
2025-03-04 10:52:45 +00:00
|
|
|
}
|
2025-03-04 17:02:18 +00:00
|
|
|
|
|
|
|
if len(parts) > 6 {
|
2025-03-04 17:07:01 +00:00
|
|
|
return WheelInfo{}, fmt.Errorf("invalid wheel filename format: too many parts in %s", filename)
|
2025-03-04 17:02:18 +00:00
|
|
|
}
|
|
|
|
|
2025-03-05 10:50:09 +00:00
|
|
|
trimmedLastTag, foundWhl := strings.CutSuffix(parts[len(parts)-1], ".whl")
|
|
|
|
|
|
|
|
if !foundWhl {
|
2025-03-04 17:07:01 +00:00
|
|
|
return WheelInfo{}, fmt.Errorf("invalid wheel filename format: missing .whl extension in %s", filename)
|
2025-03-03 20:00:50 +00:00
|
|
|
}
|
|
|
|
|
2025-03-05 10:50:09 +00:00
|
|
|
parts[len(parts)-1] = trimmedLastTag
|
2025-03-04 16:48:57 +00:00
|
|
|
|
2025-03-04 17:07:01 +00:00
|
|
|
return WheelInfo{
|
2025-03-04 17:02:18 +00:00
|
|
|
Distribution: parts[0],
|
|
|
|
Version: parts[1],
|
|
|
|
Tags: parts[2:],
|
2025-03-03 20:00:50 +00:00
|
|
|
}, nil
|
|
|
|
}
|