mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-05 22:08:27 +00:00
Repo publishing machinery.
This commit is contained in:
168
debian/publish.go
vendored
Normal file
168
debian/publish.go
vendored
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
package debian
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"github.com/smira/aptly/utils"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PublishedRepo is a published for http/ftp representation of snapshot as Debian repository
|
||||||
|
type PublishedRepo struct {
|
||||||
|
// Prefix & distribution should be unique across all published repositories
|
||||||
|
Prefix string
|
||||||
|
Distribution string
|
||||||
|
Component string
|
||||||
|
// Architectures is a list of all architectures published
|
||||||
|
Architectures []string
|
||||||
|
// Snapshot as a source of publishing
|
||||||
|
SnapshotUUID string
|
||||||
|
|
||||||
|
snapshot *Snapshot
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPublishedRepo creates new published repository
|
||||||
|
func NewPublishedRepo(prefix string, distribution string, component string, architectures []string, snapshot *Snapshot) *PublishedRepo {
|
||||||
|
return &PublishedRepo{
|
||||||
|
Prefix: prefix,
|
||||||
|
Distribution: distribution,
|
||||||
|
Component: component,
|
||||||
|
Architectures: architectures,
|
||||||
|
SnapshotUUID: snapshot.UUID,
|
||||||
|
snapshot: snapshot,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Publish publishes snapshot (repository) contents, links package files, generates Packages & Release files, signs them
|
||||||
|
func (p *PublishedRepo) Publish(repo *Repository, packageCollection *PackageCollection, signer utils.Signer) error {
|
||||||
|
err := repo.MkDir(filepath.Join(p.Prefix, "pool"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
basePath := filepath.Join(p.Prefix, "dists", p.Distribution)
|
||||||
|
err = repo.MkDir(basePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load all packages
|
||||||
|
list := NewPackageList()
|
||||||
|
|
||||||
|
p.snapshot.RefList().ForEach(func(key []byte) {
|
||||||
|
pkg, _ := packageCollection.ByKey(key)
|
||||||
|
list.Add(pkg)
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: verify/guess list of architectures
|
||||||
|
|
||||||
|
generatedFiles := map[string]*utils.ChecksumInfo{}
|
||||||
|
|
||||||
|
// For all architectures, generate release file
|
||||||
|
for _, arch := range p.Architectures {
|
||||||
|
relativePath := filepath.Join(p.Component, fmt.Sprintf("binary-%s", arch), "Packages")
|
||||||
|
err = repo.MkDir(filepath.Dir(filepath.Join(basePath, relativePath)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
packagesFile, err := repo.CreateFile(filepath.Join(basePath, relativePath))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to creates Packages file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
bufWriter := bufio.NewWriter(packagesFile)
|
||||||
|
|
||||||
|
list.ForEach(func(pkg *Package) {
|
||||||
|
if pkg.Architecture == arch || pkg.Architecture == "all" {
|
||||||
|
// TODO: error handling
|
||||||
|
pkg.Stanza().WriteTo(bufWriter)
|
||||||
|
bufWriter.WriteByte('\n')
|
||||||
|
|
||||||
|
repo.LinkFromPool(p.Prefix, p.Component, pkg.Filename, pkg.HashMD5)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
err = bufWriter.Flush()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to write Packages file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = utils.CompressFile(packagesFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to compress Packages files: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
packagesFile.Close()
|
||||||
|
|
||||||
|
checksumInfo, err := repo.ChecksumsForFile(filepath.Join(basePath, relativePath))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to collect checksums: %s", err)
|
||||||
|
}
|
||||||
|
generatedFiles[relativePath] = checksumInfo
|
||||||
|
|
||||||
|
checksumInfo, err = repo.ChecksumsForFile(filepath.Join(basePath, relativePath+".gz"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to collect checksums: %s", err)
|
||||||
|
}
|
||||||
|
generatedFiles[relativePath+".gz"] = checksumInfo
|
||||||
|
|
||||||
|
checksumInfo, err = repo.ChecksumsForFile(filepath.Join(basePath, relativePath+".bz2"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to collect checksums: %s", err)
|
||||||
|
}
|
||||||
|
generatedFiles[relativePath+".bz2"] = checksumInfo
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
release := make(Stanza)
|
||||||
|
release["Origin"] = p.Prefix + " " + p.Distribution
|
||||||
|
release["Label"] = p.Prefix + " " + p.Distribution
|
||||||
|
release["Codename"] = p.Distribution
|
||||||
|
release["Date"] = time.Now().UTC().Format("Mon, 2 Jan 2006 15:04:05 MST")
|
||||||
|
release["Components"] = p.Component
|
||||||
|
release["Architectures"] = strings.Join(p.Architectures, " ")
|
||||||
|
release["Description"] = "Generated by aptly\n"
|
||||||
|
release["MD5Sum"] = "\n"
|
||||||
|
release["SHA1"] = "\n"
|
||||||
|
release["SHA256"] = "\n"
|
||||||
|
|
||||||
|
for path, info := range generatedFiles {
|
||||||
|
release["MD5Sum"] += fmt.Sprintf(" %s %8d %s\n", info.MD5, info.Size, path)
|
||||||
|
release["SHA1"] += fmt.Sprintf(" %s %8d %s\n", info.SHA1, info.Size, path)
|
||||||
|
release["SHA256"] += fmt.Sprintf(" %s %8d %s\n", info.SHA256, info.Size, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseFile, err := repo.CreateFile(filepath.Join(basePath, "Release"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to create Release file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
bufWriter := bufio.NewWriter(releaseFile)
|
||||||
|
|
||||||
|
err = release.WriteTo(bufWriter)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to create Release file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bufWriter.Flush()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to create Release file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseFilename := releaseFile.Name()
|
||||||
|
releaseFile.Close()
|
||||||
|
|
||||||
|
err = signer.DetachedSign(releaseFilename, releaseFilename+".gpg")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to sign Release file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = signer.ClearSign(releaseFilename, filepath.Join(filepath.Dir(releaseFilename), "InRelease"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to sign Release file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user