dircache: factor DirMove code out of backends into dircache

Before this change there was lots of duplicated code in all the
dircache using backends to support DirMove.

This change factors this code into the dircache library.
This commit is contained in:
Nick Craig-Wood 2020-05-12 11:39:30 +01:00
parent a8652e2252
commit 2121c0fa23
10 changed files with 87 additions and 261 deletions

View File

@ -944,39 +944,14 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
fs.Debugf(srcFs, "Can't move directory - not same remote type") fs.Debugf(srcFs, "Can't move directory - not same remote type")
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
srcPath := path.Join(srcFs.root, srcRemote)
dstPath := path.Join(f.root, dstRemote)
// Refuse to move to or from the root srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote)
if srcPath == "" || dstPath == "" {
fs.Debugf(src, "DirMove error: Can't move root")
return errors.New("can't move root directory")
}
// Find ID of dst parent, creating subdirs if necessary
leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if err != nil {
return err
}
// Check destination does not exist
_, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return err
} else {
return fs.ErrorDirExists
}
// Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
if err != nil { if err != nil {
return err return err
} }
// Do the move // Do the move
_, err = f.move(ctx, "/folders/", srcID, leaf, directoryID) _, err = f.move(ctx, "/folders/", srcID, dstLeaf, dstDirectoryID)
if err != nil { if err != nil {
return err return err
} }

View File

