add apt gestion
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
274ea454dd
commit
c4776d81dd
22 changed files with 1465 additions and 163 deletions
128
internal/clone/apt/packages.go
Normal file
128
internal/clone/apt/packages.go
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
package apt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// DebPackage represents a single stanza from a Debian Packages file.
|
||||
type DebPackage struct {
|
||||
Package string
|
||||
Version string
|
||||
Architecture string
|
||||
Filename string // relative path, e.g. pool/main/c/curl/curl_7.88_amd64.deb
|
||||
SHA256 string
|
||||
Size int64
|
||||
Raw []byte // original stanza bytes for faithful re-emission
|
||||
}
|
||||
|
||||
// ParsePackages parses all stanzas from a Debian Packages control file.
|
||||
// Stanzas are separated by blank lines.
|
||||
func ParsePackages(data []byte) ([]DebPackage, error) {
|
||||
// Normalise line endings.
|
||||
data = bytes.ReplaceAll(data, []byte("\r\n"), []byte("\n"))
|
||||
|
||||
var pkgs []DebPackage
|
||||
stanzas := bytes.Split(data, []byte("\n\n"))
|
||||
|
||||
for _, stanza := range stanzas {
|
||||
stanza = bytes.TrimSpace(stanza)
|
||||
if len(stanza) == 0 {
|
||||
continue
|
||||
}
|
||||
pkg, err := parseStanza(stanza)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse stanza: %w", err)
|
||||
}
|
||||
pkgs = append(pkgs, pkg)
|
||||
}
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
func parseStanza(stanza []byte) (DebPackage, error) {
|
||||
var pkg DebPackage
|
||||
pkg.Raw = stanza
|
||||
|
||||
lines := bytes.Split(stanza, []byte("\n"))
|
||||
for _, rawLine := range lines {
|
||||
line := bytes.TrimRight(rawLine, " \t")
|
||||
// Continuation lines (description body etc.) start with a space — skip.
|
||||
if len(line) == 0 || line[0] == ' ' || line[0] == '\t' {
|
||||
continue
|
||||
}
|
||||
|
||||
colonIdx := bytes.IndexByte(line, ':')
|
||||
if colonIdx < 0 {
|
||||
continue
|
||||
}
|
||||
key := string(bytes.TrimSpace(line[:colonIdx]))
|
||||
value := string(bytes.TrimSpace(line[colonIdx+1:]))
|
||||
|
||||
switch key {
|
||||
case "Package":
|
||||
pkg.Package = value
|
||||
case "Version":
|
||||
pkg.Version = value
|
||||
case "Architecture":
|
||||
pkg.Architecture = value
|
||||
case "Filename":
|
||||
pkg.Filename = value
|
||||
case "SHA256":
|
||||
pkg.SHA256 = value
|
||||
case "Size":
|
||||
n, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return DebPackage{}, fmt.Errorf("bad Size value %q: %w", value, err)
|
||||
}
|
||||
pkg.Size = n
|
||||
}
|
||||
}
|
||||
|
||||
if pkg.Package == "" {
|
||||
return DebPackage{}, fmt.Errorf("stanza missing Package field")
|
||||
}
|
||||
return pkg, nil
|
||||
}
|
||||
|
||||
// FilterPackages returns only the packages for which presentOnDisk returns true.
|
||||
func FilterPackages(pkgs []DebPackage, presentOnDisk func(filename string) bool) []DebPackage {
|
||||
var out []DebPackage
|
||||
for _, p := range pkgs {
|
||||
if presentOnDisk(p.Filename) {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// emitPackages serialises a slice of DebPackage back to Packages-file format,
|
||||
// using the original Raw bytes for each stanza.
|
||||
func emitPackages(pkgs []DebPackage) []byte {
|
||||
var buf bytes.Buffer
|
||||
for i, pkg := range pkgs {
|
||||
// Strip trailing whitespace from each line within the stanza.
|
||||
lines := bytes.Split(pkg.Raw, []byte("\n"))
|
||||
for j, l := range lines {
|
||||
lines[j] = bytes.TrimRight(l, " \t")
|
||||
}
|
||||
buf.Write(bytes.Join(lines, []byte("\n")))
|
||||
if i < len(pkgs)-1 {
|
||||
buf.WriteString("\n\n")
|
||||
} else {
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// diskPresenceChecker returns a presentOnDisk func rooted at localDir.
|
||||
func diskPresenceChecker(localDir string) func(string) bool {
|
||||
return func(filename string) bool {
|
||||
p := filepath.Join(localDir, filepath.FromSlash(filename))
|
||||
_, err := os.Stat(p)
|
||||
return err == nil
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue