mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-06 22:18:28 +00:00
Refactor by separating AptlyContext into separate package. #116
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
GOVERSION=$(shell go version | awk '{print $$3;}')
|
GOVERSION=$(shell go version | awk '{print $$3;}')
|
||||||
PACKAGES=database deb files http query s3 utils
|
PACKAGES=context database deb files http query s3 utils
|
||||||
ALL_PACKAGES=aptly cmd console database deb files http query s3 utils
|
ALL_PACKAGES=aptly context cmd console database deb files http query s3 utils
|
||||||
BINPATH=$(abspath ./_vendor/bin)
|
BINPATH=$(abspath ./_vendor/bin)
|
||||||
GOM_ENVIRONMENT=-test
|
GOM_ENVIRONMENT=-test
|
||||||
PYTHON?=python
|
PYTHON?=python
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ package environment to new version.`,
|
|||||||
makeCmdPublish(),
|
makeCmdPublish(),
|
||||||
makeCmdVersion(),
|
makeCmdVersion(),
|
||||||
makeCmdPackage(),
|
makeCmdPackage(),
|
||||||
|
makeCmdAPI(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-352
@@ -1,313 +1,20 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
ctx "github.com/smira/aptly/context"
|
||||||
"github.com/smira/aptly/aptly"
|
|
||||||
"github.com/smira/aptly/console"
|
|
||||||
"github.com/smira/aptly/database"
|
|
||||||
"github.com/smira/aptly/deb"
|
|
||||||
"github.com/smira/aptly/files"
|
|
||||||
"github.com/smira/aptly/http"
|
|
||||||
"github.com/smira/aptly/s3"
|
|
||||||
"github.com/smira/aptly/utils"
|
|
||||||
"github.com/smira/commander"
|
|
||||||
"github.com/smira/flag"
|
"github.com/smira/flag"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"runtime/pprof"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AptlyContext is a common context shared by all commands
|
var context *ctx.AptlyContext
|
||||||
type AptlyContext struct {
|
|
||||||
flags, globalFlags *flag.FlagSet
|
|
||||||
configLoaded bool
|
|
||||||
|
|
||||||
progress aptly.Progress
|
|
||||||
downloader aptly.Downloader
|
|
||||||
database database.Storage
|
|
||||||
packagePool aptly.PackagePool
|
|
||||||
publishedStorages map[string]aptly.PublishedStorage
|
|
||||||
collectionFactory *deb.CollectionFactory
|
|
||||||
dependencyOptions int
|
|
||||||
architecturesList []string
|
|
||||||
// Debug features
|
|
||||||
fileCPUProfile *os.File
|
|
||||||
fileMemProfile *os.File
|
|
||||||
fileMemStats *os.File
|
|
||||||
}
|
|
||||||
|
|
||||||
var context *AptlyContext
|
|
||||||
|
|
||||||
// Check interface
|
|
||||||
var _ aptly.PublishedStorageProvider = &AptlyContext{}
|
|
||||||
|
|
||||||
// FatalError is type for panicking to abort execution with non-zero
|
|
||||||
// exit code and print meaningful explanation
|
|
||||||
type FatalError struct {
|
|
||||||
ReturnCode int
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatal panics and aborts execution with exit code 1
|
|
||||||
func Fatal(err error) {
|
|
||||||
returnCode := 1
|
|
||||||
if err == commander.ErrFlagError || err == commander.ErrCommandError {
|
|
||||||
returnCode = 2
|
|
||||||
}
|
|
||||||
panic(&FatalError{ReturnCode: returnCode, Message: err.Error()})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config loads and returns current configuration
|
|
||||||
func (context *AptlyContext) Config() *utils.ConfigStructure {
|
|
||||||
if !context.configLoaded {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
configLocation := context.globalFlags.Lookup("config").Value.String()
|
|
||||||
if configLocation != "" {
|
|
||||||
err = utils.LoadConfig(configLocation, &utils.Config)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
Fatal(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
configLocations := []string{
|
|
||||||
filepath.Join(os.Getenv("HOME"), ".aptly.conf"),
|
|
||||||
"/etc/aptly.conf",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, configLocation := range configLocations {
|
|
||||||
err = utils.LoadConfig(configLocation, &utils.Config)
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
Fatal(fmt.Errorf("error loading config file %s: %s", configLocation, err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Config file not found, creating default config at %s\n\n", configLocations[0])
|
|
||||||
utils.SaveConfig(configLocations[0], &utils.Config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.configLoaded = true
|
|
||||||
|
|
||||||
}
|
|
||||||
return &utils.Config
|
|
||||||
}
|
|
||||||
|
|
||||||
// DependencyOptions calculates options related to dependecy handling
|
|
||||||
func (context *AptlyContext) DependencyOptions() int {
|
|
||||||
if context.dependencyOptions == -1 {
|
|
||||||
context.dependencyOptions = 0
|
|
||||||
if LookupOption(context.Config().DepFollowSuggests, context.globalFlags, "dep-follow-suggests") {
|
|
||||||
context.dependencyOptions |= deb.DepFollowSuggests
|
|
||||||
}
|
|
||||||
if LookupOption(context.Config().DepFollowRecommends, context.globalFlags, "dep-follow-recommends") {
|
|
||||||
context.dependencyOptions |= deb.DepFollowRecommends
|
|
||||||
}
|
|
||||||
if LookupOption(context.Config().DepFollowAllVariants, context.globalFlags, "dep-follow-all-variants") {
|
|
||||||
context.dependencyOptions |= deb.DepFollowAllVariants
|
|
||||||
}
|
|
||||||
if LookupOption(context.Config().DepFollowSource, context.globalFlags, "dep-follow-source") {
|
|
||||||
context.dependencyOptions |= deb.DepFollowSource
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.dependencyOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArchitecturesList returns list of architectures fixed via command line or config
|
|
||||||
func (context *AptlyContext) ArchitecturesList() []string {
|
|
||||||
if context.architecturesList == nil {
|
|
||||||
context.architecturesList = context.Config().Architectures
|
|
||||||
optionArchitectures := context.globalFlags.Lookup("architectures").Value.String()
|
|
||||||
if optionArchitectures != "" {
|
|
||||||
context.architecturesList = strings.Split(optionArchitectures, ",")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.architecturesList
|
|
||||||
}
|
|
||||||
|
|
||||||
// Progress creates or returns Progress object
|
|
||||||
func (context *AptlyContext) Progress() aptly.Progress {
|
|
||||||
if context.progress == nil {
|
|
||||||
context.progress = console.NewProgress()
|
|
||||||
context.progress.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.progress
|
|
||||||
}
|
|
||||||
|
|
||||||
// Downloader returns instance of current downloader
|
|
||||||
func (context *AptlyContext) Downloader() aptly.Downloader {
|
|
||||||
if context.downloader == nil {
|
|
||||||
var downloadLimit int64
|
|
||||||
limitFlag := context.flags.Lookup("download-limit")
|
|
||||||
if limitFlag != nil {
|
|
||||||
downloadLimit = limitFlag.Value.Get().(int64)
|
|
||||||
}
|
|
||||||
if downloadLimit == 0 {
|
|
||||||
downloadLimit = context.Config().DownloadLimit
|
|
||||||
}
|
|
||||||
context.downloader = http.NewDownloader(context.Config().DownloadConcurrency,
|
|
||||||
downloadLimit*1024, context.Progress())
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.downloader
|
|
||||||
}
|
|
||||||
|
|
||||||
// DBPath builds path to database
|
|
||||||
func (context *AptlyContext) DBPath() string {
|
|
||||||
return filepath.Join(context.Config().RootDir, "db")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Database opens and returns current instance of database
|
|
||||||
func (context *AptlyContext) Database() (database.Storage, error) {
|
|
||||||
if context.database == nil {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
context.database, err = database.OpenDB(context.DBPath())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("can't open database: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.database, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloseDatabase closes the db temporarily
|
|
||||||
func (context *AptlyContext) CloseDatabase() error {
|
|
||||||
if context.database == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.database.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReOpenDatabase reopens the db after close
|
|
||||||
func (context *AptlyContext) ReOpenDatabase() error {
|
|
||||||
if context.database == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const MaxTries = 10
|
|
||||||
const Delay = 10 * time.Second
|
|
||||||
|
|
||||||
for try := 0; try < MaxTries; try++ {
|
|
||||||
err := context.database.ReOpen()
|
|
||||||
if err == nil || strings.Index(err.Error(), "resource temporarily unavailable") == -1 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
context.Progress().Printf("Unable to reopen database, sleeping %s\n", Delay)
|
|
||||||
<-time.After(Delay)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("unable to reopen the DB, maximum number of retries reached")
|
|
||||||
}
|
|
||||||
|
|
||||||
// CollectionFactory builds factory producing all kinds of collections
|
|
||||||
func (context *AptlyContext) CollectionFactory() *deb.CollectionFactory {
|
|
||||||
if context.collectionFactory == nil {
|
|
||||||
db, err := context.Database()
|
|
||||||
if err != nil {
|
|
||||||
Fatal(err)
|
|
||||||
}
|
|
||||||
context.collectionFactory = deb.NewCollectionFactory(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.collectionFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
// PackagePool returns instance of PackagePool
|
|
||||||
func (context *AptlyContext) PackagePool() aptly.PackagePool {
|
|
||||||
if context.packagePool == nil {
|
|
||||||
context.packagePool = files.NewPackagePool(context.Config().RootDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.packagePool
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPublishedStorage returns instance of PublishedStorage
|
|
||||||
func (context *AptlyContext) GetPublishedStorage(name string) aptly.PublishedStorage {
|
|
||||||
publishedStorage, ok := context.publishedStorages[name]
|
|
||||||
if !ok {
|
|
||||||
if name == "" {
|
|
||||||
publishedStorage = files.NewPublishedStorage(context.Config().RootDir)
|
|
||||||
} else if strings.HasPrefix(name, "s3:") {
|
|
||||||
params, ok := context.Config().S3PublishRoots[name[3:]]
|
|
||||||
if !ok {
|
|
||||||
Fatal(fmt.Errorf("published S3 storage %v not configured", name[3:]))
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
publishedStorage, err = s3.NewPublishedStorage(params.AccessKeyID, params.SecretAccessKey,
|
|
||||||
params.Region, params.Bucket, params.ACL, params.Prefix, params.StorageClass,
|
|
||||||
params.EncryptionMethod, params.PlusWorkaround)
|
|
||||||
if err != nil {
|
|
||||||
Fatal(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Fatal(fmt.Errorf("unknown published storage format: %v", name))
|
|
||||||
}
|
|
||||||
context.publishedStorages[name] = publishedStorage
|
|
||||||
}
|
|
||||||
|
|
||||||
return publishedStorage
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateFlags sets internal copy of flags in the context
|
|
||||||
func (context *AptlyContext) UpdateFlags(flags *flag.FlagSet) {
|
|
||||||
context.flags = flags
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShutdownContext shuts context down
|
// ShutdownContext shuts context down
|
||||||
func ShutdownContext() {
|
func ShutdownContext() {
|
||||||
if aptly.EnableDebug {
|
context.Shutdown()
|
||||||
if context.fileMemProfile != nil {
|
|
||||||
pprof.WriteHeapProfile(context.fileMemProfile)
|
|
||||||
context.fileMemProfile.Close()
|
|
||||||
context.fileMemProfile = nil
|
|
||||||
}
|
|
||||||
if context.fileCPUProfile != nil {
|
|
||||||
pprof.StopCPUProfile()
|
|
||||||
context.fileCPUProfile.Close()
|
|
||||||
context.fileCPUProfile = nil
|
|
||||||
}
|
|
||||||
if context.fileMemProfile != nil {
|
|
||||||
context.fileMemProfile.Close()
|
|
||||||
context.fileMemProfile = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if context.database != nil {
|
|
||||||
context.database.Close()
|
|
||||||
context.database = nil
|
|
||||||
}
|
|
||||||
if context.downloader != nil {
|
|
||||||
context.downloader.Abort()
|
|
||||||
context.downloader = nil
|
|
||||||
}
|
|
||||||
if context.progress != nil {
|
|
||||||
context.progress.Shutdown()
|
|
||||||
context.progress = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanupContext does partial shutdown of context
|
// CleanupContext does partial shutdown of context
|
||||||
func CleanupContext() {
|
func CleanupContext() {
|
||||||
if context.downloader != nil {
|
context.Cleanup()
|
||||||
context.downloader.Shutdown()
|
|
||||||
context.downloader = nil
|
|
||||||
}
|
|
||||||
if context.progress != nil {
|
|
||||||
context.progress.Shutdown()
|
|
||||||
context.progress = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitContext initializes context with default settings
|
// InitContext initializes context with default settings
|
||||||
@@ -318,60 +25,7 @@ func InitContext(flags *flag.FlagSet) error {
|
|||||||
panic("context already initialized")
|
panic("context already initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
context = &AptlyContext{
|
context, err = ctx.NewContext(flags)
|
||||||
flags: flags,
|
|
||||||
globalFlags: flags,
|
|
||||||
dependencyOptions: -1,
|
|
||||||
publishedStorages: map[string]aptly.PublishedStorage{},
|
|
||||||
}
|
|
||||||
|
|
||||||
if aptly.EnableDebug {
|
return err
|
||||||
cpuprofile := flags.Lookup("cpuprofile").Value.String()
|
|
||||||
if cpuprofile != "" {
|
|
||||||
context.fileCPUProfile, err = os.Create(cpuprofile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pprof.StartCPUProfile(context.fileCPUProfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
memprofile := flags.Lookup("memprofile").Value.String()
|
|
||||||
if memprofile != "" {
|
|
||||||
context.fileMemProfile, err = os.Create(memprofile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memstats := flags.Lookup("memstats").Value.String()
|
|
||||||
if memstats != "" {
|
|
||||||
interval := flags.Lookup("meminterval").Value.Get().(time.Duration)
|
|
||||||
|
|
||||||
context.fileMemStats, err = os.Create(memstats)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
context.fileMemStats.WriteString("# Time\tHeapSys\tHeapAlloc\tHeapIdle\tHeapReleased\n")
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
var stats runtime.MemStats
|
|
||||||
|
|
||||||
start := time.Now().UnixNano()
|
|
||||||
|
|
||||||
for {
|
|
||||||
runtime.ReadMemStats(&stats)
|
|
||||||
if context.fileMemStats != nil {
|
|
||||||
context.fileMemStats.WriteString(fmt.Sprintf("%d\t%d\t%d\t%d\t%d\n",
|
|
||||||
(time.Now().UnixNano()-start)/1000000, stats.HeapSys, stats.HeapAlloc, stats.HeapIdle, stats.HeapReleased))
|
|
||||||
time.Sleep(interval)
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ func aptlyMirrorCreate(cmd *commander.Command, args []string) error {
|
|||||||
return commander.ErrCommandError
|
return commander.ErrCommandError
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadSources := LookupOption(context.Config().DownloadSourcePackages, context.flags, "with-sources")
|
downloadSources := LookupOption(context.Config().DownloadSourcePackages, context.Flags(), "with-sources")
|
||||||
downloadUdebs := context.flags.Lookup("with-udebs").Value.Get().(bool)
|
downloadUdebs := context.Flags().Lookup("with-udebs").Value.Get().(bool)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
mirrorName, archiveURL, distribution string
|
mirrorName, archiveURL, distribution string
|
||||||
@@ -40,8 +40,8 @@ func aptlyMirrorCreate(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to create mirror: %s", err)
|
return fmt.Errorf("unable to create mirror: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.Filter = context.flags.Lookup("filter").Value.String()
|
repo.Filter = context.Flags().Lookup("filter").Value.String()
|
||||||
repo.FilterWithDeps = context.flags.Lookup("filter-with-deps").Value.Get().(bool)
|
repo.FilterWithDeps = context.Flags().Lookup("filter-with-deps").Value.Get().(bool)
|
||||||
|
|
||||||
if repo.Filter != "" {
|
if repo.Filter != "" {
|
||||||
_, err = query.Parse(repo.Filter)
|
_, err = query.Parse(repo.Filter)
|
||||||
@@ -50,7 +50,7 @@ func aptlyMirrorCreate(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
verifier, err := getVerifier(context.flags)
|
verifier, err := getVerifier(context.Flags())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to initialize GPG verifier: %s", err)
|
return fmt.Errorf("unable to initialize GPG verifier: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ func aptlyMirrorDrop(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to drop: %s", err)
|
return fmt.Errorf("unable to drop: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
force := context.flags.Lookup("force").Value.Get().(bool)
|
force := context.Flags().Lookup("force").Value.Get().(bool)
|
||||||
if !force {
|
if !force {
|
||||||
snapshots := context.CollectionFactory().SnapshotCollection().ByRemoteRepoSource(repo)
|
snapshots := context.CollectionFactory().SnapshotCollection().ByRemoteRepoSource(repo)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -24,7 +24,7 @@ func aptlyMirrorEdit(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to edit: %s", err)
|
return fmt.Errorf("unable to edit: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
context.flags.Visit(func(flag *flag.Flag) {
|
context.Flags().Visit(func(flag *flag.Flag) {
|
||||||
switch flag.Name {
|
switch flag.Name {
|
||||||
case "filter":
|
case "filter":
|
||||||
repo.Filter = flag.Value.String()
|
repo.Filter = flag.Value.String()
|
||||||
@@ -48,7 +48,7 @@ func aptlyMirrorEdit(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.globalFlags.Lookup("architectures").Value.String() != "" {
|
if context.GlobalFlags().Lookup("architectures").Value.String() != "" {
|
||||||
repo.Architectures = context.ArchitecturesList()
|
repo.Architectures = context.ArchitecturesList()
|
||||||
|
|
||||||
err = repo.Fetch(context.Downloader(), nil)
|
err = repo.Fetch(context.Downloader(), nil)
|
||||||
|
|||||||
+1
-1
@@ -66,7 +66,7 @@ func aptlyMirrorShow(cmd *commander.Command, args []string) error {
|
|||||||
fmt.Printf("%s: %s\n", k, repo.Meta[k])
|
fmt.Printf("%s: %s\n", k, repo.Meta[k])
|
||||||
}
|
}
|
||||||
|
|
||||||
withPackages := context.flags.Lookup("with-packages").Value.Get().(bool)
|
withPackages := context.Flags().Lookup("with-packages").Value.Get().(bool)
|
||||||
if withPackages {
|
if withPackages {
|
||||||
if repo.LastDownloadDate.IsZero() {
|
if repo.LastDownloadDate.IsZero() {
|
||||||
fmt.Printf("Unable to show package list, mirror hasn't been downloaded yet.\n")
|
fmt.Printf("Unable to show package list, mirror hasn't been downloaded yet.\n")
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
force := context.flags.Lookup("force").Value.Get().(bool)
|
force := context.Flags().Lookup("force").Value.Get().(bool)
|
||||||
if !force {
|
if !force {
|
||||||
err = repo.CheckLock()
|
err = repo.CheckLock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -39,9 +39,9 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ignoreMismatch := context.flags.Lookup("ignore-checksums").Value.Get().(bool)
|
ignoreMismatch := context.Flags().Lookup("ignore-checksums").Value.Get().(bool)
|
||||||
|
|
||||||
verifier, err := getVerifier(context.flags)
|
verifier, err := getVerifier(context.Flags())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to initialize GPG verifier: %s", err)
|
return fmt.Errorf("unable to initialize GPG verifier: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -72,8 +72,8 @@ func aptlyPackageShow(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to show: %s", err)
|
return fmt.Errorf("unable to show: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
withFiles := context.flags.Lookup("with-files").Value.Get().(bool)
|
withFiles := context.Flags().Lookup("with-files").Value.Get().(bool)
|
||||||
withReferences := context.flags.Lookup("with-references").Value.Get().(bool)
|
withReferences := context.Flags().Lookup("with-references").Value.Get().(bool)
|
||||||
|
|
||||||
w := bufio.NewWriter(os.Stdout)
|
w := bufio.NewWriter(os.Stdout)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
|
func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
components := strings.Split(context.flags.Lookup("component").Value.String(), ",")
|
components := strings.Split(context.Flags().Lookup("component").Value.String(), ",")
|
||||||
|
|
||||||
if len(args) < len(components) || len(args) > len(components)+1 {
|
if len(args) < len(components) || len(args) > len(components)+1 {
|
||||||
cmd.Usage()
|
cmd.Usage()
|
||||||
@@ -110,7 +110,7 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
|
|||||||
panic("unknown command")
|
panic("unknown command")
|
||||||
}
|
}
|
||||||
|
|
||||||
distribution := context.flags.Lookup("distribution").Value.String()
|
distribution := context.Flags().Lookup("distribution").Value.String()
|
||||||
|
|
||||||
published, err := deb.NewPublishedRepo(storage, prefix, distribution, context.ArchitecturesList(), components, sources, context.CollectionFactory())
|
published, err := deb.NewPublishedRepo(storage, prefix, distribution, context.ArchitecturesList(), components, sources, context.CollectionFactory())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -125,12 +125,12 @@ func aptlyPublishSnapshotOrRepo(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("prefix/distribution already used by another published repo: %s", duplicate)
|
return fmt.Errorf("prefix/distribution already used by another published repo: %s", duplicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
signer, err := getSigner(context.flags)
|
signer, err := getSigner(context.Flags())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to initialize GPG signer: %s", err)
|
return fmt.Errorf("unable to initialize GPG signer: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
forceOverwrite := context.flags.Lookup("force-overwrite").Value.Get().(bool)
|
forceOverwrite := context.Flags().Lookup("force-overwrite").Value.Get().(bool)
|
||||||
if forceOverwrite {
|
if forceOverwrite {
|
||||||
context.Progress().ColoredPrintf("@rWARNING@|: force overwrite mode enabled, aptly might corrupt other published repositories sharing " +
|
context.Progress().ColoredPrintf("@rWARNING@|: force overwrite mode enabled, aptly might corrupt other published repositories sharing " +
|
||||||
"the same package pool.\n")
|
"the same package pool.\n")
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
|
func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
components := strings.Split(context.flags.Lookup("component").Value.String(), ",")
|
components := strings.Split(context.Flags().Lookup("component").Value.String(), ",")
|
||||||
|
|
||||||
if len(args) < len(components)+1 || len(args) > len(components)+2 {
|
if len(args) < len(components)+1 || len(args) > len(components)+2 {
|
||||||
cmd.Usage()
|
cmd.Usage()
|
||||||
@@ -74,12 +74,12 @@ func aptlyPublishSwitch(cmd *commander.Command, args []string) error {
|
|||||||
published.UpdateSnapshot(component, snapshot)
|
published.UpdateSnapshot(component, snapshot)
|
||||||
}
|
}
|
||||||
|
|
||||||
signer, err := getSigner(context.flags)
|
signer, err := getSigner(context.Flags())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to initialize GPG signer: %s", err)
|
return fmt.Errorf("unable to initialize GPG signer: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
forceOverwrite := context.flags.Lookup("force-overwrite").Value.Get().(bool)
|
forceOverwrite := context.Flags().Lookup("force-overwrite").Value.Get().(bool)
|
||||||
if forceOverwrite {
|
if forceOverwrite {
|
||||||
context.Progress().ColoredPrintf("@rWARNING@|: force overwrite mode enabled, aptly might corrupt other published repositories sharing " +
|
context.Progress().ColoredPrintf("@rWARNING@|: force overwrite mode enabled, aptly might corrupt other published repositories sharing " +
|
||||||
"the same package pool.\n")
|
"the same package pool.\n")
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ func aptlyPublishUpdate(cmd *commander.Command, args []string) error {
|
|||||||
published.UpdateLocalRepo(component)
|
published.UpdateLocalRepo(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
signer, err := getSigner(context.flags)
|
signer, err := getSigner(context.Flags())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to initialize GPG signer: %s", err)
|
return fmt.Errorf("unable to initialize GPG signer: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
forceOverwrite := context.flags.Lookup("force-overwrite").Value.Get().(bool)
|
forceOverwrite := context.Flags().Lookup("force-overwrite").Value.Get().(bool)
|
||||||
if forceOverwrite {
|
if forceOverwrite {
|
||||||
context.Progress().ColoredPrintf("@rWARNING@|: force overwrite mode enabled, aptly might corrupt other published repositories sharing " +
|
context.Progress().ColoredPrintf("@rWARNING@|: force overwrite mode enabled, aptly might corrupt other published repositories sharing " +
|
||||||
"the same package pool.\n")
|
"the same package pool.\n")
|
||||||
|
|||||||
+2
-2
@@ -40,7 +40,7 @@ func aptlyRepoAdd(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to load packages: %s", err)
|
return fmt.Errorf("unable to load packages: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
forceReplace := context.flags.Lookup("force-replace").Value.Get().(bool)
|
forceReplace := context.Flags().Lookup("force-replace").Value.Get().(bool)
|
||||||
|
|
||||||
packageFiles := []string{}
|
packageFiles := []string{}
|
||||||
failedFiles := []string{}
|
failedFiles := []string{}
|
||||||
@@ -194,7 +194,7 @@ func aptlyRepoAdd(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to save: %s", err)
|
return fmt.Errorf("unable to save: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.flags.Lookup("remove-files").Value.Get().(bool) {
|
if context.Flags().Lookup("remove-files").Value.Get().(bool) {
|
||||||
processedFiles = utils.StrSliceDeduplicate(processedFiles)
|
processedFiles = utils.StrSliceDeduplicate(processedFiles)
|
||||||
|
|
||||||
for _, file := range processedFiles {
|
for _, file := range processedFiles {
|
||||||
|
|||||||
+3
-3
@@ -14,9 +14,9 @@ func aptlyRepoCreate(cmd *commander.Command, args []string) error {
|
|||||||
return commander.ErrCommandError
|
return commander.ErrCommandError
|
||||||
}
|
}
|
||||||
|
|
||||||
repo := deb.NewLocalRepo(args[0], context.flags.Lookup("comment").Value.String())
|
repo := deb.NewLocalRepo(args[0], context.Flags().Lookup("comment").Value.String())
|
||||||
repo.DefaultDistribution = context.flags.Lookup("distribution").Value.String()
|
repo.DefaultDistribution = context.Flags().Lookup("distribution").Value.String()
|
||||||
repo.DefaultComponent = context.flags.Lookup("component").Value.String()
|
repo.DefaultComponent = context.Flags().Lookup("component").Value.String()
|
||||||
|
|
||||||
err = context.CollectionFactory().LocalRepoCollection().Add(repo)
|
err = context.CollectionFactory().LocalRepoCollection().Add(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ func aptlyRepoDrop(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to drop: local repo is published")
|
return fmt.Errorf("unable to drop: local repo is published")
|
||||||
}
|
}
|
||||||
|
|
||||||
force := context.flags.Lookup("force").Value.Get().(bool)
|
force := context.Flags().Lookup("force").Value.Get().(bool)
|
||||||
if !force {
|
if !force {
|
||||||
snapshots := context.CollectionFactory().SnapshotCollection().ByLocalRepoSource(repo)
|
snapshots := context.CollectionFactory().SnapshotCollection().ByLocalRepoSource(repo)
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -23,16 +23,16 @@ func aptlyRepoEdit(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to edit: %s", err)
|
return fmt.Errorf("unable to edit: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.flags.Lookup("comment").Value.String() != "" {
|
if context.Flags().Lookup("comment").Value.String() != "" {
|
||||||
repo.Comment = context.flags.Lookup("comment").Value.String()
|
repo.Comment = context.Flags().Lookup("comment").Value.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.flags.Lookup("distribution").Value.String() != "" {
|
if context.Flags().Lookup("distribution").Value.String() != "" {
|
||||||
repo.DefaultDistribution = context.flags.Lookup("distribution").Value.String()
|
repo.DefaultDistribution = context.Flags().Lookup("distribution").Value.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.flags.Lookup("component").Value.String() != "" {
|
if context.Flags().Lookup("component").Value.String() != "" {
|
||||||
repo.DefaultComponent = context.flags.Lookup("component").Value.String()
|
repo.DefaultComponent = context.Flags().Lookup("component").Value.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
err = context.CollectionFactory().LocalRepoCollection().Update(repo)
|
err = context.CollectionFactory().LocalRepoCollection().Update(repo)
|
||||||
|
|||||||
+2
-2
@@ -87,7 +87,7 @@ func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
var architecturesList []string
|
var architecturesList []string
|
||||||
|
|
||||||
withDeps := context.flags.Lookup("with-deps").Value.Get().(bool)
|
withDeps := context.Flags().Lookup("with-deps").Value.Get().(bool)
|
||||||
|
|
||||||
if withDeps {
|
if withDeps {
|
||||||
dstList.PrepareIndex()
|
dstList.PrepareIndex()
|
||||||
@@ -145,7 +145,7 @@ func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to %s: %s", command, err)
|
return fmt.Errorf("unable to %s: %s", command, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.flags.Lookup("dry-run").Value.Get().(bool) {
|
if context.Flags().Lookup("dry-run").Value.Get().(bool) {
|
||||||
context.Progress().Printf("\nChanges not saved, as dry run has been requested.\n")
|
context.Progress().Printf("\nChanges not saved, as dry run has been requested.\n")
|
||||||
} else {
|
} else {
|
||||||
dstRepo.UpdateRefList(deb.NewPackageRefListFromPackageList(dstList))
|
dstRepo.UpdateRefList(deb.NewPackageRefListFromPackageList(dstList))
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ func aptlyRepoRemove(cmd *commander.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if context.flags.Lookup("dry-run").Value.Get().(bool) {
|
if context.Flags().Lookup("dry-run").Value.Get().(bool) {
|
||||||
context.Progress().Printf("\nChanges not saved, as dry run has been requested.\n")
|
context.Progress().Printf("\nChanges not saved, as dry run has been requested.\n")
|
||||||
} else {
|
} else {
|
||||||
repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))
|
repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ func aptlyRepoShow(cmd *commander.Command, args []string) error {
|
|||||||
fmt.Printf("Default Component: %s\n", repo.DefaultComponent)
|
fmt.Printf("Default Component: %s\n", repo.DefaultComponent)
|
||||||
fmt.Printf("Number of packages: %d\n", repo.NumPackages())
|
fmt.Printf("Number of packages: %d\n", repo.NumPackages())
|
||||||
|
|
||||||
withPackages := context.flags.Lookup("with-packages").Value.Get().(bool)
|
withPackages := context.Flags().Lookup("with-packages").Value.Get().(bool)
|
||||||
if withPackages {
|
if withPackages {
|
||||||
ListPackagesRefList(repo.RefList())
|
ListPackagesRefList(repo.RefList())
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -2,6 +2,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
ctx "github.com/smira/aptly/context"
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ import (
|
|||||||
func Run(cmd *commander.Command, cmdArgs []string, initContext bool) (returnCode int) {
|
func Run(cmd *commander.Command, cmdArgs []string, initContext bool) (returnCode int) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
fatal, ok := r.(*FatalError)
|
fatal, ok := r.(*ctx.FatalError)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(r)
|
panic(r)
|
||||||
}
|
}
|
||||||
@@ -22,13 +23,13 @@ func Run(cmd *commander.Command, cmdArgs []string, initContext bool) (returnCode
|
|||||||
|
|
||||||
flags, args, err := cmd.ParseFlags(cmdArgs)
|
flags, args, err := cmd.ParseFlags(cmdArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatal(err)
|
ctx.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if initContext {
|
if initContext {
|
||||||
err = InitContext(flags)
|
err = InitContext(flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatal(err)
|
ctx.Fatal(err)
|
||||||
}
|
}
|
||||||
defer ShutdownContext()
|
defer ShutdownContext()
|
||||||
}
|
}
|
||||||
@@ -37,7 +38,7 @@ func Run(cmd *commander.Command, cmdArgs []string, initContext bool) (returnCode
|
|||||||
|
|
||||||
err = cmd.Dispatch(args)
|
err = cmd.Dispatch(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatal(err)
|
ctx.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ func aptlyServe(cmd *commander.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
listen := context.flags.Lookup("listen").Value.String()
|
listen := context.Flags().Lookup("listen").Value.String()
|
||||||
|
|
||||||
listenHost, listenPort, err := net.SplitHostPort(listen)
|
listenHost, listenPort, err := net.SplitHostPort(listen)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ func aptlySnapshotDiff(cmd *commander.Command, args []string) error {
|
|||||||
return commander.ErrCommandError
|
return commander.ErrCommandError
|
||||||
}
|
}
|
||||||
|
|
||||||
onlyMatching := context.flags.Lookup("only-matching").Value.Get().(bool)
|
onlyMatching := context.Flags().Lookup("only-matching").Value.Get().(bool)
|
||||||
|
|
||||||
// Load <name-a> snapshot
|
// Load <name-a> snapshot
|
||||||
snapshotA, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
|
snapshotA, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func aptlySnapshotDrop(cmd *commander.Command, args []string) error {
|
|||||||
return fmt.Errorf("unable to drop: snapshot is published")
|
return fmt.Errorf("unable to drop: snapshot is published")
|
||||||
}
|
}
|
||||||
|
|
||||||
force := context.flags.Lookup("force").Value.Get().(bool)
|
force := context.Flags().Lookup("force").Value.Get().(bool)
|
||||||
if !force {
|
if !force {
|
||||||
snapshots := context.CollectionFactory().SnapshotCollection().BySnapshotSource(snapshot)
|
snapshots := context.CollectionFactory().SnapshotCollection().BySnapshotSource(snapshot)
|
||||||
if len(snapshots) > 0 {
|
if len(snapshots) > 0 {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func aptlySnapshotFilter(cmd *commander.Command, args []string) error {
|
|||||||
return commander.ErrCommandError
|
return commander.ErrCommandError
|
||||||
}
|
}
|
||||||
|
|
||||||
withDeps := context.flags.Lookup("with-deps").Value.Get().(bool)
|
withDeps := context.Flags().Lookup("with-deps").Value.Get().(bool)
|
||||||
|
|
||||||
// Load <source> snapshot
|
// Load <source> snapshot
|
||||||
source, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
|
source, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ func aptlySnapshotMerge(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
latest := context.flags.Lookup("latest").Value.Get().(bool)
|
latest := context.Flags().Lookup("latest").Value.Get().(bool)
|
||||||
noRemove := context.flags.Lookup("no-remove").Value.Get().(bool)
|
noRemove := context.Flags().Lookup("no-remove").Value.Get().(bool)
|
||||||
|
|
||||||
if noRemove && latest {
|
if noRemove && latest {
|
||||||
return fmt.Errorf("-no-remove and -latest can't be specified together")
|
return fmt.Errorf("-no-remove and -latest can't be specified together")
|
||||||
}
|
}
|
||||||
|
|
||||||
overrideMatching := !latest && !noRemove
|
overrideMatching := !latest && !noRemove
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ Example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flag.Bool("latest", false, "use only the latest version of each package")
|
cmd.Flag.Bool("latest", false, "use only the latest version of each package")
|
||||||
cmd.Flag.Bool("no-remove", false, "don't remove duplicate arch/name packages")
|
cmd.Flag.Bool("no-remove", false, "don't remove duplicate arch/name packages")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ func aptlySnapshotPull(cmd *commander.Command, args []string) error {
|
|||||||
return commander.ErrCommandError
|
return commander.ErrCommandError
|
||||||
}
|
}
|
||||||
|
|
||||||
noDeps := context.flags.Lookup("no-deps").Value.Get().(bool)
|
noDeps := context.Flags().Lookup("no-deps").Value.Get().(bool)
|
||||||
noRemove := context.flags.Lookup("no-remove").Value.Get().(bool)
|
noRemove := context.Flags().Lookup("no-remove").Value.Get().(bool)
|
||||||
allMatches := context.flags.Lookup("all-matches").Value.Get().(bool)
|
allMatches := context.Flags().Lookup("all-matches").Value.Get().(bool)
|
||||||
|
|
||||||
// Load <name> snapshot
|
// Load <name> snapshot
|
||||||
snapshot, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
|
snapshot, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
|
||||||
@@ -129,7 +129,7 @@ func aptlySnapshotPull(cmd *commander.Command, args []string) error {
|
|||||||
})
|
})
|
||||||
alreadySeen = nil
|
alreadySeen = nil
|
||||||
|
|
||||||
if context.flags.Lookup("dry-run").Value.Get().(bool) {
|
if context.Flags().Lookup("dry-run").Value.Get().(bool) {
|
||||||
context.Progress().Printf("\nNot creating snapshot, as dry run was requested.\n")
|
context.Progress().Printf("\nNot creating snapshot, as dry run was requested.\n")
|
||||||
} else {
|
} else {
|
||||||
// Create <destination> snapshot
|
// Create <destination> snapshot
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error
|
|||||||
return fmt.Errorf("unable to search: %s", err)
|
return fmt.Errorf("unable to search: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
withDeps := context.flags.Lookup("with-deps").Value.Get().(bool)
|
withDeps := context.Flags().Lookup("with-deps").Value.Get().(bool)
|
||||||
architecturesList := []string{}
|
architecturesList := []string{}
|
||||||
|
|
||||||
if withDeps {
|
if withDeps {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func aptlySnapshotShow(cmd *commander.Command, args []string) error {
|
|||||||
fmt.Printf("Description: %s\n", snapshot.Description)
|
fmt.Printf("Description: %s\n", snapshot.Description)
|
||||||
fmt.Printf("Number of packages: %d\n", snapshot.NumPackages())
|
fmt.Printf("Number of packages: %d\n", snapshot.NumPackages())
|
||||||
|
|
||||||
withPackages := context.flags.Lookup("with-packages").Value.Get().(bool)
|
withPackages := context.Flags().Lookup("with-packages").Value.Get().(bool)
|
||||||
if withPackages {
|
if withPackages {
|
||||||
ListPackagesRefList(snapshot.RefList())
|
ListPackagesRefList(snapshot.RefList())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,394 @@
|
|||||||
|
// Package context provides single entry to all resources
|
||||||
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/smira/aptly/aptly"
|
||||||
|
"github.com/smira/aptly/console"
|
||||||
|
"github.com/smira/aptly/database"
|
||||||
|
"github.com/smira/aptly/deb"
|
||||||
|
"github.com/smira/aptly/files"
|
||||||
|
"github.com/smira/aptly/http"
|
||||||
|
"github.com/smira/aptly/s3"
|
||||||
|
"github.com/smira/aptly/utils"
|
||||||
|
"github.com/smira/commander"
|
||||||
|
"github.com/smira/flag"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"runtime/pprof"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AptlyContext is a common context shared by all commands
|
||||||
|
type AptlyContext struct {
|
||||||
|
flags, globalFlags *flag.FlagSet
|
||||||
|
configLoaded bool
|
||||||
|
|
||||||
|
progress aptly.Progress
|
||||||
|
downloader aptly.Downloader
|
||||||
|
database database.Storage
|
||||||
|
packagePool aptly.PackagePool
|
||||||
|
publishedStorages map[string]aptly.PublishedStorage
|
||||||
|
collectionFactory *deb.CollectionFactory
|
||||||
|
dependencyOptions int
|
||||||
|
architecturesList []string
|
||||||
|
// Debug features
|
||||||
|
fileCPUProfile *os.File
|
||||||
|
fileMemProfile *os.File
|
||||||
|
fileMemStats *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check interface
|
||||||
|
var _ aptly.PublishedStorageProvider = &AptlyContext{}
|
||||||
|
|
||||||
|
// FatalError is type for panicking to abort execution with non-zero
|
||||||
|
// exit code and print meaningful explanation
|
||||||
|
type FatalError struct {
|
||||||
|
ReturnCode int
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatal panics and aborts execution with exit code 1
|
||||||
|
func Fatal(err error) {
|
||||||
|
returnCode := 1
|
||||||
|
if err == commander.ErrFlagError || err == commander.ErrCommandError {
|
||||||
|
returnCode = 2
|
||||||
|
}
|
||||||
|
panic(&FatalError{ReturnCode: returnCode, Message: err.Error()})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config loads and returns current configuration
|
||||||
|
func (context *AptlyContext) Config() *utils.ConfigStructure {
|
||||||
|
if !context.configLoaded {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
configLocation := context.globalFlags.Lookup("config").Value.String()
|
||||||
|
if configLocation != "" {
|
||||||
|
err = utils.LoadConfig(configLocation, &utils.Config)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
configLocations := []string{
|
||||||
|
filepath.Join(os.Getenv("HOME"), ".aptly.conf"),
|
||||||
|
"/etc/aptly.conf",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, configLocation := range configLocations {
|
||||||
|
err = utils.LoadConfig(configLocation, &utils.Config)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
Fatal(fmt.Errorf("error loading config file %s: %s", configLocation, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Config file not found, creating default config at %s\n\n", configLocations[0])
|
||||||
|
utils.SaveConfig(configLocations[0], &utils.Config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.configLoaded = true
|
||||||
|
|
||||||
|
}
|
||||||
|
return &utils.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupOption checks boolean flag with default (usually config) and command-line
|
||||||
|
// setting
|
||||||
|
func (context *AptlyContext) LookupOption(defaultValue bool, name string) (result bool) {
|
||||||
|
result = defaultValue
|
||||||
|
|
||||||
|
if context.globalFlags.IsSet(name) {
|
||||||
|
result = context.globalFlags.Lookup(name).Value.Get().(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DependencyOptions calculates options related to dependecy handling
|
||||||
|
func (context *AptlyContext) DependencyOptions() int {
|
||||||
|
if context.dependencyOptions == -1 {
|
||||||
|
context.dependencyOptions = 0
|
||||||
|
if context.LookupOption(context.Config().DepFollowSuggests, "dep-follow-suggests") {
|
||||||
|
context.dependencyOptions |= deb.DepFollowSuggests
|
||||||
|
}
|
||||||
|
if context.LookupOption(context.Config().DepFollowRecommends, "dep-follow-recommends") {
|
||||||
|
context.dependencyOptions |= deb.DepFollowRecommends
|
||||||
|
}
|
||||||
|
if context.LookupOption(context.Config().DepFollowAllVariants, "dep-follow-all-variants") {
|
||||||
|
context.dependencyOptions |= deb.DepFollowAllVariants
|
||||||
|
}
|
||||||
|
if context.LookupOption(context.Config().DepFollowSource, "dep-follow-source") {
|
||||||
|
context.dependencyOptions |= deb.DepFollowSource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.dependencyOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArchitecturesList returns list of architectures fixed via command line or config
|
||||||
|
func (context *AptlyContext) ArchitecturesList() []string {
|
||||||
|
if context.architecturesList == nil {
|
||||||
|
context.architecturesList = context.Config().Architectures
|
||||||
|
optionArchitectures := context.globalFlags.Lookup("architectures").Value.String()
|
||||||
|
if optionArchitectures != "" {
|
||||||
|
context.architecturesList = strings.Split(optionArchitectures, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.architecturesList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Progress creates or returns Progress object
|
||||||
|
func (context *AptlyContext) Progress() aptly.Progress {
|
||||||
|
if context.progress == nil {
|
||||||
|
context.progress = console.NewProgress()
|
||||||
|
context.progress.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.progress
|
||||||
|
}
|
||||||
|
|
||||||
|
// Downloader returns instance of current downloader
|
||||||
|
func (context *AptlyContext) Downloader() aptly.Downloader {
|
||||||
|
if context.downloader == nil {
|
||||||
|
var downloadLimit int64
|
||||||
|
limitFlag := context.flags.Lookup("download-limit")
|
||||||
|
if limitFlag != nil {
|
||||||
|
downloadLimit = limitFlag.Value.Get().(int64)
|
||||||
|
}
|
||||||
|
if downloadLimit == 0 {
|
||||||
|
downloadLimit = context.Config().DownloadLimit
|
||||||
|
}
|
||||||
|
context.downloader = http.NewDownloader(context.Config().DownloadConcurrency,
|
||||||
|
downloadLimit*1024, context.Progress())
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.downloader
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBPath builds path to database
|
||||||
|
func (context *AptlyContext) DBPath() string {
|
||||||
|
return filepath.Join(context.Config().RootDir, "db")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database opens and returns current instance of database
|
||||||
|
func (context *AptlyContext) Database() (database.Storage, error) {
|
||||||
|
if context.database == nil {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
context.database, err = database.OpenDB(context.DBPath())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't open database: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.database, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseDatabase closes the db temporarily
|
||||||
|
func (context *AptlyContext) CloseDatabase() error {
|
||||||
|
if context.database == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.database.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReOpenDatabase reopens the db after close
|
||||||
|
func (context *AptlyContext) ReOpenDatabase() error {
|
||||||
|
if context.database == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const MaxTries = 10
|
||||||
|
const Delay = 10 * time.Second
|
||||||
|
|
||||||
|
for try := 0; try < MaxTries; try++ {
|
||||||
|
err := context.database.ReOpen()
|
||||||
|
if err == nil || strings.Index(err.Error(), "resource temporarily unavailable") == -1 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
context.Progress().Printf("Unable to reopen database, sleeping %s\n", Delay)
|
||||||
|
<-time.After(Delay)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("unable to reopen the DB, maximum number of retries reached")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CollectionFactory builds factory producing all kinds of collections
|
||||||
|
func (context *AptlyContext) CollectionFactory() *deb.CollectionFactory {
|
||||||
|
if context.collectionFactory == nil {
|
||||||
|
db, err := context.Database()
|
||||||
|
if err != nil {
|
||||||
|
Fatal(err)
|
||||||
|
}
|
||||||
|
context.collectionFactory = deb.NewCollectionFactory(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.collectionFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackagePool returns instance of PackagePool
|
||||||
|
func (context *AptlyContext) PackagePool() aptly.PackagePool {
|
||||||
|
if context.packagePool == nil {
|
||||||
|
context.packagePool = files.NewPackagePool(context.Config().RootDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.packagePool
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPublishedStorage returns instance of PublishedStorage
|
||||||
|
func (context *AptlyContext) GetPublishedStorage(name string) aptly.PublishedStorage {
|
||||||
|
publishedStorage, ok := context.publishedStorages[name]
|
||||||
|
if !ok {
|
||||||
|
if name == "" {
|
||||||
|
publishedStorage = files.NewPublishedStorage(context.Config().RootDir)
|
||||||
|
} else if strings.HasPrefix(name, "s3:") {
|
||||||
|
params, ok := context.Config().S3PublishRoots[name[3:]]
|
||||||
|
if !ok {
|
||||||
|
Fatal(fmt.Errorf("published S3 storage %v not configured", name[3:]))
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
publishedStorage, err = s3.NewPublishedStorage(params.AccessKeyID, params.SecretAccessKey,
|
||||||
|
params.Region, params.Bucket, params.ACL, params.Prefix, params.StorageClass,
|
||||||
|
params.EncryptionMethod, params.PlusWorkaround)
|
||||||
|
if err != nil {
|
||||||
|
Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Fatal(fmt.Errorf("unknown published storage format: %v", name))
|
||||||
|
}
|
||||||
|
context.publishedStorages[name] = publishedStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
return publishedStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFlags sets internal copy of flags in the context
|
||||||
|
func (context *AptlyContext) UpdateFlags(flags *flag.FlagSet) {
|
||||||
|
context.flags = flags
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags returns current command flags
|
||||||
|
func (context *AptlyContext) Flags() *flag.FlagSet {
|
||||||
|
return context.flags
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalFlags returns flags passed to all commands
|
||||||
|
func (context *AptlyContext) GlobalFlags() *flag.FlagSet {
|
||||||
|
return context.globalFlags
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown shuts context down
|
||||||
|
func (context *AptlyContext) Shutdown() {
|
||||||
|
if aptly.EnableDebug {
|
||||||
|
if context.fileMemProfile != nil {
|
||||||
|
pprof.WriteHeapProfile(context.fileMemProfile)
|
||||||
|
context.fileMemProfile.Close()
|
||||||
|
context.fileMemProfile = nil
|
||||||
|
}
|
||||||
|
if context.fileCPUProfile != nil {
|
||||||
|
pprof.StopCPUProfile()
|
||||||
|
context.fileCPUProfile.Close()
|
||||||
|
context.fileCPUProfile = nil
|
||||||
|
}
|
||||||
|
if context.fileMemProfile != nil {
|
||||||
|
context.fileMemProfile.Close()
|
||||||
|
context.fileMemProfile = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if context.database != nil {
|
||||||
|
context.database.Close()
|
||||||
|
context.database = nil
|
||||||
|
}
|
||||||
|
if context.downloader != nil {
|
||||||
|
context.downloader.Abort()
|
||||||
|
context.downloader = nil
|
||||||
|
}
|
||||||
|
if context.progress != nil {
|
||||||
|
context.progress.Shutdown()
|
||||||
|
context.progress = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup does partial shutdown of context
|
||||||
|
func (context *AptlyContext) Cleanup() {
|
||||||
|
if context.downloader != nil {
|
||||||
|
context.downloader.Shutdown()
|
||||||
|
context.downloader = nil
|
||||||
|
}
|
||||||
|
if context.progress != nil {
|
||||||
|
context.progress.Shutdown()
|
||||||
|
context.progress = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewContext initializes context with default settings
|
||||||
|
func NewContext(flags *flag.FlagSet) (*AptlyContext, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
context := &AptlyContext{
|
||||||
|
flags: flags,
|
||||||
|
globalFlags: flags,
|
||||||
|
dependencyOptions: -1,
|
||||||
|
publishedStorages: map[string]aptly.PublishedStorage{},
|
||||||
|
}
|
||||||
|
|
||||||
|
if aptly.EnableDebug {
|
||||||
|
cpuprofile := flags.Lookup("cpuprofile").Value.String()
|
||||||
|
if cpuprofile != "" {
|
||||||
|
context.fileCPUProfile, err = os.Create(cpuprofile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pprof.StartCPUProfile(context.fileCPUProfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
memprofile := flags.Lookup("memprofile").Value.String()
|
||||||
|
if memprofile != "" {
|
||||||
|
context.fileMemProfile, err = os.Create(memprofile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memstats := flags.Lookup("memstats").Value.String()
|
||||||
|
if memstats != "" {
|
||||||
|
interval := flags.Lookup("meminterval").Value.Get().(time.Duration)
|
||||||
|
|
||||||
|
context.fileMemStats, err = os.Create(memstats)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
context.fileMemStats.WriteString("# Time\tHeapSys\tHeapAlloc\tHeapIdle\tHeapReleased\n")
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
var stats runtime.MemStats
|
||||||
|
|
||||||
|
start := time.Now().UnixNano()
|
||||||
|
|
||||||
|
for {
|
||||||
|
runtime.ReadMemStats(&stats)
|
||||||
|
if context.fileMemStats != nil {
|
||||||
|
context.fileMemStats.WriteString(fmt.Sprintf("%d\t%d\t%d\t%d\t%d\n",
|
||||||
|
(time.Now().UnixNano()-start)/1000000, stats.HeapSys, stats.HeapAlloc, stats.HeapIdle, stats.HeapReleased))
|
||||||
|
time.Sleep(interval)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return context, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user