Major refactoring of files in package: hide them in Package type.

This commit is contained in:
Andrey Smirnov
2014-01-05 13:02:33 +04:00
parent 06f1c62ef0
commit 4aa24048d5
8 changed files with 272 additions and 95 deletions
+127 -31
View File
@@ -7,18 +7,38 @@ import (
"github.com/smira/aptly/utils"
"github.com/ugorji/go/codec"
"os"
"path/filepath"
"strconv"
"strings"
)
// PackageFile is a single file entry in package
type PackageFile struct {
Filename string
Checksums utils.ChecksumInfo
}
// Verify that package file is present and correct
func (f *PackageFile) Verify(packageRepo *Repository) (bool, error) {
poolPath, err := packageRepo.PoolPath(f.Filename, f.Checksums.MD5)
if err != nil {
return false, err
}
st, err := os.Stat(poolPath)
if err != nil {
return false, nil
}
// verify size
// TODO: verify checksum if configured
return st.Size() == f.Checksums.Size, nil
}
// Package is single instance of Debian package
//
// TODO: support source & binary
type Package struct {
Name string
Version string
Filename string
Filesize int64
Architecture string
Source string
// Various dependencies
@@ -26,10 +46,8 @@ type Package struct {
PreDepends []string
Suggests []string
Recommends []string
// Hashsums of package contents
HashMD5 string
HashSHA1 string
HashSHA256 string
// Files in package
Files []PackageFile
// Extra information from stanza
Extra Stanza
}
@@ -50,24 +68,32 @@ func NewPackageFromControlFile(input Stanza) *Package {
result := &Package{
Name: input["Package"],
Version: input["Version"],
Filename: input["Filename"],
Architecture: input["Architecture"],
Source: input["Source"],
HashMD5: input["MD5sum"],
HashSHA1: input["SHA1"],
HashSHA256: input["SHA256"],
Files: make([]PackageFile, 0, 1),
}
delete(input, "Package")
delete(input, "Version")
delete(input, "Filename")
delete(input, "Architecture")
delete(input, "Source")
filesize, _ := strconv.ParseInt(input["Size"], 10, 64)
result.Files = append(result.Files, PackageFile{
Filename: input["Filename"],
Checksums: utils.ChecksumInfo{
Size: filesize,
MD5: input["MD5sum"],
SHA1: input["SHA1"],
SHA256: input["SHA256"],
},
})
delete(input, "Filename")
delete(input, "MD5sum")
delete(input, "SHA1")
delete(input, "SHA256")
result.Filesize, _ = strconv.ParseInt(input["Size"], 10, 64)
delete(input, "Size")
result.Depends = parseDependencies(input, "Depends")
@@ -111,18 +137,18 @@ func (p *Package) Stanza() (result Stanza) {
result = p.Extra.Copy()
result["Package"] = p.Name
result["Version"] = p.Version
result["Filename"] = p.Filename
result["Filename"] = p.Files[0].Filename
result["Architecture"] = p.Architecture
result["Source"] = p.Source
if p.HashMD5 != "" {
result["MD5sum"] = p.HashMD5
if p.Files[0].Checksums.MD5 != "" {
result["MD5sum"] = p.Files[0].Checksums.MD5
}
if p.HashSHA1 != "" {
result["SHA1"] = p.HashSHA1
if p.Files[0].Checksums.SHA1 != "" {
result["SHA1"] = p.Files[0].Checksums.SHA1
}
if p.HashSHA256 != "" {
result["SHA256"] = p.HashSHA256
if p.Files[0].Checksums.SHA256 != "" {
result["SHA256"] = p.Files[0].Checksums.SHA256
}
if p.Depends != nil {
@@ -138,28 +164,98 @@ func (p *Package) Stanza() (result Stanza) {
result["Recommends"] = strings.Join(p.Recommends, ", ")
}
result["Size"] = fmt.Sprintf("%d", p.Filesize)
result["Size"] = fmt.Sprintf("%d", p.Files[0].Checksums.Size)
return
}
// Equals compares two packages to be identical
func (p *Package) Equals(p2 *Package) bool {
return p.Name == p2.Name && p.Version == p2.Version && p.Filename == p2.Filename &&
if len(p.Files) != len(p2.Files) {
return false
}
for i, f := range p.Files {
if p2.Files[i] != f {
return false
}
}
return p.Name == p2.Name && p.Version == p2.Version &&
p.Architecture == p2.Architecture && utils.StrSlicesEqual(p.Depends, p2.Depends) &&
utils.StrSlicesEqual(p.PreDepends, p2.PreDepends) && utils.StrSlicesEqual(p.Suggests, p2.Suggests) &&
utils.StrSlicesEqual(p.Recommends, p2.Recommends) && utils.StrMapsEqual(p.Extra, p2.Extra) &&
p.Filesize == p2.Filesize && p.HashMD5 == p2.HashMD5 && p.HashSHA1 == p2.HashSHA1 &&
p.HashSHA256 == p2.HashSHA256 && p.Source == p2.Source
p.Source == p2.Source
}
// VerifyFile verifies integrity and existence of local files for the package
func (p *Package) VerifyFile(filepath string) bool {
st, err := os.Stat(filepath)
// LinkFromPool links package file from pool to dist's pool location
func (p *Package) LinkFromPool(packageRepo *Repository, prefix string, component string) error {
poolDir, err := p.PoolDirectory()
if err != nil {
return false
return err
}
return st.Size() == p.Filesize
for i, f := range p.Files {
sourcePath, err := packageRepo.PoolPath(f.Filename, f.Checksums.MD5)
if err != nil {
return err
}
relPath, err := packageRepo.LinkFromPool(prefix, component, sourcePath, poolDir)
if err != nil {
return err
}
p.Files[i].Filename = relPath
}
return nil
}
// PoolDirectory returns directory in package pool for this package files
func (p *Package) PoolDirectory() (string, error) {
source := p.Source
if source == "" {
source = p.Name
}
if len(source) < 2 {
return "", fmt.Errorf("package source %s too short", source)
}
var subdir string
if strings.HasPrefix(source, "lib") {
subdir = source[:4]
} else {
subdir = source[:1]
}
return filepath.Join(subdir, source), nil
}
// DownloadList returns list of missing package files for download in format
// [[srcpath, dstpath]]
func (p *Package) DownloadList(packageRepo *Repository) (result [][]string, err error) {
result = make([][]string, 0, 1)
for _, f := range p.Files {
poolPath, err := packageRepo.PoolPath(f.Filename, f.Checksums.MD5)
if err != nil {
return nil, err
}
verified, err := f.Verify(packageRepo)
if err != nil {
return nil, err
}
if !verified {
result = append(result, []string{f.Filename, poolPath})
}
}
return result, nil
}
// PackageCollection does management of packages in DB