mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-06-02 04:50:49 +00:00
Allow management of components
This commit allows to add, remove and update components of published repositories without the need to recreate them. Signed-off-by: Christoph Fiehe <c.fiehe@eurodata.de>
This commit is contained in:
committed by
André Roth
parent
767bc6bd0b
commit
bd64232eb6
+219
-10
@@ -21,6 +21,12 @@ import (
|
||||
"github.com/aptly-dev/aptly/utils"
|
||||
)
|
||||
|
||||
type PublishedRepoUpdateResult struct {
|
||||
AddedSources map[string]string
|
||||
UpdatedSources map[string]string
|
||||
RemovedSources map[string]string
|
||||
}
|
||||
|
||||
type repoSourceItem struct {
|
||||
// Pointer to snapshot if SourceKind == "snapshot"
|
||||
snapshot *Snapshot
|
||||
@@ -73,6 +79,168 @@ type PublishedRepo struct {
|
||||
|
||||
// Support multiple distributions
|
||||
MultiDist bool
|
||||
|
||||
// Revision
|
||||
Revision *PublishedRepoRevision
|
||||
}
|
||||
|
||||
type PublishedRepoRevision struct {
|
||||
// Map of sources: component name -> snapshot name/local repo Name
|
||||
Sources map[string]string
|
||||
}
|
||||
|
||||
func (result *PublishedRepoUpdateResult) AddedComponents() []string {
|
||||
components := make([]string, 0, len(result.AddedSources))
|
||||
for component := range result.AddedSources {
|
||||
components = append(components, component)
|
||||
}
|
||||
sort.Strings(components)
|
||||
|
||||
return components
|
||||
}
|
||||
|
||||
func (result *PublishedRepoUpdateResult) UpdatedComponents() []string {
|
||||
components := make([]string, 0, len(result.UpdatedSources))
|
||||
for component := range result.UpdatedSources {
|
||||
components = append(components, component)
|
||||
}
|
||||
sort.Strings(components)
|
||||
|
||||
return components
|
||||
}
|
||||
|
||||
func (result *PublishedRepoUpdateResult) RemovedComponents() []string {
|
||||
components := make([]string, 0, len(result.RemovedSources))
|
||||
for component := range result.RemovedSources {
|
||||
components = append(components, component)
|
||||
}
|
||||
sort.Strings(components)
|
||||
|
||||
return components
|
||||
}
|
||||
|
||||
func (revision *PublishedRepoRevision) Components() []string {
|
||||
components := make([]string, 0, len(revision.Sources))
|
||||
for component := range revision.Sources {
|
||||
components = append(components, component)
|
||||
}
|
||||
sort.Strings(components)
|
||||
|
||||
return components
|
||||
}
|
||||
|
||||
func (revision *PublishedRepoRevision) SourceNames() []string {
|
||||
sources := revision.Sources
|
||||
names := make([]string, 0, len(sources))
|
||||
for _, component := range revision.Components() {
|
||||
names = append(names, sources[component])
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
func (p *PublishedRepo) DropRevision() *PublishedRepoRevision {
|
||||
revision := p.Revision
|
||||
p.Revision = nil
|
||||
|
||||
return revision
|
||||
}
|
||||
|
||||
func (p *PublishedRepo) ObtainRevision() *PublishedRepoRevision {
|
||||
revision := p.Revision
|
||||
if revision == nil {
|
||||
sources := make(map[string]string, len(p.Sources))
|
||||
for _, component := range p.Components() {
|
||||
item := p.sourceItems[component]
|
||||
if item.snapshot != nil {
|
||||
sources[component] = item.snapshot.Name
|
||||
} else if item.localRepo != nil {
|
||||
sources[component] = item.localRepo.Name
|
||||
} else {
|
||||
panic("no snapshot/localRepo")
|
||||
}
|
||||
}
|
||||
revision = &PublishedRepoRevision{
|
||||
Sources: sources,
|
||||
}
|
||||
p.Revision = revision
|
||||
}
|
||||
return revision
|
||||
}
|
||||
|
||||
func (p *PublishedRepo) Update(collectionFactory *CollectionFactory, _ aptly.Progress) (*PublishedRepoUpdateResult, error) {
|
||||
result := &PublishedRepoUpdateResult{
|
||||
AddedSources: map[string]string{},
|
||||
UpdatedSources: map[string]string{},
|
||||
RemovedSources: map[string]string{},
|
||||
}
|
||||
|
||||
revision := p.ObtainRevision()
|
||||
p.DropRevision()
|
||||
|
||||
publishedComponents := p.Components()
|
||||
|
||||
for _, component := range publishedComponents {
|
||||
name, exists := revision.Sources[component]
|
||||
if !exists {
|
||||
p.RemoveComponent(component)
|
||||
result.RemovedSources[component] = name
|
||||
}
|
||||
}
|
||||
|
||||
if p.SourceKind == SourceLocalRepo {
|
||||
localRepoCollection := collectionFactory.LocalRepoCollection()
|
||||
for component, name := range revision.Sources {
|
||||
localRepo, err := localRepoCollection.ByName(name)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = localRepoCollection.LoadComplete(localRepo)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
_, exists := p.Sources[component]
|
||||
if exists {
|
||||
// Even in the case, when the local repository has not been changed as package source,
|
||||
// it may contain a modified set of packages that requires (re-)publication.
|
||||
p.UpdateLocalRepo(component, localRepo)
|
||||
result.UpdatedSources[component] = name
|
||||
} else {
|
||||
p.UpdateLocalRepo(component, localRepo)
|
||||
result.AddedSources[component] = name
|
||||
}
|
||||
}
|
||||
} else if p.SourceKind == SourceSnapshot {
|
||||
snapshotCollection := collectionFactory.SnapshotCollection()
|
||||
for component, name := range revision.Sources {
|
||||
snapshot, err := snapshotCollection.ByName(name)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = snapshotCollection.LoadComplete(snapshot)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
sourceUUID, exists := p.Sources[component]
|
||||
if exists {
|
||||
if snapshot.UUID != sourceUUID {
|
||||
p.UpdateSnapshot(component, snapshot)
|
||||
result.UpdatedSources[component] = name
|
||||
}
|
||||
} else {
|
||||
p.UpdateSnapshot(component, snapshot)
|
||||
result.AddedSources[component] = name
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return result, fmt.Errorf("unknown published repository type")
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ParsePrefix splits [storage:]prefix into components
|
||||
@@ -281,14 +449,42 @@ func NewPublishedRepo(storage, prefix, distribution string, architectures []stri
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// MarshalJSON requires object to filled by "LoadShallow" or "LoadComplete"
|
||||
func (p *PublishedRepo) MarshalJSON() ([]byte, error) {
|
||||
type sourceInfo struct {
|
||||
Component, Name string
|
||||
type sourceInfo struct {
|
||||
Component, Name string
|
||||
}
|
||||
|
||||
func (revision *PublishedRepoRevision) ToJSON() map[string]any {
|
||||
sources := []sourceInfo{}
|
||||
for _, component := range revision.Components() {
|
||||
name := revision.Sources[component]
|
||||
sources = append(sources, sourceInfo{
|
||||
Component: component,
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
return map[string]any{"Sources": sources}
|
||||
}
|
||||
|
||||
func (revision *PublishedRepoRevision) MarshalJSON() ([]byte, error) {
|
||||
sources := []sourceInfo{}
|
||||
for _, component := range revision.Components() {
|
||||
name := revision.Sources[component]
|
||||
sources = append(sources, sourceInfo{
|
||||
Component: component,
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
|
||||
return json.Marshal(map[string]interface{}{
|
||||
"Sources": sources,
|
||||
})
|
||||
}
|
||||
|
||||
// MarshalJSON requires object to filled by "LoadShallow" or "LoadComplete"
|
||||
func (p *PublishedRepo) MarshalJSON() ([]byte, error) {
|
||||
sources := []sourceInfo{}
|
||||
for component, item := range p.sourceItems {
|
||||
for _, component := range p.Components() {
|
||||
item := p.sourceItems[component]
|
||||
name := ""
|
||||
if item.snapshot != nil {
|
||||
name = item.snapshot.Name
|
||||
@@ -444,20 +640,25 @@ func (p *PublishedRepo) SourceNames() []string {
|
||||
return sources
|
||||
}
|
||||
|
||||
// UpdateLocalRepo updates content from local repo in component
|
||||
func (p *PublishedRepo) UpdateLocalRepo(component string) {
|
||||
// UpdateLocalRepo inserts/updates local repository source for component
|
||||
func (p *PublishedRepo) UpdateLocalRepo(component string, localRepo *LocalRepo) {
|
||||
if p.SourceKind != SourceLocalRepo {
|
||||
panic("not local repo publish")
|
||||
}
|
||||
|
||||
item := p.sourceItems[component]
|
||||
item.packageRefs = item.localRepo.RefList()
|
||||
item, exists := p.sourceItems[component]
|
||||
if !exists {
|
||||
item = repoSourceItem{}
|
||||
}
|
||||
item.localRepo = localRepo
|
||||
item.packageRefs = localRepo.RefList()
|
||||
p.sourceItems[component] = item
|
||||
|
||||
p.Sources[component] = localRepo.UUID
|
||||
p.rePublishing = true
|
||||
}
|
||||
|
||||
// UpdateSnapshot switches snapshot for component
|
||||
// UpdateSnapshot inserts/updates snapshot source for component
|
||||
func (p *PublishedRepo) UpdateSnapshot(component string, snapshot *Snapshot) {
|
||||
if p.SourceKind != SourceSnapshot {
|
||||
panic("not snapshot publish")
|
||||
@@ -474,6 +675,14 @@ func (p *PublishedRepo) UpdateSnapshot(component string, snapshot *Snapshot) {
|
||||
p.rePublishing = true
|
||||
}
|
||||
|
||||
// RemoveComponent removes component from published repository
|
||||
func (p *PublishedRepo) RemoveComponent(component string) {
|
||||
delete(p.Sources, component)
|
||||
delete(p.sourceItems, component)
|
||||
|
||||
p.rePublishing = true
|
||||
}
|
||||
|
||||
// Encode does msgpack encoding of PublishedRepo
|
||||
func (p *PublishedRepo) Encode() []byte {
|
||||
var buf bytes.Buffer
|
||||
|
||||
Reference in New Issue
Block a user