opendrive: fix uploaded objects returning the wrong hash and modtime

Objects looked up by name used the /folder/itembyname.json endpoint
which does not return the file's MD5 hash, so NewObject returned
objects with no hash. Read the metadata with /file/info.json (which
does return the hash) instead, using itembyname only to find the file
id when it isn't known.

Copy and Move returned objects with only the id and size filled in,
leaving the modtime and hash empty, and SetModTime kept nanosecond
precision in memory while the server stores seconds. These made the
returned objects differ from a fresh listing of the same objects.
This commit is contained in:
Nick Craig-Wood
2026-07-17 18:29:39 +01:00
parent 727c11e081
commit 13354ac438
+37 -28
View File
@@ -413,9 +413,14 @@ func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (fs.Object,
return nil, err
}
size, _ := strconv.ParseInt(response.Size, 10, 64)
dstObj.id = response.FileID
dstObj.size = size
// Read the metadata back so the object returned matches what a
// fresh listing would return, in particular modtime and hash
err = dstObj.readMetaData(ctx)
if err != nil {
return nil, err
}
return dstObj, nil
}
@@ -520,9 +525,14 @@ func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (fs.Object,
return nil, err
}
size, _ := strconv.ParseInt(response.Size, 10, 64)
dstObj.id = response.FileID
dstObj.size = size
// Read the metadata back so the object returned matches what a
// fresh listing would return, in particular modtime and hash
err = dstObj.readMetaData(ctx)
if err != nil {
return nil, err
}
return dstObj, nil
}
@@ -963,7 +973,8 @@ func (o *Object) SetModTime(ctx context.Context, modTime time.Time) error {
return o.fs.shouldRetry(ctx, resp, err)
})
o.modTime = modTime
// The server only stores second precision modtimes
o.modTime = time.Unix(modTime.Unix(), 0)
return err
}
@@ -1138,46 +1149,44 @@ func (o *Object) readMetaData(ctx context.Context) (err error) {
var resp *http.Response
fileInfo := File{}
// If we know the object id perform a direct lookup
// because the /folder/itembyname.json endpoint is unreliable:
// newly created objects take an arbitrary amount of time to show up
if o.id != "" {
// Find the object id with /folder/itembyname.json if we don't
// know it already. Note that this endpoint is unreliable:
// newly created objects take an arbitrary amount of time to show up.
if o.id == "" {
folderList := FolderList{}
opts := rest.Opts{
Method: "GET",
Path: fmt.Sprintf("/file/info.json/%s?session_id=%s",
o.id, o.fs.session.SessionID),
Path: fmt.Sprintf("/folder/itembyname.json/%s/%s?name=%s",
o.fs.session.SessionID, directoryID, url.QueryEscape(o.fs.opt.Enc.FromStandardName(leaf))),
}
err = o.fs.pacer.Call(func() (bool, error) {
resp, err = o.fs.srv.CallJSON(ctx, &opts, nil, &fileInfo)
resp, err = o.fs.srv.CallJSON(ctx, &opts, nil, &folderList)
return o.fs.shouldRetry(ctx, resp, err)
})
if err != nil {
return fmt.Errorf("failed to get fileinfo: %w", err)
return fmt.Errorf("failed to get folder list: %w", err)
}
o.id = fileInfo.FileID
o.modTime = time.Unix(fileInfo.DateModified, 0)
o.md5 = fileInfo.FileHash
o.size = fileInfo.Size
return nil
if len(folderList.Files) == 0 {
return fs.ErrorObjectNotFound
}
o.id = folderList.Files[0].FileID
}
folderList := FolderList{}
// Read the metadata using a direct lookup as, unlike
// /folder/itembyname.json, it returns the FileHash
opts := rest.Opts{
Method: "GET",
Path: fmt.Sprintf("/folder/itembyname.json/%s/%s?name=%s",
o.fs.session.SessionID, directoryID, url.QueryEscape(o.fs.opt.Enc.FromStandardName(leaf))),
Path: fmt.Sprintf("/file/info.json/%s?session_id=%s",
o.id, o.fs.session.SessionID),
}
err = o.fs.pacer.Call(func() (bool, error) {
resp, err = o.fs.srv.CallJSON(ctx, &opts, nil, &folderList)
resp, err = o.fs.srv.CallJSON(ctx, &opts, nil, &fileInfo)
return o.fs.shouldRetry(ctx, resp, err)
})
if err != nil {
return fmt.Errorf("failed to get folder list: %w", err)
return fmt.Errorf("failed to get fileinfo: %w", err)
}
if len(folderList.Files) == 0 {
return fs.ErrorObjectNotFound
}
fileInfo = folderList.Files[0]
o.id = fileInfo.FileID
o.modTime = time.Unix(fileInfo.DateModified, 0)
o.md5 = fileInfo.FileHash