Update commands to handle multiple components repositories. #36

This commit is contained in:
Andrey Smirnov
2014-06-04 17:43:16 +04:00
parent d218159455
commit 9a34b4ff1f
5 changed files with 177 additions and 64 deletions
+7 -1
View File
@@ -15,6 +15,12 @@ Command publishes current state of local repository ready to be consumed
by apt tools. Published repostiories appear under rootDir/public directory. by apt tools. Published repostiories appear under rootDir/public directory.
Valid GPG key is required for publishing. Valid GPG key is required for publishing.
Multiple component repository could be published by specifying several
components split by commas via -component flag and multiple local
repositories as the arguments:
aptly publish repo -component=main,contrib repo-main repo-contrib
It is not recommended to publish local repositories directly unless the It is not recommended to publish local repositories directly unless the
repository is for testing purposes and changes happen frequently. For repository is for testing purposes and changes happen frequently. For
production usage please take snapshot of repository and publish it production usage please take snapshot of repository and publish it
@@ -27,7 +33,7 @@ Example:
Flag: *flag.NewFlagSet("aptly-publish-repo", flag.ExitOnError), Flag: *flag.NewFlagSet("aptly-publish-repo", flag.ExitOnError),
} }
cmd.Flag.String("distribution", "", "distribution name to publish") cmd.Flag.String("distribution", "", "distribution name to publish")
cmd.Flag.String("component", "", "component name to publish") cmd.Flag.String("component", "", "component name to publish (for multi-component publishing, separate components with commas)")
cmd.Flag.String("gpg-key", "", "GPG key ID to use when signing the release") 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.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("secret-keyring", "", "GPG secret keyring to use (instead of default)")
+78 -34
View File
@@ -11,69 +11,106 @@ import (
func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error { func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
var err error var err error
if len(args) < 1 || len(args) > 2 {
components := strings.Split(context.flags.Lookup("component").Value.String(), ",")
if len(args) < len(components) || len(args) > len(components)+1 {
cmd.Usage() cmd.Usage()
return commander.ErrCommandError return commander.ErrCommandError
} }
name := args[0]
var prefix string var prefix string
if len(args) == 2 { if len(args) == len(components)+1 {
prefix = args[1] prefix = args[len(components)]
args = args[0 : len(args)-1]
} else { } else {
prefix = "" prefix = ""
} }
var ( var (
source interface{} sources = []interface{}{}
message string message string
) )
if cmd.Name() == "snapshot" { if cmd.Name() == "snapshot" {
var snapshot *deb.Snapshot var (
snapshot, err = context.CollectionFactory().SnapshotCollection().ByName(name) snapshot *deb.Snapshot
if err != nil { emptyWarning = false
return fmt.Errorf("unable to publish: %s", err) parts = []string{}
)
for _, name := range args {
snapshot, err = context.CollectionFactory().SnapshotCollection().ByName(name)
if err != nil {
return fmt.Errorf("unable to publish: %s", err)
}
err = context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
if err != nil {
return fmt.Errorf("unable to publish: %s", err)
}
sources = append(sources, snapshot)
parts = append(parts, snapshot.Name)
if snapshot.NumPackages() == 0 {
emptyWarning = true
}
} }
err = context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot) if len(parts) == 1 {
if err != nil { message = fmt.Sprintf("Snapshot %s", parts[0])
return fmt.Errorf("unable to publish: %s", err) } else {
message = fmt.Sprintf("Snapshots %s", strings.Join(parts, ", "))
} }
source = snapshot if emptyWarning {
message = fmt.Sprintf("Snapshot %s", snapshot.Name)
if snapshot.NumPackages() == 0 {
context.Progress().Printf("Warning: publishing from empty source, architectures list should be complete, it can't be changed after publishing (use -architectures flag)\n") context.Progress().Printf("Warning: publishing from empty source, architectures list should be complete, it can't be changed after publishing (use -architectures flag)\n")
} }
} else if cmd.Name() == "repo" { } else if cmd.Name() == "repo" {
var localRepo *deb.LocalRepo var (
localRepo, err = context.CollectionFactory().LocalRepoCollection().ByName(name) localRepo *deb.LocalRepo
if err != nil { emptyWarning = false
return fmt.Errorf("unable to publish: %s", err) parts = []string{}
)
for _, name := range args {
localRepo, err = context.CollectionFactory().LocalRepoCollection().ByName(name)
if err != nil {
return fmt.Errorf("unable to publish: %s", err)
}
err = context.CollectionFactory().LocalRepoCollection().LoadComplete(localRepo)
if err != nil {
return fmt.Errorf("unable to publish: %s", err)
}
sources = append(sources, localRepo)
parts = append(parts, localRepo.Name)
if localRepo.NumPackages() == 0 {
emptyWarning = true
}
} }
err = context.CollectionFactory().LocalRepoCollection().LoadComplete(localRepo) if len(parts) == 1 {
if err != nil { message = fmt.Sprintf("Local repo %s", parts[0])
return fmt.Errorf("unable to publish: %s", err) } else {
message = fmt.Sprintf("Local repos %s", strings.Join(parts, ", "))
} }
source = localRepo if emptyWarning {
message = fmt.Sprintf("Local repo %s", localRepo.Name)
if localRepo.NumPackages() == 0 {
context.Progress().Printf("Warning: publishing from empty source, architectures list should be complete, it can't be changed after publishing (use -architectures flag)\n") context.Progress().Printf("Warning: publishing from empty source, architectures list should be complete, it can't be changed after publishing (use -architectures flag)\n")
} }
} else { } else {
panic("unknown command") panic("unknown command")
} }
component := context.flags.Lookup("component").Value.String()
distribution := context.flags.Lookup("distribution").Value.String() distribution := context.flags.Lookup("distribution").Value.String()
published, err := deb.NewPublishedRepo(prefix, distribution, context.ArchitecturesList(), []string{component}, []interface{}{source}, context.CollectionFactory()) published, err := deb.NewPublishedRepo(prefix, distribution, context.ArchitecturesList(), components, sources, context.CollectionFactory())
if err != nil { if err != nil {
return fmt.Errorf("unable to publish: %s", err) return fmt.Errorf("unable to publish: %s", err)
} }
@@ -101,7 +138,8 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
return fmt.Errorf("unable to save to DB: %s", err) return fmt.Errorf("unable to save to DB: %s", err)
} }
prefix, component, distribution = published.Prefix, strings.Join(published.Components(), " "), published.Distribution var repoComponents string
prefix, repoComponents, distribution = published.Prefix, strings.Join(published.Components(), " "), published.Distribution
if prefix == "." { if prefix == "." {
prefix = "" prefix = ""
} else if !strings.HasSuffix(prefix, "/") { } else if !strings.HasSuffix(prefix, "/") {
@@ -111,9 +149,9 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
context.Progress().Printf("\n%s has been successfully published.\nPlease setup your webserver to serve directory '%s' with autoindexing.\n", context.Progress().Printf("\n%s has been successfully published.\nPlease setup your webserver to serve directory '%s' with autoindexing.\n",
message, context.PublishedStorage().PublicPath()) message, context.PublishedStorage().PublicPath())
context.Progress().Printf("Now you can add following line to apt sources:\n") context.Progress().Printf("Now you can add following line to apt sources:\n")
context.Progress().Printf(" deb http://your-server/%s %s %s\n", prefix, distribution, component) context.Progress().Printf(" deb http://your-server/%s %s %s\n", prefix, distribution, repoComponents)
if utils.StrSliceHasItem(published.Architectures, "source") { if utils.StrSliceHasItem(published.Architectures, "source") {
context.Progress().Printf(" deb-src http://your-server/%s %s %s\n", prefix, distribution, component) context.Progress().Printf(" deb-src http://your-server/%s %s %s\n", prefix, distribution, repoComponents)
} }
context.Progress().Printf("Don't forget to add your GPG key to apt with apt-key.\n") context.Progress().Printf("Don't forget to add your GPG key to apt with apt-key.\n")
context.Progress().Printf("\nYou can also use `aptly serve` to publish your repositories over HTTP quickly.\n") context.Progress().Printf("\nYou can also use `aptly serve` to publish your repositories over HTTP quickly.\n")
@@ -131,6 +169,12 @@ Command publishes snapshot as Debian repository ready to be consumed
by apt tools. Published repostiories appear under rootDir/public directory. by apt tools. Published repostiories appear under rootDir/public directory.
Valid GPG key is required for publishing. Valid GPG key is required for publishing.
Multiple component repository could be published by specifying several
components split by commas via -component flag and multiple snapshots
as the arguments:
aptly publish snapshot -component=main,contrib snap-main snap-contrib
Example: Example:
$ aptly publish snapshot wheezy-main $ aptly publish snapshot wheezy-main
@@ -138,7 +182,7 @@ Example:
Flag: *flag.NewFlagSet("aptly-publish-snapshot", flag.ExitOnError), Flag: *flag.NewFlagSet("aptly-publish-snapshot", flag.ExitOnError),
} }
cmd.Flag.String("distribution", "", "distribution name to publish") cmd.Flag.String("distribution", "", "distribution name to publish")
cmd.Flag.String("component", "", "component name to publish") cmd.Flag.String("component", "", "component name to publish (for multi-component publishing, separate components with commas)")
cmd.Flag.String("gpg-key", "", "GPG key ID to use when signing the release") 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.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("secret-keyring", "", "GPG secret keyring to use (instead of default)")
+38 -21
View File
@@ -5,11 +5,15 @@ import (
"github.com/smira/aptly/deb" "github.com/smira/aptly/deb"
"github.com/smira/commander" "github.com/smira/commander"
"github.com/smira/flag" "github.com/smira/flag"
"strings"
) )
func aptlyPublishSwitch(cmd *commander.Command, args []string) error { func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
var err error var err error
if len(args) < 2 || len(args) > 3 {
components := strings.Split(context.flags.Lookup("component").Value.String(), ",")
if len(args) < len(components)+1 || len(args) > len(components)+2 {
cmd.Usage() cmd.Usage()
return commander.ErrCommandError return commander.ErrCommandError
} }
@@ -18,25 +22,15 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
prefix := "." prefix := "."
var ( var (
name string names []string
snapshot *deb.Snapshot snapshot *deb.Snapshot
) )
if len(args) == 3 { if len(args) == len(components)+2 {
prefix = args[1] prefix = args[1]
name = args[2] names = args[2:]
} else { } else {
name = args[1] names = args[1:]
}
snapshot, err = context.CollectionFactory().SnapshotCollection().ByName(name)
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
}
err = context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
} }
var published *deb.PublishedRepo var published *deb.PublishedRepo
@@ -55,13 +49,28 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
return fmt.Errorf("unable to update: %s", err) return fmt.Errorf("unable to update: %s", err)
} }
components := published.Components() publishedComponents := published.Components()
if len(components) > 1 { if len(components) == 1 && len(publishedComponents) == 1 && components[0] == "" {
panic("TODO: NOT IMPLEMENTED YET") components = publishedComponents
} }
component := components[0]
published.UpdateSnapshot(component, snapshot) if len(names) != len(components) {
return fmt.Errorf("mismatch in number of components (%d) and snapshots (%d)", len(components), len(names))
}
for i, component := range components {
snapshot, err = context.CollectionFactory().SnapshotCollection().ByName(names[i])
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
}
err = context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
if err != nil {
return fmt.Errorf("unable to switch: %s", err)
}
published.UpdateSnapshot(component, snapshot)
}
signer, err := getSigner(context.flags) signer, err := getSigner(context.flags)
if err != nil { if err != nil {
@@ -96,7 +105,14 @@ func makeCmdPublishSwitch() *commander.Command {
Short: "update published repository by switching to new snapshot", Short: "update published repository by switching to new snapshot",
Long: ` Long: `
Command switches in-place published repository with new snapshot contents. All Command switches in-place published repository with new snapshot contents. All
publishing parameters are preserved (architecture list, distribution, component). 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
same order, e.g.:
aptly publish update -component=main,contrib wheezy wh-main wh-contrib
Example: Example:
@@ -108,6 +124,7 @@ Example:
cmd.Flag.Var(&keyRingsFlag{}, "keyring", "GPG keyring to use (instead of default)") 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("secret-keyring", "", "GPG secret keyring to use (instead of default)")
cmd.Flag.Bool("skip-signing", false, "don't sign Release files with GPG") cmd.Flag.Bool("skip-signing", false, "don't sign Release files with GPG")
cmd.Flag.String("component", "", "component names to update (for multi-component publishing, separate components with commas)")
return cmd return cmd
} }
+5 -5
View File
@@ -38,12 +38,9 @@ func aptlyPublishUpdate(cmd *commander.Command, args []string) error {
} }
components := published.Components() components := published.Components()
if len(components) > 1 { for _, component := range components {
panic("TODO: NOT IMPLEMENTED YET") published.UpdateLocalRepo(component)
} }
component := components[0]
published.UpdateLocalRepo(component)
signer, err := getSigner(context.flags) signer, err := getSigner(context.flags)
if err != nil { if err != nil {
@@ -82,6 +79,9 @@ and <prefix> should be occupied with local repository published
using command aptly publish repo. Update happens in-place with using command aptly publish repo. Update happens in-place with
minimum possible downtime for published repository. minimum possible downtime for published repository.
For multiple component published repositories, all local repositories
are updated.
Example: Example:
$ aptly publish update wheezy ppa $ aptly publish update wheezy ppa
+49 -3
View File
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "APTLY" "1" "May 2014" "" "" .TH "APTLY" "1" "June 2014" "" ""
. .
.SH "NAME" .SH "NAME"
\fBaptly\fR \- Debian repository management tool \fBaptly\fR \- Debian repository management tool
@@ -744,6 +744,19 @@ display list in machine\-readable format
Command publishes current state of local repository ready to be consumed by apt tools\. Published repostiories appear under rootDir/public directory\. Valid GPG key is required for publishing\. Command publishes current state of local repository ready to be consumed by apt tools\. Published repostiories appear under rootDir/public directory\. Valid GPG key is required for publishing\.
. .
.P .P
Multiple component repository could be published by specifying several components split by commas via \-component flag and multiple local repositories as the arguments:
.
.IP "" 4
.
.nf
aptly publish repo \-component=main,contrib repo\-main repo\-contrib
.
.fi
.
.IP "" 0
.
.P
It is not recommended to publish local repositories directly unless the repository is for testing purposes and changes happen frequently\. For production usage please take snapshot of repository and publish it using publish snapshot command\. It is not recommended to publish local repositories directly unless the repository is for testing purposes and changes happen frequently\. For production usage please take snapshot of repository and publish it using publish snapshot command\.
. .
.P .P
@@ -764,7 +777,7 @@ Options:
. .
.TP .TP
\-\fBcomponent\fR= \-\fBcomponent\fR=
component name to publish component name to publish (for multi\-component publishing, separate components with commas)
. .
.TP .TP
\-\fBdistribution\fR= \-\fBdistribution\fR=
@@ -801,6 +814,19 @@ don\(cqt sign Release files with GPG
Command publishes snapshot as Debian repository ready to be consumed by apt tools\. Published repostiories appear under rootDir/public directory\. Valid GPG key is required for publishing\. Command publishes snapshot as Debian repository ready to be consumed by apt tools\. Published repostiories appear under rootDir/public directory\. Valid GPG key is required for publishing\.
. .
.P .P
Multiple component repository could be published by specifying several components split by commas via \-component flag and multiple snapshots as the arguments:
.
.IP "" 4
.
.nf
aptly publish snapshot \-component=main,contrib snap\-main snap\-contrib
.
.fi
.
.IP "" 0
.
.P
Example: Example:
. .
.IP "" 4 .IP "" 4
@@ -818,7 +844,7 @@ Options:
. .
.TP .TP
\-\fBcomponent\fR= \-\fBcomponent\fR=
component name to publish component name to publish (for multi\-component publishing, separate components with commas)
. .
.TP .TP
\-\fBdistribution\fR= \-\fBdistribution\fR=
@@ -855,6 +881,19 @@ don\(cqt sign Release files with GPG
Command switches in\-place published repository with new snapshot contents\. All publishing parameters are preserved (architecture list, distribution, component)\. Command switches in\-place published repository with new snapshot contents\. All publishing parameters are preserved (architecture list, distribution, component)\.
. .
.P .P
For multiple component repositories, flag \-component should be given with list of components to update\. Corresponding snapshots should be given in the same order, e\.g\.:
.
.IP "" 4
.
.nf
aptly publish update \-component=main,contrib wheezy wh\-main wh\-contrib
.
.fi
.
.IP "" 0
.
.P
Example: Example:
. .
.IP "" 4 .IP "" 4
@@ -871,6 +910,10 @@ $ aptly publish update wheezy ppa wheezy\-7\.5
Options: Options:
. .
.TP .TP
\-\fBcomponent\fR=
component names to update (for multi\-component publishing, separate components with commas)
.
.TP
\-\fBgpg\-key\fR= \-\fBgpg\-key\fR=
GPG key ID to use when signing the release GPG key ID to use when signing the release
. .
@@ -893,6 +936,9 @@ don\(cqt sign Release files with GPG
Command re\-publishes (updates) published local repository\. \fIdistribution\fR and \fIprefix\fR should be occupied with local repository published using command aptly publish repo\. Update happens in\-place with minimum possible downtime for published repository\. Command re\-publishes (updates) published local repository\. \fIdistribution\fR and \fIprefix\fR should be occupied with local repository published using command aptly publish repo\. Update happens in\-place with minimum possible downtime for published repository\.
. .
.P .P
For multiple component published repositories, all local repositories are updated\.
.
.P
Example: Example:
. .
.IP "" 4 .IP "" 4