Files
kopia/cli/command_repository_create.go

121 lines
4.3 KiB
Go

package cli
import (
"fmt"
"os"
kingpin "gopkg.in/alecthomas/kingpin.v2"
"github.com/kopia/kopia/block"
"github.com/kopia/kopia/internal/units"
"github.com/kopia/kopia/metadata"
"github.com/kopia/kopia/object"
"github.com/kopia/kopia/repo"
"github.com/kopia/kopia/storage"
)
var (
createCommand = repositoryCommands.Command("create", "Create new repository in a specified location.")
createRepositoryLocation = createCommand.Arg("location", "Location where to create the repository").Required().String()
createMetadataEncryptionFormat = createCommand.Flag("metadata-encryption", "Metadata item encryption.").PlaceHolder("FORMAT").Default(metadata.SupportedEncryptionAlgorithms[0]).Enum(metadata.SupportedEncryptionAlgorithms...)
createObjectFormat = createCommand.Flag("object-format", "Format of repository objects.").PlaceHolder("FORMAT").Default(block.DefaultFormat).Enum(block.SupportedFormats...)
createObjectSplitter = createCommand.Flag("object-splitter", "The splitter to use for new objects in the repository").Default("DYNAMIC").Enum(object.SupportedSplitters...)
createMinBlockSize = createCommand.Flag("min-block-size", "Minimum size of a data block.").PlaceHolder("KB").Default("1024").Int()
createAvgBlockSize = createCommand.Flag("avg-block-size", "Average size of a data block.").PlaceHolder("KB").Default("10240").Int()
createMaxBlockSize = createCommand.Flag("max-block-size", "Maximum size of a data block.").PlaceHolder("KB").Default("20480").Int()
createMaxPackedContentLength = createCommand.Flag("max-packed-file-size", "Minimum size of a file to include in a pack.").PlaceHolder("KB").Default("4096").Int()
createOverwrite = createCommand.Flag("overwrite", "Overwrite existing data (DANGEROUS).").Bool()
createOnly = createCommand.Flag("create-only", "Create repository, but don't connect to it.").Short('c').Bool()
)
func init() {
setupConnectOptions(createCommand)
createCommand.Action(runCreateCommand)
}
func newRepositoryOptionsFromFlags() *repo.NewRepositoryOptions {
return &repo.NewRepositoryOptions{
MetadataEncryptionAlgorithm: *createMetadataEncryptionFormat,
BlockFormat: *createObjectFormat,
Splitter: *createObjectSplitter,
MinBlockSize: *createMinBlockSize * 1024,
AvgBlockSize: *createAvgBlockSize * 1024,
MaxBlockSize: *createMaxBlockSize * 1024,
MaxPackedContentLength: *createMaxPackedContentLength * 1024,
}
}
func openStorageAndEnsureEmpty(url string) (storage.Storage, error) {
s, err := newStorageFromURL(getContext(), url)
if err != nil {
return nil, err
}
ch, cancel := s.ListBlocks("")
d, hasData := <-ch
cancel()
if hasData {
if d.Error != nil {
return nil, d.Error
}
if !*createOverwrite {
return nil, fmt.Errorf("found existing data in %v, specify --overwrite to use anyway", url)
}
}
return s, nil
}
func runCreateCommand(_ *kingpin.ParseContext) error {
st, err := openStorageAndEnsureEmpty(*createRepositoryLocation)
if err != nil {
return fmt.Errorf("unable to get repository storage: %v", err)
}
options := newRepositoryOptionsFromFlags()
creds, err := getRepositoryCredentials(true)
if err != nil {
return fmt.Errorf("unable to get credentials: %v", err)
}
fmt.Fprintf(os.Stderr, "Initializing repository with:\n")
fmt.Fprintf(os.Stderr, " metadata encryption: %v\n", options.MetadataEncryptionAlgorithm)
fmt.Fprintf(os.Stderr, " block format: %v\n", options.BlockFormat)
switch options.Splitter {
case "DYNAMIC":
fmt.Fprintf(os.Stderr, " object splitter: DYNAMIC with block sizes (min:%v avg:%v max:%v)\n",
units.BytesStringBase2(int64(options.MinBlockSize)),
units.BytesStringBase2(int64(options.AvgBlockSize)),
units.BytesStringBase2(int64(options.MaxBlockSize)))
case "FIXED":
fmt.Fprintf(os.Stderr, " object splitter: FIXED with with block size: %v\n", units.BytesStringBase2(int64(options.MaxBlockSize)))
case "NEVER":
fmt.Fprintf(os.Stderr, " object splitter: NEVER\n")
}
if err := repo.Initialize(st, options, creds); err != nil {
return fmt.Errorf("cannot initialize repository: %v", err)
}
if !*createOnly {
err := repo.Connect(getContext(), repositoryConfigFileName(), st, creds, connectOptions())
if err != nil {
return err
}
fmt.Fprintln(os.Stderr, "Connected to repository:", *createRepositoryLocation)
}
return nil
}