xtool/cppkg: InstallPkg KnownLatestVersion
This commit is contained in:
@@ -18,6 +18,7 @@ package cppkg
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -30,6 +31,7 @@ import (
|
|||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/goplus/llgo/internal/github"
|
"github.com/goplus/llgo/internal/github"
|
||||||
|
"github.com/qiniu/x/byteutil"
|
||||||
"github.com/qiniu/x/httputil"
|
"github.com/qiniu/x/httputil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -98,9 +100,9 @@ func getRelease(pkg *Package, tagPattern string) (ret *githubRelease, err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Install installs the specified package using Conan.
|
// Install installs the specified package using Conan.
|
||||||
func (p *Manager) Install(pkg *Package, flags int) (err error) {
|
func (p *Manager) Install(pkg *Package, options []string, flags int) (buildDir string, err error) {
|
||||||
outDir := p.outDir(pkg)
|
buildDir = p.BuildDir(pkg, options)
|
||||||
os.MkdirAll(outDir, os.ModePerm)
|
os.MkdirAll(buildDir, os.ModePerm)
|
||||||
|
|
||||||
var rev string
|
var rev string
|
||||||
var gr *githubRelease
|
var gr *githubRelease
|
||||||
@@ -115,17 +117,17 @@ func (p *Manager) Install(pkg *Package, flags int) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = copyDirR(conanfileDir, outDir)
|
err = copyDirR(conanfileDir, buildDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conanfilePy, err = os.ReadFile(outDir + "/conanfile.py")
|
conanfilePy, err = os.ReadFile(buildDir + "/conanfile.py")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conandataFile := outDir + "/conandata.yml"
|
conandataFile := buildDir + "/conandata.yml"
|
||||||
conandataYml, err = os.ReadFile(conandataFile)
|
conandataYml, err = os.ReadFile(conandataFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -138,7 +140,7 @@ func (p *Manager) Install(pkg *Package, flags int) (err error) {
|
|||||||
fromVer := template.FromVer
|
fromVer := template.FromVer
|
||||||
source, ok := cd.Sources[fromVer]
|
source, ok := cd.Sources[fromVer]
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrVersionNotFound
|
return "", ErrVersionNotFound
|
||||||
}
|
}
|
||||||
cd.Sources = map[string]any{
|
cd.Sources = map[string]any{
|
||||||
pkgVer: replaceVer(source, fromVer, pkgVer),
|
pkgVer: replaceVer(source, fromVer, pkgVer),
|
||||||
@@ -152,10 +154,10 @@ func (p *Manager) Install(pkg *Package, flags int) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
rev = recipeRevision(pkg, gr, conandataYml)
|
rev = recipeRevision(pkg, gr, conandataYml)
|
||||||
conanfileDir = outDir
|
conanfileDir = buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
outFile := outDir + "/out.json"
|
outFile := buildDir + "/out.json"
|
||||||
out, err := os.Create(outFile)
|
out, err := os.Create(outFile)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
defer out.Close()
|
defer out.Close()
|
||||||
@@ -165,15 +167,16 @@ func (p *Manager) Install(pkg *Package, flags int) (err error) {
|
|||||||
|
|
||||||
nameAndVer := pkg.Name + "/" + pkgVer
|
nameAndVer := pkg.Name + "/" + pkgVer
|
||||||
if template == nil {
|
if template == nil {
|
||||||
return conanInstall(nameAndVer, outDir, conanfileDir, out, flags)
|
err = conanInstall(nameAndVer, buildDir, conanfileDir, out, options, flags)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logFile := ""
|
logFile := ""
|
||||||
if flags&LogRevertProxy != 0 {
|
if flags&LogRevertProxy != 0 {
|
||||||
logFile = outDir + "/rp.log"
|
logFile = buildDir + "/rp.log"
|
||||||
}
|
}
|
||||||
return remoteProxy(flags, logFile, func() error {
|
err = remoteProxy(flags, logFile, func() error {
|
||||||
return conanInstall(nameAndVer, outDir, conanfileDir, out, flags)
|
return conanInstall(nameAndVer, buildDir, conanfileDir, out, options, flags)
|
||||||
}, func(mux *http.ServeMux) {
|
}, func(mux *http.ServeMux) {
|
||||||
base := "/v2/conans/" + nameAndVer
|
base := "/v2/conans/" + nameAndVer
|
||||||
revbase := base + "/_/_/revisions/" + rev
|
revbase := base + "/_/_/revisions/" + rev
|
||||||
@@ -217,7 +220,7 @@ func (p *Manager) Install(pkg *Package, flags int) (err error) {
|
|||||||
httputil.ReplyWithStream(w, http.StatusOK, "text/plain", strings.NewReader(data), int64(len(data)))
|
httputil.ReplyWithStream(w, http.StatusOK, "text/plain", strings.NewReader(data), int64(len(data)))
|
||||||
})
|
})
|
||||||
mux.HandleFunc(revbase+"/files/conan_export.tgz", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc(revbase+"/files/conan_export.tgz", func(w http.ResponseWriter, r *http.Request) {
|
||||||
conanExportTgz, err := tgzOfConandata(outDir)
|
conanExportTgz, err := tgzOfConandata(buildDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
replyError(w, err)
|
replyError(w, err)
|
||||||
return
|
return
|
||||||
@@ -228,19 +231,31 @@ func (p *Manager) Install(pkg *Package, flags int) (err error) {
|
|||||||
httputil.ReplyWith(w, http.StatusOK, "application/x-gzip", conanExportTgz)
|
httputil.ReplyWith(w, http.StatusOK, "application/x-gzip", conanExportTgz)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Manager) outDir(pkg *Package) string {
|
func (p *Manager) BuildDir(pkg *Package, options []string) string {
|
||||||
return p.cacheDir + "/build/" + pkg.Name + "@" + pkg.Version
|
dir := p.cacheDir + "/build/" + pkg.Name + "@" + pkg.Version
|
||||||
|
if options != nil {
|
||||||
|
h := md5.New()
|
||||||
|
for _, opt := range options {
|
||||||
|
h.Write(byteutil.Bytes(opt))
|
||||||
|
}
|
||||||
|
hash := base64.RawURLEncoding.EncodeToString(h.Sum(nil))
|
||||||
|
dir += "/" + hash
|
||||||
|
} else {
|
||||||
|
dir += "/static"
|
||||||
|
}
|
||||||
|
return dir
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Manager) conanfileDir(pkgPath, pkgFolder string) string {
|
func (p *Manager) conanfileDir(pkgPath, pkgFolder string) string {
|
||||||
root := p.indexRoot()
|
root := p.IndexRoot()
|
||||||
return root + "/" + pkgPath + "/" + pkgFolder
|
return root + "/" + pkgPath + "/" + pkgFolder
|
||||||
}
|
}
|
||||||
|
|
||||||
func conanInstall(pkg, outDir, conanfileDir string, out io.Writer, flags int) (err error) {
|
func conanInstall(pkg, outDir, conanfileDir string, out io.Writer, options []string, flags int) (err error) {
|
||||||
args := make([]string, 0, 12)
|
args := make([]string, 0, 16)
|
||||||
args = append(args, "install",
|
args = append(args, "install",
|
||||||
"--requires", pkg,
|
"--requires", pkg,
|
||||||
"--generator", "PkgConfigDeps",
|
"--generator", "PkgConfigDeps",
|
||||||
@@ -248,6 +263,9 @@ func conanInstall(pkg, outDir, conanfileDir string, out io.Writer, flags int) (e
|
|||||||
"--format", "json",
|
"--format", "json",
|
||||||
"--output-folder", outDir,
|
"--output-folder", outDir,
|
||||||
)
|
)
|
||||||
|
for _, opt := range options {
|
||||||
|
args = append(args, "--options", opt)
|
||||||
|
}
|
||||||
quietInstall := flags&ToolQuietInstall != 0
|
quietInstall := flags&ToolQuietInstall != 0
|
||||||
cmd, err := conanCmd.New(quietInstall, args...)
|
cmd, err := conanCmd.New(quietInstall, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -29,15 +29,21 @@ const (
|
|||||||
// pkgAndVer: 7bitcoder/7bitconf@1.2.0
|
// pkgAndVer: 7bitcoder/7bitconf@1.2.0
|
||||||
func Install(pkgAndVer string, flags int) {
|
func Install(pkgAndVer string, flags int) {
|
||||||
pkgPath, ver := parsePkgVer(pkgAndVer)
|
pkgPath, ver := parsePkgVer(pkgAndVer)
|
||||||
|
_, _, err := InstallPkg(pkgPath, ver, nil, flags)
|
||||||
|
check(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstallPkg installs a package with the given package path and version.
|
||||||
|
func InstallPkg(pkgPath, ver string, options []string, flags int) (pkg *Package, buildDir string, err error) {
|
||||||
m, err := New("")
|
m, err := New("")
|
||||||
check(err)
|
if err != nil {
|
||||||
|
return
|
||||||
pkg, err := m.Lookup(pkgPath, ver, flags)
|
}
|
||||||
check(err)
|
pkg, err = m.Lookup(pkgPath, ver, flags)
|
||||||
|
if err == nil {
|
||||||
err = m.Install(pkg, flags)
|
buildDir, err = m.Install(pkg, options, flags)
|
||||||
check(err)
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePkgVer(pkg string) (string, string) {
|
func parsePkgVer(pkg string) (string, string) {
|
||||||
|
|||||||
@@ -36,13 +36,10 @@ type Manager struct {
|
|||||||
cacheDir string
|
cacheDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New creates a new package manager.
|
||||||
func New(cacheDir string) (ret *Manager, err error) {
|
func New(cacheDir string) (ret *Manager, err error) {
|
||||||
if cacheDir == "" {
|
if cacheDir == "" {
|
||||||
cacheDir, err = os.UserCacheDir()
|
cacheDir = CacheDir()
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cacheDir += "/cppkg"
|
|
||||||
}
|
}
|
||||||
os.MkdirAll(cacheDir, os.ModePerm)
|
os.MkdirAll(cacheDir, os.ModePerm)
|
||||||
ret = &Manager{
|
ret = &Manager{
|
||||||
@@ -51,6 +48,15 @@ func New(cacheDir string) (ret *Manager, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheDir returns the cache directory to manage C/C++ packages.
|
||||||
|
func CacheDir() string {
|
||||||
|
cacheDir, err := os.UserCacheDir()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return cacheDir + "/cppkg"
|
||||||
|
}
|
||||||
|
|
||||||
type version struct {
|
type version struct {
|
||||||
Folder string `yaml:"folder"`
|
Folder string `yaml:"folder"`
|
||||||
}
|
}
|
||||||
@@ -68,6 +74,17 @@ type config struct {
|
|||||||
Template Template `yaml:"template"`
|
Template Template `yaml:"template"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getKnownLatestVer returns the latest known version and its details.
|
||||||
|
// It returns empty version if no known version is found.
|
||||||
|
func (p *config) getKnownLatestVer() (ver string, v version) {
|
||||||
|
for ver1, v1 := range p.Versions {
|
||||||
|
if ver == "" || compareVer(ver1, ver) > 0 {
|
||||||
|
ver, v = ver1, v1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Package represents a C/C++ package.
|
// Package represents a C/C++ package.
|
||||||
type Package struct {
|
type Package struct {
|
||||||
Name string
|
Name string
|
||||||
@@ -96,11 +113,14 @@ const (
|
|||||||
|
|
||||||
// LogRevertProxy is a flag to log revert proxy.
|
// LogRevertProxy is a flag to log revert proxy.
|
||||||
LogRevertProxy
|
LogRevertProxy
|
||||||
|
|
||||||
|
// KnownLatestVersion is a flag to use the known latest version.
|
||||||
|
KnownLatestVersion
|
||||||
)
|
)
|
||||||
|
|
||||||
// Lookup looks up a package by its path and version.
|
// Lookup looks up a package by its path and version.
|
||||||
func (p *Manager) Lookup(pkgPath, ver string, flags int) (_ *Package, err error) {
|
func (p *Manager) Lookup(pkgPath, ver string, flags int) (_ *Package, err error) {
|
||||||
root := p.indexRoot()
|
root := p.IndexRoot()
|
||||||
err = indexUpate(root, flags)
|
err = indexUpate(root, flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -118,6 +138,11 @@ func (p *Manager) Lookup(pkgPath, ver string, flags int) (_ *Package, err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ver == "" || ver == "latest" {
|
if ver == "" || ver == "latest" {
|
||||||
|
if flags&KnownLatestVersion != 0 {
|
||||||
|
if ver, v := conf.getKnownLatestVer(); ver != "" {
|
||||||
|
return &Package{conf.PkgName, pkgPath, ver, v.Folder, nil, nil}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
if conf.Template.Tag == "" {
|
if conf.Template.Tag == "" {
|
||||||
return nil, ErrDynamicTag
|
return nil, ErrDynamicTag
|
||||||
}
|
}
|
||||||
@@ -144,7 +169,7 @@ func (p *Manager) Lookup(pkgPath, ver string, flags int) (_ *Package, err error)
|
|||||||
return &Package{conf.PkgName, pkgPath, ver, templ.Folder, &templ, nil}, nil
|
return &Package{conf.PkgName, pkgPath, ver, templ.Folder, &templ, nil}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Manager) indexRoot() string {
|
func (p *Manager) IndexRoot() string {
|
||||||
return p.cacheDir + "/index"
|
return p.cacheDir + "/index"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user