// Remove removes published repository, cleaning up directories, files func (collection *PublishedRepoCollection) Remove(publishedStorageProvider aptly.PublishedStorageProvider, storage, prefix, distribution string, collectionFactory *CollectionFactory, progress aptly.Progress) error { repo, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution) if err != nil { return err } removePrefix := true removePoolComponents := repo.Components() cleanComponents := []string{} repoPosition := -1 for i, r := range collection.list { if r == repo { repoPosition = i continue } if r.Storage == repo.Storage && r.Prefix == repo.Prefix { removePrefix = false rComponents := r.Components() for _, component := range rComponents { if utils.StrSliceHasItem(removePoolComponents, component) { removePoolComponents = utils.StrSlicesSubstract(removePoolComponents, []string{component}) cleanComponents = append(cleanComponents, component) } } } } err = repo.RemoveFiles(publishedStorageProvider, removePrefix, removePoolComponents, progress) if err != nil { return err } collection.list[len(collection.list)-1], collection.list[repoPosition], collection.list = nil, collection.list[len(collection.list)-1], collection.list[:len(collection.list)-1] if len(cleanComponents) > 0 { err = collection.CleanupPrefixComponentFiles(repo.Prefix, cleanComponents, publishedStorageProvider.GetPublishedStorage(storage), collectionFactory, progress) if err != nil { return err } } err = collection.db.Delete(repo.Key()) if err != nil { return err } for _, component := range repo.Components() { err = collection.db.Delete(repo.RefKey(component)) if err != nil { return err } } return nil }
// BySnapshotSource looks up snapshots that have specified snapshot as a source func (collection *SnapshotCollection) BySnapshotSource(snapshot *Snapshot) []*Snapshot { result := make([]*Snapshot, 0) for _, s := range collection.list { if s.SourceKind == "snapshot" && utils.StrSliceHasItem(s.SourceIDs, snapshot.UUID) { result = append(result, s) } } return result }
// ByLocalRepoSource looks up snapshots that have specified LocalRepo as a source func (collection *SnapshotCollection) ByLocalRepoSource(repo *LocalRepo) []*Snapshot { result := make([]*Snapshot, 0) for _, s := range collection.list { if s.SourceKind == "local" && utils.StrSliceHasItem(s.SourceIDs, repo.UUID) { result = append(result, s) } } return result }
func (u *Uploaders) expandGroupsInternal(items []string, trail []string) []string { result := []string{} for _, item := range items { // stop infinite recursion if utils.StrSliceHasItem(trail, item) { continue } group, ok := u.Groups[item] if !ok { result = append(result, item) } else { newTrail := append([]string(nil), trail...) result = append(result, u.expandGroupsInternal(group, append(newTrail, item))...) } } return result }
// MatchesDependency checks whether package matches specified dependency func (p *Package) MatchesDependency(dep Dependency) bool { if dep.Architecture != "" && !p.MatchesArchitecture(dep.Architecture) { return false } if dep.Relation == VersionDontCare { if utils.StrSliceHasItem(p.Provides, dep.Pkg) { return true } return dep.Pkg == p.Name } if dep.Pkg != p.Name { return false } r := CompareVersions(p.Version, dep.Version) switch dep.Relation { case VersionEqual: return r == 0 case VersionLess: return r < 0 case VersionGreater: return r > 0 case VersionLessOrEqual: return r <= 0 case VersionGreaterOrEqual: return r >= 0 case VersionPatternMatch: matched, err := filepath.Match(dep.Version, p.Version) return err == nil && matched case VersionRegexp: return dep.Regexp.FindStringIndex(p.Version) != nil } panic("unknown relation") }
// WriteTo dumps sorted mapping of files to qualified package names func (index *ContentsIndex) WriteTo(w io.Writer) (int64, error) { var n int64 paths := make([]string, len(index.index)) i := 0 for path := range index.index { paths[i] = path i++ } sort.Strings(paths) nn, err := fmt.Fprintf(w, "%s %s\n", "FILE", "LOCATION") n += int64(nn) if err != nil { return n, err } for _, path := range paths { packages := index.index[path] parts := make([]string, 0, len(packages)) for i := range packages { name := packages[i].QualifiedName() if !utils.StrSliceHasItem(parts, name) { parts = append(parts, name) } } nn, err = fmt.Fprintf(w, "%s %s\n", path, strings.Join(parts, ",")) n += int64(nn) if err != nil { return n, err } } return n, nil }
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 param string if len(args) == len(components)+1 { param = args[len(components)] args = args[0 : len(args)-1] } else { param = "" } storage, prefix := deb.ParsePrefix(param) 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(storage, prefix, distribution, context.ArchitecturesList(), components, sources, context.CollectionFactory()) if err != nil { return fmt.Errorf("unable to publish: %s", err) } published.Origin = context.Flags().Lookup("origin").Value.String() published.Label = context.Flags().Lookup("label").Value.String() if context.Flags().IsSet("skip-contents") { published.SkipContents = context.Flags().Lookup("skip-contents").Value.Get().(bool) } 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) } 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") } err = published.Publish(context.PackagePool(), context, context.CollectionFactory(), signer, context.Progress(), forceOverwrite) 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.GetPublishedStorage(storage).(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 }
// CleanupPrefixComponentFiles removes all unreferenced files in published storage under prefix/component pair func (collection *PublishedRepoCollection) CleanupPrefixComponentFiles(prefix string, components []string, publishedStorage aptly.PublishedStorage, collectionFactory *CollectionFactory, progress aptly.Progress) error { var err error referencedFiles := map[string][]string{} if progress != nil { progress.Printf("Cleaning up prefix %#v components %s...\n", prefix, strings.Join(components, ", ")) } for _, r := range collection.list { if r.Prefix == prefix { matches := false repoComponents := r.Components() for _, component := range components { if utils.StrSliceHasItem(repoComponents, component) { matches = true break } } if !matches { continue } err = collection.LoadComplete(r, collectionFactory) if err != nil { return err } for _, component := range components { if utils.StrSliceHasItem(repoComponents, component) { packageList, err := NewPackageListFromRefList(r.RefList(component), collectionFactory.PackageCollection(), progress) if err != nil { return err } packageList.ForEach(func(p *Package) error { poolDir, err := p.PoolDirectory() if err != nil { return err } for _, f := range p.Files() { referencedFiles[component] = append(referencedFiles[component], filepath.Join(poolDir, f.Filename)) } return nil }) } } } } for _, component := range components { sort.Strings(referencedFiles[component]) rootPath := filepath.Join(prefix, "pool", component) existingFiles, err := publishedStorage.Filelist(rootPath) if err != nil { return err } sort.Strings(existingFiles) filesToDelete := utils.StrSlicesSubstract(existingFiles, referencedFiles[component]) for _, file := range filesToDelete { err = publishedStorage.Remove(filepath.Join(rootPath, file)) if err != nil { return err } } } return nil }
// Architectures returns list of architectures present in packages and flag if source packages are present. // // If includeSource is true, meta-architecture "source" would be present in the list func (l *PackageList) Architectures(includeSource bool) (result []string) { result = make([]string, 0, 10) for _, pkg := range l.packages { if pkg.Architecture != "all" && (pkg.Architecture != "source" || includeSource) && !utils.StrSliceHasItem(result, pkg.Architecture) { result = append(result, pkg.Architecture) } } return }
func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error { var err error if len(args) < 1 || len(args) > 2 { cmd.Usage() return err } name := args[0] var prefix string if len(args) == 2 { prefix = args[1] } else { prefix = "" } var ( source interface{} message string ) if cmd.Name() == "snapshot" { var snapshot *deb.Snapshot 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) } source = snapshot message = fmt.Sprintf("Snapshot %s", snapshot.Name) } else if cmd.Name() == "repo" { var localRepo *deb.LocalRepo 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) } source = localRepo message = fmt.Sprintf("Local repo %s", localRepo.Name) } else { panic("unknown command") } component := context.flags.Lookup("component").Value.String() distribution := context.flags.Lookup("distribution").Value.String() published, err := deb.NewPublishedRepo(prefix, distribution, component, context.ArchitecturesList(), source, 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) } prefix, component, distribution = published.Prefix, published.Component, published.Distribution if prefix == "." { prefix = "" } else if !strings.HasSuffix(prefix, "/") { prefix += "/" } context.Progress().Printf("\n%s has been successfully published.\nPlease setup your webserver to serve directory '%s' with autoindexing.\n", message, context.PublishedStorage().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, component) if utils.StrSliceHasItem(published.Architectures, "source") { context.Progress().Printf(" deb-src http://your-server/%s %s %s\n", prefix, distribution, component) } 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 aptlyServe(cmd *commander.Command, args []string) error { var err error if len(args) != 0 { cmd.Usage() return commander.ErrCommandError } if context.CollectionFactory().PublishedRepoCollection().Len() == 0 { fmt.Printf("No published repositories, unable to serve.\n") return nil } listen := context.Flags().Lookup("listen").Value.String() listenHost, listenPort, err := net.SplitHostPort(listen) if err != nil { return fmt.Errorf("wrong -listen specification: %s", err) } if listenHost == "" { listenHost, err = os.Hostname() if err != nil { listenHost = "localhost" } } fmt.Printf("Serving published repositories, recommended apt sources list:\n\n") sources := make(sort.StringSlice, 0, context.CollectionFactory().PublishedRepoCollection().Len()) published := make(map[string]*deb.PublishedRepo, context.CollectionFactory().PublishedRepoCollection().Len()) err = context.CollectionFactory().PublishedRepoCollection().ForEach(func(repo *deb.PublishedRepo) error { err := context.CollectionFactory().PublishedRepoCollection().LoadComplete(repo, context.CollectionFactory()) if err != nil { return err } sources = append(sources, repo.String()) published[repo.String()] = repo return nil }) if err != nil { return fmt.Errorf("unable to serve: %s", err) } sort.Strings(sources) for _, source := range sources { repo := published[source] prefix := repo.Prefix if prefix == "." { prefix = "" } else { prefix += "/" } fmt.Printf("# %s\ndeb http://%s:%s/%s %s %s\n", repo, listenHost, listenPort, prefix, repo.Distribution, strings.Join(repo.Components(), " ")) if utils.StrSliceHasItem(repo.Architectures, "source") { fmt.Printf("deb-src http://%s:%s/%s %s %s\n", listenHost, listenPort, prefix, repo.Distribution, strings.Join(repo.Components(), " ")) } } publicPath := context.GetPublishedStorage("").(aptly.LocalPublishedStorage).PublicPath() ShutdownContext() fmt.Printf("\nStarting web server at: %s (press Ctrl+C to quit)...\n", listen) err = http.ListenAndServe(listen, http.FileServer(http.Dir(publicPath))) if err != nil { return fmt.Errorf("unable to serve: %s", err) } return nil }
func (a *Api) PublishSwitch(prefix, distribution string, snapshots []PublishSource, forceOverwrite bool, signingOptions SigningOptions) (*deb.PublishedRepo, error) { param := parseEscapedPath(prefix) storage, prefix := deb.ParsePrefix(param) signer, err := getSigner(&signingOptions) if err != nil { return nil, fmt.Errorf("unable to initialize GPG signer: %s", err) } // published.LoadComplete would touch local repo collection localRepoCollection := a.Ctx().CollectionFactory().LocalRepoCollection() localRepoCollection.RLock() defer localRepoCollection.RUnlock() snapshotCollection := a.Ctx().CollectionFactory().SnapshotCollection() snapshotCollection.RLock() defer snapshotCollection.RUnlock() collection := a.Ctx().CollectionFactory().PublishedRepoCollection() collection.Lock() defer collection.Unlock() published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution) if err != nil { return nil, fmt.Errorf("unable to update: %s", err) } err = collection.LoadComplete(published, a.Ctx().CollectionFactory()) if err != nil { return nil, fmt.Errorf("unable to update: %s", err) } var updatedComponents []string if published.SourceKind == "local" { if len(snapshots) > 0 { return nil, fmt.Errorf("snapshots shouldn't be given when updating local repo") } updatedComponents = published.Components() for _, component := range updatedComponents { published.UpdateLocalRepo(component) } } else if published.SourceKind == "snapshot" { publishedComponents := published.Components() for _, snapshotInfo := range snapshots { if !utils.StrSliceHasItem(publishedComponents, snapshotInfo.Component) { return nil, fmt.Errorf("component %s is not in published repository", snapshotInfo.Component) } snapshot, err := snapshotCollection.ByName(snapshotInfo.Name) if err != nil { return nil, err } err = snapshotCollection.LoadComplete(snapshot) if err != nil { return nil, err } published.UpdateSnapshot(snapshotInfo.Component, snapshot) updatedComponents = append(updatedComponents, snapshotInfo.Component) } } else { return nil, fmt.Errorf("unknown published repository type") } err = published.Publish(a.Ctx().PackagePool(), a.Ctx(), a.Ctx().CollectionFactory(), signer, nil, forceOverwrite) if err != nil { return nil, fmt.Errorf("unable to update: %s", err) } err = collection.Update(published) if err != nil { return nil, fmt.Errorf("unable to save to DB: %s", err) } err = collection.CleanupPrefixComponentFiles(published.Prefix, updatedComponents, a.Ctx().GetPublishedStorage(storage), a.Ctx().CollectionFactory(), nil) if err != nil { return nil, fmt.Errorf("unable to update: %s", err) } return published, nil }
func aptlyServe(cmd *commander.Command, args []string) error { var err error publishedCollection := debian.NewPublishedRepoCollection(context.database) snapshotCollection := debian.NewSnapshotCollection(context.database) if publishedCollection.Len() == 0 { fmt.Printf("No published repositories, unable to serve.\n") return nil } listen := cmd.Flag.Lookup("listen").Value.String() listenHost, listenPort, err := net.SplitHostPort(listen) if err != nil { return fmt.Errorf("wrong -listen specification: %s", err) } if listenHost == "" { listenHost, err = os.Hostname() if err != nil { listenHost = "localhost" } } fmt.Printf("Serving published repositories, recommended apt sources list:\n\n") sources := make(sort.StringSlice, 0, publishedCollection.Len()) published := make(map[string]*debian.PublishedRepo, publishedCollection.Len()) err = publishedCollection.ForEach(func(repo *debian.PublishedRepo) error { err := publishedCollection.LoadComplete(repo, snapshotCollection) if err != nil { return err } sources = append(sources, repo.String()) published[repo.String()] = repo return nil }) if err != nil { return fmt.Errorf("unable to serve: %s", err) } sort.Strings(sources) for _, source := range sources { repo := published[source] prefix := repo.Prefix if prefix == "." { prefix = "" } else { prefix += "/" } fmt.Printf("# %s\ndeb http://%s:%s/%s %s %s\n", repo, listenHost, listenPort, prefix, repo.Distribution, repo.Component) if utils.StrSliceHasItem(repo.Architectures, "source") { fmt.Printf("deb-src http://%s:%s/%s %s %s\n", listenHost, listenPort, prefix, repo.Distribution, repo.Component) } } context.database.Close() fmt.Printf("\nStarting web server at: %s (press Ctrl+C to quit)...\n", listen) err = http.ListenAndServe(listen, http.FileServer(http.Dir(context.packageRepository.PublicPath()))) if err != nil { return fmt.Errorf("unable to serve: %s", err) } return nil }
// PUT /publish/:prefix/:distribution func apiPublishUpdateSwitch(c *gin.Context) { param := parseEscapedPath(c.Params.ByName("prefix")) storage, prefix := deb.ParsePrefix(param) distribution := c.Params.ByName("distribution") var b struct { ForceOverwrite bool Signing SigningOptions SkipContents *bool Snapshots []struct { Component string `binding:"required"` Name string `binding:"required"` } } if !c.Bind(&b) { return } signer, err := getSigner(&b.Signing) if err != nil { c.Fail(500, fmt.Errorf("unable to initialize GPG signer: %s", err)) return } // published.LoadComplete would touch local repo collection localRepoCollection := context.CollectionFactory().LocalRepoCollection() localRepoCollection.RLock() defer localRepoCollection.RUnlock() snapshotCollection := context.CollectionFactory().SnapshotCollection() snapshotCollection.RLock() defer snapshotCollection.RUnlock() collection := context.CollectionFactory().PublishedRepoCollection() collection.Lock() defer collection.Unlock() published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution) if err != nil { c.Fail(404, fmt.Errorf("unable to update: %s", err)) return } err = collection.LoadComplete(published, context.CollectionFactory()) if err != nil { c.Fail(500, fmt.Errorf("unable to update: %s", err)) return } var updatedComponents []string if published.SourceKind == "local" { if len(b.Snapshots) > 0 { c.Fail(400, fmt.Errorf("snapshots shouldn't be given when updating local repo")) return } updatedComponents = published.Components() for _, component := range updatedComponents { published.UpdateLocalRepo(component) } } else if published.SourceKind == "snapshot" { publishedComponents := published.Components() for _, snapshotInfo := range b.Snapshots { if !utils.StrSliceHasItem(publishedComponents, snapshotInfo.Component) { c.Fail(404, fmt.Errorf("component %s is not in published repository", snapshotInfo.Component)) return } snapshot, err := snapshotCollection.ByName(snapshotInfo.Name) if err != nil { c.Fail(404, err) return } err = snapshotCollection.LoadComplete(snapshot) if err != nil { c.Fail(500, err) return } published.UpdateSnapshot(snapshotInfo.Component, snapshot) updatedComponents = append(updatedComponents, snapshotInfo.Component) } } else { c.Fail(500, fmt.Errorf("unknown published repository type")) return } if b.SkipContents != nil { published.SkipContents = *b.SkipContents } err = published.Publish(context.PackagePool(), context, context.CollectionFactory(), signer, nil, b.ForceOverwrite) if err != nil { c.Fail(500, fmt.Errorf("unable to update: %s", err)) return } err = collection.Update(published) if err != nil { c.Fail(500, fmt.Errorf("unable to save to DB: %s", err)) return } err = collection.CleanupPrefixComponentFiles(published.Prefix, updatedComponents, context.GetPublishedStorage(storage), context.CollectionFactory(), nil) if err != nil { c.Fail(500, fmt.Errorf("unable to update: %s", err)) return } c.JSON(200, published) }
func aptlyPublishSwitch(cmd *commander.Command, args []string) error { var err error 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 := "." var ( names []string snapshot *deb.Snapshot ) if len(args) == len(components)+2 { param = args[1] names = args[2:] } else { names = args[1:] } storage, prefix := deb.ParsePrefix(param) var published *deb.PublishedRepo published, err = context.CollectionFactory().PublishedRepoCollection().ByStoragePrefixDistribution(storage, prefix, distribution) if err != nil { return fmt.Errorf("unable to update: %s", err) } if published.SourceKind != "snapshot" { return fmt.Errorf("unable to update: not a snapshot publish") } err = context.CollectionFactory().PublishedRepoCollection().LoadComplete(published, context.CollectionFactory()) if err != nil { return fmt.Errorf("unable to update: %s", err) } publishedComponents := published.Components() if len(components) == 1 && len(publishedComponents) == 1 && components[0] == "" { components = publishedComponents } 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 { if !utils.StrSliceHasItem(publishedComponents, component) { return fmt.Errorf("unable to switch: component %s is not in published repository", component) } 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()) 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) } err = published.Publish(context.PackagePool(), context, context.CollectionFactory(), signer, context.Progress(), forceOverwrite) if err != nil { return fmt.Errorf("unable to publish: %s", err) } err = context.CollectionFactory().PublishedRepoCollection().Update(published) if err != nil { return fmt.Errorf("unable to save to DB: %s", err) } err = context.CollectionFactory().PublishedRepoCollection().CleanupPrefixComponentFiles(published.Prefix, components, context.GetPublishedStorage(storage), context.CollectionFactory(), context.Progress()) if err != nil { return fmt.Errorf("unable to update: %s", err) } context.Progress().Printf("\nPublish for snapshot %s has been successfully switched to new snapshot.\n", published.String()) return err }
func aptlyPublishSnapshot(cmd *commander.Command, args []string) error { var err error if len(args) < 1 || len(args) > 2 { cmd.Usage() return err } name := args[0] var prefix string if len(args) == 2 { prefix = args[1] } else { prefix = "" } publishedCollecton := debian.NewPublishedRepoCollection(context.database) snapshotCollection := debian.NewSnapshotCollection(context.database) snapshot, err := snapshotCollection.ByName(name) if err != nil { return fmt.Errorf("unable to publish: %s", err) } err = snapshotCollection.LoadComplete(snapshot) if err != nil { return fmt.Errorf("unable to publish: %s", err) } var sourceRepo *debian.RemoteRepo if snapshot.SourceKind == "repo" && len(snapshot.SourceIDs) == 1 { repoCollection := debian.NewRemoteRepoCollection(context.database) sourceRepo, _ = repoCollection.ByUUID(snapshot.SourceIDs[0]) } component := cmd.Flag.Lookup("component").Value.String() if component == "" { if sourceRepo != nil && len(sourceRepo.Components) == 1 { component = sourceRepo.Components[0] } else { component = "main" } } distribution := cmd.Flag.Lookup("distribution").Value.String() if distribution == "" { if sourceRepo != nil { distribution = sourceRepo.Distribution } if distribution == "" { return fmt.Errorf("unable to guess distribution name, please specify explicitly") } } published, err := debian.NewPublishedRepo(prefix, distribution, component, context.architecturesList, snapshot) if err != nil { return fmt.Errorf("unable to publish: %s", err) } duplicate := publishedCollecton.CheckDuplicate(published) if duplicate != nil { publishedCollecton.LoadComplete(duplicate, snapshotCollection) return fmt.Errorf("prefix/distribution already used by another published repo: %s", duplicate) } signer, err := getSigner(cmd) if err != nil { return fmt.Errorf("unable to initialize GPG signer: %s", err) } packageCollection := debian.NewPackageCollection(context.database) err = published.Publish(context.packagePool, context.publishedStorage, packageCollection, signer) if err != nil { return fmt.Errorf("unable to publish: %s", err) } err = publishedCollecton.Add(published) if err != nil { return fmt.Errorf("unable to save to DB: %s", err) } if prefix != "" && !strings.HasSuffix(prefix, "/") { prefix += "/" } fmt.Printf("\nSnapshot %s has been successfully published.\nPlease setup your webserver to serve directory '%s' with autoindexing.\n", snapshot.Name, context.publishedStorage.PublicPath()) fmt.Printf("Now you can add following line to apt sources:\n") fmt.Printf(" deb http://your-server/%s %s %s\n", prefix, distribution, component) if utils.StrSliceHasItem(published.Architectures, "source") { fmt.Printf(" deb-src http://your-server/%s %s %s\n", prefix, distribution, component) } fmt.Printf("Don't forget to add your GPG key to apt with apt-key.\n") fmt.Printf("\nYou can also use `aptly serve` to publish your repositories over HTTP quickly.\n") return err }