Arch Linux helpers and parsers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

199 lines
4.6 KiB

package archlinux
import (
"bufio"
"fmt"
"io"
"net/url"
"strconv"
"strings"
"time"
)
// ReadPackageInfo reads a package description from a .PKGINFO file
func ReadPackageInfo(r io.Reader) (*Package, error) {
pkg := new(Package)
if n, ok := r.(namer); ok {
pkg.Filename = n.Name()
}
if err := pkg.readPackageInfo(r); err != nil {
return nil, err
}
if pkg.Name == "" {
return nil, ErrNoPackageName
}
if pkg.Version == "" {
return nil, ErrNoPackageVersion
}
if pkg.Release == "" {
return nil, ErrNoPackageRelease
}
return pkg, nil
}
func (pkg *Package) readBuildInfo(r io.Reader) (err error) {
s := bufio.NewScanner(r)
for s.Scan() {
if err = s.Err(); err != nil {
if err == io.EOF {
err = nil
}
break
}
fields := strings.SplitN(s.Text(), " = ", 2)
if len(fields) != 2 {
continue
}
switch fields[0] {
case "buildenv":
pkg.BuildEnv = append(pkg.BuildEnv, fields[1])
case "options":
pkg.Options = append(pkg.Options, fields[1])
}
}
return
}
func (pkg *Package) readPackageInfo(r io.Reader) (err error) {
s := bufio.NewScanner(r)
for s.Scan() {
if err = s.Err(); err != nil {
if err == io.EOF {
err = nil
}
break
}
fields := strings.SplitN(s.Text(), " = ", 2)
if len(fields) != 2 {
continue
}
switch fields[0] {
case "pkgname":
pkg.Name = fields[1]
case "pkgbase":
pkg.Base = fields[1]
case "pkgver":
if i := strings.IndexByte(fields[1], '-'); i != -1 {
pkg.Version, pkg.Release = fields[1][:i], fields[1][i+1:]
} else {
return fmt.Errorf("archlinux: invalid version %q", fields[1])
}
case "pkgdesc":
pkg.Description = fields[1]
case "url":
if pkg.URL, err = url.Parse(fields[1]); err != nil {
return fmt.Errorf("archlinux: invalid url %q: %v", fields[1], err)
}
case "builddate":
var t int64
if t, err = strconv.ParseInt(fields[1], 10, 64); err != nil {
return fmt.Errorf("archlinux: invalid build date %q: %v", fields[1], err)
}
pkg.BuildDate = time.Unix(t, 0)
case "packager":
pkg.Packager = fields[1]
case "size":
if pkg.Size, err = strconv.ParseInt(fields[1], 10, 64); err != nil {
return fmt.Errorf("archlinux: invalid size %q: %v", fields[1], err)
}
case "arch":
pkg.Arch = append(pkg.Arch, fields[1])
case "group":
pkg.Groups = append(pkg.Groups, fields[1])
case "license":
pkg.License = append(pkg.License, fields[1])
case "backup":
pkg.Backup = append(pkg.Backup, fields[1])
case "replaces":
pkg.Replaces = append(pkg.Replaces, fields[1])
case "depend":
pkg.Depends = append(pkg.Depends, fields[1])
case "conflict":
pkg.Conflicts = append(pkg.Conflicts, fields[1])
case "provides":
pkg.Provides = append(pkg.Provides, fields[1])
case "optdepend":
pkg.OptionalDepends = append(pkg.OptionalDepends, fields[1])
case "makedepend":
pkg.MakeDepends = append(pkg.MakeDepends, fields[1])
case "checkdepend":
pkg.CheckDepends = append(pkg.CheckDepends, fields[1])
default:
return fmt.Errorf("archlinux: unknown PKGINFO field %q", fields[0])
}
}
return
}
// WritePackageInfo writes a PKGINFO to the supplied Writer
func (pkg *Package) WritePackageInfo(w io.Writer) error {
var (
fields = []struct {
Key string
Value interface{}
}{
{"pkgname", pkg.Name},
{"pkgbase", pkg.Base},
{"pkgver", pkg.Version + "-" + pkg.Release},
{"pkgdesc", pkg.Description},
{"url", pkg.URL},
{"builddate", pkg.BuildDate},
{"packager", pkg.Packager},
{"size", pkg.Size},
{"arch", pkg.Arch},
{"license", pkg.License},
{"provides", pkg.Provides},
{"conflicts", pkg.Conflicts},
{"replaces", pkg.Replaces},
{"backup", pkg.Backup},
{"depend", pkg.Depends},
{"optdepend", pkg.OptionalDepends},
{"makedepend", pkg.MakeDepends},
{"checkdepend", pkg.CheckDepends},
}
err error
)
if _, err = fmt.Fprintln(w, "# Generated by maze.io/archlinux.v0\n#", time.Now().UTC().Format(time.UnixDate)); err != nil {
return err
}
for _, f := range fields {
switch value := f.Value.(type) {
case string:
if value == "" {
continue
}
if _, err = fmt.Fprintln(w, f.Key, "=", value); err != nil {
return err
}
case []string:
if len(value) > 0 {
for _, v := range value {
if v == "" {
continue
}
if _, err = fmt.Fprintln(w, f.Key, "=", v); err != nil {
return err
}
}
}
case int64:
if value > 0 {
if _, err = fmt.Fprintln(w, f.Key, "=", value); err != nil {
return err
}
}
case *url.URL:
if value == nil {
continue
}
if _, err = fmt.Fprintln(w, f.Key, "=", value.String()); err != nil {
return err
}
}
}
return nil
}