From 2a587d21c480abcb7c14928fa8ee09524190b43b Mon Sep 17 00:00:00 2001 From: nielash Date: Fri, 8 Aug 2025 23:38:05 -0400 Subject: [PATCH] azurefiles: fix hash getting erased when modtime is set Before this change, setting an object's modtime with o.SetModTime() (without updating the file's content) would inadvertently erase its md5 hash. The documentation notes: "If this property isn't specified on the request, the property is cleared for the file. Subsequent calls to Get File Properties won't return this property, unless it's explicitly set on the file again." https://learn.microsoft.com/en-us/rest/api/storageservices/set-file-properties#common-request-headers This change fixes the issue by setting ContentMD5 (and ContentType), to the extent we have it, during SetModTime. Discovered on bisync integration tests such as TestBisyncRemoteRemote/resolve --- backend/azurefiles/azurefiles.go | 11 +++++++---- fstest/test_all/config.yaml | 2 -- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/backend/azurefiles/azurefiles.go b/backend/azurefiles/azurefiles.go index cb9dd2793..a9fed6e2b 100644 --- a/backend/azurefiles/azurefiles.go +++ b/backend/azurefiles/azurefiles.go @@ -453,7 +453,7 @@ func newFsFromOptions(ctx context.Context, name, root string, opt *Options) (fs. return nil, fmt.Errorf("create new shared key credential failed: %w", err) } case opt.UseAZ: - var options = azidentity.AzureCLICredentialOptions{} + options := azidentity.AzureCLICredentialOptions{} cred, err = azidentity.NewAzureCLICredential(&options) fmt.Println(cred) if err != nil { @@ -550,7 +550,7 @@ func newFsFromOptions(ctx context.Context, name, root string, opt *Options) (fs. case opt.UseMSI: // Specifying a user-assigned identity. Exactly one of the above IDs must be specified. // Validate and ensure exactly one is set. (To do: better validation.) - var b2i = map[bool]int{false: 0, true: 1} + b2i := map[bool]int{false: 0, true: 1} set := b2i[opt.MSIClientID != ""] + b2i[opt.MSIObjectID != ""] + b2i[opt.MSIResourceID != ""] if set > 1 { return nil, errors.New("more than one user-assigned identity ID is set") @@ -583,7 +583,6 @@ func newFsFromOptions(ctx context.Context, name, root string, opt *Options) (fs. token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ Scopes: []string{"api://AzureADTokenExchange"}, }) - if err != nil { return "", fmt.Errorf("failed to acquire MSI token: %w", err) } @@ -855,7 +854,7 @@ func (f *Fs) List(ctx context.Context, dir string) (fs.DirEntries, error) { return entries, err } - var opt = &directory.ListFilesAndDirectoriesOptions{ + opt := &directory.ListFilesAndDirectoriesOptions{ Include: directory.ListFilesInclude{ Timestamps: true, }, @@ -1014,6 +1013,10 @@ func (o *Object) SetModTime(ctx context.Context, t time.Time) error { SMBProperties: &file.SMBProperties{ LastWriteTime: &t, }, + HTTPHeaders: &file.HTTPHeaders{ + ContentMD5: o.md5, + ContentType: &o.contentType, + }, } _, err := o.fileClient().SetHTTPHeaders(ctx, &opt) if err != nil { diff --git a/fstest/test_all/config.yaml b/fstest/test_all/config.yaml index 65955e948..b57248c65 100644 --- a/fstest/test_all/config.yaml +++ b/fstest/test_all/config.yaml @@ -429,8 +429,6 @@ backends: - TestMultithreadCopyAbort - backend: "azurefiles" remote: "TestAzureFiles:" - ignoretests: - - cmd/bisync - backend: "pcloud" remote: "TestPcloud:" fastlist: true