Files
kopia/cli/storage_filesystem.go
Jarek Kowalski ad4b222939 cli: added support for copying (or moving) snapshot history (#703)
Both source and destination can be specified using user@host,
@host or user@host:/path where destination values override the
corresponding parts of the source, so both targeted
and mass copying is supported.

Supported combinations are:

Source:             Destination         Behavior
---------------------------------------------------
@host1              @host2              copy snapshots from all users of host1
user1@host1         @host2              copy all snapshots to user1@host2
user1@host1         user2@host2         copy all snapshots to user2@host2
user1@host1:/path1  @host2              copy to user1@host2:/path1
user1@host1:/path1  user2@host2         copy to user2@host2:/path1
user1@host1:/path1  user2@host2:/path2  copy snapshots from single path

When --move is specified, the matching source snapshots are also deleted.

* cli: upgraded kingpin to latest version (not tagged)

This allows using `EnableFileExpansion` to disable treating
arguments prefixed with "@" as file includes.
2020-12-04 16:34:55 -08:00

88 lines
2.2 KiB
Go

package cli
import (
"context"
"os"
"strconv"
"github.com/alecthomas/kingpin"
"github.com/kopia/kopia/repo/blob"
"github.com/kopia/kopia/repo/blob/filesystem"
)
var options filesystem.Options
const (
defaultFileMode = 0o600
defaultDirMode = 0o700
)
var (
connectOwnerUID string
connectOwnerGID string
connectFileMode string
connectDirMode string
connectFlat bool
)
func connect(ctx context.Context, isNew bool) (blob.Storage, error) {
fso := options
if v := connectOwnerUID; v != "" {
fso.FileUID = getIntPtrValue(v, 10)
}
if v := connectOwnerGID; v != "" {
fso.FileGID = getIntPtrValue(v, 10)
}
fso.FileMode = getFileModeValue(connectFileMode, defaultFileMode)
fso.DirectoryMode = getFileModeValue(connectDirMode, defaultDirMode)
if connectFlat {
fso.DirectoryShards = []int{}
}
if isNew {
log(ctx).Debugf("creating directory for repository: %v dir mode: %v", fso.Path, fso.DirectoryMode)
if err := os.MkdirAll(fso.Path, fso.DirectoryMode); err != nil {
log(ctx).Warningf("unable to create directory: %v", fso.Path)
}
}
return filesystem.New(ctx, &fso)
}
func init() {
RegisterStorageConnectFlags(
"filesystem",
"a filesystem",
func(cmd *kingpin.CmdClause) {
cmd.Flag("path", "Path to the repository").Required().StringVar(&options.Path)
cmd.Flag("owner-uid", "User ID owning newly created files").PlaceHolder("USER").StringVar(&connectOwnerUID)
cmd.Flag("owner-gid", "Group ID owning newly created files").PlaceHolder("GROUP").StringVar(&connectOwnerGID)
cmd.Flag("file-mode", "File mode for newly created files (0600)").PlaceHolder("MODE").StringVar(&connectFileMode)
cmd.Flag("dir-mode", "Mode of newly directory files (0700)").PlaceHolder("MODE").StringVar(&connectDirMode)
cmd.Flag("flat", "Use flat directory structure").BoolVar(&connectFlat)
},
connect)
}
func getIntPtrValue(value string, base int) *int {
if int64Val, err := strconv.ParseInt(value, base, 32); err == nil {
intVal := int(int64Val)
return &intVal
}
return nil
}
func getFileModeValue(value string, def os.FileMode) os.FileMode {
if uint32Val, err := strconv.ParseUint(value, 8, 32); err == nil {
return os.FileMode(uint32Val)
}
return def
}