deb-simple/packages.go

249 lines
4.7 KiB
Go
Raw Normal View History

2018-10-14 08:17:04 +00:00
package main
import (
"regexp"
"fmt"
"strings"
"os"
"bytes"
"bufio"
"compress/gzip"
"encoding/hex"
"io"
"io/ioutil"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"github.com/blang/semver"
2017-06-12 00:41:49 +00:00
"encoding/json"
2018-10-14 08:14:17 +00:00
"gitea.meow.tf/deb-simple/deb/archive"
"path"
)
var (
variableRegexp = regexp.MustCompile("(.*?):\\s*(.*)")
)
type PackageFile struct {
2017-06-12 00:41:49 +00:00
Path string `json:"path"`
Name string `json:"name"`
Size int64 `json:"size"`
MD5Hash string `json:"md5"`
SHA1Hash string `json:"sha1"`
SHA256Hash string `json:"sha256"`
ControlData string `json:"control"`
Info *Package `json:"info"`
}
type Package struct {
2017-06-12 00:41:49 +00:00
Package string `json:"package"`
Version string `json:"version"`
Architecture string `json:"architecture"`
}
func parsePackageData(ctlData string) *Package {
res := &Package{}
for _, match := range variableRegexp.FindAllStringSubmatch(ctlData, -1) {
switch match[1] {
case "Package":
res.Package = match[2]
case "Architecture":
res.Architecture = match[2]
case "Version":
res.Version = match[2]
}
}
return res
}
type Distro struct {
2017-06-12 00:41:49 +00:00
Name string `json:"name"`
Architectures map[string]map[string]*PackageFile `json:"architectures"`
}
var (
distros map[string]*Distro = make(map[string]*Distro)
)
2017-06-12 00:41:49 +00:00
func loadCache(dist string) error {
f, err := os.Open(path.Join(conf.DistPath(dist), "dist.json"))
2017-06-12 00:41:49 +00:00
if err != nil {
return err
}
defer f.Close()
var distro Distro
if err := json.NewDecoder(f).Decode(&distro); err != nil {
return err
}
distros[dist] = &distro
return nil
}
func saveCache(dist *Distro) error {
f, err := os.Create(path.Join(conf.DistPath(dist.Name), "dist.json"))
2017-06-12 00:41:49 +00:00
if err != nil {
return err
}
defer f.Close()
if err := json.NewEncoder(f).Encode(dist); err != nil {
return err
}
return nil
}
func buildPackageList(config Conf, distro, arch string) (map[string]*PackageFile, error) {
m := make(map[string]*PackageFile)
if err := scanRecursive(config.PoolPath(distro, arch), m); err != nil {
return nil, err
}
return m, nil
}
func scanRecursive(base string, m map[string]*PackageFile) error {
dirList, err := ioutil.ReadDir(base)
if err != nil {
return err
}
for _, file := range dirList {
if file.IsDir() {
if err := scanRecursive(path.Join(base, file.Name()), m); err != nil {
return err
}
continue
}
if !strings.HasSuffix(file.Name(), "deb") {
continue
}
2017-09-14 03:57:03 +00:00
p, err := newPackageFile(path.Join(base, file.Name()))
if err != nil {
return err
}
if old, exists := m[p.Info.Package]; exists {
v1, err := semver.Parse(old.Info.Version)
v2, err2 := semver.Parse(p.Info.Version)
if err == nil && err2 == nil && v1.Compare(v2) > 0 {
// Use old version
continue
}
}
m[p.Info.Package] = p
}
return nil
}
2017-09-14 03:57:03 +00:00
func newPackageFile(filePath string) (*PackageFile, error) {
p := &PackageFile{
2017-09-14 03:57:03 +00:00
Name: path.Base(filePath),
Path: stripPrefix(filePath, conf.Repo.Root),
}
var err error
2017-09-14 03:57:03 +00:00
p.ControlData, err = archive.InspectPackage(filePath)
if err != nil {
return nil, err
}
p.Info = parsePackageData(p.ControlData)
2017-09-14 03:57:03 +00:00
if stat, err := os.Stat(filePath); err == nil {
p.Size = stat.Size()
}
2017-09-14 03:57:03 +00:00
f, err := os.Open(filePath)
if err != nil {
return nil, err
}
2017-09-14 04:23:39 +00:00
defer f.Close()
var (
md5hash = md5.New()
sha1hash = sha1.New()
sha256hash = sha256.New()
)
w := io.MultiWriter(md5hash, sha1hash, sha256hash)
if _, err := io.Copy(w, f); err != nil {
return nil, err
}
p.MD5Hash = hex.EncodeToString(md5hash.Sum(nil))
p.SHA1Hash = hex.EncodeToString(sha1hash.Sum(nil))
p.SHA256Hash = hex.EncodeToString(sha256hash.Sum(nil))
return p, nil
}
func createPackagesCached(config Conf, distro, arch string, packages map[string]*PackageFile) error {
stdFile, err := os.Create(path.Join(config.ArchPath(distro, arch), "Packages"))
if err != nil {
return fmt.Errorf("failed to create packages: %s", err)
}
defer stdFile.Close()
gzipFile, err := os.Create(path.Join(config.ArchPath(distro, arch), "Packages.gz"))
if err != nil {
return fmt.Errorf("failed to create packages.gz: %s", err)
}
defer gzipFile.Close()
gzWriter := gzip.NewWriter(gzipFile)
defer gzWriter.Close()
stdOut := bufio.NewWriter(stdFile)
// loop through each directory
// run inspectPackage
for _, p := range packages {
var packBuf bytes.Buffer
packBuf.WriteString(p.ControlData)
dir := path.Join("pool/main", distro, arch, p.Info.Package[0:1], p.Info.Package, p.Name)
fmt.Fprintf(&packBuf, "Filename: %s\n", dir)
fmt.Fprintf(&packBuf, "Size: %d\n", p.Size)
fmt.Fprintf(&packBuf, "MD5sum: %s\n", p.MD5Hash)
fmt.Fprintf(&packBuf, "SHA1: %s\n", p.SHA1Hash)
fmt.Fprintf(&packBuf, "SHA256: %s\n", p.SHA256Hash)
packBuf.WriteString("\n\n")
stdOut.Write(packBuf.Bytes())
gzWriter.Write(packBuf.Bytes())
}
stdOut.Flush()
gzWriter.Flush()
return nil
}