@ -2542,47 +2542,19 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
fs.Debugf(srcFs, "Can't move directory - not same remote type") fs.Debugf(srcFs, "Can't move directory - not same remote type")
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
srcPath := path.Join(srcFs.root, srcRemote)
dstPath := path.Join(f.root, dstRemote)
// Refuse to move to or from the root srcID, srcDirectoryID, srcLeaf, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote)
if srcPath == "" || dstPath == "" {
fs.Debugf(src, "DirMove error: Can't move root")
return errors.New("can't move root directory")
}
// Find ID of dst parent, creating subdirs if necessary
leaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if err != nil { if err != nil {
return err return err
} }
_ = srcLeaf
dstDirectoryID = actualID(dstDirectoryID) dstDirectoryID = actualID(dstDirectoryID)
// Check destination does not exist
_, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return err
} else {
return fs.ErrorDirExists
}
// Find ID of src parent
_, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false)
if err != nil {
return err
}
srcDirectoryID = actualID(srcDirectoryID) srcDirectoryID = actualID(srcDirectoryID)
// Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
if err != nil {
return err
}
// Do the move // Do the move
patch := drive.File{ patch := drive.File{
Name: leaf, Name: dstLeaf,
} }
err = f.pacer.Call(func() (bool, error) { err = f.pacer.Call(func() (bool, error) {
_, err = f.svc.Files.Update(shortcutID(srcID), &patch). _, err = f.svc.Files.Update(shortcutID(srcID), &patch).

View File

@ -1159,27 +1159,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
fs.Debugf(srcFs, "Can't move directory - not same remote type") fs.Debugf(srcFs, "Can't move directory - not same remote type")
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
srcPath := path.Join(srcFs.root, srcRemote)
dstPath := path.Join(f.root, dstRemote)
// Refuse to move to or from the root srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote)
if srcPath == "" || dstPath == "" {
fs.Debugf(src, "DirMove error: Can't move root")
return errors.New("can't move root directory")
}
// Find ID of dst parent, creating subdirs if necessary
leaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if err != nil { if err != nil {
return err return err
} }
parsedDstDirID, dstDriveID, _ := parseNormalizedID(dstDirectoryID) parsedDstDirID, dstDriveID, _ := parseNormalizedID(dstDirectoryID)
// Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
if err != nil {
return err
}
_, srcDriveID, _ := parseNormalizedID(srcID) _, srcDriveID, _ := parseNormalizedID(srcID)
if dstDriveID != srcDriveID { if dstDriveID != srcDriveID {
@ -1188,16 +1174,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
// Check destination does not exist
_, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return err
} else {
return fs.ErrorDirExists
}
// Get timestamps of src so they can be preserved // Get timestamps of src so they can be preserved
srcInfo, _, err := srcFs.readMetaDataForPathRelativeToID(ctx, srcID, "") srcInfo, _, err := srcFs.readMetaDataForPathRelativeToID(ctx, srcID, "")
if err != nil { if err != nil {
@ -1207,7 +1183,7 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
// Do the move // Do the move
opts := newOptsCall(srcID, "PATCH", "") opts := newOptsCall(srcID, "PATCH", "")
move := api.MoveItemRequest{ move := api.MoveItemRequest{
Name: f.opt.Enc.FromStandardName(leaf), Name: f.opt.Enc.FromStandardName(dstLeaf),
ParentReference: &api.ItemReference{ ParentReference: &api.ItemReference{
DriveID: dstDriveID, DriveID: dstDriveID,
ID: parsedDstDirID, ID: parsedDstDirID,

View File

@ -473,33 +473,8 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
fs.Debugf(srcFs, "Can't move directory - not same remote type") fs.Debugf(srcFs, "Can't move directory - not same remote type")
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
srcPath := path.Join(srcFs.root, srcRemote)
dstPath := path.Join(f.root, dstRemote)
// Refuse to move to or from the root srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote)
if srcPath == "" || dstPath == "" {
fs.Debugf(src, "DirMove error: Can't move root")
return errors.New("can't move root directory")
}
// Find ID of dst parent, creating subdirs if necessary
leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if err != nil {
return err
}
// Check destination does not exist
_, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return err
} else {
return fs.ErrorDirExists
}
// Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
if err != nil { if err != nil {
return err return err
} }
@ -511,9 +486,9 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
moveFolderData := moveCopyFolder{ moveFolderData := moveCopyFolder{
SessionID: f.session.SessionID, SessionID: f.session.SessionID,
FolderID: srcID, FolderID: srcID,
DstFolderID: directoryID, DstFolderID: dstDirectoryID,
Move: "true", Move: "true",
NewFolderName: leaf, NewFolderName: dstLeaf,
} }
opts := rest.Opts{ opts := rest.Opts{
Method: "POST", Method: "POST",

View File

@ -727,33 +727,8 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
fs.Debugf(srcFs, "Can't move directory - not same remote type") fs.Debugf(srcFs, "Can't move directory - not same remote type")
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
srcPath := path.Join(srcFs.root, srcRemote)
dstPath := path.Join(f.root, dstRemote)
// Refuse to move to or from the root srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote)
if srcPath == "" || dstPath == "" {
fs.Debugf(src, "DirMove error: Can't move root")
return errors.New("can't move root directory")
}
// Find ID of dst parent, creating subdirs if necessary
leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if err != nil {
return err
}
// Check destination does not exist
_, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return err
} else {
return fs.ErrorDirExists
}
// Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
if err != nil { if err != nil {
return err return err
} }
@ -765,8 +740,8 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
Parameters: url.Values{}, Parameters: url.Values{},
} }
opts.Parameters.Set("folderid", dirIDtoNumber(srcID)) opts.Parameters.Set("folderid", dirIDtoNumber(srcID))
opts.Parameters.Set("toname", f.opt.Enc.FromStandardName(leaf)) opts.Parameters.Set("toname", f.opt.Enc.FromStandardName(dstLeaf))
opts.Parameters.Set("tofolderid", dirIDtoNumber(directoryID)) opts.Parameters.Set("tofolderid", dirIDtoNumber(dstDirectoryID))
var resp *http.Response var resp *http.Response
var result api.ItemResult var result api.ItemResult
err = f.pacer.Call(func() (bool, error) { err = f.pacer.Call(func() (bool, error) {

View File

@ -731,45 +731,14 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
fs.Debugf(srcFs, "Can't move directory - not same remote type") fs.Debugf(srcFs, "Can't move directory - not same remote type")
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
srcPath := path.Join(srcFs.root, srcRemote)
dstPath := path.Join(f.root, dstRemote)
// Refuse to move to or from the root srcID, srcDirectoryID, srcLeaf, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote)
if srcPath == "" || dstPath == "" {
fs.Debugf(src, "DirMove error: Can't move root")
return errors.New("can't move root directory")
}
// Find ID of dst parent, creating subdirs if necessary
leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if err != nil {
return err
}
// Check destination does not exist
_, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return err
} else {
return fs.ErrorDirExists
}
// Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
if err != nil {
return err
}
// Find ID of src parent, not creating subdirs
srcLeaf, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false)
if err != nil { if err != nil {
return err return err
} }
// Do the move // Do the move
err = f.move(ctx, false, srcID, srcLeaf, leaf, srcDirectoryID, directoryID) err = f.move(ctx, false, srcID, srcLeaf, dstLeaf, srcDirectoryID, dstDirectoryID)
if err != nil { if err != nil {
return err return err
} }

View File

@ -625,32 +625,8 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
if !ok { if !ok {
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
srcPath := path.Join(srcFs.root, srcRemote)
dstPath := path.Join(f.root, dstRemote)
// Refuse to move to or from the root srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote)
if srcPath == "" || dstPath == "" {
return errors.New("can't move root directory")
}
// Find ID of dst parent, creating subdirs if necessary
leaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if err != nil {
return err
}
// Check destination does not exist
_, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return err
} else {
return fs.ErrorDirExists
}
// Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
if err != nil { if err != nil {
return err return err
} }
@ -659,7 +635,7 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
params := url.Values{} params := url.Values{}
params.Set("file_id", srcID) params.Set("file_id", srcID)
params.Set("parent_id", dstDirectoryID) params.Set("parent_id", dstDirectoryID)
params.Set("name", f.opt.Enc.FromStandardName(leaf)) params.Set("name", f.opt.Enc.FromStandardName(dstLeaf))
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/move", strings.NewReader(params.Encode())) req, err := f.client.NewRequest(ctx, "POST", "/v2/files/move", strings.NewReader(params.Encode()))
if err != nil { if err != nil {
return false, err return false, err

View File

@ -1019,45 +1019,14 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
fs.Debugf(srcFs, "Can't move directory - not same remote type") fs.Debugf(srcFs, "Can't move directory - not same remote type")
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
srcPath := path.Join(srcFs.root, srcRemote)
dstPath := path.Join(f.root, dstRemote)
// Refuse to move to or from the root srcID, srcDirectoryID, srcLeaf, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote)
if srcPath == "" || dstPath == "" {
fs.Debugf(src, "DirMove error: Can't move root")
return errors.New("can't move root directory")
}
// Find ID of dst parent, creating subdirs if necessary
leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if err != nil {
return err
}
// Check destination does not exist
_, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return err
} else {
return fs.ErrorDirExists
}
// Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
if err != nil {
return err
}
// Find ID of src parent, not creating subdirs
srcLeaf, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false)
if err != nil { if err != nil {
return err return err
} }
// Do the move // Do the move
_, err = f.move(ctx, false, srcID, srcLeaf, leaf, srcDirectoryID, directoryID) _, err = f.move(ctx, false, srcID, srcLeaf, dstLeaf, srcDirectoryID, dstDirectoryID)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1019,39 +1019,14 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
fs.Debugf(srcFs, "Can't move directory - not same remote type") fs.Debugf(srcFs, "Can't move directory - not same remote type")
return fs.ErrorCantDirMove return fs.ErrorCantDirMove
} }
srcPath := path.Join(srcFs.root, srcRemote)
dstPath := path.Join(f.root, dstRemote)
// Refuse to move to or from the root srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote)
if srcPath == "" || dstPath == "" {
fs.Debugf(src, "DirMove error: Can't move root")
return errors.New("can't move root directory")
}
// Find ID of dst parent, creating subdirs if necessary
leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if err != nil {
return err
}
// Check destination does not exist
_, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return err
} else {
return fs.ErrorDirExists
}
// Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
if err != nil { if err != nil {
return err return err
} }
// Do the move // Do the move
err = f.moveDir(ctx, srcID, leaf, directoryID) err = f.moveDir(ctx, srcID, dstLeaf, dstDirectoryID)
if err != nil { if err != nil {
return err return err
} }

View File

@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"path"
"strings" "strings"
"sync" "sync"
@ -368,3 +369,66 @@ func (dc *DirCache) ResetRoot() {
// Put the root directory in // Put the root directory in
dc.Put("", dc.rootID) dc.Put("", dc.rootID)
} }
// DirMove prepares to move the directory (srcDC, srcRoot, srcRemote)
// into the directory (dc, dstRoot, dstRemote)
//
// It does all the checking, creates intermediate directories and
// returns leafs and IDs ready for the move.
//
// This returns
//
// - srcID - ID of the source directory
// - srcDirectoryID - ID of the parent of the source directory
// - srcLeaf - leaf name of the source directory
// - dstDirectoryID - ID of the parent of the destination directory
// - dstLeaf - leaf name of the destination directory
//
// These should be used to do the actual move then
// srcDC.FlushDir(srcRemote) should be called.
func (dc *DirCache) DirMove(
ctx context.Context, srcDC *DirCache, srcRoot, srcRemote, dstRoot, dstRemote string) (srcID, srcDirectoryID, srcLeaf, dstDirectoryID, dstLeaf string, err error) {
var (
dstDC = dc
srcPath = path.Join(srcRoot, srcRemote)
dstPath = path.Join(dstRoot, dstRemote)
)
// Refuse to move to or from the root
if srcPath == "" || dstPath == "" {
// fs.Debugf(src, "DirMove error: Can't move root")
err = errors.New("can't move root directory")
return
}
// Find ID of dst parent, creating subdirs if necessary
dstLeaf, dstDirectoryID, err = dstDC.FindPath(ctx, dstRemote, true)
if err != nil {
return
}
// Check destination does not exist
_, err = dstDC.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound {
// OK
} else if err != nil {
return
} else {
err = fs.ErrorDirExists
return
}
// Find ID of src parent
srcLeaf, srcDirectoryID, err = srcDC.FindPath(ctx, srcRemote, false)
if err != nil {
return
}
// Find ID of src
srcID, err = srcDC.FindDir(ctx, srcRemote, false)
if err != nil {
return
}
return
}