All checks were successful
Golang test / go-test (push) Successful in 23s
Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
package apt
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"iter"
|
|
"net/http"
|
|
"net/url"
|
|
"path"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"sirherobrine23.com.br/sirherobrine23/go-dpkg/deb822"
|
|
"sirherobrine23.com.br/sirherobrine23/go-dpkg/dpkg"
|
|
"sirherobrine23.com.br/sirherobrine23/go-dpkg/internal/descompress"
|
|
)
|
|
|
|
// ReleaseSum represents a mapping from a string key (such as a file name or section name)
|
|
// to a slice of Sum values, where each Sum contains checksum information for the corresponding entry.
|
|
// This is typically used to store and organize checksums for files listed in an APT Release file.
|
|
type ReleaseSum map[string][]Sum
|
|
|
|
// Files sum from Release
|
|
type Sum struct {
|
|
File string
|
|
Hash string
|
|
Size int64
|
|
}
|
|
|
|
// SumLines parses a string containing multiple checksum lines (typically from a Debian Release file)
|
|
// and returns a ReleaseSum map containing the parsed sums. Each line is expected to contain a hash, a size,
|
|
// and a filename, separated by spaces. The function splits each line, extracts the hash, size, and file name,
|
|
// and appends the result to the ReleaseSum map keyed by the file name without its extension.
|
|
// Returns an error if any size value cannot be parsed as an integer.
|
|
func SumLines(data string) (ReleaseSum, error) {
|
|
sums := ReleaseSum{}
|
|
|
|
for name := range deb822.ToSlice(data) {
|
|
hash := name[:strings.Index(name, " ")]
|
|
name = strings.TrimSpace(name[len(hash):])
|
|
|
|
sizeStr := name[:strings.Index(name, " ")]
|
|
name = strings.TrimSpace(name[len(sizeStr):])
|
|
size, err := strconv.ParseInt(sizeStr, 10, 64)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ext := path.Ext(name)
|
|
mapText := name[:len(name)-len(ext)]
|
|
sums[mapText] = append(sums[mapText], Sum{
|
|
Hash: hash,
|
|
Size: size,
|
|
File: name,
|
|
})
|
|
}
|
|
return sums, nil
|
|
}
|
|
|
|
func (sum Sum) IsBinaryPackage() bool {
|
|
if strings.ToLower(path.Base(sum.File[:len(sum.File)-len(path.Ext(sum.File))])) == "packages" {
|
|
nodes := strings.Split(sum.File, "/")
|
|
if len(nodes) == 3 && strings.HasPrefix(nodes[1], "binary-") {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Return packages from sum file
|
|
func (sum Sum) Pkgs(SuiteName string, AptSrc *AptSource) iter.Seq2[*dpkg.Package, error] {
|
|
return func(yield func(*dpkg.Package, error) bool) {
|
|
if !sum.IsBinaryPackage() {
|
|
yield(nil, fmt.Errorf("this sum require have Package last element"))
|
|
return
|
|
}
|
|
|
|
r, metaIndex, metaURI := io.Reader(nil), 0, (*url.URL)(nil)
|
|
for metaIndex, metaURI = range AptSrc.URIs {
|
|
metaURI = metaURI.ResolveReference(&url.URL{Path: path.Join(metaURI.Path, "dists", SuiteName, sum.File)})
|
|
res, err := http.Get(metaURI.String())
|
|
if err != nil {
|
|
yield(nil, err)
|
|
return
|
|
} else if res.StatusCode != 200 {
|
|
if metaIndex == len(AptSrc.URIs)-1 {
|
|
yield(nil, (*HttpError)(res))
|
|
return
|
|
}
|
|
continue
|
|
}
|
|
defer res.Body.Close()
|
|
if r, err = descompress.Descompress(res.Body); err != nil {
|
|
yield(nil, fmt.Errorf("cannot descompress body: %s", err))
|
|
return
|
|
}
|
|
}
|
|
|
|
if metaURI == nil {
|
|
yield(nil, fmt.Errorf("cannot get Packages file"))
|
|
return
|
|
}
|
|
|
|
pkgReader := deb822.NewReader(r)
|
|
for {
|
|
pkgData, err := pkgReader.Deb822()
|
|
switch err {
|
|
case deb822.ErrNextDeb822:
|
|
continue
|
|
case io.EOF:
|
|
return
|
|
case nil:
|
|
pkg := &dpkg.Package{}
|
|
err = pkg.FromMap(pkgData)
|
|
if !yield(pkg, err) {
|
|
return
|
|
}
|
|
default:
|
|
yield(nil, err)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|