Skip to content

Commit 0a9921f

Browse files
gaoyifanCopilot
andauthored
fix(aliyundrive_open): resolve file duplication issues and improve path handling (#8358)
* fix(aliyundrive_open): resolve file duplication issues and improve path handling 1. Fix file duplication by implementing a new removeDuplicateFiles method that cleans up duplicate files after operations 2. Change Move operation to use "ignore" for check_name_mode instead of "refuse" to allow moves when destination has same filename 3. Set Copy operation to handle duplicates by removing them after successful copy 4. Improve path handling for all file operations (Move, Rename, Put, MakeDir) by properly maintaining the full path of objects 5. Implement GetRoot interface for proper root object initialization with correct path 6. Add proper path management in List operation to ensure objects have correct paths 7. Fix path handling in error cases and improve logging of failures * refactor(aliyundrive_open): change error logging to warnings for duplicate file removal Updated the Move, Rename, and Copy methods to log warnings instead of errors when duplicate file removal fails, as the primary operations have already completed successfully. This improves the clarity of logs without affecting the functionality. * Update drivers/aliyundrive_open/util.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 88abb32 commit 0a9921f

2 files changed

Lines changed: 121 additions & 12 deletions

File tree

drivers/aliyundrive_open/driver.go

Lines changed: 87 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"net/http"
8+
"path/filepath"
89
"time"
910

1011
"github.com/Xhofe/rateg"
@@ -14,6 +15,7 @@ import (
1415
"github.com/alist-org/alist/v3/internal/model"
1516
"github.com/alist-org/alist/v3/pkg/utils"
1617
"github.com/go-resty/resty/v2"
18+
log "github.com/sirupsen/logrus"
1719
)
1820

1921
type AliyundriveOpen struct {
@@ -72,6 +74,18 @@ func (d *AliyundriveOpen) Drop(ctx context.Context) error {
7274
return nil
7375
}
7476

77+
// GetRoot implements the driver.GetRooter interface to properly set up the root object
78+
func (d *AliyundriveOpen) GetRoot(ctx context.Context) (model.Obj, error) {
79+
return &model.Object{
80+
ID: d.RootFolderID,
81+
Path: "/",
82+
Name: "root",
83+
Size: 0,
84+
Modified: d.Modified,
85+
IsFolder: true,
86+
}, nil
87+
}
88+
7589
func (d *AliyundriveOpen) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
7690
if d.limitList == nil {
7791
return nil, fmt.Errorf("driver not init")
@@ -80,9 +94,17 @@ func (d *AliyundriveOpen) List(ctx context.Context, dir model.Obj, args model.Li
8094
if err != nil {
8195
return nil, err
8296
}
83-
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
84-
return fileToObj(src), nil
97+
98+
objs, err := utils.SliceConvert(files, func(src File) (model.Obj, error) {
99+
obj := fileToObj(src)
100+
// Set the correct path for the object
101+
if dir.GetPath() != "" {
102+
obj.Path = filepath.Join(dir.GetPath(), obj.GetName())
103+
}
104+
return obj, nil
85105
})
106+
107+
return objs, err
86108
}
87109

88110
func (d *AliyundriveOpen) link(ctx context.Context, file model.Obj) (*model.Link, error) {
@@ -132,7 +154,16 @@ func (d *AliyundriveOpen) MakeDir(ctx context.Context, parentDir model.Obj, dirN
132154
if err != nil {
133155
return nil, err
134156
}
135-
return fileToObj(newDir), nil
157+
obj := fileToObj(newDir)
158+
159+
// Set the correct Path for the returned directory object
160+
if parentDir.GetPath() != "" {
161+
obj.Path = filepath.Join(parentDir.GetPath(), dirName)
162+
} else {
163+
obj.Path = "/" + dirName
164+
}
165+
166+
return obj, nil
136167
}
137168

138169
func (d *AliyundriveOpen) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
@@ -142,20 +173,24 @@ func (d *AliyundriveOpen) Move(ctx context.Context, srcObj, dstDir model.Obj) (m
142173
"drive_id": d.DriveId,
143174
"file_id": srcObj.GetID(),
144175
"to_parent_file_id": dstDir.GetID(),
145-
"check_name_mode": "refuse", // optional:ignore,auto_rename,refuse
176+
"check_name_mode": "ignore", // optional:ignore,auto_rename,refuse
146177
//"new_name": "newName", // The new name to use when a file of the same name exists
147178
}).SetResult(&resp)
148179
})
149180
if err != nil {
150181
return nil, err
151182
}
152-
if resp.Exist {
153-
return nil, errors.New("existence of files with the same name")
154-
}
155183

156184
if srcObj, ok := srcObj.(*model.ObjThumb); ok {
157185
srcObj.ID = resp.FileID
158186
srcObj.Modified = time.Now()
187+
srcObj.Path = filepath.Join(dstDir.GetPath(), srcObj.GetName())
188+
189+
// Check for duplicate files in the destination directory
190+
if err := d.removeDuplicateFiles(ctx, dstDir.GetPath(), srcObj.GetName(), srcObj.GetID()); err != nil {
191+
// Only log a warning instead of returning an error since the move operation has already completed successfully
192+
log.Warnf("Failed to remove duplicate files after move: %v", err)
193+
}
159194
return srcObj, nil
160195
}
161196
return nil, nil
@@ -173,19 +208,47 @@ func (d *AliyundriveOpen) Rename(ctx context.Context, srcObj model.Obj, newName
173208
if err != nil {
174209
return nil, err
175210
}
176-
return fileToObj(newFile), nil
211+
212+
// Check for duplicate files in the parent directory
213+
parentPath := filepath.Dir(srcObj.GetPath())
214+
if err := d.removeDuplicateFiles(ctx, parentPath, newName, newFile.FileId); err != nil {
215+
// Only log a warning instead of returning an error since the rename operation has already completed successfully
216+
log.Warnf("Failed to remove duplicate files after rename: %v", err)
217+
}
218+
219+
obj := fileToObj(newFile)
220+
221+
// Set the correct Path for the renamed object
222+
if parentPath != "" && parentPath != "." {
223+
obj.Path = filepath.Join(parentPath, newName)
224+
} else {
225+
obj.Path = "/" + newName
226+
}
227+
228+
return obj, nil
177229
}
178230

179231
func (d *AliyundriveOpen) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
232+
var resp MoveOrCopyResp
180233
_, err := d.request("/adrive/v1.0/openFile/copy", http.MethodPost, func(req *resty.Request) {
181234
req.SetBody(base.Json{
182235
"drive_id": d.DriveId,
183236
"file_id": srcObj.GetID(),
184237
"to_parent_file_id": dstDir.GetID(),
185-
"auto_rename": true,
186-
})
238+
"auto_rename": false,
239+
}).SetResult(&resp)
187240
})
188-
return err
241+
if err != nil {
242+
return err
243+
}
244+
245+
// Check for duplicate files in the destination directory
246+
if err := d.removeDuplicateFiles(ctx, dstDir.GetPath(), srcObj.GetName(), resp.FileID); err != nil {
247+
// Only log a warning instead of returning an error since the copy operation has already completed successfully
248+
log.Warnf("Failed to remove duplicate files after copy: %v", err)
249+
}
250+
251+
return nil
189252
}
190253

