dircache: simplify interface, fix corner cases and apply to backends

Dircache was changed to:

- Remove special cases for the root directory
- Remove Fatal errors
- Call FindRoot on behalf of the user wherever possible
- Bring up to modern Go standards

Backends were changed to:

- Remove calls to FindRoot
- Change calls to FindRootAndPath to FindPath
- Don't make special cases for the root

This fixes several corner cases, for example removing a non existent
directory if FindRoot hasn't been called.
This commit is contained in:
Nick Craig-Wood 2020-05-11 17:24:37 +01:00
parent 81151523af
commit a8652e2252
14 changed files with 234 additions and 633 deletions

View File

@ -514,10 +514,6 @@ func (f *Fs) listAll(dirID string, title string, directoriesOnly bool, filesOnly
// This should return ErrDirNotFound if the directory isn't // This should return ErrDirNotFound if the directory isn't
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -665,7 +661,7 @@ func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options .
return nil, err return nil, err
} }
// If not create it // If not create it
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -696,13 +692,7 @@ func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options .
// Mkdir creates the container if it doesn't exist // Mkdir creates the container if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -724,10 +714,6 @@ func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (fs.Object,
} }
// create the destination directory if necessary // create the destination directory if necessary
err := f.dirCache.FindRoot(ctx, true)
if err != nil {
return nil, err
}
srcLeaf, srcDirectoryID, err := srcObj.fs.dirCache.FindPath(ctx, srcObj.remote, false) srcLeaf, srcDirectoryID, err := srcObj.fs.dirCache.FindPath(ctx, srcObj.remote, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -797,36 +783,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err = srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
findPath := dstRemote dstLeaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
if dstRemote == "" {
findPath = f.root
}
dstLeaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -835,16 +798,9 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists return fs.ErrorDirExists
} }
}
// Find ID of src parent // Find ID of src parent
findPath = srcRemote _, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false)
var srcDirectoryID string
if srcRemote == "" {
srcDirectoryID, err = srcFs.dirCache.RootParentID()
} else {
_, srcDirectoryID, err = srcFs.dirCache.FindPath(ctx, findPath, false)
}
if err != nil { if err != nil {
return err return err
} }
@ -890,10 +846,6 @@ func (f *Fs) purgeCheck(ctx context.Context, dir string, check bool) error {
return errors.New("can't purge root directory") return errors.New("can't purge root directory")
} }
dc := f.dirCache dc := f.dirCache
err := dc.FindRoot(ctx, false)
if err != nil {
return err
}
rootID, err := dc.FindDir(ctx, dir, false) rootID, err := dc.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err
@ -1037,7 +989,7 @@ func (o *Object) readMetaData(ctx context.Context) (err error) {
if o.info != nil { if o.info != nil {
return nil return nil
} }
leaf, directoryID, err := o.fs.dirCache.FindRootAndPath(ctx, o.remote, false) leaf, directoryID, err := o.fs.dirCache.FindPath(ctx, o.remote, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return fs.ErrorObjectNotFound return fs.ErrorObjectNotFound

View File

@ -329,7 +329,7 @@ func shouldRetry(resp *http.Response, err error) (bool, error) {
// readMetaDataForPath reads the metadata from the path // readMetaDataForPath reads the metadata from the path
func (f *Fs) readMetaDataForPath(ctx context.Context, path string) (info *api.Item, err error) { func (f *Fs) readMetaDataForPath(ctx context.Context, path string) (info *api.Item, err error) {
// defer fs.Trace(f, "path=%q", path)("info=%+v, err=%v", &info, &err) // defer fs.Trace(f, "path=%q", path)("info=%+v, err=%v", &info, &err)
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, path, false) leaf, directoryID, err := f.dirCache.FindPath(ctx, path, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return nil, fs.ErrorObjectNotFound return nil, fs.ErrorObjectNotFound
@ -617,10 +617,6 @@ OUTER:
// This should return ErrDirNotFound if the directory isn't // This should return ErrDirNotFound if the directory isn't
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -661,7 +657,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
// Used to create new objects // Used to create new objects
func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) { func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) {
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err = f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err = f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return return
} }
@ -717,13 +713,7 @@ func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo,
// Mkdir creates the container if it doesn't exist // Mkdir creates the container if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -748,10 +738,6 @@ func (f *Fs) purgeCheck(ctx context.Context, dir string, check bool) error {
return errors.New("can't purge root directory") return errors.New("can't purge root directory")
} }
dc := f.dirCache dc := f.dirCache
err := dc.FindRoot(ctx, false)
if err != nil {
return err
}
rootID, err := dc.FindDir(ctx, dir, false) rootID, err := dc.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err
@ -967,37 +953,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err := srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
var leaf, directoryID string leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
findPath := dstRemote
if dstRemote == "" {
findPath = f.root
}
leaf, directoryID, err = f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -1006,7 +968,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists return fs.ErrorDirExists
} }
}
// Find ID of src // Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
@ -1330,7 +1291,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
remote := o.Remote() remote := o.Remote()
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err := o.fs.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := o.fs.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1589,10 +1589,6 @@ func (f *Fs) findImportFormat(mimeType string) string {
// This should return ErrDirNotFound if the directory isn't // This should return ErrDirNotFound if the directory isn't
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1814,10 +1810,6 @@ func (f *Fs) listRRunner(ctx context.Context, wg *sync.WaitGroup, in chan listRE
// Don't implement this unless you have a more efficient way // Don't implement this unless you have a more efficient way
// of listing recursively that doing a directory traversal. // of listing recursively that doing a directory traversal.
func (f *Fs) ListR(ctx context.Context, dir string, callback fs.ListRCallback) (err error) { func (f *Fs) ListR(ctx context.Context, dir string, callback fs.ListRCallback) (err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err
@ -2026,7 +2018,7 @@ func (f *Fs) itemToDirEntry(remote string, item *drive.File) (entry fs.DirEntry,
// //
// Used to create new objects // Used to create new objects
func (f *Fs) createFileInfo(ctx context.Context, remote string, modTime time.Time) (*drive.File, error) { func (f *Fs) createFileInfo(ctx context.Context, remote string, modTime time.Time) (*drive.File, error) {
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -2189,13 +2181,7 @@ func (f *Fs) MergeDirs(ctx context.Context, dirs []fs.Directory) error {
// Mkdir creates the container if it doesn't exist // Mkdir creates the container if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -2368,11 +2354,11 @@ func (f *Fs) Purge(ctx context.Context) error {
if f.opt.TrashedOnly { if f.opt.TrashedOnly {
return errors.New("Can't purge with --drive-trashed-only. Use delete if you want to selectively delete files") return errors.New("Can't purge with --drive-trashed-only. Use delete if you want to selectively delete files")
} }
err := f.dirCache.FindRoot(ctx, false) rootID, err := f.dirCache.RootID(ctx, false)
if err != nil { if err != nil {
return err return err
} }
err = f.delete(ctx, shortcutID(f.dirCache.RootID()), f.opt.UseTrash) err = f.delete(ctx, shortcutID(rootID), f.opt.UseTrash)
f.dirCache.ResetRoot() f.dirCache.ResetRoot()
if err != nil { if err != nil {
return err return err
@ -2565,38 +2551,14 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err := srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
var leaf, dstDirectoryID string leaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
findPath := dstRemote
if dstRemote == "" {
findPath = f.root
}
leaf, dstDirectoryID, err = f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
dstDirectoryID = actualID(dstDirectoryID) dstDirectoryID = actualID(dstDirectoryID)
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -2605,15 +2567,9 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists return fs.ErrorDirExists
} }
}
// Find ID of src parent // Find ID of src parent
var srcDirectoryID string _, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false)
if srcRemote == "" {
srcDirectoryID, err = srcFs.dirCache.RootParentID()
} else {
_, srcDirectoryID, err = srcFs.dirCache.FindPath(ctx, srcRemote, false)
}
if err != nil { if err != nil {
return err return err
} }
@ -2878,11 +2834,10 @@ func (f *Fs) makeShortcut(ctx context.Context, srcPath string, dstFs *Fs, dstPat
isDir := false isDir := false
if srcPath == "" { if srcPath == "" {
// source is root directory // source is root directory
err = f.dirCache.FindRoot(ctx, false) srcID, err = f.dirCache.RootID(ctx, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
srcID = f.dirCache.RootID()
isDir = true isDir = true
} else if srcObj, err := srcFs.NewObject(ctx, srcPath); err != nil { } else if srcObj, err := srcFs.NewObject(ctx, srcPath); err != nil {
if err != fs.ErrorNotAFile { if err != fs.ErrorNotAFile {
@ -3111,7 +3066,7 @@ func (f *Fs) getRemoteInfo(ctx context.Context, remote string) (info *drive.File
// getRemoteInfoWithExport returns a drive.File and the export settings for the remote // getRemoteInfoWithExport returns a drive.File and the export settings for the remote
func (f *Fs) getRemoteInfoWithExport(ctx context.Context, remote string) ( func (f *Fs) getRemoteInfoWithExport(ctx context.Context, remote string) (
info *drive.File, extension, exportName, exportMimeType string, isDocument bool, err error) { info *drive.File, extension, exportName, exportMimeType string, isDocument bool, err error) {
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, remote, false) leaf, directoryID, err := f.dirCache.FindPath(ctx, remote, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return nil, "", "", "", false, fs.ErrorObjectNotFound return nil, "", "", "", false, fs.ErrorObjectNotFound

View File

@ -148,11 +148,6 @@ func (f *Fs) listFolders(ctx context.Context, directoryID int) (foldersList *Fol
} }
func (f *Fs) listDir(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) listDir(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -264,7 +264,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
// NewObject finds the Object at remote. If it can't be found // NewObject finds the Object at remote. If it can't be found
// it returns the error ErrorObjectNotFound. // it returns the error ErrorObjectNotFound.
func (f *Fs) NewObject(ctx context.Context, remote string) (fs.Object, error) { func (f *Fs) NewObject(ctx context.Context, remote string) (fs.Object, error) {
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, remote, false) leaf, directoryID, err := f.dirCache.FindPath(ctx, remote, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return nil, fs.ErrorObjectNotFound return nil, fs.ErrorObjectNotFound
@ -334,7 +334,7 @@ func (f *Fs) putUnchecked(ctx context.Context, in io.Reader, remote string, size
return nil, err return nil, err
} }
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -389,13 +389,7 @@ func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo,
// //
// Shouldn't return an error if it already exists // Shouldn't return an error if it already exists
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -403,11 +397,6 @@ func (f *Fs) Mkdir(ctx context.Context, dir string) error {
// //
// Return an error if it doesn't exist or isn't empty // Return an error if it doesn't exist or isn't empty
func (f *Fs) Rmdir(ctx context.Context, dir string) error { func (f *Fs) Rmdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err

View File

@ -498,13 +498,13 @@ func (f *Fs) readMetaDataForPath(ctx context.Context, path string) (info *api.It
var dirCacheFoundRoot bool var dirCacheFoundRoot bool
var rootNormalizedID string var rootNormalizedID string
if f.dirCache != nil { if f.dirCache != nil {
var dirCacheRootIDExists bool rootNormalizedID, err = f.dirCache.RootID(ctx, false)
rootNormalizedID, dirCacheRootIDExists = f.dirCache.Get("") dirCacheRootIDExists := err == nil
if f.root == "" { if f.root == "" {
// if f.root == "", it means f.root is the absolute root of the drive // if f.root == "", it means f.root is the absolute root of the drive
// and its ID should have been found in NewFs // and its ID should have been found in NewFs
dirCacheFoundRoot = dirCacheRootIDExists dirCacheFoundRoot = dirCacheRootIDExists
} else if _, err := f.dirCache.RootParentID(); err == nil { } else if _, err := f.dirCache.RootParentID(ctx, false); err == nil {
// if root is in a folder, it must have a parent folder, and // if root is in a folder, it must have a parent folder, and
// if dirCache has found root in NewFs, the parent folder's ID // if dirCache has found root in NewFs, the parent folder's ID
// should be present. // should be present.
@ -813,10 +813,6 @@ OUTER:
// This should return ErrDirNotFound if the directory isn't // This should return ErrDirNotFound if the directory isn't
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -864,7 +860,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
// Used to create new objects // Used to create new objects
func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) { func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) {
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err = f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err = f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return nil, leaf, directoryID, err return nil, leaf, directoryID, err
} }
@ -895,13 +891,7 @@ func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options .
// Mkdir creates the container if it doesn't exist // Mkdir creates the container if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -924,10 +914,6 @@ func (f *Fs) purgeCheck(ctx context.Context, dir string, check bool) error {
return errors.New("can't purge root directory") return errors.New("can't purge root directory")
} }
dc := f.dirCache dc := f.dirCache
err := dc.FindRoot(ctx, false)
if err != nil {
return err
}
rootID, err := dc.FindDir(ctx, dir, false) rootID, err := dc.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err
@ -1182,31 +1168,8 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err := srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
var leaf, dstDirectoryID string leaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
findPath := dstRemote
if dstRemote == "" {
findPath = f.root
}
leaf, dstDirectoryID, err = f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
@ -1226,7 +1189,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} }
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -1235,7 +1197,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists 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, "")

View File

@ -280,13 +280,7 @@ func errorHandler(resp *http.Response) error {
// Mkdir creates the folder if it doesn't exist // Mkdir creates the folder if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
// fs.Debugf(nil, "Mkdir(\"%s\")", dir) // fs.Debugf(nil, "Mkdir(\"%s\")", dir)
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -312,10 +306,6 @@ func (f *Fs) purgeCheck(ctx context.Context, dir string, check bool) error {
return errors.New("can't purge root directory") return errors.New("can't purge root directory")
} }
dc := f.dirCache dc := f.dirCache
err := dc.FindRoot(ctx, false)
if err != nil {
return err
}
rootID, err := dc.FindDir(ctx, dir, false) rootID, err := dc.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err
@ -492,37 +482,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err = srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
var leaf, directoryID string leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
findPath := dstRemote
if dstRemote == "" {
findPath = f.root
}
leaf, directoryID, err = f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -531,7 +497,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists return fs.ErrorDirExists
} }
}
// Find ID of src // Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
@ -620,7 +585,7 @@ func (f *Fs) NewObject(ctx context.Context, remote string) (fs.Object, error) {
// Used to create new objects // Used to create new objects
func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) { func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) {
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err = f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err = f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return nil, leaf, directoryID, err return nil, leaf, directoryID, err
} }
@ -803,10 +768,6 @@ func (f *Fs) FindLeaf(ctx context.Context, pathID, leaf string) (pathIDOut strin
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
// fs.Debugf(nil, "List(%v)", dir) // fs.Debugf(nil, "List(%v)", dir)
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1079,7 +1040,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
} }
func (o *Object) readMetaData(ctx context.Context) (err error) { func (o *Object) readMetaData(ctx context.Context) (err error) {
leaf, directoryID, err := o.fs.dirCache.FindRootAndPath(ctx, o.remote, false) leaf, directoryID, err := o.fs.dirCache.FindPath(ctx, o.remote, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return fs.ErrorObjectNotFound return fs.ErrorObjectNotFound

View File

@ -198,7 +198,7 @@ func shouldRetry(resp *http.Response, err error) (bool, error) {
// readMetaDataForPath reads the metadata from the path // readMetaDataForPath reads the metadata from the path
func (f *Fs) readMetaDataForPath(ctx context.Context, path string) (info *api.Item, err error) { func (f *Fs) readMetaDataForPath(ctx context.Context, path string) (info *api.Item, err error) {
// defer fs.Trace(f, "path=%q", path)("info=%+v, err=%v", &info, &err) // defer fs.Trace(f, "path=%q", path)("info=%+v, err=%v", &info, &err)
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, path, false) leaf, directoryID, err := f.dirCache.FindPath(ctx, path, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return nil, fs.ErrorObjectNotFound return nil, fs.ErrorObjectNotFound
@ -455,10 +455,6 @@ func (f *Fs) listAll(ctx context.Context, dirID string, directoriesOnly bool, fi
// This should return ErrDirNotFound if the directory isn't // This should return ErrDirNotFound if the directory isn't
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -499,7 +495,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
// Used to create new objects // Used to create new objects
func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) { func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) {
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err = f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err = f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return return
} }
@ -530,13 +526,7 @@ func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options .
// Mkdir creates the container if it doesn't exist // Mkdir creates the container if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -548,10 +538,6 @@ func (f *Fs) purgeCheck(ctx context.Context, dir string, check bool) error {
return errors.New("can't purge root directory") return errors.New("can't purge root directory")
} }
dc := f.dirCache dc := f.dirCache
err := dc.FindRoot(ctx, false)
if err != nil {
return err
}
rootID, err := dc.FindDir(ctx, dir, false) rootID, err := dc.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err
@ -659,7 +645,7 @@ func (f *Fs) Purge(ctx context.Context) error {
// CleanUp empties the trash // CleanUp empties the trash
func (f *Fs) CleanUp(ctx context.Context) error { func (f *Fs) CleanUp(ctx context.Context) error {
err := f.dirCache.FindRoot(ctx, false) rootID, err := f.dirCache.RootID(ctx, false)
if err != nil { if err != nil {
return err return err
} }
@ -668,7 +654,7 @@ func (f *Fs) CleanUp(ctx context.Context) error {
Path: "/trash_clear", Path: "/trash_clear",
Parameters: url.Values{}, Parameters: url.Values{},
} }
opts.Parameters.Set("folderid", dirIDtoNumber(f.dirCache.RootID())) opts.Parameters.Set("folderid", dirIDtoNumber(rootID))
var resp *http.Response var resp *http.Response
var result api.Error var result api.Error
return f.pacer.Call(func() (bool, error) { return f.pacer.Call(func() (bool, error) {
@ -750,37 +736,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err := srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
var leaf, directoryID string leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
findPath := dstRemote
if dstRemote == "" {
findPath = f.root
}
leaf, directoryID, err = f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -789,7 +751,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists return fs.ErrorDirExists
} }
}
// Find ID of src // Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
@ -1111,7 +1072,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
remote := o.Remote() remote := o.Remote()
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err := o.fs.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := o.fs.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return err return err
} }

View File

@ -183,7 +183,7 @@ func shouldRetry(resp *http.Response, err error) (bool, error) {
// readMetaDataForPath reads the metadata from the path // readMetaDataForPath reads the metadata from the path
func (f *Fs) readMetaDataForPath(ctx context.Context, path string, directoriesOnly bool, filesOnly bool) (info *api.Item, err error) { func (f *Fs) readMetaDataForPath(ctx context.Context, path string, directoriesOnly bool, filesOnly bool) (info *api.Item, err error) {
// defer fs.Trace(f, "path=%q", path)("info=%+v, err=%v", &info, &err) // defer fs.Trace(f, "path=%q", path)("info=%+v, err=%v", &info, &err)
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, path, false) leaf, directoryID, err := f.dirCache.FindPath(ctx, path, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return nil, fs.ErrorObjectNotFound return nil, fs.ErrorObjectNotFound
@ -450,10 +450,6 @@ func (f *Fs) listAll(ctx context.Context, dirID string, directoriesOnly bool, fi
// This should return ErrDirNotFound if the directory isn't // This should return ErrDirNotFound if the directory isn't
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -493,7 +489,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
// Used to create new objects // Used to create new objects
func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) { func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) {
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err = f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err = f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return return
} }
@ -544,13 +540,7 @@ func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo,
// Mkdir creates the container if it doesn't exist // Mkdir creates the container if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -562,10 +552,6 @@ func (f *Fs) purgeCheck(ctx context.Context, dir string, check bool) error {
return errors.New("can't purge root directory") return errors.New("can't purge root directory")
} }
dc := f.dirCache dc := f.dirCache
err := dc.FindRoot(ctx, false)
if err != nil {
return err
}
rootID, err := dc.FindDir(ctx, dir, false) rootID, err := dc.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err
@ -754,37 +740,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err := srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
var leaf, directoryID string leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
findPath := dstRemote
if dstRemote == "" {
findPath = f.root
}
leaf, directoryID, err = f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -793,7 +755,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists return fs.ErrorDirExists
} }
}
// Find ID of src // Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
@ -802,12 +763,7 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} }
// Find ID of src parent, not creating subdirs // Find ID of src parent, not creating subdirs
var srcLeaf, srcDirectoryID string srcLeaf, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false)
findPath = srcRemote
if srcRemote == "" {
findPath = srcFs.root
}
srcLeaf, srcDirectoryID, err = srcFs.dirCache.FindPath(ctx, findPath, false)
if err != nil { if err != nil {
return err return err
} }
@ -990,7 +946,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
size := src.Size() size := src.Size()
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err := o.fs.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := o.fs.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return err return err
} }

View File

@ -197,10 +197,6 @@ func (f *Fs) FindLeaf(ctx context.Context, pathID, leaf string) (pathIDOut strin
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
// defer log.Trace(f, "dir=%v", dir)("err=%v", &err) // defer log.Trace(f, "dir=%v", dir)("err=%v", &err)
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -260,7 +256,7 @@ func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo,
// defer log.Trace(f, "src=%+v", src)("o=%+v, err=%v", &o, &err) // defer log.Trace(f, "src=%+v", src)("o=%+v, err=%v", &o, &err)
size := src.Size() size := src.Size()
remote := src.Remote() remote := src.Remote()
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -458,13 +454,7 @@ func (f *Fs) makeUploadPatchRequest(ctx context.Context, location string, in io.
// Mkdir creates the container if it doesn't exist // Mkdir creates the container if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) (err error) { func (f *Fs) Mkdir(ctx context.Context, dir string) (err error) {
// defer log.Trace(f, "dir=%v", dir)("err=%v", &err) // defer log.Trace(f, "dir=%v", dir)("err=%v", &err)
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true) _, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -528,12 +518,11 @@ func (f *Fs) Purge(ctx context.Context) (err error) {
if f.root == "" { if f.root == "" {
return errors.New("can't purge root directory") return errors.New("can't purge root directory")
} }
err = f.dirCache.FindRoot(ctx, false) rootIDs, err := f.dirCache.RootID(ctx, false)
if err != nil { if err != nil {
return err return err
} }
rootID := atoi(rootIDs)
rootID := atoi(f.dirCache.RootID())
// Let putio delete the filesystem tree // Let putio delete the filesystem tree
err = f.pacer.Call(func() (bool, error) { err = f.pacer.Call(func() (bool, error) {
// fs.Debugf(f, "deleting file: %d", rootID) // fs.Debugf(f, "deleting file: %d", rootID)
@ -559,7 +548,7 @@ func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (o fs.Objec
if !ok { if !ok {
return nil, fs.ErrorCantCopy return nil, fs.ErrorCantCopy
} }
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -598,7 +587,7 @@ func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (o fs.Objec
if !ok { if !ok {
return nil, fs.ErrorCantMove return nil, fs.ErrorCantMove
} }
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -644,37 +633,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err = srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
var leaf, dstDirectoryID string leaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
findPath := dstRemote
if dstRemote == "" {
findPath = f.root
}
leaf, dstDirectoryID, err = f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -683,7 +648,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists return fs.ErrorDirExists
} }
}
// Find ID of src // Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)

View File

@ -125,7 +125,7 @@ func (o *Object) setMetadataFromEntry(info putio.File) error {
// Reads the entry for a file from putio // Reads the entry for a file from putio
func (o *Object) readEntry(ctx context.Context) (f *putio.File, err error) { func (o *Object) readEntry(ctx context.Context) (f *putio.File, err error) {
// defer log.Trace(o, "")("f=%+v, err=%v", f, &err) // defer log.Trace(o, "")("f=%+v, err=%v", f, &err)
leaf, directoryID, err := o.fs.dirCache.FindRootAndPath(ctx, o.remote, false) leaf, directoryID, err := o.fs.dirCache.FindPath(ctx, o.remote, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return nil, fs.ErrorObjectNotFound return nil, fs.ErrorObjectNotFound

View File

@ -350,7 +350,7 @@ func (f *Fs) readMetaDataForID(ctx context.Context, id string, directoriesOnly b
// readMetaDataForPath reads the metadata from the path // readMetaDataForPath reads the metadata from the path
func (f *Fs) readMetaDataForPath(ctx context.Context, path string, directoriesOnly bool, filesOnly bool) (info *api.Item, err error) { func (f *Fs) readMetaDataForPath(ctx context.Context, path string, directoriesOnly bool, filesOnly bool) (info *api.Item, err error) {
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, path, false) leaf, directoryID, err := f.dirCache.FindPath(ctx, path, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return nil, fs.ErrorObjectNotFound return nil, fs.ErrorObjectNotFound
@ -700,10 +700,6 @@ func (f *Fs) listAll(ctx context.Context, dirID string, directoriesOnly bool, fi
// This should return ErrDirNotFound if the directory isn't // This should return ErrDirNotFound if the directory isn't
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -743,7 +739,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
// Used to create new objects // Used to create new objects
func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) { func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) {
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err = f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err = f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return return
} }
@ -799,13 +795,7 @@ func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo,
// Mkdir creates the container if it doesn't exist // Mkdir creates the container if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -817,10 +807,6 @@ func (f *Fs) purgeCheck(ctx context.Context, dir string, check bool) error {
return errors.New("can't purge root directory") return errors.New("can't purge root directory")
} }
dc := f.dirCache dc := f.dirCache
err := dc.FindRoot(ctx, false)
if err != nil {
return err
}
rootID, err := dc.FindDir(ctx, dir, false) rootID, err := dc.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err
@ -1042,37 +1028,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err := srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
var leaf, directoryID string leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
findPath := dstRemote
if dstRemote == "" {
findPath = f.root
}
leaf, directoryID, err = f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -1081,7 +1043,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists return fs.ErrorDirExists
} }
}
// Find ID of src // Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
@ -1090,12 +1051,7 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} }
// Find ID of src parent, not creating subdirs // Find ID of src parent, not creating subdirs
var srcLeaf, srcDirectoryID string srcLeaf, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false)
findPath = srcRemote
if srcRemote == "" {
findPath = srcFs.root
}
srcLeaf, srcDirectoryID, err = srcFs.dirCache.FindPath(ctx, findPath, false)
if err != nil { if err != nil {
return err return err
} }
@ -1402,7 +1358,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
isLargeFile := size < 0 || size > int64(o.fs.opt.UploadCutoff) isLargeFile := size < 0 || size > int64(o.fs.opt.UploadCutoff)
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err := o.fs.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := o.fs.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return err return err
} }

View File

@ -255,7 +255,7 @@ func shouldRetry(resp *http.Response, err error) (bool, error) {
// readMetaDataForPath reads the metadata from the path // readMetaDataForPath reads the metadata from the path
func (f *Fs) readMetaDataForPath(ctx context.Context, path string) (info *api.File, err error) { func (f *Fs) readMetaDataForPath(ctx context.Context, path string) (info *api.File, err error) {
// defer fs.Trace(f, "path=%q", path)("info=%+v, err=%v", &info, &err) // defer fs.Trace(f, "path=%q", path)("info=%+v, err=%v", &info, &err)
leaf, directoryID, err := f.dirCache.FindRootAndPath(ctx, path, false) leaf, directoryID, err := f.dirCache.FindPath(ctx, path, false)
if err != nil { if err != nil {
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
return nil, fs.ErrorObjectNotFound return nil, fs.ErrorObjectNotFound
@ -663,10 +663,6 @@ OUTER:
// This should return ErrDirNotFound if the directory isn't // This should return ErrDirNotFound if the directory isn't
// found. // found.
func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) { func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
err = f.dirCache.FindRoot(ctx, false)
if err != nil {
return nil, err
}
directoryID, err := f.dirCache.FindDir(ctx, dir, false) directoryID, err := f.dirCache.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -709,7 +705,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
// Used to create new objects // Used to create new objects
func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) { func (f *Fs) createObject(ctx context.Context, remote string, modTime time.Time, size int64) (o *Object, leaf string, directoryID string, err error) {
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err = f.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err = f.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return return
} }
@ -765,13 +761,7 @@ func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo,
// Mkdir creates the container if it doesn't exist // Mkdir creates the container if it doesn't exist
func (f *Fs) Mkdir(ctx context.Context, dir string) error { func (f *Fs) Mkdir(ctx context.Context, dir string) error {
err := f.dirCache.FindRoot(ctx, true) _, err := f.dirCache.FindDir(ctx, dir, true)
if err != nil {
return err
}
if dir != "" {
_, err = f.dirCache.FindDir(ctx, dir, true)
}
return err return err
} }
@ -807,10 +797,6 @@ func (f *Fs) purgeCheck(ctx context.Context, dir string, check bool) error {
return errors.New("can't purge root directory") return errors.New("can't purge root directory")
} }
dc := f.dirCache dc := f.dirCache
err := dc.FindRoot(ctx, false)
if err != nil {
return err
}
directoryID, err := dc.FindDir(ctx, dir, false) directoryID, err := dc.FindDir(ctx, dir, false)
if err != nil { if err != nil {
return err return err
@ -1042,37 +1028,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
return errors.New("can't move root directory") return errors.New("can't move root directory")
} }
// find the root src directory
err := srcFs.dirCache.FindRoot(ctx, false)
if err != nil {
return err
}
// find the root dst directory
if dstRemote != "" {
err = f.dirCache.FindRoot(ctx, true)
if err != nil {
return err
}
} else {
if f.dirCache.FoundRoot() {
return fs.ErrorDirExists
}
}
// Find ID of dst parent, creating subdirs if necessary // Find ID of dst parent, creating subdirs if necessary
var leaf, directoryID string leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true)
findPath := dstRemote
if dstRemote == "" {
findPath = f.root
}
leaf, directoryID, err = f.dirCache.FindPath(ctx, findPath, true)
if err != nil { if err != nil {
return err return err
} }
// Check destination does not exist // Check destination does not exist
if dstRemote != "" {
_, err = f.dirCache.FindDir(ctx, dstRemote, false) _, err = f.dirCache.FindDir(ctx, dstRemote, false)
if err == fs.ErrorDirNotFound { if err == fs.ErrorDirNotFound {
// OK // OK
@ -1081,7 +1043,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
} else { } else {
return fs.ErrorDirExists return fs.ErrorDirExists
} }
}
// Find ID of src // Find ID of src
srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false)
@ -1289,7 +1250,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
remote := o.Remote() remote := o.Remote()
// Create the directory for the object if it doesn't exist // Create the directory for the object if it doesn't exist
leaf, directoryID, err := o.fs.dirCache.FindRootAndPath(ctx, remote, true) leaf, directoryID, err := o.fs.dirCache.FindPath(ctx, remote, true)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,4 +1,5 @@
// Package dircache provides a simple cache for caching directory to path lookups // Package dircache provides a simple cache for caching directory ID
// to path lookups and the inverse.
package dircache package dircache
// _methods are called without the lock // _methods are called without the lock
@ -7,7 +8,6 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"log"
"strings" "strings"
"sync" "sync"
@ -17,19 +17,23 @@ import (
// DirCache caches paths to directory IDs and vice versa // DirCache caches paths to directory IDs and vice versa
type DirCache struct { type DirCache struct {
cacheMu sync.RWMutex cacheMu sync.RWMutex // protects cache and invCache
cache map[string]string cache map[string]string
invCache map[string]string invCache map[string]string
mu sync.Mutex
fs DirCacher // Interface to find and make stuff mu sync.Mutex // protects the below
fs DirCacher // Interface to find and make directories
trueRootID string // ID of the absolute root trueRootID string // ID of the absolute root
root string // the path we are working on root string // the path the cache is rooted on
rootID string // ID of the root directory rootID string // ID of the root directory
rootParentID string // ID of the root's parent directory rootParentID string // ID of the root's parent directory
foundRoot bool // Whether we have found the root or not foundRoot bool // Whether we have found the root or not
} }
// DirCacher describes an interface for doing the low level directory work // DirCacher describes an interface for doing the low level directory work
//
// This should be implemented by the backend and will be called by the
// dircache package when appropriate.
type DirCacher interface { type DirCacher interface {
FindLeaf(ctx context.Context, pathID, leaf string) (pathIDOut string, found bool, err error) FindLeaf(ctx context.Context, pathID, leaf string) (pathIDOut string, found bool, err error)
CreateDir(ctx context.Context, pathID, leaf string) (newID string, err error) CreateDir(ctx context.Context, pathID, leaf string) (newID string, err error)
@ -37,6 +41,15 @@ type DirCacher interface {
// New makes a DirCache // New makes a DirCache
// //
// This is created with the true root ID and the root path.
//
// In order to use the cache FindRoot() must be called on it without
// error. This isn't done at initialization as it isn't known whether
// the root and intermediate directories need to be created or not.
//
// Most of the utility functions wil call FindRoot() on the caller's
// behalf with the create flag passed in.
//
// The cache is safe for concurrent use // The cache is safe for concurrent use
func New(root string, trueRootID string, fs DirCacher) *DirCache { func New(root string, trueRootID string, fs DirCacher) *DirCache {
d := &DirCache{ d := &DirCache{
@ -74,23 +87,29 @@ func (dc *DirCache) String() string {
return buf.String() return buf.String()
} }
// Get an ID given a path // Get a directory ID given a path
//
// Returns the ID and a boolean as to whether it was found or not in
// the cache.
func (dc *DirCache) Get(path string) (id string, ok bool) { func (dc *DirCache) Get(path string) (id string, ok bool) {
dc.cacheMu.RLock() dc.cacheMu.RLock()
id, ok = dc.cache[path] id, ok = dc.cache[path]
dc.cacheMu.RUnlock() dc.cacheMu.RUnlock()
return return id, ok
} }
// GetInv gets a path given an ID // GetInv gets a path given a directory ID
//
// Returns the path and a boolean as to whether it was found or not in
// the cache.
func (dc *DirCache) GetInv(id string) (path string, ok bool) { func (dc *DirCache) GetInv(id string) (path string, ok bool) {
dc.cacheMu.RLock() dc.cacheMu.RLock()
path, ok = dc.invCache[id] path, ok = dc.invCache[id]
dc.cacheMu.RUnlock() dc.cacheMu.RUnlock()
return return path, ok
} }
// Put a path, id into the map // Put a (path, directory ID) pair into the cache
func (dc *DirCache) Put(path, id string) { func (dc *DirCache) Put(path, id string) {
dc.cacheMu.Lock() dc.cacheMu.Lock()
dc.cache[path] = id dc.cache[path] = id
@ -98,7 +117,7 @@ func (dc *DirCache) Put(path, id string) {
dc.cacheMu.Unlock() dc.cacheMu.Unlock()
} }
// Flush the map of all data // Flush the cache of all data
func (dc *DirCache) Flush() { func (dc *DirCache) Flush() {
dc.cacheMu.Lock() dc.cacheMu.Lock()
dc.cache = make(map[string]string) dc.cache = make(map[string]string)
@ -106,9 +125,10 @@ func (dc *DirCache) Flush() {
dc.cacheMu.Unlock() dc.cacheMu.Unlock()
} }
// FlushDir flushes the map of all data starting with dir // FlushDir flushes the map of all data starting with with the path
// dir.
// //
// If dir is empty then this is equivalent to calling ResetRoot // If dir is empty string then this is equivalent to calling ResetRoot
func (dc *DirCache) FlushDir(dir string) { func (dc *DirCache) FlushDir(dir string) {
if dir == "" { if dir == "" {
dc.ResetRoot() dc.ResetRoot()
@ -159,39 +179,29 @@ func SplitPath(path string) (directory, leaf string) {
// //
// If create is set it will make the directory if not found // If create is set it will make the directory if not found
// //
// Algorithm: // It will call FindRoot if it hasn't been called already
// Look in the cache for the path, if found return the pathID
// If not found strip the last path off the path and recurse
// Now have a parent directory id, so look in the parent for self and return it
func (dc *DirCache) FindDir(ctx context.Context, path string, create bool) (pathID string, err error) { func (dc *DirCache) FindDir(ctx context.Context, path string, create bool) (pathID string, err error) {
dc.mu.Lock() dc.mu.Lock()
defer dc.mu.Unlock() defer dc.mu.Unlock()
err = dc._findRoot(ctx, create)
if err != nil {
return "", err
}
return dc._findDir(ctx, path, create) return dc._findDir(ctx, path, create)
} }
// Look for the root and in the cache - safe to call without the mu // Unlocked findDir
func (dc *DirCache) _findDirInCache(path string) string { //
// fmt.Println("Finding",path,"create",create,"cache",cache) // Call with a lock on mu
func (dc *DirCache) _findDir(ctx context.Context, path string, create bool) (pathID string, err error) {
// If it is the root, then return it // If it is the root, then return it
if path == "" { if path == "" {
// fmt.Println("Root") return dc.rootID, nil
return dc.rootID
} }
// If it is in the cache then return it // If it is in the cache then return it
pathID, ok := dc.Get(path) pathID, ok := dc.Get(path)
if ok { if ok {
// fmt.Println("Cache hit on", path)
return pathID
}
return ""
}
// Unlocked findDir - must have mu
func (dc *DirCache) _findDir(ctx context.Context, path string, create bool) (pathID string, err error) {
pathID = dc._findDirInCache(path)
if pathID != "" {
return pathID, nil return pathID, nil
} }
@ -232,29 +242,48 @@ func (dc *DirCache) _findDir(ctx context.Context, path string, create bool) (pat
// FindPath finds the leaf and directoryID from a path // FindPath finds the leaf and directoryID from a path
// //
// Do not call FindPath with the root directory - it will return an error // If called with path == "" then it will return the ID of the parent
// directory of the root and the leaf name of the root in that
// directory. Note that it won't create the root directory in this
// case even if create is true.
// //
// If create is set parent directories will be created if they don't exist // If create is set parent directories will be created if they don't exist
//
// It will call FindRoot if it hasn't been called already
func (dc *DirCache) FindPath(ctx context.Context, path string, create bool) (leaf, directoryID string, err error) { func (dc *DirCache) FindPath(ctx context.Context, path string, create bool) (leaf, directoryID string, err error) {
if path == "" { if path == "" {
err = errors.New("internal error: can't call FindPath with root directory") _, leaf = SplitPath(dc.root)
return directoryID, err = dc.RootParentID(ctx, create)
} else {
var directory string
directory, leaf = SplitPath(path)
directoryID, err = dc.FindDir(ctx, directory, create)
} }
dc.mu.Lock() return leaf, directoryID, err
defer dc.mu.Unlock()
directory, leaf := SplitPath(path)
directoryID, err = dc._findDir(ctx, directory, create)
return
} }
// FindRoot finds the root directory if not already found // FindRoot finds the root directory if not already found
// //
// If successful this changes the root of the cache from the true root
// to the root specified by the path passed into New.
//
// Resets the root directory // Resets the root directory
// //
// If create is set it will make the directory if not found // If create is set it will make the directory if not found
func (dc *DirCache) FindRoot(ctx context.Context, create bool) error { func (dc *DirCache) FindRoot(ctx context.Context, create bool) error {
dc.mu.Lock() dc.mu.Lock()
defer dc.mu.Unlock() defer dc.mu.Unlock()
return dc._findRoot(ctx, create)
}
// _findRoot finds the root directory if not already found
//
// Resets the root directory
//
// If create is set it will make the directory if not found
//
// Call with mu held
func (dc *DirCache) _findRoot(ctx context.Context, create bool) error {
if dc.foundRoot { if dc.foundRoot {
return nil return nil
} }
@ -277,51 +306,51 @@ func (dc *DirCache) FindRoot(ctx context.Context, create bool) error {
return nil return nil
} }
// FindRootAndPath finds the root first if not found then finds leaf and directoryID from a path
//
// If create is set parent directories will be created if they don't exist
func (dc *DirCache) FindRootAndPath(ctx context.Context, path string, create bool) (leaf, directoryID string, err error) {
err = dc.FindRoot(ctx, create)
if err != nil {
return
}
return dc.FindPath(ctx, path, create)
}
// FoundRoot returns whether the root directory has been found yet // FoundRoot returns whether the root directory has been found yet
//
// Call this from FindLeaf or CreateDir only
func (dc *DirCache) FoundRoot() bool { func (dc *DirCache) FoundRoot() bool {
dc.mu.Lock()
defer dc.mu.Unlock()
return dc.foundRoot return dc.foundRoot
} }
// RootID returns the ID of the root directory // RootID returns the ID of the root directory
// //
// This should be called after FindRoot // If create is set it will make the root directory if not found
func (dc *DirCache) RootID() string { func (dc *DirCache) RootID(ctx context.Context, create bool) (ID string, err error) {
dc.mu.Lock() dc.mu.Lock()
defer dc.mu.Unlock() defer dc.mu.Unlock()
if !dc.foundRoot { err = dc._findRoot(ctx, create)
log.Fatalf("Internal Error: RootID() called before FindRoot") if err != nil {
return "", err
} }
return dc.rootID return dc.rootID, nil
} }
// RootParentID returns the ID of the parent of the root directory // RootParentID returns the ID of the parent of the root directory
// //
// This should be called after FindRoot // If create is set it will make the root parent directory if not found (but not the root)
func (dc *DirCache) RootParentID() (string, error) { func (dc *DirCache) RootParentID(ctx context.Context, create bool) (ID string, err error) {
dc.mu.Lock() dc.mu.Lock()
defer dc.mu.Unlock() defer dc.mu.Unlock()
if !dc.foundRoot { if !dc.foundRoot {
return "", errors.New("internal error: RootID() called before FindRoot") if dc.root == "" {
return "", errors.New("is root directory")
}
// Find the rootParentID without creating the root
rootParent, _ := SplitPath(dc.root)
rootParentID, err := dc._findDir(ctx, rootParent, create)
if err != nil {
return "", err
}
dc.rootParentID = rootParentID
} else {
if dc.rootID == dc.trueRootID {
return "", errors.New("is root directory")
}
} }
if dc.rootParentID == "" { if dc.rootParentID == "" {
return "", errors.New("internal error: didn't find rootParentID") return "", errors.New("internal error: didn't find rootParentID")
} }
if dc.rootID == dc.trueRootID {
return "", errors.New("is root directory")
}
return dc.rootParentID, nil return dc.rootParentID, nil
} }