package: xtool/cppkg
This commit is contained in:
160
xtool/cppkg/manager.go
Normal file
160
xtool/cppkg/manager.go
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2025 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cppkg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/goccy/go-yaml"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
var gitCmd = NewTool("git", []string{
|
||||
"brew install git",
|
||||
"apt-get install git",
|
||||
})
|
||||
|
||||
// Manager represents a package manager for C/C++ packages.
|
||||
type Manager struct {
|
||||
cacheDir string
|
||||
}
|
||||
|
||||
func New(cacheDir string) (ret *Manager, err error) {
|
||||
if cacheDir == "" {
|
||||
cacheDir, err = os.UserCacheDir()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cacheDir += "/cppkg"
|
||||
}
|
||||
os.MkdirAll(cacheDir, os.ModePerm)
|
||||
ret = &Manager{
|
||||
cacheDir: cacheDir,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type version struct {
|
||||
Folder string `yaml:"folder"`
|
||||
}
|
||||
|
||||
// Template represents a template for package versions.
|
||||
type Template struct {
|
||||
FromVer string `yaml:"from"`
|
||||
Folder string `yaml:"folder"`
|
||||
Tag string `yaml:"tag,omitempty"` // pattern with *, empty if dynamic tag
|
||||
}
|
||||
|
||||
type config struct {
|
||||
PkgName string `yaml:"name"`
|
||||
Versions map[string]version `yaml:"versions"`
|
||||
Template Template `yaml:"template"`
|
||||
}
|
||||
|
||||
// Package represents a C/C++ package.
|
||||
type Package struct {
|
||||
Name string
|
||||
Path string
|
||||
Version string
|
||||
Folder string
|
||||
Template *Template
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrVersionNotFound is returned when the specified version is not found.
|
||||
ErrVersionNotFound = errors.New("version not found")
|
||||
)
|
||||
|
||||
const (
|
||||
// IndexAutoUpdate is a flag to automatically update the index.
|
||||
IndexAutoUpdate = 1 << iota
|
||||
|
||||
// ToolQuietInstall is a flag to suppress output during installation.
|
||||
ToolQuietInstall
|
||||
|
||||
// LogRevertProxy is a flag to log revert proxy.
|
||||
LogRevertProxy
|
||||
)
|
||||
|
||||
// Lookup looks up a package by its path and version.
|
||||
func (p *Manager) Lookup(pkgPath, ver string, flags int) (_ *Package, err error) {
|
||||
root := p.indexRoot()
|
||||
err = indexUpate(root, flags)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pkgDir := root + "/" + pkgPath
|
||||
confFile := pkgDir + "/config.yml"
|
||||
b, err := os.ReadFile(confFile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var conf config
|
||||
err = yaml.Unmarshal(b, &conf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v, ok := conf.Versions[ver]; ok {
|
||||
return &Package{conf.PkgName, pkgPath, ver, v.Folder, nil}, nil
|
||||
}
|
||||
if compareVer(ver, conf.Template.FromVer) < 0 {
|
||||
err = ErrVersionNotFound
|
||||
return
|
||||
}
|
||||
folder := conf.Template.Folder
|
||||
return &Package{conf.PkgName, pkgPath, ver, folder, &conf.Template}, nil
|
||||
}
|
||||
|
||||
func (p *Manager) indexRoot() string {
|
||||
return p.cacheDir + "/index"
|
||||
}
|
||||
|
||||
func indexUpate(root string, flags int) (err error) {
|
||||
if _, err = os.Stat(root + "/.git"); os.IsNotExist(err) {
|
||||
os.RemoveAll(root)
|
||||
return indexInit(root, flags)
|
||||
}
|
||||
if flags&IndexAutoUpdate != 0 {
|
||||
quietInstall := flags&ToolQuietInstall != 0
|
||||
git, e := gitCmd.New(quietInstall, "pull", "--ff-only", "origin", "main")
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
git.Dir = root
|
||||
git.Stdout = os.Stdout
|
||||
git.Stderr = os.Stderr
|
||||
err = git.Run()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func indexInit(root string, flags int) (err error) {
|
||||
quietInstall := flags&ToolQuietInstall != 0
|
||||
git, err := gitCmd.New(quietInstall, "clone", "https://github.com/goplus/cppkg.git", root)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
git.Stdout = os.Stdout
|
||||
git.Stderr = os.Stderr
|
||||
err = git.Run()
|
||||
return
|
||||
}
|
||||
|
||||
func compareVer(v1, v2 string) int {
|
||||
return semver.Compare("v"+v1, "v"+v2)
|
||||
}
|
||||
Reference in New Issue
Block a user