191254
func (d *AliyundriveOpen) Remove(ctx context.Context, obj model.Obj) error {
@@ -203,7 +266,18 @@ func (d *AliyundriveOpen) Remove(ctx context.Context, obj model.Obj) error {
203266
}
204267

205268
func (d *AliyundriveOpen) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) (model.Obj, error) {
206-
return d.upload(ctx, dstDir, stream, up)
269+
obj, err := d.upload(ctx, dstDir, stream, up)
270+
271+
// Set the correct Path for the returned file object
272+
if obj != nil && obj.GetPath() == "" {
273+
if dstDir.GetPath() != "" {
274+
if objWithPath, ok := obj.(model.SetPath); ok {
275+
objWithPath.SetPath(filepath.Join(dstDir.GetPath(), obj.GetName()))
276+
}
277+
}
278+
}
279+
280+
return obj, err
207281
}
208282

209283
func (d *AliyundriveOpen) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
@@ -235,3 +309,4 @@ var _ driver.MkdirResult = (*AliyundriveOpen)(nil)
235309
var _ driver.MoveResult = (*AliyundriveOpen)(nil)
236310
var _ driver.RenameResult = (*AliyundriveOpen)(nil)
237311
var _ driver.PutResult = (*AliyundriveOpen)(nil)
312+
var _ driver.GetRooter = (*AliyundriveOpen)(nil)

drivers/aliyundrive_open/util.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"github.com/alist-org/alist/v3/drivers/base"
13+
"github.com/alist-org/alist/v3/internal/model"
1314
"github.com/alist-org/alist/v3/internal/op"
1415
"github.com/alist-org/alist/v3/pkg/utils"
1516
"github.com/go-resty/resty/v2"
@@ -186,3 +187,36 @@ func (d *AliyundriveOpen) getAccessToken() string {
186187
}
187188
return d.AccessToken
188189
}
190+
191+
// Remove duplicate files with the same name in the given directory path,
192+
// preserving the file with the given skipID if provided
193+
func (d *AliyundriveOpen) removeDuplicateFiles(ctx context.Context, parentPath string, fileName string, skipID string) error {
194+
// Handle empty path (root directory) case
195+
if parentPath == "" {
196+
parentPath = "/"
197+
}
198+
199+
// List all files in the parent directory
200+
files, err := op.List(ctx, d, parentPath, model.ListArgs{})
201+
if err != nil {
202+
return err
203+
}
204+
205+
// Find all files with the same name
206+
var duplicates []model.Obj
207+
for _, file := range files {
208+
if file.GetName() == fileName && file.GetID() != skipID {
209+
duplicates = append(duplicates, file)
210+
}
211+
}
212+
213+
// Remove all duplicates files, except the file with the given ID
214+
for _, file := range duplicates {
215+
err := d.Remove(ctx, file)
216+
if err != nil {
217+
return err
218+
}
219+
}
220+
221+
return nil
222+
}

0 commit comments

Comments
 (0)