|
- package archlinux
-
- import (
- "bufio"
- "encoding/base64"
- "encoding/hex"
- "fmt"
- "io"
- "net/url"
- "reflect"
- "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) {
- values, encodings := parsePackageFields(parseFieldInfo, pkg)
- 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
- }
-
- v, ok := values[fields[0]]
- if !ok {
- return fmt.Errorf("archlinux: unknown PKGINFO field %q", fields[0])
- }
- if err = setPackageValue(pkg, v, fields[1], encodings[fields[0]]); err != nil {
- return
- }
- }
- return
- }
-
- func parseFieldInfo(field reflect.StructField) (name, encoding string) {
- tag := field.Tag.Get("pkginfo")
- switch tag {
- case "-":
- // Ignored tag
- case "":
- // No desc tag, default to upper case field name
- name = strings.ToLower(field.Name)
- default:
- if i := strings.IndexByte(tag, ','); i != -1 {
- name, encoding = tag[:i], tag[i+1:]
- } else {
- name = tag
- }
- }
- return
- }
-
- // WritePackageInfo writes a PKGINFO to the supplied Writer
- func (pkg *Package) WritePackageInfo(w io.Writer) (int, error) {
- var (
- value = reflect.Indirect(reflect.ValueOf(pkg))
- typ = value.Type()
- total, n int
- err error
- )
- for i := 0; i < value.NumField(); i++ {
- fieldValue := value.Field(i)
- fieldType := typ.Field(i)
- name, encoding := parseFieldInfo(fieldType)
- if name == "" {
- // No name means ignored field
- continue
- }
- switch v := fieldValue.Interface().(type) {
- case string:
- if v == "" {
- continue
- }
- switch encoding {
- case "":
- // No additional encoding
- case evrEncoding:
- // Epoch:Version-Release
- if pkg.Epoch > 0 {
- v = fmt.Sprintf("%d:%s-%s", pkg.Epoch, pkg.Version, pkg.Release)
- } else {
- v = fmt.Sprintf("%s-%s", pkg.Version, pkg.Release)
- }
- }
- if n, err = fmt.Fprintf(w, "%s = %s\n", name, v); err != nil {
- return total + n, err
- }
- total += n
- case []string:
- if len(v) == 0 {
- continue
- }
- for _, s := range v {
- if n, err = fmt.Fprintf(w, "%s = %s\n", name, s); err != nil {
- return total + n, err
- }
- }
- total += n
- case []byte:
- if len(v) == 0 {
- continue
- }
- var o []byte
- switch encoding {
- case "":
- o = v
- case base64Encoding:
- o = make([]byte, base64.StdEncoding.EncodedLen(len(v)))
- base64.StdEncoding.Encode(o, v)
- case hexEncoding:
- o = make([]byte, hex.EncodedLen(len(v)))
- hex.Encode(o, v)
- }
- if n, err = fmt.Fprintf(w, "%s = %s\n", name, o); err != nil {
- return total + n, err
- }
- total += n
- case int64:
- if v == 0 {
- continue
- }
- if n, err = fmt.Fprintf(w, "%s = %d\n", name, v); err != nil {
- return total + n, err
- }
- total += n
- case time.Time:
- if v.Equal(timeZero) {
- continue
- }
- if n, err = fmt.Fprintf(w, "%s = %d\n", name, v.Unix()); err != nil {
- return total + n, err
- }
- total += n
- case *url.URL:
- if v == nil {
- continue
- }
- if n, err = fmt.Fprintf(w, "%s = %s\n", name, v); err != nil {
- return total + n, err
- }
- total += n
- default:
- return total, fmt.Errorf("archlinux: can't write %T to info", v)
- }
- }
- return total, nil
- /*
- 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
- */
- }
|