package lib import ( "archive/tar" "bufio" "compress/gzip" "fmt" "io" "os" "path" "strings" "unicode" "github.com/bigkevmcd/go-configparser" ) type Pool struct { Maintainer string `json:"-"` Pubkey string `json:"-"` Size string `json:"-"` Display string `json:"display"` Branch string `json:"branch"` Source string `json:"source"` Name string `json:"name"` URL string `json:"url"` Dir string `json:"dir"` } func (p *Pool) ID() string { var res string = "" for _, c := range p.Display { if unicode.IsDigit(c) || unicode.IsLetter(c) { res += string(c) continue } res += "-" } return strings.TrimSuffix(res, "-") } func (p *Pool) Load(list *[]Package) error { var err error if p.Dir == "" { return fmt.Errorf("pool directory is not specified") } if err = p.LoadInfo(); err != nil { return err } if err = p.LoadList(list); err != nil { return err } return nil } func (p *Pool) LoadList(list *[]Package) error { var ( list_path string list_file *os.File gzip_reader io.Reader header *tar.Header err error ) list_path = path.Join(p.Dir, "LIST") if list_file, err = os.Open(list_path); err != nil { return err } defer list_file.Close() if gzip_reader, err = gzip.NewReader(bufio.NewReader(list_file)); err != nil { return err } reader := tar.NewReader(gzip_reader) for header, err = reader.Next(); err == nil; header, err = reader.Next() { if header.Typeflag != tar.TypeReg { continue } if path.Base(header.Name) != "DATA" { return fmt.Errorf("LIST archive contains an unknown file") } var pkg Package if err = pkg.Load(reader); err != nil { return err } pkg.Archive = path.Join(p.Dir, fmt.Sprintf("%s_%s.mpf", pkg.Name, pkg.Version)) pkg.Pool = p *list = append(*list, pkg) } return nil } func (p *Pool) LoadInfo() error { var ( info_path string info_file *os.File section string size int64 err error ) info_path = path.Join(p.Dir, "INFO") if info_file, err = os.Open(info_path); err != nil { return err } parser := configparser.New() if err = parser.ParseReader(bufio.NewReader(info_file)); err != nil { return err } section = "DEFAULT" for _, s := range parser.Sections() { if s == "DEFAULT" { continue } section = s break } if section == "DEFAULT" { return fmt.Errorf("DATA does not contain any sections") } if p.Name != section { return fmt.Errorf("pool name (\"%s\") doesn't match with \"%s\"", p.Name, section) } if p.Maintainer, err = parser.Get(p.Name, "maintainer"); err != nil { return err } if size, err = parser.GetInt64(section, "size"); err != nil { return err } p.Size = SizeFromBytes(size) if p.Pubkey, err = parser.Get(section, "pubkey"); err != nil { return err } return nil }