package cmd import ( "fmt" "github.com/smira/aptly/aptly" "github.com/smira/aptly/deb" "github.com/smira/aptly/utils" "github.com/smira/commander" "github.com/smira/flag" "strings" ) func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error { var err error components := strings.Split(context.flags.Lookup("component").Value.String(), ",") if len(args) < len(components) || len(args) > len(components)+1 { cmd.Usage() return commander.ErrCommandError } var prefix string if len(args) == len(components)+1 { prefix = args[len(components)] args = args[0 : len(args)-1] } else { prefix = "" } var ( sources = []interface{}{} message string ) if cmd.Name() == "snapshot" { var ( snapshot *deb.Snapshot emptyWarning = false 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 } } if len(parts) == 1 { message = fmt.Sprintf("Snapshot %s has", parts[0]) } else { message = fmt.Sprintf("Snapshots %s have", strings.Join(parts, ", ")) } if emptyWarning { 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" { var ( localRepo *deb.LocalRepo emptyWarning = false 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 } } if len(parts) == 1 { message = fmt.Sprintf("Local repo %s has", parts[0]) } else { message = fmt.Sprintf("Local repos %s have", strings.Join(parts, ", ")) } if emptyWarning { 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 { panic("unknown command") } distribution := context.flags.Lookup("distribution").Value.String() published, err := deb.NewPublishedRepo(prefix, distribution, context.ArchitecturesList(), components, sources, context.CollectionFactory()) if err != nil { return fmt.Errorf("unable to publish: %s", err) } published.Origin = cmd.Flag.Lookup("origin").Value.String() published.Label = cmd.Flag.Lookup("label").Value.String() duplicate := context.CollectionFactory().PublishedRepoCollection().CheckDuplicate(published) if duplicate != nil { context.CollectionFactory().PublishedRepoCollection().LoadComplete(duplicate, context.CollectionFactory()) return fmt.Errorf("prefix/distribution already used by another published repo: %s", duplicate) } signer, err := getSigner(context.flags) if err != nil { return fmt.Errorf("unable to initialize GPG signer: %s", err) } err = published.Publish(context.PackagePool(), context.PublishedStorage(), context.CollectionFactory(), signer, context.Progress()) if err != nil { return fmt.Errorf("unable to publish: %s", err) } err = context.CollectionFactory().PublishedRepoCollection().Add(published) if err != nil { return fmt.Errorf("unable to save to DB: %s", err) } var repoComponents string prefix, repoComponents, distribution = published.Prefix, strings.Join(published.Components(), " "), published.Distribution if prefix == "." { prefix = "" } else if !strings.HasSuffix(prefix, "/") { prefix += "/" } context.Progress().Printf("\n%s been successfully published.\n", message) if localStorage, ok := context.PublishedStorage().(aptly.LocalPublishedStorage); ok { context.Progress().Printf("Please setup your webserver to serve directory '%s' with autoindexing.\n", localStorage.PublicPath()) } 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, repoComponents) if utils.StrSliceHasItem(published.Architectures, "source") { 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("\nYou can also use `aptly serve` to publish your repositories over HTTP quickly.\n") return err } func makeCmdPublishSnapshot() *commander.Command { cmd := &commander.Command{ Run: aptlyPublishSnapshotOrRepo, UsageLine: "snapshot []", Short: "publish snapshot", Long: ` 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. 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: $ aptly publish snapshot wheezy-main `, Flag: *flag.NewFlagSet("aptly-publish-snapshot", flag.ExitOnError), } cmd.Flag.String("distribution", "", "distribution 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.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.Bool("skip-signing", false, "don't sign Release files with GPG") cmd.Flag.String("origin", "", "origin name to publish") cmd.Flag.String("label", "", "label to publish") return cmd }