The sync report flags (--combined, --missing-on-src, --missing-on-dst, --match, --differ, --error and --dest-after) were only wired up in the CLI commands so there was no way to get these reports over the rc or from librclone. This adds boolean parameters of the same names as operations/check (combined, missingOnSrc, missingOnDst, match, differ, error and destAfter) to sync/sync, sync/copy and sync/move. Each requested report is returned as an array of strings in the output, just as operations/check does. All default to off so existing callers see no change in the output. To share the code between the CLI and the rc the report writer helper from operations/check is exported as operations.RcReportWriter, the lsf defaults for --dest-after are moved into operations.NewSyncLoggerOpt and the listing setup and --no-traverse warnings from operationsflags.ConfigureLoggers into LoggerOpt.Init.
133 lines
5.1 KiB
Go
133 lines
5.1 KiB
Go
// Package operationsflags defines the flags used by rclone operations.
|
|
// It is decoupled into a separate package so it can be replaced.
|
|
package operationsflags
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/rclone/rclone/fs"
|
|
"github.com/rclone/rclone/fs/config/flags"
|
|
"github.com/rclone/rclone/fs/operations"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/pflag"
|
|
)
|
|
|
|
//go:embed operationsflags.md
|
|
var help string
|
|
|
|
// Help returns the help string cleaned up to simplify appending
|
|
func Help() string {
|
|
return strings.TrimSpace(help)
|
|
}
|
|
|
|
// AddLoggerFlagsOptions contains options for the Logger Flags
|
|
type AddLoggerFlagsOptions struct {
|
|
Combined string // a file with file names with leading sigils
|
|
MissingOnSrc string // files only in the destination
|
|
MissingOnDst string // files only in the source
|
|
Match string // matching files
|
|
Differ string // differing files
|
|
ErrFile string // files with errors of some kind
|
|
DestAfter string // files that exist on the destination post-sync
|
|
}
|
|
|
|
// AnySet checks if any of the logger flags have a non-blank value
|
|
func (o AddLoggerFlagsOptions) AnySet() bool {
|
|
return anyNotBlank(o.Combined, o.MissingOnSrc, o.MissingOnDst, o.Match, o.Differ, o.ErrFile, o.DestAfter)
|
|
}
|
|
|
|
func anyNotBlank(s ...string) bool {
|
|
for _, x := range s {
|
|
if x != "" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// AddLoggerFlags adds the logger flags to the cmdFlags command
|
|
func AddLoggerFlags(cmdFlags *pflag.FlagSet, opt *operations.LoggerOpt, flagsOpt *AddLoggerFlagsOptions) {
|
|
flags.StringVarP(cmdFlags, &flagsOpt.Combined, "combined", "", flagsOpt.Combined, "Make a combined report of changes to this file", "Sync")
|
|
flags.StringVarP(cmdFlags, &flagsOpt.MissingOnSrc, "missing-on-src", "", flagsOpt.MissingOnSrc, "Report all files missing from the source to this file", "Sync")
|
|
flags.StringVarP(cmdFlags, &flagsOpt.MissingOnDst, "missing-on-dst", "", flagsOpt.MissingOnDst, "Report all files missing from the destination to this file", "Sync")
|
|
flags.StringVarP(cmdFlags, &flagsOpt.Match, "match", "", flagsOpt.Match, "Report all matching files to this file", "Sync")
|
|
flags.StringVarP(cmdFlags, &flagsOpt.Differ, "differ", "", flagsOpt.Differ, "Report all non-matching files to this file", "Sync")
|
|
flags.StringVarP(cmdFlags, &flagsOpt.ErrFile, "error", "", flagsOpt.ErrFile, "Report all files with errors (hashing or reading) to this file", "Sync")
|
|
flags.StringVarP(cmdFlags, &flagsOpt.DestAfter, "dest-after", "", flagsOpt.DestAfter, "Report all files that exist on the dest post-sync", "Sync")
|
|
|
|
// lsf flags for destAfter
|
|
def := operations.NewSyncLoggerOpt()
|
|
flags.StringVarP(cmdFlags, &opt.Format, "format", "F", def.Format, "Output format - see lsf help for details", "Sync")
|
|
flags.StringVarP(cmdFlags, &opt.TimeFormat, "timeformat", "t", def.TimeFormat, "Specify a custom time format - see docs for details (default: 2006-01-02 15:04:05)", "")
|
|
flags.StringVarP(cmdFlags, &opt.Separator, "separator", "s", def.Separator, "Separator for the items in the format", "Sync")
|
|
flags.BoolVarP(cmdFlags, &opt.DirSlash, "dir-slash", "d", def.DirSlash, "Append a slash to directory names", "Sync")
|
|
opt.HashType = def.HashType
|
|
flags.FVarP(cmdFlags, &opt.HashType, "hash", "", "Use this hash when `h` is used in the format MD5|SHA-1|DropboxHash", "Sync")
|
|
flags.BoolVarP(cmdFlags, &opt.FilesOnly, "files-only", "", def.FilesOnly, "Only list files", "Sync")
|
|
flags.BoolVarP(cmdFlags, &opt.DirsOnly, "dirs-only", "", def.DirsOnly, "Only list directories", "Sync")
|
|
flags.BoolVarP(cmdFlags, &opt.Csv, "csv", "", def.Csv, "Output in CSV format", "Sync")
|
|
flags.BoolVarP(cmdFlags, &opt.Absolute, "absolute", "", def.Absolute, "Put a leading / in front of path names", "Sync")
|
|
// flags.BoolVarP(cmdFlags, &recurse, "recursive", "R", false, "Recurse into the listing", "")
|
|
}
|
|
|
|
// ConfigureLoggers verifies and sets up writers for log files requested via CLI flags
|
|
func ConfigureLoggers(ctx context.Context, fdst fs.Fs, command *cobra.Command, opt *operations.LoggerOpt, flagsOpt AddLoggerFlagsOptions) (func(), error) {
|
|
closers := []io.Closer{}
|
|
|
|
open := func(name string, pout *io.Writer) error {
|
|
if name == "" {
|
|
return nil
|
|
}
|
|
if name == "-" {
|
|
*pout = os.Stdout
|
|
return nil
|
|
}
|
|
out, err := os.Create(name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*pout = out
|
|
closers = append(closers, out)
|
|
return nil
|
|
}
|
|
|
|
if err := open(flagsOpt.Combined, &opt.Combined); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := open(flagsOpt.MissingOnSrc, &opt.MissingOnSrc); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := open(flagsOpt.MissingOnDst, &opt.MissingOnDst); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := open(flagsOpt.Match, &opt.Match); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := open(flagsOpt.Differ, &opt.Differ); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := open(flagsOpt.ErrFile, &opt.Error); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := open(flagsOpt.DestAfter, &opt.DestAfter); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
close := func() {
|
|
for _, closer := range closers {
|
|
err := closer.Close()
|
|
if err != nil {
|
|
fs.Errorf(nil, "Failed to close report output: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
opt.Init(ctx, fdst, command.Flags())
|
|
|
|
return close, nil
|
|
}
|