|
- package grsync
-
- import (
- "fmt"
- "io"
- "os"
- "os/exec"
- "strconv"
- "strings"
- )
-
- // Rsync is wrapper under rsync
- type Rsync struct {
- Source string
- Destination string
-
- cmd *exec.Cmd
- }
-
- // RsyncOptions for rsync
- type RsyncOptions struct {
- // Verbose increase verbosity
- Verbose bool
- // Quet suppress non-error messages
- Quiet bool
- // Checksum skip based on checksum, not mod-time & size
- Checksum bool
- // Archve is archive mode; equals -rlptgoD (no -H,-A,-X)
- Archive bool
- // Recurse into directories
- Recursive bool
- // Relative option to use relative path names
- Relative bool
- // NoImliedDirs don't send implied dirs with --relative
- NoImpliedDirs bool
- // Update skip files that are newer on the receiver
- Update bool
- // Inplace update destination files in-place
- Inplace bool
- // Append data onto shorter files
- Append bool
- // AppendVerify --append w/old data in file checksum
- AppendVerify bool
- // Dirs transfer directories without recursing
- Dirs bool
- // Links copy symlinks as symlinks
- Links bool
- // CopyLinks transform symlink into referent file/dir
- CopyLinks bool
- // CopyUnsafeLinks only "unsafe" symlinks are transformed
- CopyUnsafeLinks bool
- // SafeLinks ignore symlinks that point outside the tree
- SafeLinks bool
- // CopyDirLinks transform symlink to dir into referent dir
- CopyDirLinks bool
- // KeepDirLinks treat symlinked dir on receiver as dir
- KeepDirLinks bool
- // HardLinks preserve hard links
- HardLinks bool
- // Perms preserve permissions
- Perms bool
- // Executability preserve executability
- Executability bool
- // CHMOD affect file and/or directory permissions
- CHMOD os.FileMode
- // Acls preserve ACLs (implies -p)
- ACLs bool
- // XAttrs preserve extended attributes
- XAttrs bool
- // Owner preserve owner (super-user only)
- Owner bool
- // Group preserve group
- Group bool
- // Devices preserve device files (super-user only)
- Devices bool
- // Specials preserve special files
- Specials bool
- // Times preserve modification times
- Times bool
- // omit directories from --times
- OmitDirTimes bool
- // Super receiver attempts super-user activities
- Super bool
- // FakeSuper store/recover privileged attrs using xattrs
- FakeSuper bool
- // Sparce handle sparse files efficiently
- Sparse bool
- // DryRun perform a trial run with no changes made
- DryRun bool
- // WholeFile copy files whole (w/o delta-xfer algorithm)
- WholeFile bool
- // OneFileSystem don't cross filesystem boundaries
- OneFileSystem bool
- // BlockSize block-size=SIZE force a fixed checksum block-size
- BlockSize int
- // Rsh -rsh=COMMAND specify the remote shell to use
- Rsh string
- // RsyncProgramm rsync-path=PROGRAM specify the rsync to run on remote machine
- RsyncProgramm string
- // Existing skip creating new files on receiver
- Existing bool
- // IgnoreExisting skip updating files that exist on receiver
- IgnoreExisting bool
- // RemoveSourceFiles sender removes synchronized files (non-dir)
- RemoveSourceFiles bool
- // Delete delete extraneous files from dest dirs
- Delete bool
- // DeleteBefore receiver deletes before transfer, not during
- DeleteBefore bool
- // DeleteDuring receiver deletes during the transfer
- DeleteDuring bool
- // DeleteDelay find deletions during, delete after
- DeleteDelay bool
- // DeleteAfter receiver deletes after transfer, not during
- DeleteAfter bool
- // DeleteExcluded also delete excluded files from dest dirs
- DeleteExcluded bool
- // IgnoreErrors delete even if there are I/O errors
- IgnoreErrors bool
- // Force deletion of dirs even if not empty
- Force bool
- // MaxDelete max-delete=NUM don't delete more than NUM files
- MaxDelete int
- // MaxSize max-size=SIZE don't transfer any file larger than SIZE
- MaxSize int
- // MinSize don't transfer any file smaller than SIZE
- MinSize int
- // Partial keep partially transferred files
- Partial bool
- // PartialDir partial-dir=DIR
- PartialDir string
- // DelayUpdates put all updated files into place at end
- DelayUpdates bool
- // PruneEmptyDirs prune empty directory chains from file-list
- PruneEmptyDirs bool
- // NumericIDs don't map uid/gid values by user/group name
- NumericIDs bool
- // Timeout timeout=SECONDS set I/O timeout in seconds
- Timeout int
- // Contimeout contimeout=SECONDS set daemon connection timeout in seconds
- Contimeout int
- // IgnoreTimes don't skip files that match size and time
- IgnoreTimes bool
- // SizeOnly skip files that match in size
- SizeOnly bool
- // ModifyWindow modify-window=NUM compare mod-times with reduced accuracy
- ModifyWindow bool
- // TempDir temp-dir=DIR create temporary files in directory DIR
- TempDir string
- // Fuzzy find similar file for basis if no dest file
- Fuzzy bool
- // CompareDest compare-dest=DIR also compare received files relative to DIR
- CompareDest string
- // CopyDest copy-dest=DIR ... and include copies of unchanged files
- CopyDest string
- // LinkDest link-dest=DIR hardlink to files in DIR when unchanged
- LinkDest string
- // Compress file data during the transfer
- Compress bool
- // CompressLevel explicitly set compression level
- CompressLevel int
- // SkipCompress skip-compress=LIST skip compressing files with suffix in LIST
- SkipCompress []string
- // CVSExclude auto-ignore files in the same way CVS does
- CVSExclude bool
- // Stats give some file-transfer stats
- Stats bool
- // HumanReadable output numbers in a human-readable format
- HumanReadable bool
- // Progress show progress during transfer
- Progress bool
- // 端口
- Port int
- // 密钥文件
- PasswordFile string
- // Info
- Info string
-
- // ipv4
- IPv4 bool
- // ipv6
- IPv6 bool
- }
-
- // StdoutPipe returns a pipe that will be connected to the command's
- // standard output when the command starts.
- func (r Rsync) StdoutPipe() (io.ReadCloser, error) {
- return r.cmd.StdoutPipe()
- }
-
- // StderrPipe returns a pipe that will be connected to the command's
- // standard error when the command starts.
- func (r Rsync) StderrPipe() (io.ReadCloser, error) {
- return r.cmd.StderrPipe()
- }
-
- // Run start rsync task
- func (r Rsync) Run() error {
- if !isExist(r.Destination) {
- if err := createDir(r.Destination); err != nil {
- return err
- }
- }
-
- if err := r.cmd.Start(); err != nil {
- return err
- }
-
- return r.cmd.Wait()
- }
-
- // NewRsync returns task with described options
- func NewRsync(source, destination string, options RsyncOptions) *Rsync {
- arguments := append(getArguments(options), source, destination)
- return &Rsync{
- Source: source,
- Destination: destination,
- cmd: exec.Command("rsync", arguments...),
- }
- }
-
- func getArguments(options RsyncOptions) []string {
- arguments := []string{}
- if options.Verbose {
- arguments = append(arguments, "--verbose")
- }
-
- if options.Checksum {
- arguments = append(arguments, "--checksum")
- }
-
- if options.Quiet {
- arguments = append(arguments, "--quiet")
- }
-
- if options.Archive {
- arguments = append(arguments, "--archive")
- }
-
- if options.Recursive {
- arguments = append(arguments, "--recursive")
- }
-
- if options.Relative {
- arguments = append(arguments, "--relative")
- }
-
- if options.NoImpliedDirs {
- arguments = append(arguments, "--no-implied-dirs")
- }
-
- if options.Update {
- arguments = append(arguments, "--update")
- }
-
- if options.Inplace {
- arguments = append(arguments, "--inplace")
- }
-
- if options.Append {
- arguments = append(arguments, "--append")
- }
-
- if options.AppendVerify {
- arguments = append(arguments, "--append-verify")
- }
-
- if options.Dirs {
- arguments = append(arguments, "--dirs")
- }
-
- if options.Links {
- arguments = append(arguments, "--links")
- }
-
- if options.CopyLinks {
- arguments = append(arguments, "--copy-links")
- }
-
- if options.CopyUnsafeLinks {
- arguments = append(arguments, "--copy-unsafe-links")
- }
-
- if options.SafeLinks {
- arguments = append(arguments, "--safe-links")
- }
-
- if options.CopyDirLinks {
- arguments = append(arguments, "--copy-dir-links")
- }
-
- if options.KeepDirLinks {
- arguments = append(arguments, "--keep-dir-links")
- }
-
- if options.HardLinks {
- arguments = append(arguments, "--hard-links")
- }
-
- if options.Perms {
- arguments = append(arguments, "--perms")
- }
-
- if options.Executability {
- arguments = append(arguments, "--executability")
- }
-
- if options.ACLs {
- arguments = append(arguments, "--acls")
- }
-
- if options.XAttrs {
- arguments = append(arguments, "--xattrs")
- }
-
- if options.Owner {
- arguments = append(arguments, "--owner")
- }
-
- if options.Group {
- arguments = append(arguments, "--group")
- }
-
- if options.Devices {
- arguments = append(arguments, "--devices")
- }
-
- if options.Port > 0 {
- arguments = append(arguments, fmt.Sprintf("--port=%d", options.Port))
- }
-
- if options.Specials {
- arguments = append(arguments, "--specials")
- }
-
- if options.Times {
- arguments = append(arguments, "--times")
- }
-
- if options.OmitDirTimes {
- arguments = append(arguments, "--omit-dir-times")
- }
-
- if options.Super {
- arguments = append(arguments, "--super")
- }
-
- if options.FakeSuper {
- arguments = append(arguments, "--fake-super")
- }
-
- if options.Sparse {
- arguments = append(arguments, "--sparse")
- }
-
- if options.DryRun {
- arguments = append(arguments, "--dry-run")
- }
-
- if options.WholeFile {
- arguments = append(arguments, "--whole-file")
- }
-
- if options.OneFileSystem {
- arguments = append(arguments, "--one-file-system")
- }
-
- if options.BlockSize > 0 {
- arguments = append(arguments, "--block-size", strconv.Itoa(options.BlockSize))
- }
-
- if options.Rsh != "" {
- arguments = append(arguments, "--rsh", options.Rsh)
- }
-
- if options.RsyncProgramm != "" {
- arguments = append(arguments, "--rsync-programm", options.RsyncProgramm)
- }
-
- if options.Existing {
- arguments = append(arguments, "--existing")
- }
-
- if options.IgnoreExisting {
- arguments = append(arguments, "--ignore-existing")
- }
-
- if options.RemoveSourceFiles {
- arguments = append(arguments, "--remove-source-files")
- }
-
- if options.Delete {
- arguments = append(arguments, "--delete")
- }
-
- if options.DeleteBefore {
- arguments = append(arguments, "--delete-before")
- }
-
- if options.DeleteDuring {
- arguments = append(arguments, "--delete-during")
- }
-
- if options.DeleteDelay {
- arguments = append(arguments, "--delete-delay")
- }
-
- if options.DeleteAfter {
- arguments = append(arguments, "--delete-after")
- }
-
- if options.DeleteExcluded {
- arguments = append(arguments, "--delete-excluded")
- }
-
- if options.IgnoreErrors {
- arguments = append(arguments, "--ignore-errors")
- }
-
- if options.Force {
- arguments = append(arguments, "--force")
- }
-
- if options.MaxDelete > 0 {
- arguments = append(arguments, "--max-delete", strconv.Itoa(options.MaxDelete))
- }
-
- if options.MaxSize > 0 {
- arguments = append(arguments, "--max-size", strconv.Itoa(options.MaxSize))
- }
-
- if options.MinSize > 0 {
- arguments = append(arguments, "--min-size", strconv.Itoa(options.MinSize))
- }
-
- if options.Partial {
- arguments = append(arguments, "--partial")
- }
-
- if options.PartialDir != "" {
- arguments = append(arguments, "--partial-dir", options.PartialDir)
- }
-
- if options.DelayUpdates {
- arguments = append(arguments, "--delay-updates")
- }
-
- if options.PruneEmptyDirs {
- arguments = append(arguments, "--prune-empty-dirs")
- }
-
- if options.NumericIDs {
- arguments = append(arguments, "--numeric-ids")
- }
-
- if options.Timeout > 0 {
- arguments = append(arguments, "--timeout", strconv.Itoa(options.Timeout))
- }
-
- if options.Contimeout > 0 {
- arguments = append(arguments, "--contimeout", strconv.Itoa(options.Contimeout))
- }
-
- if options.IgnoreTimes {
- arguments = append(arguments, "--ignore-times")
- }
-
- if options.SizeOnly {
- arguments = append(arguments, "--size-only")
- }
-
- if options.ModifyWindow {
- arguments = append(arguments, "--modify-window")
- }
-
- if options.TempDir != "" {
- arguments = append(arguments, "--temp-dir", options.TempDir)
- }
-
- if options.Fuzzy {
- arguments = append(arguments, "--fuzzy")
- }
-
- if options.CompareDest != "" {
- arguments = append(arguments, "--compare-dest", options.CompareDest)
- }
-
- if options.CopyDest != "" {
- arguments = append(arguments, "--copy-dest", options.CopyDest)
- }
-
- if options.LinkDest != "" {
- arguments = append(arguments, "--link-dest", options.LinkDest)
- }
-
- if options.Compress {
- arguments = append(arguments, "--compress")
- }
-
- if options.CompressLevel > 0 {
- arguments = append(arguments, "--compress-level", strconv.Itoa(options.CompressLevel))
- }
-
- if len(options.SkipCompress) > 0 {
- arguments = append(arguments, "--skip-compress", strings.Join(options.SkipCompress, ","))
- }
-
- if options.CVSExclude {
- arguments = append(arguments, "--cvs-exclude")
- }
-
- if options.Stats {
- arguments = append(arguments, "--stats")
- }
-
- if options.HumanReadable {
- arguments = append(arguments, "--human-readable")
- }
-
- if options.Progress {
- arguments = append(arguments, "--progress")
- }
-
- if options.IPv4 {
- arguments = append(arguments, "--ipv4")
- }
-
- if options.IPv6 {
- arguments = append(arguments, "--ipv6")
- }
-
- if options.Info != "" {
- arguments = append(arguments, "--info", options.Info)
- }
-
- if options.PasswordFile != "" {
- arguments = append(arguments, "--password-file", options.PasswordFile)
- }
-
- return arguments
- }
-
- func createDir(dir string) error {
- cmd := exec.Command("mkdir", "-p", dir)
- if err := cmd.Start(); err != nil {
- return err
- }
- return cmd.Wait()
- }
-
- func isExist(p string) bool {
- stat, err := os.Stat(p)
- return os.IsExist(err) && stat.IsDir()
- }
|