Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to add/switch components of a published local repository #1356

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
263 changes: 216 additions & 47 deletions api/publish.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func Router(c *ctx.AptlyContext) http.Handler {
{

api.GET("/publish", apiPublishList)
api.GET("/publish/:prefix/:distribution", apiPublishShow)
api.POST("/publish", apiPublishRepoOrSnapshot)
api.POST("/publish/:prefix", apiPublishRepoOrSnapshot)
api.PUT("/publish/:prefix/:distribution", apiPublishUpdateSwitch)
Expand Down
1 change: 1 addition & 0 deletions cmd/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func makeCmdPublish() *commander.Command {
UsageLine: "publish",
Short: "manage published repositories",
Subcommands: []*commander.Command{
makeCmdPublishAdd(),
makeCmdPublishDrop(),
makeCmdPublishList(),
makeCmdPublishRepo(),
Expand Down
175 changes: 175 additions & 0 deletions cmd/publish_add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package cmd

import (
"fmt"
"strings"

"github.com/aptly-dev/aptly/deb"
"github.com/aptly-dev/aptly/utils"
"github.com/smira/commander"
"github.com/smira/flag"
)

func aptlyPublishAdd(cmd *commander.Command, args []string) error {
var (
err error
names []string
published *deb.PublishedRepo
)

components := strings.Split(context.Flags().Lookup("component").Value.String(), ",")

if len(args) < len(components)+1 || len(args) > len(components)+2 {
cmd.Usage()
return commander.ErrCommandError
}

distribution := args[0]
param := "."

if len(args) == len(components)+2 {
param = args[1]
names = args[2:]
} else {
names = args[1:]
}

if len(names) != len(components) {
return fmt.Errorf("mismatch in number of components (%d) and sources (%d)", len(components), len(names))
}

storage, prefix := deb.ParsePrefix(param)

collectionFactory := context.NewCollectionFactory()
published, err = collectionFactory.PublishedRepoCollection().ByStoragePrefixDistribution(storage, prefix, distribution)
if err != nil {
return fmt.Errorf("unable to add: %s", err)
}

err = collectionFactory.PublishedRepoCollection().LoadComplete(published, collectionFactory)
if err != nil {
return fmt.Errorf("unable to add: %s", err)
}

publishedComponents := published.Components()

if published.SourceKind == deb.SourceLocalRepo {
localRepoCollection := collectionFactory.LocalRepoCollection()
for i, component := range components {
if utils.StrSliceHasItem(publishedComponents, component) {
return fmt.Errorf("unable to add: component %s already exists in published local repository", component)
}

localRepo, err := localRepoCollection.ByName(names[i])
if err != nil {
return fmt.Errorf("unable to add: %s", err)
}

err = localRepoCollection.LoadComplete(localRepo)
if err != nil {
return fmt.Errorf("unable to add: %s", err)
}

published.UpsertLocalRepo(component, localRepo)
}
} else if published.SourceKind == deb.SourceSnapshot {
snapshotCollection := collectionFactory.SnapshotCollection()
for i, component := range components {
if utils.StrSliceHasItem(publishedComponents, component) {
return fmt.Errorf("unable to add: component %s already exists in published snapshot repository", component)
}

snapshot, err := snapshotCollection.ByName(names[i])
if err != nil {
return fmt.Errorf("unable to add: %s", err)
}

err = snapshotCollection.LoadComplete(snapshot)
if err != nil {
return fmt.Errorf("unable to add: %s", err)
}

published.UpsertSnapshot(component, snapshot)
}
} else {
return fmt.Errorf("unknown published repository type")
}

signer, err := getSigner(context.Flags())
if err != nil {
return fmt.Errorf("unable to initialize GPG signer: %s", err)
}

forceOverwrite := context.Flags().Lookup("force-overwrite").Value.Get().(bool)
if forceOverwrite {
context.Progress().ColoredPrintf("@rWARNING@|: force overwrite mode enabled, aptly might corrupt other published repositories sharing " +
"the same package pool.\n")
}

if context.Flags().IsSet("skip-contents") {
published.SkipContents = context.Flags().Lookup("skip-contents").Value.Get().(bool)
}

if context.Flags().IsSet("skip-bz2") {
published.SkipBz2 = context.Flags().Lookup("skip-bz2").Value.Get().(bool)
}

if context.Flags().IsSet("multi-dist") {
published.MultiDist = context.Flags().Lookup("multi-dist").Value.Get().(bool)
}

err = published.Publish(context.PackagePool(), context, collectionFactory, signer, context.Progress(), forceOverwrite)
if err != nil {
return fmt.Errorf("unable to publish: %s", err)
}

err = collectionFactory.PublishedRepoCollection().Update(published)
if err != nil {
return fmt.Errorf("unable to save to DB: %s", err)
}

context.Progress().Printf("\nPublished %s repository %s has been successfully updated by adding new source.\n", published.SourceKind, published.String())

return err
}

func makeCmdPublishAdd() *commander.Command {
cmd := &commander.Command{
Run: aptlyPublishAdd,
UsageLine: "add <distribution> [[<endpoint>:]<prefix>] <source>",
Short: "add package source to published repository",
Long: `
The command adds (in place) one or multiple package sources to a published repository.
All publishing parameters are preserved (architecture list, distribution, ...).

The flag -component is mandatory. Use a comma-separated list of components,
if multiple components should be added. The number of given components must be
equal to the number of sources, e.g.:

aptly publish add -component=main,contrib wheezy wheezy-main wheezy-contrib

Example:

$ aptly publish add -component=contrib wheezy ppa wheezy-contrib

This command assigns the snapshot wheezy-contrib to the component contrib and
adds it as new package source to the published repository ppa/wheezy.
`,
Flag: *flag.NewFlagSet("aptly-publish-add", flag.ExitOnError),
}
cmd.Flag.String("gpg-key", "", "GPG key ID to use when signing the release")
cmd.Flag.Var(&keyRingsFlag{}, "keyring", "GPG keyring to use (instead of default)")
cmd.Flag.String("secret-keyring", "", "GPG secret keyring to use (instead of default)")
cmd.Flag.String("passphrase", "", "GPG passphrase for the key (warning: could be insecure)")
cmd.Flag.String("passphrase-file", "", "GPG passphrase-file for the key (warning: could be insecure)")
cmd.Flag.String("prefix", "", "publishing prefix in the form of [<endpoint>:]<prefix>")
cmd.Flag.Bool("batch", false, "run GPG with detached tty")
cmd.Flag.Bool("skip-signing", false, "don't sign Release files with GPG")
cmd.Flag.Bool("skip-contents", false, "don't generate Contents indexes")
cmd.Flag.Bool("skip-bz2", false, "don't generate bzipped indexes")
cmd.Flag.String("component", "", "component names to add (for multi-component publishing, separate components with commas)")
cmd.Flag.Bool("force-overwrite", false, "overwrite files in package pool in case of mismatch")
cmd.Flag.Bool("multi-dist", false, "enable multiple packages with the same filename in different distributions")

return cmd
}
3 changes: 2 additions & 1 deletion cmd/publish_show.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ func aptlyPublishShowTxt(_ *commander.Command, args []string) error {
fmt.Printf("Architectures: %s\n", strings.Join(repo.Architectures, " "))

fmt.Printf("Sources:\n")
for component, sourceID := range repo.Sources {
for _, component := range repo.Components() {
sourceID := repo.Sources[component]
var name string
if repo.SourceKind == deb.SourceSnapshot {
source, e := collectionFactory.SnapshotCollection().ByUUID(sourceID)
Expand Down
7 changes: 5 additions & 2 deletions cmd/publish_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
origin := context.Flags().Lookup("origin").Value.String()
notAutomatic := context.Flags().Lookup("notautomatic").Value.String()
butAutomaticUpgrades := context.Flags().Lookup("butautomaticupgrades").Value.String()
multiDist := context.Flags().Lookup("multi-dist").Value.Get().(bool)

published, err := deb.NewPublishedRepo(storage, prefix, distribution, context.ArchitecturesList(), components, sources, collectionFactory)
if err != nil {
Expand Down Expand Up @@ -150,6 +149,10 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
published.AcquireByHash = context.Flags().Lookup("acquire-by-hash").Value.Get().(bool)
}

if context.Flags().IsSet("multi-dist") {
published.MultiDist = context.Flags().Lookup("multi-dist").Value.Get().(bool)
}

duplicate := collectionFactory.PublishedRepoCollection().CheckDuplicate(published)
if duplicate != nil {
collectionFactory.PublishedRepoCollection().LoadComplete(duplicate, collectionFactory)
Expand All @@ -166,7 +169,7 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
context.Progress().ColoredPrintf("@rWARNING@|: force overwrite mode enabled, aptly might corrupt other published repositories sharing the same package pool.\n")
}

err = published.Publish(context.PackagePool(), context, collectionFactory, signer, context.Progress(), forceOverwrite, multiDist)
err = published.Publish(context.PackagePool(), context, collectionFactory, signer, context.Progress(), forceOverwrite)
if err != nil {
return fmt.Errorf("unable to publish: %s", err)
}
Expand Down
86 changes: 56 additions & 30 deletions cmd/publish_switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ import (
"strings"

"github.com/aptly-dev/aptly/deb"
"github.com/aptly-dev/aptly/utils"
"github.com/smira/commander"
"github.com/smira/flag"
)

func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
var err error
var (
err error
names []string
)

components := strings.Split(context.Flags().Lookup("component").Value.String(), ",")
multiDist := context.Flags().Lookup("multi-dist").Value.Get().(bool)

if len(args) < len(components)+1 || len(args) > len(components)+2 {
cmd.Usage()
Expand All @@ -23,11 +26,6 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
distribution := args[0]
param := "."

var (
names []string
snapshot *deb.Snapshot
)

if len(args) == len(components)+2 {
param = args[1]
names = args[2:]
Expand All @@ -42,16 +40,12 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
collectionFactory := context.NewCollectionFactory()
published, err = collectionFactory.PublishedRepoCollection().ByStoragePrefixDistribution(storage, prefix, distribution)
if err != nil {
return fmt.Errorf("unable to update: %s", err)
}

if published.SourceKind != deb.SourceSnapshot {
return fmt.Errorf("unable to update: not a snapshot publish")
return fmt.Errorf("unable to switch: %s", err)
}

err = collectionFactory.PublishedRepoCollection().LoadComplete(published, collectionFactory)
if err != nil {
return fmt.Errorf("unable to update: %s", err)
return fmt.Errorf("unable to switch: %s", err)
}

publishedComponents := published.Components()
Expand All @@ -63,18 +57,46 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
return fmt.Errorf("mismatch in number of components (%d) and snapshots (%d)", len(components), len(names))
}

for i, component := range components {
snapshot, err = collectionFactory.SnapshotCollection().ByName(names[i])
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
}
if published.SourceKind == deb.SourceLocalRepo {
localRepoCollection := collectionFactory.LocalRepoCollection()
for i, component := range components {
if !utils.StrSliceHasItem(publishedComponents, component) {
return fmt.Errorf("unable to switch: component %s does not exist in published repository", component)
}

err = collectionFactory.SnapshotCollection().LoadComplete(snapshot)
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
}
localRepo, err := localRepoCollection.ByName(names[i])
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
}

published.UpdateSnapshot(component, snapshot)
err = localRepoCollection.LoadComplete(localRepo)
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
}

published.UpsertLocalRepo(component, localRepo)
}
} else if published.SourceKind == deb.SourceSnapshot {
snapshotCollection := collectionFactory.SnapshotCollection()
for i, component := range components {
if !utils.StrSliceHasItem(publishedComponents, component) {
return fmt.Errorf("unable to switch: component %s does not exist in published repository", component)
}

snapshot, err := snapshotCollection.ByName(names[i])
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
}

err = snapshotCollection.LoadComplete(snapshot)
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
}

published.UpsertSnapshot(component, snapshot)
}
} else {
return fmt.Errorf("unknown published repository type")
}

signer, err := getSigner(context.Flags())
Expand All @@ -96,7 +118,11 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
published.SkipBz2 = context.Flags().Lookup("skip-bz2").Value.Get().(bool)
}

err = published.Publish(context.PackagePool(), context, collectionFactory, signer, context.Progress(), forceOverwrite, multiDist)
if context.Flags().IsSet("multi-dist") {
published.MultiDist = context.Flags().Lookup("multi-dist").Value.Get().(bool)
}

err = published.Publish(context.PackagePool(), context, collectionFactory, signer, context.Progress(), forceOverwrite)
if err != nil {
return fmt.Errorf("unable to publish: %s", err)
}
Expand All @@ -111,27 +137,27 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
err = collectionFactory.PublishedRepoCollection().CleanupPrefixComponentFiles(published.Prefix, components,
context.GetPublishedStorage(storage), collectionFactory, context.Progress())
if err != nil {
return fmt.Errorf("unable to update: %s", err)
return fmt.Errorf("unable to switch: %s", err)
}
}

context.Progress().Printf("\nPublish for snapshot %s has been successfully switched to new snapshot.\n", published.String())
context.Progress().Printf("\nPublished %s repository %s has been successfully switched to new source.\n", published.SourceKind, published.String())

return err
}

func makeCmdPublishSwitch() *commander.Command {
cmd := &commander.Command{
Run: aptlyPublishSwitch,
UsageLine: "switch <distribution> [[<endpoint>:]<prefix>] <new-snapshot>",
Short: "update published repository by switching to new snapshot",
UsageLine: "switch <distribution> [[<endpoint>:]<prefix>] <new-source>",
Short: "update published repository by switching to new source",
Long: `
Command switches in-place published snapshots with new snapshot contents. All
Command switches in-place published snapshots with new source contents. All
publishing parameters are preserved (architecture list, distribution,
component).

For multiple component repositories, flag -component should be given with
list of components to update. Corresponding snapshots should be given in the
list of components to update. Corresponding sources should be given in the
same order, e.g.:

aptly publish switch -component=main,contrib wheezy wh-main wh-contrib
Expand Down
Loading
Loading