mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 00:13:49 +01:00
drive: added moveid function to backend
This commit is contained in:
parent
d8bc542ffc
commit
6b1bf5fbc0
@ -3559,6 +3559,41 @@ func (f *Fs) copyID(ctx context.Context, id, dest string) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// move file with id to dest (original file is deleted, unlike with copy)
|
||||||
|
func (f *Fs) moveID(ctx context.Context, id, dest string) (err error) {
|
||||||
|
info, err := f.getFile(ctx, id, f.getFileFields(ctx))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't find id: %w", err)
|
||||||
|
}
|
||||||
|
if info.MimeType == driveFolderType {
|
||||||
|
return fmt.Errorf("can't copy directory use: rclone copy --drive-root-folder-id %s %s %s", id, fs.ConfigString(f), dest)
|
||||||
|
}
|
||||||
|
info.Name = f.opt.Enc.ToStandardName(info.Name)
|
||||||
|
o, err := f.newObjectWithInfo(ctx, info.Name, info)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
destDir, destLeaf, err := fspath.Split(dest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if destLeaf == "" {
|
||||||
|
destLeaf = path.Base(o.Remote())
|
||||||
|
}
|
||||||
|
if destDir == "" {
|
||||||
|
destDir = "."
|
||||||
|
}
|
||||||
|
dstFs, err := cache.Get(ctx, destDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = operations.Move(ctx, dstFs, nil, destLeaf, o)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("move failed: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Run the drive query calling fn on each entry found
|
// Run the drive query calling fn on each entry found
|
||||||
func (f *Fs) queryFn(ctx context.Context, query string, fn func(*drive.File)) (err error) {
|
func (f *Fs) queryFn(ctx context.Context, query string, fn func(*drive.File)) (err error) {
|
||||||
list := f.svc.Files.List()
|
list := f.svc.Files.List()
|
||||||
@ -3789,6 +3824,29 @@ component will be used as the file name.
|
|||||||
If the destination is a drive backend then server-side copying will be
|
If the destination is a drive backend then server-side copying will be
|
||||||
attempted if possible.
|
attempted if possible.
|
||||||
|
|
||||||
|
Use the --interactive/-i or --dry-run flag to see what would be copied before copying.
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
Name: "moveid",
|
||||||
|
Short: "Move files by ID",
|
||||||
|
Long: `This command copies files by ID
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
rclone backend moveid drive: ID path
|
||||||
|
rclone backend moveid drive: ID1 path1 ID2 path2
|
||||||
|
|
||||||
|
It moves the drive file with ID given to the path (an rclone path which
|
||||||
|
will be passed internally to rclone copyto). The ID and path pairs can be
|
||||||
|
repeated.
|
||||||
|
|
||||||
|
The path should end with a / to indicate copy the file as named to
|
||||||
|
this directory. If it doesn't end with a / then the last path
|
||||||
|
component will be used as the file name.
|
||||||
|
|
||||||
|
If the destination is a drive backend then server-side copying will be
|
||||||
|
attempted if possible.
|
||||||
|
|
||||||
Use the --interactive/-i or --dry-run flag to see what would be copied before copying.
|
Use the --interactive/-i or --dry-run flag to see what would be copied before copying.
|
||||||
`,
|
`,
|
||||||
}, {
|
}, {
|
||||||
@ -3982,6 +4040,19 @@ func (f *Fs) Command(ctx context.Context, name string, arg []string, opt map[str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
case "moveid":
|
||||||
|
if len(arg)%2 != 0 {
|
||||||
|
return nil, errors.New("need an even number of arguments")
|
||||||
|
}
|
||||||
|
for len(arg) > 0 {
|
||||||
|
id, dest := arg[0], arg[1]
|
||||||
|
arg = arg[2:]
|
||||||
|
err = f.moveID(ctx, id, dest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed moving %q to %q: %w", id, dest, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
case "exportformats":
|
case "exportformats":
|
||||||
return f.exportFormats(ctx), nil
|
return f.exportFormats(ctx), nil
|
||||||
case "importformats":
|
case "importformats":
|
||||||
|
@ -524,6 +524,51 @@ func (f *Fs) InternalTestCopyID(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestIntegration/FsMkdir/FsPutFiles/Internal/MoveID
|
||||||
|
func (f *Fs) InternalTestMoveID(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
obj, err := f.NewObject(ctx, existingFile)
|
||||||
|
require.NoError(t, err)
|
||||||
|
o := obj.(*Object)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
|
||||||
|
checkFile := func(name string) {
|
||||||
|
filePath := filepath.Join(dir, name)
|
||||||
|
fi, err := os.Stat(filePath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, int64(100), fi.Size())
|
||||||
|
err = os.Remove(filePath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("BadID", func(t *testing.T) {
|
||||||
|
err = f.moveID(ctx, "ID-NOT-FOUND", dir+"/")
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "couldn't find id")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Directory", func(t *testing.T) {
|
||||||
|
rootID, err := f.dirCache.RootID(ctx, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = f.moveID(ctx, rootID, dir+"/")
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "can't copy directory")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WithoutDestName", func(t *testing.T) {
|
||||||
|
err = f.moveID(ctx, o.id, dir+"/")
|
||||||
|
require.NoError(t, err)
|
||||||
|
checkFile(path.Base(existingFile))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WithDestName", func(t *testing.T) {
|
||||||
|
err = f.moveID(ctx, o.id, dir+"/potato.txt")
|
||||||
|
require.NoError(t, err)
|
||||||
|
checkFile("potato.txt")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// TestIntegration/FsMkdir/FsPutFiles/Internal/Query
|
// TestIntegration/FsMkdir/FsPutFiles/Internal/Query
|
||||||
func (f *Fs) InternalTestQuery(t *testing.T) {
|
func (f *Fs) InternalTestQuery(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@ -648,6 +693,7 @@ func (f *Fs) InternalTest(t *testing.T) {
|
|||||||
t.Run("Shortcuts", f.InternalTestShortcuts)
|
t.Run("Shortcuts", f.InternalTestShortcuts)
|
||||||
t.Run("UnTrash", f.InternalTestUnTrash)
|
t.Run("UnTrash", f.InternalTestUnTrash)
|
||||||
t.Run("CopyID", f.InternalTestCopyID)
|
t.Run("CopyID", f.InternalTestCopyID)
|
||||||
|
t.Run("MoveID", f.InternalTestMoveID)
|
||||||
t.Run("Query", f.InternalTestQuery)
|
t.Run("Query", f.InternalTestQuery)
|
||||||
t.Run("AgeQuery", f.InternalTestAgeQuery)
|
t.Run("AgeQuery", f.InternalTestAgeQuery)
|
||||||
t.Run("ShouldRetry", f.InternalTestShouldRetry)
|
t.Run("ShouldRetry", f.InternalTestShouldRetry)
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user