Skip to content

Commit

Permalink
corrected arch package implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
thionic committed May 20, 2024
1 parent ef64354 commit 1a49dd9
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 176 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ require (
github.com/microcosm-cc/bluemonday v1.0.26
github.com/microsoft/go-mssqldb v1.7.0
github.com/minio/minio-go/v7 v7.0.69
github.com/minio/sha256-simd v1.0.1
github.com/msteinert/pam v1.2.0
github.com/nektos/act v0.2.52
github.com/niklasfasching/go-org v1.7.0
Expand Down Expand Up @@ -231,7 +232,6 @@ require (
github.com/mholt/acmez v1.2.0 // indirect
github.com/miekg/dns v1.1.58 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
Expand Down
52 changes: 43 additions & 9 deletions modules/packages/arch/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,22 @@ import (
"github.com/mholt/archiver/v3"
)

// Arch Linux Packages
// https://man.archlinux.org/man/PKGBUILD.5

const (
PropertyDescription = "arch.description"
PropertySignature = "arch.signature"
PropertyDescription = "arch.description"
PropertySignature = "arch.signature"
PropertyCompressedSize = "arch.compsize"
PropertyInstalledSize = "arch.inssize"
PropertySHA256 = "arch.sha256"
PropertyBuildDate = "arch.builddate"
PropertyPackager = "arch.packager"
PropertyArch = "arch.architecture"
PropertyDistribution = "arch.distribution"
)

var (
// https://man.archlinux.org/man/PKGBUILD.5
reName = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+$`)
reVer = regexp.MustCompile(`^[a-zA-Z0-9:_.+]+-+[0-9]+$`)
reOptDep = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+$|^[a-zA-Z0-9@._+-]+(:.*)`)
Expand All @@ -38,7 +47,7 @@ var (

type Package struct {
Name string `json:"name"`
Version string `json:"version"`
Version string `json:"version"` // Includes version, release and epoch
VersionMetadata VersionMetadata
FileMetadata FileMetadata
}
Expand All @@ -56,23 +65,25 @@ type VersionMetadata struct {
OptDepends []string `json:"opt_depends,omitempty"`
MakeDepends []string `json:"make_depends,omitempty"`
CheckDepends []string `json:"check_depends,omitempty"`
Conflicts []string `json:"conflicts,omitempty"`
Replaces []string `json:"replaces,omitempty"`
Backup []string `json:"backup,omitempty"`
Xdata []string `json:"xdata,omitempty"`
}

// Metadata related to specific pakcage file.
// This metadata might vary for different architecture and distribution.
type FileMetadata struct {
CompressedSize int64 `json:"compressed_size"`
InstalledSize int64 `json:"installed_size"`
MD5 string `json:"md5"`
SHA256 string `json:"sha256"`
BuildDate int64 `json:"build_date"`
Packager string `json:"packager"`
Arch string `json:"arch"`
}

// Function that receives arch package archive data and returns it's metadata.
func ParsePackage(r io.Reader, md5, sha256 []byte, size int64) (*Package, error) {
func ParsePackage(r io.Reader, sha256 []byte, size int64) (*Package, error) {
zstd := archiver.NewTarZstd()
err := zstd.Open(r, 0)
if err != nil {
Expand Down Expand Up @@ -114,7 +125,6 @@ func ParsePackage(r io.Reader, md5, sha256 []byte, size int64) (*Package, error)

pkg.FileMetadata.CompressedSize = size
pkg.FileMetadata.SHA256 = hex.EncodeToString(sha256)
pkg.FileMetadata.MD5 = hex.EncodeToString(md5)

return pkg, nil
}
Expand Down Expand Up @@ -171,6 +181,12 @@ func ParsePackageInfo(r io.Reader) (*Package, error) {
p.VersionMetadata.Backup = append(p.VersionMetadata.Backup, value)
case "group":
p.VersionMetadata.Groups = append(p.VersionMetadata.Groups, value)
case "conflict":
p.VersionMetadata.Conflicts = append(p.VersionMetadata.Conflicts, value)
case "replaces":
p.VersionMetadata.Replaces = append(p.VersionMetadata.Replaces, value)
case "xdata":
p.VersionMetadata.Xdata = append(p.VersionMetadata.Xdata, value)
case "builddate":
bd, err := strconv.ParseInt(value, 10, 64)
if err != nil {
Expand All @@ -183,6 +199,8 @@ func ParsePackageInfo(r io.Reader) (*Package, error) {
return nil, err
}
p.FileMetadata.InstalledSize = is
default:
return nil, util.NewInvalidArgumentErrorf("property is not supported %s", key)
}
}

Expand Down Expand Up @@ -228,6 +246,21 @@ func ValidatePackageSpec(p *Package) error {
return util.NewInvalidArgumentErrorf("invalid provides: " + p)
}
}
for _, p := range p.VersionMetadata.Conflicts {
if !rePkgVer.MatchString(p) {
return util.NewInvalidArgumentErrorf("invalid conflicts: " + p)
}
}
for _, p := range p.VersionMetadata.Replaces {
if !rePkgVer.MatchString(p) {
return util.NewInvalidArgumentErrorf("invalid replaces: " + p)
}
}
for _, p := range p.VersionMetadata.Replaces {
if !rePkgVer.MatchString(p) {
return util.NewInvalidArgumentErrorf("invalid xdata: " + p)
}
}
for _, od := range p.VersionMetadata.OptDepends {
if !reOptDep.MatchString(od) {
return util.NewInvalidArgumentErrorf("invalid optional dependency: " + od)
Expand All @@ -243,7 +276,7 @@ func ValidatePackageSpec(p *Package) error {

// Create pacman package description file.
func (p *Package) Desc() string {
entries := [40]string{
entries := [44]string{
"FILENAME", fmt.Sprintf("%s-%s-%s.pkg.tar.zst", p.Name, p.Version, p.FileMetadata.Arch),
"NAME", p.Name,
"BASE", p.VersionMetadata.Base,
Expand All @@ -252,13 +285,14 @@ func (p *Package) Desc() string {
"GROUPS", strings.Join(p.VersionMetadata.Groups, "\n"),
"CSIZE", fmt.Sprintf("%d", p.FileMetadata.CompressedSize),
"ISIZE", fmt.Sprintf("%d", p.FileMetadata.InstalledSize),
"MD5SUM", p.FileMetadata.MD5,
"SHA256SUM", p.FileMetadata.SHA256,
"URL", p.VersionMetadata.ProjectURL,
"LICENSE", strings.Join(p.VersionMetadata.License, "\n"),
"ARCH", p.FileMetadata.Arch,
"BUILDDATE", fmt.Sprintf("%d", p.FileMetadata.BuildDate),
"PACKAGER", p.FileMetadata.Packager,
"REPLACES", strings.Join(p.VersionMetadata.Replaces, "\n"),
"CONFLICTS", strings.Join(p.VersionMetadata.Conflicts, "\n"),
"PROVIDES", strings.Join(p.VersionMetadata.Provides, "\n"),
"DEPENDS", strings.Join(p.VersionMetadata.Depends, "\n"),
"OPTDEPENDS", strings.Join(p.VersionMetadata.OptDepends, "\n"),
Expand Down
8 changes: 3 additions & 5 deletions modules/packages/arch/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ arch = x86_64
})
assert.NoError(t, errors.Join(mfile.Close(), archive.Close(), err))

_, err = ParsePackage(&buf, []byte{}, []byte{}, 0)
_, err = ParsePackage(&buf, []byte{}, 0)

assert.NoError(t, err)
})
Expand All @@ -95,7 +95,7 @@ arch = x86_64

assert.NoError(t, archive.Close())

_, err = ParsePackage(&buf, []byte{}, []byte{}, 0)
_, err = ParsePackage(&buf, []byte{}, 0)

assert.Error(t, err)
assert.Contains(t, err.Error(), ".PKGINFO file not found")
Expand All @@ -119,7 +119,7 @@ arch = x86_64
})
assert.NoError(t, errors.Join(pfile.Close(), archive.Close(), err))

_, err = ParsePackage(&buf, []byte{}, []byte{}, 0)
_, err = ParsePackage(&buf, []byte{}, 0)

assert.Error(t, err)
assert.Contains(t, err.Error(), ".MTREE file not found")
Expand Down Expand Up @@ -195,7 +195,6 @@ func TestValidatePackageSpec(t *testing.T) {
FileMetadata: FileMetadata{
CompressedSize: 1,
InstalledSize: 2,
MD5: "abc",
SHA256: "def",
BuildDate: 3,
Packager: "smon",
Expand Down Expand Up @@ -424,7 +423,6 @@ dummy6
FileMetadata: FileMetadata{
CompressedSize: 401,
InstalledSize: 1500453,
MD5: "5016660ef3d9aa148a7b72a08d3df1b2",
SHA256: "9fa4ede47e35f5971e4f26ecadcbfb66ab79f1d638317ac80334a3362dedbabd",
BuildDate: 1681646714,
Packager: "Jelle van der Waa <jelle@archlinux.org>",
Expand Down
30 changes: 22 additions & 8 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3451,14 +3451,28 @@ alpine.repository.repositories = Repositories
alpine.repository.architectures = Architectures
arch.pacmanconf = Add server with related distribution and architecture to <code>/etc/pacman.conf</code>:
arch.pacmansync = Sync package with pacman:
arch.documentation = For more information on the arch mirrors, see %sthe documentation%s.
arch.properties = Package properties
arch.description = Description
arch.provides = Provides
arch.depends = Depends
arch.optdepends = Optional depends
arch.makedepends = Make depends
arch.checkdepends = Check depends
arch.version.properties = Version properties
arch.version.description = Description
arch.version.projecturl = ProjectURL
arch.version.groups = Groups
arch.version.provides = Provides
arch.version.license = License
arch.version.depends = Depends
arch.version.optdepends = Optional depends
arch.version.makedepends = Make depends
arch.version.checkdepends = Check depends
arch.version.conflicts = Conflicts
arch.version.replaces = Replaces
arch.version.backup = Backup
arch.version.xdata = Xdata
arch.file.properties = File properties
arch.file.compsize = Compressed size
arch.file.inssize = Installed size
arch.file.sha256 = SHA-256
arch.file.builddate = Build date
arch.file.packager = Packager
arch.file.architecture = Architecture
arch.file.distribution = Distribution
cargo.registry = Setup this registry in the Cargo configuration file (for example <code>~/.cargo/config.toml</code>):
cargo.install = To install the package using Cargo, run the following command:
chef.registry = Setup this registry in your <code>~/.chef/config.rb</code> file:
Expand Down
8 changes: 4 additions & 4 deletions routers/api/packages/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,11 @@ func CommonRoutes() *web.Route {
})
}, reqPackageAccess(perm.AccessModeRead))
r.Group("/arch", func() {
r.Put("/push/{filename}/{distro}", reqPackageAccess(perm.AccessModeWrite), arch.Push)
r.Put("/push/{filename}/{distro}/{sign}", reqPackageAccess(perm.AccessModeWrite), arch.Push)
r.Delete("/remove/{package}/{version}", reqPackageAccess(perm.AccessModeWrite), arch.Remove)
r.Put("/push/{distro}", reqPackageAccess(perm.AccessModeWrite), arch.Push)
r.Put("/push/{distro}/{sign}", reqPackageAccess(perm.AccessModeWrite), arch.Push)
r.Get("/{distro}/{arch}/{file}", arch.Get)
})
r.Delete("/remove/{package}/{version}/{distro}/{arch}", reqPackageAccess(perm.AccessModeWrite), arch.Remove)
}, reqPackageAccess(perm.AccessModeRead))
r.Group("/cargo", func() {
r.Group("/api/v1/crates", func() {
r.Get("", cargo.SearchPackages)
Expand Down
Loading

0 comments on commit 1a49dd9

Please sign in to comment.