From 3349b055f59d3185abd3db78a4818503b292e7f6 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 10 Jun 2021 13:11:00 +0100 Subject: [PATCH] fichier: fix move of files in the same directory See: https://forum.rclone.org/t/1fichier-rclone-does-not-allow-to-rename-files-and-folders-when-you-mount-a-1fichier-disk-drive/24726/24 --- backend/fichier/api.go | 28 +++++++++++++++++++++++++ backend/fichier/fichier.go | 42 ++++++++++++++++++++++++++++---------- backend/fichier/structs.go | 24 ++++++++++++++++++++++ 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/backend/fichier/api.go b/backend/fichier/api.go index 51c7bd61b..a2143bd31 100644 --- a/backend/fichier/api.go +++ b/backend/fichier/api.go @@ -404,6 +404,34 @@ func (f *Fs) copyFile(ctx context.Context, url string, folderID int, rename stri return response, nil } +func (f *Fs) renameFile(ctx context.Context, url string, newName string) (response *RenameFileResponse, err error) { + request := &RenameFileRequest{ + URLs: []RenameFileURL{ + { + URL: url, + Filename: newName, + }, + }, + } + + opts := rest.Opts{ + Method: "POST", + Path: "/file/rename.cgi", + } + + response = &RenameFileResponse{} + err = f.pacer.Call(func() (bool, error) { + resp, err := f.rest.CallJSON(ctx, &opts, request, response) + return shouldRetry(ctx, resp, err) + }) + + if err != nil { + return nil, errors.Wrap(err, "couldn't rename file") + } + + return response, nil +} + func (f *Fs) getUploadNode(ctx context.Context) (response *GetUploadNodeResponse, err error) { // fs.Debugf(f, "Requesting Upload node") diff --git a/backend/fichier/fichier.go b/backend/fichier/fichier.go index 753eadf10..ad9311c23 100644 --- a/backend/fichier/fichier.go +++ b/backend/fichier/fichier.go @@ -437,25 +437,45 @@ func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (fs.Object, return nil, fs.ErrorCantMove } + // Find current directory ID + _, currentDirectoryID, err := f.dirCache.FindPath(ctx, remote, false) + if err != nil { + return nil, err + } + // Create temporary object dstObj, leaf, directoryID, err := f.createObject(ctx, remote) if err != nil { return nil, err } - folderID, err := strconv.Atoi(directoryID) - if err != nil { - return nil, err - } - resp, err := f.moveFile(ctx, srcObj.file.URL, folderID, leaf) - if err != nil { - return nil, errors.Wrap(err, "couldn't move file") - } - if resp.Status != "OK" { - return nil, errors.Errorf("couldn't move file: %s", resp.Message) + // If it is in the correct directory, just rename it + var url string + if currentDirectoryID == directoryID { + resp, err := f.renameFile(ctx, srcObj.file.URL, leaf) + if err != nil { + return nil, errors.Wrap(err, "couldn't rename file") + } + if resp.Status != "OK" { + return nil, errors.Errorf("couldn't rename file: %s", resp.Message) + } + url = resp.URLs[0].URL + } else { + folderID, err := strconv.Atoi(directoryID) + if err != nil { + return nil, err + } + resp, err := f.moveFile(ctx, srcObj.file.URL, folderID, leaf) + if err != nil { + return nil, errors.Wrap(err, "couldn't move file") + } + if resp.Status != "OK" { + return nil, errors.Errorf("couldn't move file: %s", resp.Message) + } + url = resp.URLs[0] } - file, err := f.readFileInfo(ctx, resp.URLs[0]) + file, err := f.readFileInfo(ctx, url) if err != nil { return nil, errors.New("couldn't read file data") } diff --git a/backend/fichier/structs.go b/backend/fichier/structs.go index c00d05989..ab40fb25a 100644 --- a/backend/fichier/structs.go +++ b/backend/fichier/structs.go @@ -90,6 +90,30 @@ type FileCopy struct { ToURL string `json:"to_url"` } +// RenameFileURL is the data structure to rename a single file +type RenameFileURL struct { + URL string `json:"url"` + Filename string `json:"filename"` +} + +// RenameFileRequest is the request structure of the corresponding request +type RenameFileRequest struct { + URLs []RenameFileURL `json:"urls"` + Pretty int `json:"pretty"` +} + +// RenameFileResponse is the response structure of the corresponding request +type RenameFileResponse struct { + Status string `json:"status"` + Message string `json:"message"` + Renamed int `json:"renamed"` + URLs []struct { + URL string `json:"url"` + OldFilename string `json:"old_filename"` + NewFilename string `json:"new_filename"` + } `json:"urls"` +} + // GetUploadNodeResponse is the response structure of the corresponding request type GetUploadNodeResponse struct { ID string `json:"id"`