func aptlyPublishDrop(cmd *commander.Command, args []string) error { var err error if len(args) < 1 || len(args) > 2 { cmd.Usage() return err } distribution := args[0] prefix := "." if len(args) == 2 { prefix = args[1] } publishedCollecton := debian.NewPublishedRepoCollection(context.database) err = publishedCollecton.Remove(context.packageRepository, prefix, distribution) if err != nil { return fmt.Errorf("unable to remove: %s", err) } fmt.Printf("\nPublished repositroy has been removed successfully.\n") return err }
func aptlySnapshotDrop(cmd *commander.Command, args []string) error { var err error if len(args) != 1 { cmd.Usage() return err } name := args[0] snapshotCollection := debian.NewSnapshotCollection(context.database) snapshot, err := snapshotCollection.ByName(name) if err != nil { return fmt.Errorf("unable to drop: %s", err) } publishedRepoCollection := debian.NewPublishedRepoCollection(context.database) published := publishedRepoCollection.BySnapshot(snapshot) if len(published) > 0 { fmt.Printf("Snapshot `%s` is published currently:\n", snapshot.Name) for _, repo := range published { err = publishedRepoCollection.LoadComplete(repo, snapshotCollection) if err != nil { return fmt.Errorf("unable to load published: %s", err) } fmt.Printf(" * %s\n", repo) } return fmt.Errorf("unable to drop: snapshot is published") } force := cmd.Flag.Lookup("force").Value.Get().(bool) if !force { snapshots := snapshotCollection.BySnapshotSource(snapshot) if len(snapshots) > 0 { fmt.Printf("Snapshot `%s` was used as a source in following snapshots:\n", snapshot.Name) for _, snap := range snapshots { fmt.Printf(" * %s\n", snap) } return fmt.Errorf("won't delete snapshot that was used as source for other snapshots, use -force to override") } } err = snapshotCollection.Drop(snapshot) if err != nil { return fmt.Errorf("unable to drop: %s", err) } fmt.Printf("Snapshot `%s` has been dropped.\n", snapshot.Name) return err }
func aptlyPublishList(cmd *commander.Command, args []string) error { var err error if len(args) != 0 { cmd.Usage() return err } publishedCollecton := debian.NewPublishedRepoCollection(context.database) snapshotCollection := debian.NewSnapshotCollection(context.database) if publishedCollecton.Len() == 0 { fmt.Printf("No snapshots have been published. Publish a snapshot by running `aptly publish snapshot ...`.\n") return err } published := make([]string, 0, publishedCollecton.Len()) err = publishedCollecton.ForEach(func(repo *debian.PublishedRepo) error { err := publishedCollecton.LoadComplete(repo, snapshotCollection) if err != nil { return err } published = append(published, repo.String()) return nil }) if err != nil { return fmt.Errorf("unable to load list of repos: %s", err) } sort.Strings(published) fmt.Printf("Published repositories:\n") for _, description := range published { fmt.Printf(" * %s\n", description) } return err }
func aptlyGraph(cmd *commander.Command, args []string) error { var err error graph := gographviz.NewGraph() graph.SetDir(true) graph.SetName("aptly") existingNodes := map[string]bool{} fmt.Printf("Loading mirrors...\n") repoCollection := debian.NewRemoteRepoCollection(context.database) err = repoCollection.ForEach(func(repo *debian.RemoteRepo) error { err := repoCollection.LoadComplete(repo) if err != nil { return err } graph.AddNode("aptly", graphvizEscape(repo.UUID), map[string]string{ "shape": "Mrecord", "style": "filled", "fillcolor": "darkgoldenrod1", "label": graphvizEscape(fmt.Sprintf("{Mirror %s|url: %s|dist: %s|comp: %s|arch: %s|pkgs: %d}", repo.Name, repo.ArchiveRoot, repo.Distribution, strings.Join(repo.Components, ", "), strings.Join(repo.Architectures, ", "), repo.NumPackages())), }) existingNodes[repo.UUID] = true return nil }) if err != nil { return err } fmt.Printf("Loading local repos...\n") localRepoCollection := debian.NewLocalRepoCollection(context.database) err = localRepoCollection.ForEach(func(repo *debian.LocalRepo) error { err := localRepoCollection.LoadComplete(repo) if err != nil { return err } graph.AddNode("aptly", graphvizEscape(repo.UUID), map[string]string{ "shape": "Mrecord", "style": "filled", "fillcolor": "mediumseagreen", "label": graphvizEscape(fmt.Sprintf("{Repo %s|comment: %s|pkgs: %d}", repo.Name, repo.Comment, repo.NumPackages())), }) existingNodes[repo.UUID] = true return nil }) if err != nil { return err } fmt.Printf("Loading snapshots...\n") snapshotCollection := debian.NewSnapshotCollection(context.database) snapshotCollection.ForEach(func(snapshot *debian.Snapshot) error { existingNodes[snapshot.UUID] = true return nil }) err = snapshotCollection.ForEach(func(snapshot *debian.Snapshot) error { err := snapshotCollection.LoadComplete(snapshot) if err != nil { return err } description := snapshot.Description if snapshot.SourceKind == "repo" { description = "Snapshot from repo" } graph.AddNode("aptly", graphvizEscape(snapshot.UUID), map[string]string{ "shape": "Mrecord", "style": "filled", "fillcolor": "cadetblue1", "label": graphvizEscape(fmt.Sprintf("{Snapshot %s|%s|pkgs: %d}", snapshot.Name, description, snapshot.NumPackages())), }) if snapshot.SourceKind == "repo" || snapshot.SourceKind == "local" || snapshot.SourceKind == "snapshot" { for _, uuid := range snapshot.SourceIDs { _, exists := existingNodes[uuid] if exists { graph.AddEdge(graphvizEscape(uuid), "", graphvizEscape(snapshot.UUID), "", true, nil) } } } return nil }) if err != nil { return err } fmt.Printf("Loading published repos...\n") publishedCollection := debian.NewPublishedRepoCollection(context.database) publishedCollection.ForEach(func(repo *debian.PublishedRepo) error { graph.AddNode("aptly", graphvizEscape(repo.UUID), map[string]string{ "shape": "Mrecord", "style": "filled", "fillcolor": "darkolivegreen1", "label": graphvizEscape(fmt.Sprintf("{Published %s/%s|comp: %s|arch: %s}", repo.Prefix, repo.Distribution, repo.Component, strings.Join(repo.Architectures, ", "))), }) _, exists := existingNodes[repo.SnapshotUUID] if exists { graph.AddEdge(graphvizEscape(repo.SnapshotUUID), "", graphvizEscape(repo.UUID), "", true, nil) } return nil }) fmt.Printf("Generating graph...\n") buf := bytes.NewBufferString(graph.String()) tempfile, err := ioutil.TempFile("", "aptly-graph") if err != nil { return err } tempfile.Close() os.Remove(tempfile.Name()) tempfilename := tempfile.Name() + ".png" command := exec.Command("dot", "-Tpng", "-o"+tempfilename) command.Stderr = os.Stderr stdin, err := command.StdinPipe() if err != nil { return err } err = command.Start() if err != nil { return fmt.Errorf("unable to execute dot: %s (is graphviz package installed?)", err) } _, err = io.Copy(stdin, buf) if err != nil { return err } err = stdin.Close() if err != nil { return err } err = command.Wait() if err != nil { return err } err = exec.Command("open", tempfilename).Run() if err != nil { fmt.Printf("Rendered to PNG file: %s\n", tempfilename) err = nil } 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.packageRepository, 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.packageRepository.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) 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 }
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 }