mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-01-12 03:21:33 +00:00
Repository name, uuid, persistence, lookup.
This commit is contained in:
119
debian/remote.go
vendored
119
debian/remote.go
vendored
@@ -2,10 +2,14 @@
|
||||
package debian
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/go-uuid/uuid"
|
||||
"fmt"
|
||||
"github.com/smira/aptly/database"
|
||||
"github.com/smira/aptly/utils"
|
||||
debc "github.com/smira/godebiancontrol"
|
||||
"github.com/ugorji/go/codec"
|
||||
"log"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
@@ -15,35 +19,48 @@ import (
|
||||
// Repostitory could be filtered when fetching by components, architectures
|
||||
// TODO: support flat format
|
||||
type RemoteRepo struct {
|
||||
ArchiveRoot string
|
||||
Distribution string
|
||||
Components []string
|
||||
// Permanent internal ID
|
||||
UUID string
|
||||
// User-assigned name
|
||||
Name string
|
||||
// Root of Debian archive, URL
|
||||
ArchiveRoot string
|
||||
// Distribution name, e.g. squeeze
|
||||
Distribution string
|
||||
// List of components to fetch, if empty, then fetch all components
|
||||
Components []string
|
||||
// List of architectures to fetch, if empty, then fetch all architectures
|
||||
Architectures []string
|
||||
archiveRootURL *url.URL
|
||||
}
|
||||
|
||||
// NewRemoteRepo creates new instance of Debian remote repository with specified params
|
||||
func NewRemoteRepo(archiveRoot string, distribution string, components []string, architectures []string) (*RemoteRepo, error) {
|
||||
func NewRemoteRepo(name string, archiveRoot string, distribution string, components []string, architectures []string) (*RemoteRepo, error) {
|
||||
result := &RemoteRepo{
|
||||
UUID: uuid.New(),
|
||||
Name: name,
|
||||
ArchiveRoot: archiveRoot,
|
||||
Distribution: distribution,
|
||||
Components: components,
|
||||
Architectures: architectures,
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
result.archiveRootURL, err = url.Parse(archiveRoot)
|
||||
err := result.prepare()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (repo *RemoteRepo) prepare() error {
|
||||
var err error
|
||||
repo.archiveRootURL, err = url.Parse(repo.ArchiveRoot)
|
||||
return err
|
||||
}
|
||||
|
||||
// String interface
|
||||
func (repo *RemoteRepo) String() string {
|
||||
return fmt.Sprintf("%s %s", repo.ArchiveRoot, repo.Distribution)
|
||||
return fmt.Sprintf("[%s]: %s %s", repo.Name, repo.ArchiveRoot, repo.Distribution)
|
||||
}
|
||||
|
||||
// ReleaseURL returns URL to Release file in repo root
|
||||
@@ -166,3 +183,87 @@ func (repo *RemoteRepo) Download(d utils.Downloader, db database.Storage, packag
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode does msgpack encoding of RemoteRepo
|
||||
func (repo *RemoteRepo) Encode() []byte {
|
||||
var buf bytes.Buffer
|
||||
|
||||
encoder := codec.NewEncoder(&buf, &codec.MsgpackHandle{})
|
||||
encoder.Encode(repo)
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// Decode decodes msgpack representation into RemoteRepo
|
||||
func (repo *RemoteRepo) Decode(input []byte) error {
|
||||
decoder := codec.NewDecoderBytes(input, &codec.MsgpackHandle{})
|
||||
err := decoder.Decode(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return repo.prepare()
|
||||
}
|
||||
|
||||
// Key is a unique id in DB
|
||||
func (repo *RemoteRepo) Key() []byte {
|
||||
return []byte("R" + repo.UUID)
|
||||
}
|
||||
|
||||
// RemoteRepoCollection does listing, updating/adding/deleting of RemoteRepos
|
||||
type RemoteRepoCollection struct {
|
||||
db database.Storage
|
||||
list []*RemoteRepo
|
||||
}
|
||||
|
||||
// NewRemoteRepoCollection loads RemoteRepos from DB and makes up collection
|
||||
func NewRemoteRepoCollection(db database.Storage) *RemoteRepoCollection {
|
||||
result := &RemoteRepoCollection{
|
||||
db: db,
|
||||
}
|
||||
|
||||
blobs := db.FetchByPrefix([]byte("R"))
|
||||
result.list = make([]*RemoteRepo, 0, len(blobs))
|
||||
|
||||
for _, blob := range blobs {
|
||||
r := &RemoteRepo{}
|
||||
if err := r.Decode(blob); err != nil {
|
||||
log.Printf("Error decoding mirror: %s\n", err)
|
||||
} else {
|
||||
result.list = append(result.list, r)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Add appends new repo to collection and saves it
|
||||
func (collection *RemoteRepoCollection) Add(repo *RemoteRepo) error {
|
||||
for _, r := range collection.list {
|
||||
if r.Name == repo.Name {
|
||||
return fmt.Errorf("mirror with name %s already exists", repo.Name)
|
||||
}
|
||||
}
|
||||
|
||||
err := collection.Update(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
collection.list = append(collection.list, repo)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update stores updated information about repo in DB
|
||||
func (collection *RemoteRepoCollection) Update(repo *RemoteRepo) error {
|
||||
return collection.db.Put(repo.Key(), repo.Encode())
|
||||
}
|
||||
|
||||
// ByName looks up repository by name
|
||||
func (collection *RemoteRepoCollection) ByName(name string) (*RemoteRepo, error) {
|
||||
for _, r := range collection.list {
|
||||
if r.Name == name {
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("mirror with name %s not found", name)
|
||||
}
|
||||
|
||||
62
debian/remote_test.go
vendored
62
debian/remote_test.go
vendored
@@ -1,6 +1,7 @@
|
||||
package debian
|
||||
|
||||
import (
|
||||
"github.com/smira/aptly/database"
|
||||
"github.com/smira/aptly/utils"
|
||||
. "launchpad.net/gocheck"
|
||||
"testing"
|
||||
@@ -19,12 +20,12 @@ type RemoteRepoSuite struct {
|
||||
var _ = Suite(&RemoteRepoSuite{})
|
||||
|
||||
func (s *RemoteRepoSuite) SetUpTest(c *C) {
|
||||
s.repo, _ = NewRemoteRepo("http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{})
|
||||
s.repo, _ = NewRemoteRepo("yandex", "http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{})
|
||||
s.downloader = utils.NewFakeDownloader().ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/Release", exampleReleaseFile)
|
||||
}
|
||||
|
||||
func (s *RemoteRepoSuite) TestInvalidURL(c *C) {
|
||||
_, err := NewRemoteRepo("http://lolo%2", "squeeze", []string{"main"}, []string{})
|
||||
_, err := NewRemoteRepo("s", "http://lolo%2", "squeeze", []string{"main"}, []string{})
|
||||
c.Assert(err, ErrorMatches, ".*hexadecimal escape in host.*")
|
||||
}
|
||||
|
||||
@@ -36,6 +37,11 @@ func (s *RemoteRepoSuite) TestBinaryURL(c *C) {
|
||||
c.Assert(s.repo.BinaryURL("main", "amd64").String(), Equals, "http://mirror.yandex.ru/debian/dists/squeeze/main/binary-amd64/Packages")
|
||||
}
|
||||
|
||||
func (s *RemoteRepoSuite) TestPackageURL(c *C) {
|
||||
c.Assert(s.repo.PackageURL("pool/main/0/0ad/0ad_0~r11863-2_i386.deb").String(), Equals,
|
||||
"http://mirror.yandex.ru/debian/pool/main/0/0ad/0ad_0~r11863-2_i386.deb")
|
||||
}
|
||||
|
||||
func (s *RemoteRepoSuite) TestFetch(c *C) {
|
||||
err := s.repo.Fetch(s.downloader)
|
||||
c.Assert(err, IsNil)
|
||||
@@ -44,17 +50,65 @@ func (s *RemoteRepoSuite) TestFetch(c *C) {
|
||||
}
|
||||
|
||||
func (s *RemoteRepoSuite) TestFetchWrongArchitecture(c *C) {
|
||||
s.repo, _ = NewRemoteRepo("http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{"xyz"})
|
||||
s.repo, _ = NewRemoteRepo("s", "http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{"xyz"})
|
||||
err := s.repo.Fetch(s.downloader)
|
||||
c.Assert(err, ErrorMatches, "architecture xyz not available in repo.*")
|
||||
}
|
||||
|
||||
func (s *RemoteRepoSuite) TestFetchWrongComponent(c *C) {
|
||||
s.repo, _ = NewRemoteRepo("http://mirror.yandex.ru/debian/", "squeeze", []string{"xyz"}, []string{"i386"})
|
||||
s.repo, _ = NewRemoteRepo("s", "http://mirror.yandex.ru/debian/", "squeeze", []string{"xyz"}, []string{"i386"})
|
||||
err := s.repo.Fetch(s.downloader)
|
||||
c.Assert(err, ErrorMatches, "component xyz not available in repo.*")
|
||||
}
|
||||
|
||||
func (s *RemoteRepoSuite) TestEncodeDecode(c *C) {
|
||||
repo := &RemoteRepo{}
|
||||
err := repo.Decode(s.repo.Encode())
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
c.Check(repo.Name, Equals, "yandex")
|
||||
c.Check(repo.ArchiveRoot, Equals, "http://mirror.yandex.ru/debian/")
|
||||
}
|
||||
|
||||
func (s *RemoteRepoSuite) TestKey(c *C) {
|
||||
c.Assert(len(s.repo.Key()), Equals, 37)
|
||||
}
|
||||
|
||||
type RemoteRepoCollectionSuite struct {
|
||||
db database.Storage
|
||||
collection *RemoteRepoCollection
|
||||
}
|
||||
|
||||
var _ = Suite(&RemoteRepoCollectionSuite{})
|
||||
|
||||
func (s *RemoteRepoCollectionSuite) SetUpTest(c *C) {
|
||||
s.db, _ = database.OpenDB(c.MkDir())
|
||||
s.collection = NewRemoteRepoCollection(s.db)
|
||||
}
|
||||
|
||||
func (s *RemoteRepoCollectionSuite) TearDownTest(c *C) {
|
||||
s.db.Close()
|
||||
}
|
||||
|
||||
func (s *RemoteRepoCollectionSuite) TestAddByName(c *C) {
|
||||
r, err := s.collection.ByName("yandex")
|
||||
c.Assert(err, ErrorMatches, "*.not found")
|
||||
|
||||
repo, _ := NewRemoteRepo("yandex", "http://mirror.yandex.ru/debian/", "squeeze", []string{"main"}, []string{})
|
||||
c.Assert(s.collection.Add(repo), IsNil)
|
||||
c.Assert(s.collection.Add(repo), ErrorMatches, ".*already exists")
|
||||
|
||||
r, err = s.collection.ByName("yandex")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(r.String(), Equals, repo.String())
|
||||
|
||||
collection := NewRemoteRepoCollection(s.db)
|
||||
r, err = collection.ByName("yandex")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(r.String(), Equals, repo.String())
|
||||
|
||||
}
|
||||
|
||||
const exampleReleaseFile = `Origin: LP-PPA-agenda-developers-daily
|
||||
Label: Agenda Daily Builds
|
||||
Suite: precise
|
||||
|
||||
Reference in New Issue
Block a user