mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 19:55:29 +08:00
Implement check and help commands
This commit is contained in:
parent
335667fdcb
commit
90a2c86eb3
36
fs.go
36
fs.go
|
@ -74,6 +74,27 @@ func checkClose(c io.Closer, err *error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the two files to see if the MD5sums are the same
|
||||||
|
//
|
||||||
|
// May return an error which will already have been logged
|
||||||
|
//
|
||||||
|
// If an error is returned it will return false
|
||||||
|
func CheckMd5sums(src, dst FsObject) (bool, error) {
|
||||||
|
srcMd5, err := src.Md5sum()
|
||||||
|
if err != nil {
|
||||||
|
FsLog(src, "Failed to calculate src md5: %s", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
dstMd5, err := dst.Md5sum()
|
||||||
|
if err != nil {
|
||||||
|
FsLog(dst, "Failed to calculate dst md5: %s", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
// FsDebug("Src MD5 %s", srcMd5)
|
||||||
|
// FsDebug("Dst MD5 %s", obj.Hash)
|
||||||
|
return srcMd5 == dstMd5, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Checks to see if the src and dst objects are equal by looking at
|
// Checks to see if the src and dst objects are equal by looking at
|
||||||
// size, mtime and MD5SUM
|
// size, mtime and MD5SUM
|
||||||
//
|
//
|
||||||
|
@ -114,19 +135,8 @@ func Equal(src, dst FsObject) bool {
|
||||||
|
|
||||||
// mtime is unreadable or different but size is the same so
|
// mtime is unreadable or different but size is the same so
|
||||||
// check the MD5SUM
|
// check the MD5SUM
|
||||||
srcMd5, err := src.Md5sum()
|
same, err := CheckMd5sums(src, dst)
|
||||||
if err != nil {
|
if !same {
|
||||||
FsDebug(src, "Failed to calculate src md5: %s", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
dstMd5, err := dst.Md5sum()
|
|
||||||
if err != nil {
|
|
||||||
FsDebug(dst, "Failed to calculate dst md5: %s", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// FsDebug("Src MD5 %s", srcMd5)
|
|
||||||
// FsDebug("Dst MD5 %s", obj.Hash)
|
|
||||||
if srcMd5 != dstMd5 {
|
|
||||||
FsDebug(src, "Md5sums differ")
|
FsDebug(src, "Md5sums differ")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
Todo
|
Todo
|
||||||
|
* FIXME: More -dry-run checks for object transfer
|
||||||
* Check logging in various parts
|
* Check logging in various parts
|
||||||
* Make logging controllable with flags (mostly done)
|
* Make logging controllable with flags (mostly done)
|
||||||
* progress meter would be nice! Do this by wrapping the Reader with a progress bar
|
* progress meter would be nice! Do this by wrapping the Reader with a progress bar
|
||||||
|
@ -12,7 +13,6 @@ Todo
|
||||||
* Windows paths? Do we need to translate / and \?
|
* Windows paths? Do we need to translate / and \?
|
||||||
* Make a fs.Errorf and count errors and log them at a different level
|
* Make a fs.Errorf and count errors and log them at a different level
|
||||||
* add -modify-window flag - fs should keep knowledge of resolution
|
* add -modify-window flag - fs should keep knowledge of resolution
|
||||||
* add check command to compare local MD5SUMs with remote
|
|
||||||
|
|
||||||
Ideas
|
Ideas
|
||||||
* optimise remote copy container to another container using remote
|
* optimise remote copy container to another container using remote
|
||||||
|
|
120
swiftsync.go
120
swiftsync.go
|
@ -125,16 +125,16 @@ func Sync(fdst, fsrc Fs) {
|
||||||
// Read the destination files first
|
// Read the destination files first
|
||||||
// FIXME could do this in parallel and make it use less memory
|
// FIXME could do this in parallel and make it use less memory
|
||||||
delFiles := make(map[string]FsObject)
|
delFiles := make(map[string]FsObject)
|
||||||
for dstFile := range fdst.List() {
|
for dst := range fdst.List() {
|
||||||
delFiles[dstFile.Remote()] = dstFile
|
delFiles[dst.Remote()] = dst
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read source files checking them off against dest files
|
// Read source files checking them off against dest files
|
||||||
to_be_checked := make(FsObjectsChan, *transfers)
|
to_be_checked := make(FsObjectsChan, *transfers)
|
||||||
go func() {
|
go func() {
|
||||||
for srcFile := range fsrc.List() {
|
for src := range fsrc.List() {
|
||||||
delete(delFiles, srcFile.Remote())
|
delete(delFiles, src.Remote())
|
||||||
to_be_checked <- srcFile
|
to_be_checked <- src
|
||||||
}
|
}
|
||||||
close(to_be_checked)
|
close(to_be_checked)
|
||||||
}()
|
}()
|
||||||
|
@ -172,6 +172,74 @@ func Sync(fdst, fsrc Fs) {
|
||||||
DeleteFiles(toDelete)
|
DeleteFiles(toDelete)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks the files in fsrc and fdst according to Size and MD5SUM
|
||||||
|
func Check(fdst, fsrc Fs) {
|
||||||
|
// Read the destination files first
|
||||||
|
// FIXME could do this in parallel and make it use less memory
|
||||||
|
dstFiles := make(map[string]FsObject)
|
||||||
|
for dst := range fdst.List() {
|
||||||
|
dstFiles[dst.Remote()] = dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the source files checking them against dstFiles
|
||||||
|
// FIXME could do this in parallel and make it use less memory
|
||||||
|
srcFiles := make(map[string]FsObject)
|
||||||
|
commonFiles := make(map[string][]FsObject)
|
||||||
|
for src := range fsrc.List() {
|
||||||
|
remote := src.Remote()
|
||||||
|
if dst, ok := dstFiles[remote]; ok {
|
||||||
|
commonFiles[remote] = []FsObject{dst, src}
|
||||||
|
delete(dstFiles, remote)
|
||||||
|
} else {
|
||||||
|
srcFiles[remote] = src
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Files in %s but not in %s", fdst, fsrc)
|
||||||
|
for remote := range dstFiles {
|
||||||
|
log.Printf(remote)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Files in %s but not in %s", fsrc, fdst)
|
||||||
|
for remote := range srcFiles {
|
||||||
|
log.Printf(remote)
|
||||||
|
}
|
||||||
|
|
||||||
|
checks := make(chan []FsObject, *transfers)
|
||||||
|
go func() {
|
||||||
|
for _, check := range commonFiles {
|
||||||
|
checks <- check
|
||||||
|
}
|
||||||
|
close(checks)
|
||||||
|
}()
|
||||||
|
|
||||||
|
var checkerWg sync.WaitGroup
|
||||||
|
checkerWg.Add(*checkers)
|
||||||
|
for i := 0; i < *checkers; i++ {
|
||||||
|
go func() {
|
||||||
|
defer checkerWg.Done()
|
||||||
|
for check := range checks {
|
||||||
|
dst, src := check[0], check[1]
|
||||||
|
if src.Size() != dst.Size() {
|
||||||
|
FsLog(src, "Sizes differ")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
same, err := CheckMd5sums(src, dst)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !same {
|
||||||
|
FsLog(src, "Md5sums differ")
|
||||||
|
}
|
||||||
|
FsDebug(src, "OK")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Waiting for checks to finish")
|
||||||
|
checkerWg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
// List the Fs to stdout
|
// List the Fs to stdout
|
||||||
func List(f Fs) {
|
func List(f Fs) {
|
||||||
// FIXME error?
|
// FIXME error?
|
||||||
|
@ -268,9 +336,8 @@ var Commands = []Command{
|
||||||
unchanged files, testing first by modification time then by
|
unchanged files, testing first by modification time then by
|
||||||
MD5SUM. Deletes any files that exist in source that don't
|
MD5SUM. Deletes any files that exist in source that don't
|
||||||
exist in destination. Since this can cause data loss, test
|
exist in destination. Since this can cause data loss, test
|
||||||
first with the -dry-run flag.
|
first with the -dry-run flag.`,
|
||||||
|
|
||||||
`,
|
|
||||||
Sync,
|
Sync,
|
||||||
2, 2,
|
2, 2,
|
||||||
},
|
},
|
||||||
|
@ -279,9 +346,8 @@ var Commands = []Command{
|
||||||
`[<path>]
|
`[<path>]
|
||||||
|
|
||||||
List the path. If no parameter is supplied then it lists the
|
List the path. If no parameter is supplied then it lists the
|
||||||
available swift containers.
|
available swift containers.`,
|
||||||
|
|
||||||
`,
|
|
||||||
list,
|
list,
|
||||||
0, 1,
|
0, 1,
|
||||||
},
|
},
|
||||||
|
@ -289,9 +355,8 @@ var Commands = []Command{
|
||||||
"mkdir",
|
"mkdir",
|
||||||
`<path>
|
`<path>
|
||||||
|
|
||||||
Make the path if it doesn't already exist
|
Make the path if it doesn't already exist`,
|
||||||
|
|
||||||
`,
|
|
||||||
mkdir,
|
mkdir,
|
||||||
1, 1,
|
1, 1,
|
||||||
},
|
},
|
||||||
|
@ -300,9 +365,8 @@ var Commands = []Command{
|
||||||
`<path>
|
`<path>
|
||||||
|
|
||||||
Remove the path. Note that you can't remove a path with
|
Remove the path. Note that you can't remove a path with
|
||||||
objects in it, use purge for that
|
objects in it, use purge for that.`,
|
||||||
|
|
||||||
`,
|
|
||||||
rmdir,
|
rmdir,
|
||||||
1, 1,
|
1, 1,
|
||||||
},
|
},
|
||||||
|
@ -310,12 +374,31 @@ var Commands = []Command{
|
||||||
"purge",
|
"purge",
|
||||||
`<path>
|
`<path>
|
||||||
|
|
||||||
Remove the path and all of its contents.
|
Remove the path and all of its contents.`,
|
||||||
|
|
||||||
`,
|
|
||||||
purge,
|
purge,
|
||||||
1, 1,
|
1, 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"check",
|
||||||
|
`<source> <destination>
|
||||||
|
|
||||||
|
Checks the files in the source and destination match. It
|
||||||
|
compares sizes and MD5SUMs and prints a report of files which
|
||||||
|
don't match. It doesn't alter the source or destination.`,
|
||||||
|
|
||||||
|
Check,
|
||||||
|
2, 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"help",
|
||||||
|
`
|
||||||
|
|
||||||
|
This help.`,
|
||||||
|
|
||||||
|
nil,
|
||||||
|
0, 0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// syntaxError prints the syntax
|
// syntaxError prints the syntax
|
||||||
|
@ -329,7 +412,7 @@ Subcommands:
|
||||||
`)
|
`)
|
||||||
for i := range Commands {
|
for i := range Commands {
|
||||||
cmd := &Commands[i]
|
cmd := &Commands[i]
|
||||||
fmt.Fprintf(os.Stderr, " %s: %s\n", cmd.name, cmd.help)
|
fmt.Fprintf(os.Stderr, " %s: %s\n\n", cmd.name, cmd.help)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "Options:\n")
|
fmt.Fprintf(os.Stderr, "Options:\n")
|
||||||
|
@ -407,5 +490,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the actual command
|
// Run the actual command
|
||||||
|
if found.run != nil {
|
||||||
found.run(fdst, fsrc)
|
found.run(fdst, fsrc)
|
||||||
|
} else {
|
||||||
|
syntaxError()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user