build: modernize Go code with go fix for go1.25
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"net/http"
|
||||
"path"
|
||||
"slices"
|
||||
@@ -729,8 +730,8 @@ func parseXMsTags(s string) (map[string]string, error) {
|
||||
return map[string]string{}, nil
|
||||
}
|
||||
out := make(map[string]string)
|
||||
parts := strings.Split(s, ",")
|
||||
for _, p := range parts {
|
||||
parts := strings.SplitSeq(s, ",")
|
||||
for p := range parts {
|
||||
p = strings.TrimSpace(p)
|
||||
if p == "" {
|
||||
continue
|
||||
@@ -893,9 +894,7 @@ func assembleCopyParams(ctx context.Context, f *Fs, src fs.Object, srcProps *blo
|
||||
if meta == nil {
|
||||
meta = make(map[string]*string, len(userMeta))
|
||||
}
|
||||
for k, v := range userMeta {
|
||||
meta[k] = v
|
||||
}
|
||||
maps.Copy(meta, userMeta)
|
||||
}
|
||||
// Apply tags if any
|
||||
if len(mappedTags) > 0 {
|
||||
@@ -992,9 +991,7 @@ func (o *Object) applyMappedMetadata(ctx context.Context, src fs.ObjectInfo, ui
|
||||
if o.tags == nil {
|
||||
o.tags = make(map[string]string, len(tags))
|
||||
}
|
||||
for k, v := range tags {
|
||||
o.tags[k] = v
|
||||
}
|
||||
maps.Copy(o.tags, tags)
|
||||
}
|
||||
|
||||
if mappedModTime != nil {
|
||||
@@ -1859,9 +1856,7 @@ func (f *Fs) copySinglepart(ctx context.Context, remote, dstContainer, dstPath s
|
||||
// Apply tags and post-copy headers only when mapping requested changes
|
||||
if len(tags) > 0 {
|
||||
options.BlobTags = make(map[string]string, len(tags))
|
||||
for k, v := range tags {
|
||||
options.BlobTags[k] = v
|
||||
}
|
||||
maps.Copy(options.BlobTags, tags)
|
||||
}
|
||||
if hadMapping {
|
||||
// Only set metadata explicitly when mapping was requested; otherwise
|
||||
@@ -2062,9 +2057,7 @@ func (o *Object) Metadata(ctx context.Context) (fs.Metadata, error) {
|
||||
|
||||
// Merge user metadata (already lower-cased keys)
|
||||
metadataMu.Lock()
|
||||
for k, v := range o.meta {
|
||||
m[k] = v
|
||||
}
|
||||
maps.Copy(m, o.meta)
|
||||
metadataMu.Unlock()
|
||||
|
||||
return m, nil
|
||||
|
||||
@@ -287,13 +287,13 @@ type StartLargeFileRequest struct {
|
||||
|
||||
// StartLargeFileResponse is the response to StartLargeFileRequest
|
||||
type StartLargeFileResponse struct {
|
||||
ID string `json:"fileId"` // The unique identifier for this version of this file. Used with b2_get_file_info, b2_download_file_by_id, and b2_delete_file_version.
|
||||
Name string `json:"fileName"` // The name of this file, which can be used with b2_download_file_by_name.
|
||||
AccountID string `json:"accountId"` // The identifier for the account.
|
||||
BucketID string `json:"bucketId"` // The unique ID of the bucket.
|
||||
ContentType string `json:"contentType"` // The MIME type of the file.
|
||||
Info map[string]string `json:"fileInfo"` // The custom information that was uploaded with the file. This is a JSON object, holding the name/value pairs that were uploaded with the file.
|
||||
UploadTimestamp Timestamp `json:"uploadTimestamp,omitempty"` // This is a UTC time when this file was uploaded.
|
||||
ID string `json:"fileId"` // The unique identifier for this version of this file. Used with b2_get_file_info, b2_download_file_by_id, and b2_delete_file_version.
|
||||
Name string `json:"fileName"` // The name of this file, which can be used with b2_download_file_by_name.
|
||||
AccountID string `json:"accountId"` // The identifier for the account.
|
||||
BucketID string `json:"bucketId"` // The unique ID of the bucket.
|
||||
ContentType string `json:"contentType"` // The MIME type of the file.
|
||||
Info map[string]string `json:"fileInfo"` // The custom information that was uploaded with the file. This is a JSON object, holding the name/value pairs that were uploaded with the file.
|
||||
UploadTimestamp Timestamp `json:"uploadTimestamp"` // This is a UTC time when this file was uploaded.
|
||||
}
|
||||
|
||||
// GetUploadPartURLRequest is passed to b2_get_upload_part_url
|
||||
|
||||
@@ -116,8 +116,8 @@ type Date struct {
|
||||
type DateFilter struct {
|
||||
Dates []Date `json:"dates,omitempty"`
|
||||
Ranges []struct {
|
||||
StartDate Date `json:"startDate,omitempty"`
|
||||
EndDate Date `json:"endDate,omitempty"`
|
||||
StartDate Date `json:"startDate"`
|
||||
EndDate Date `json:"endDate"`
|
||||
} `json:"ranges,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -583,9 +583,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
|
||||
entriesMu.Unlock()
|
||||
}
|
||||
for range checkers {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
for remote := range in {
|
||||
file := &Object{
|
||||
fs: f,
|
||||
@@ -601,7 +599,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e
|
||||
fs.Debugf(remote, "skipping because of error: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
for _, name := range names {
|
||||
isDir := name[len(name)-1] == '/'
|
||||
|
||||
@@ -599,7 +599,7 @@ type UpdateFileInfo struct {
|
||||
Signature string `json:"signature,omitempty"`
|
||||
Size int64 `json:"size,omitempty"`
|
||||
WrappingKey string `json:"wrapping_key,omitempty"`
|
||||
} `json:"data,omitempty"`
|
||||
} `json:"data"`
|
||||
DocumentID string `json:"document_id"`
|
||||
FileFlags FileFlags `json:"file_flags"`
|
||||
Mtime int64 `json:"mtime"`
|
||||
@@ -849,10 +849,10 @@ type DriveItem struct {
|
||||
NumberOfItems int64 `json:"numberOfItems"`
|
||||
Status string `json:"status"`
|
||||
Extension string `json:"extension,omitempty"`
|
||||
DateModified time.Time `json:"dateModified,omitempty"`
|
||||
DateChanged time.Time `json:"dateChanged,omitempty"`
|
||||
DateModified time.Time `json:"dateModified"`
|
||||
DateChanged time.Time `json:"dateChanged"`
|
||||
Size int64 `json:"size,omitempty"`
|
||||
LastOpenTime time.Time `json:"lastOpenTime,omitempty"`
|
||||
LastOpenTime time.Time `json:"lastOpenTime"`
|
||||
Urls struct {
|
||||
URLDownload string `json:"url_download"`
|
||||
} `json:"urls"`
|
||||
|
||||
@@ -33,12 +33,10 @@ func TestRemove(t *testing.T) {
|
||||
assert.True(t, exists())
|
||||
// close the file in the background
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
require.NoError(t, fd.Close())
|
||||
}()
|
||||
})
|
||||
// delete the open file
|
||||
err = remove(name)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
func remove(name string) (err error) {
|
||||
const maxTries = 10
|
||||
var sleepTime = 1 * time.Millisecond
|
||||
for i := 0; i < maxTries; i++ {
|
||||
for i := range maxTries {
|
||||
err = os.Remove(name)
|
||||
if err == nil {
|
||||
break
|
||||
|
||||
@@ -112,7 +112,7 @@ type ListItem struct {
|
||||
Count struct {
|
||||
Folders int `json:"folders"`
|
||||
Files int `json:"files"`
|
||||
} `json:"count,omitempty"`
|
||||
} `json:"count"`
|
||||
Kind string `json:"kind"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
@@ -154,7 +154,7 @@ type FolderInfoResponse struct {
|
||||
Type string `json:"type"`
|
||||
Home string `json:"home"`
|
||||
List []ListItem `json:"list"`
|
||||
} `json:"body,omitempty"`
|
||||
} `json:"body"`
|
||||
Time int64 `json:"time"`
|
||||
Status int `json:"status"`
|
||||
Email string `json:"email"`
|
||||
|
||||
@@ -50,12 +50,12 @@ type Identity struct {
|
||||
// to represent a set of identities associated with various events for
|
||||
// an item, such as created by or last modified by.
|
||||
type IdentitySet struct {
|
||||
User Identity `json:"user,omitempty"`
|
||||
Application Identity `json:"application,omitempty"`
|
||||
Device Identity `json:"device,omitempty"`
|
||||
Group Identity `json:"group,omitempty"`
|
||||
SiteGroup Identity `json:"siteGroup,omitempty"` // The SharePoint group associated with this action. Optional.
|
||||
SiteUser Identity `json:"siteUser,omitempty"` // The SharePoint user associated with this action. Optional.
|
||||
User Identity `json:"user"`
|
||||
Application Identity `json:"application"`
|
||||
Device Identity `json:"device"`
|
||||
Group Identity `json:"group"`
|
||||
SiteGroup Identity `json:"siteGroup"` // The SharePoint group associated with this action. Optional.
|
||||
SiteUser Identity `json:"siteUser"` // The SharePoint user associated with this action. Optional.
|
||||
}
|
||||
|
||||
// Quota groups storage space quota-related information on OneDrive into a single structure.
|
||||
@@ -155,8 +155,8 @@ type FileFacet struct {
|
||||
// facet can be used to specify the last modified date or created date
|
||||
// of the item as it was on the local device.
|
||||
type FileSystemInfoFacet struct {
|
||||
CreatedDateTime Timestamp `json:"createdDateTime,omitempty"` // The UTC date and time the file was created on a client.
|
||||
LastModifiedDateTime Timestamp `json:"lastModifiedDateTime,omitempty"` // The UTC date and time the file was last modified on a client.
|
||||
CreatedDateTime Timestamp `json:"createdDateTime"` // The UTC date and time the file was created on a client.
|
||||
LastModifiedDateTime Timestamp `json:"lastModifiedDateTime"` // The UTC date and time the file was last modified on a client.
|
||||
}
|
||||
|
||||
// DeletedFacet indicates that the item on OneDrive has been
|
||||
@@ -175,10 +175,10 @@ type PackageFacet struct {
|
||||
// SharedType indicates a DriveItem has been shared with others. The resource includes information about how the item is shared.
|
||||
// If a Driveitem has a non-null shared facet, the item has been shared.
|
||||
type SharedType struct {
|
||||
Owner IdentitySet `json:"owner,omitempty"` // The identity of the owner of the shared item. Read-only.
|
||||
Scope string `json:"scope,omitempty"` // Indicates the scope of how the item is shared: anonymous, organization, or users. Read-only.
|
||||
SharedBy IdentitySet `json:"sharedBy,omitempty"` // The identity of the user who shared the item. Read-only.
|
||||
SharedDateTime Timestamp `json:"sharedDateTime,omitempty"` // The UTC date and time when the item was shared. Read-only.
|
||||
Owner IdentitySet `json:"owner"` // The identity of the owner of the shared item. Read-only.
|
||||
Scope string `json:"scope,omitempty"` // Indicates the scope of how the item is shared: anonymous, organization, or users. Read-only.
|
||||
SharedBy IdentitySet `json:"sharedBy"` // The identity of the user who shared the item. Read-only.
|
||||
SharedDateTime Timestamp `json:"sharedDateTime"` // The UTC date and time when the item was shared. Read-only.
|
||||
}
|
||||
|
||||
// SharingInvitationType groups invitation-related data items into a single structure.
|
||||
|
||||
+18
-18
@@ -75,8 +75,8 @@ type ErrorDetails struct {
|
||||
Type string `json:"@type,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
Metadata struct{} `json:"metadata,omitempty"` // TODO: undiscovered yet
|
||||
Locale string `json:"locale,omitempty"` // e.g. "en"
|
||||
Metadata struct{} `json:"metadata"` // TODO: undiscovered yet
|
||||
Locale string `json:"locale,omitempty"` // e.g. "en"
|
||||
Message string `json:"message,omitempty"`
|
||||
StackEntries []any `json:"stack_entries,omitempty"` // TODO: undiscovered yet
|
||||
Detail string `json:"detail,omitempty"`
|
||||
@@ -189,8 +189,8 @@ type File struct {
|
||||
Apps []*FileApp `json:"apps,omitempty"`
|
||||
Audit *FileAudit `json:"audit,omitempty"`
|
||||
Collection string `json:"collection,omitempty"` // TODO
|
||||
CreatedTime Time `json:"created_time,omitempty"`
|
||||
DeleteTime Time `json:"delete_time,omitempty"`
|
||||
CreatedTime Time `json:"created_time"`
|
||||
DeleteTime Time `json:"delete_time"`
|
||||
FileCategory string `json:"file_category,omitempty"` // "AUDIO", "VIDEO"
|
||||
FileExtension string `json:"file_extension,omitempty"`
|
||||
FolderType string `json:"folder_type,omitempty"`
|
||||
@@ -202,7 +202,7 @@ type File struct {
|
||||
Md5Checksum string `json:"md5_checksum,omitempty"`
|
||||
Medias []*Media `json:"medias,omitempty"`
|
||||
MimeType string `json:"mime_type,omitempty"`
|
||||
ModifiedTime Time `json:"modified_time,omitempty"` // updated when renamed or moved
|
||||
ModifiedTime Time `json:"modified_time"` // updated when renamed or moved
|
||||
Name string `json:"name,omitempty"`
|
||||
OriginalFileIndex int `json:"original_file_index,omitempty"` // TODO
|
||||
OriginalURL string `json:"original_url,omitempty"`
|
||||
@@ -221,7 +221,7 @@ type File struct {
|
||||
ThumbnailLink string `json:"thumbnail_link,omitempty"`
|
||||
Trashed bool `json:"trashed,omitempty"`
|
||||
UserID string `json:"user_id,omitempty"`
|
||||
UserModifiedTime Time `json:"user_modified_time,omitempty"`
|
||||
UserModifiedTime Time `json:"user_modified_time"`
|
||||
WebContentLink string `json:"web_content_link,omitempty"`
|
||||
Writable bool `json:"writable,omitempty"`
|
||||
}
|
||||
@@ -252,7 +252,7 @@ type Media struct {
|
||||
AudioCodec string `json:"audio_codec,omitempty"` // "pcm_bluray", "aac"
|
||||
VideoType string `json:"video_type,omitempty"` // "mpegts"
|
||||
HdrType string `json:"hdr_type,omitempty"`
|
||||
} `json:"video,omitempty"`
|
||||
} `json:"video"`
|
||||
Link *Link `json:"link,omitempty"`
|
||||
NeedMoreQuota bool `json:"need_more_quota,omitempty"`
|
||||
VipTypes []any `json:"vip_types,omitempty"` // TODO maybe list of something?
|
||||
@@ -290,11 +290,11 @@ type FileApp struct {
|
||||
NeedMoreQuota bool `json:"need_more_quota,omitempty"`
|
||||
IconLink string `json:"icon_link,omitempty"`
|
||||
IsDefault bool `json:"is_default,omitempty"`
|
||||
Params struct{} `json:"params,omitempty"` // TODO
|
||||
Params struct{} `json:"params"` // TODO
|
||||
CategoryIDs []any `json:"category_ids,omitempty"`
|
||||
AdSceneType int `json:"ad_scene_type,omitempty"`
|
||||
Space string `json:"space,omitempty"`
|
||||
Links struct{} `json:"links,omitempty"` // TODO
|
||||
Links struct{} `json:"links"` // TODO
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
@@ -320,8 +320,8 @@ type Task struct {
|
||||
FileName string `json:"file_name,omitempty"`
|
||||
FileSize string `json:"file_size,omitempty"`
|
||||
Message string `json:"message,omitempty"` // e.g. "Saving"
|
||||
CreatedTime Time `json:"created_time,omitempty"`
|
||||
UpdatedTime Time `json:"updated_time,omitempty"`
|
||||
CreatedTime Time `json:"created_time"`
|
||||
UpdatedTime Time `json:"updated_time"`
|
||||
ThirdTaskID string `json:"third_task_id,omitempty"` // TODO
|
||||
Phase string `json:"phase,omitempty"` // e.g. "PHASE_TYPE_RUNNING"
|
||||
Progress int `json:"progress,omitempty"`
|
||||
@@ -368,7 +368,7 @@ type ResumableParams struct {
|
||||
AccessKeySecret string `json:"access_key_secret,omitempty"`
|
||||
Bucket string `json:"bucket,omitempty"`
|
||||
Endpoint string `json:"endpoint,omitempty"`
|
||||
Expiration Time `json:"expiration,omitempty"`
|
||||
Expiration Time `json:"expiration"`
|
||||
Key string `json:"key,omitempty"`
|
||||
SecurityToken string `json:"security_token,omitempty"`
|
||||
}
|
||||
@@ -409,7 +409,7 @@ type About struct {
|
||||
Kind string `json:"kind,omitempty"` // "drive#about"
|
||||
Quota *Quota `json:"quota,omitempty"`
|
||||
ExpiresAt string `json:"expires_at,omitempty"`
|
||||
Quotas struct{} `json:"quotas,omitempty"` // maybe []*Quota?
|
||||
Quotas struct{} `json:"quotas"` // maybe []*Quota?
|
||||
}
|
||||
|
||||
// Quota informs drive quota
|
||||
@@ -445,8 +445,8 @@ type User struct {
|
||||
PhoneNumber string `json:"phone_number,omitempty"`
|
||||
Password string `json:"password,omitempty"` // "SET" if configured
|
||||
Status string `json:"status,omitempty"` // "ACTIVE"
|
||||
CreatedAt Time `json:"created_at,omitempty"`
|
||||
PasswordUpdatedAt Time `json:"password_updated_at,omitempty"`
|
||||
CreatedAt Time `json:"created_at"`
|
||||
PasswordUpdatedAt Time `json:"password_updated_at"`
|
||||
}
|
||||
|
||||
// UserProvider details third-party authentication
|
||||
@@ -464,11 +464,11 @@ type VIP struct {
|
||||
Message string `json:"message,omitempty"`
|
||||
RedirectURI string `json:"redirect_uri,omitempty"`
|
||||
Data struct {
|
||||
Expire Time `json:"expire,omitempty"`
|
||||
Expire Time `json:"expire"`
|
||||
Status string `json:"status,omitempty"` // "invalid" or "ok"
|
||||
Type string `json:"type,omitempty"` // "novip" or "platinum"
|
||||
UserID string `json:"user_id,omitempty"` // same as User.Sub
|
||||
} `json:"data,omitempty"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// DecompressResult is a response to RequestDecompress
|
||||
@@ -538,7 +538,7 @@ type CaptchaToken struct {
|
||||
CaptchaToken string `json:"captcha_token"`
|
||||
ExpiresIn int64 `json:"expires_in"` // currently 300s
|
||||
// API doesn't provide Expiry field and thus it should be populated from ExpiresIn on retrieval
|
||||
Expiry time.Time `json:"expiry,omitempty"`
|
||||
Expiry time.Time `json:"expiry"`
|
||||
URL string `json:"url,omitempty"` // a link for users to solve captcha
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ func (f *Fs) refreshJWTToken(ctx context.Context) (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid token received from server")
|
||||
}
|
||||
var claims map[string]interface{}
|
||||
var claims map[string]any
|
||||
if err := json.Unmarshal(payload, &claims); err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -182,7 +182,7 @@ func (f *Fs) refreshJWTToken(ctx context.Context) (string, error) {
|
||||
return f.token, nil
|
||||
}
|
||||
|
||||
func (f *Fs) callAPI(ctx context.Context, method, path string, response interface{}) (*http.Response, error) {
|
||||
func (f *Fs) callAPI(ctx context.Context, method, path string, response any) (*http.Response, error) {
|
||||
token, err := f.refreshJWTToken(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
@@ -203,9 +204,7 @@ func (s *shadeChunkWriter) WriteChunk(ctx context.Context, chunkNumber int, read
|
||||
var uploadRes *http.Response
|
||||
if len(partURL.Headers) > 0 {
|
||||
opts.ExtraHeaders = make(map[string]string)
|
||||
for k, v := range partURL.Headers {
|
||||
opts.ExtraHeaders[k] = v
|
||||
}
|
||||
maps.Copy(opts.ExtraHeaders, partURL.Headers)
|
||||
}
|
||||
|
||||
err = s.f.pacer.Call(func() (bool, error) {
|
||||
|
||||
@@ -27,8 +27,8 @@ type Item struct {
|
||||
FileCount int32 `json:"FileCount,omitempty"`
|
||||
Name string `json:"Name,omitempty"`
|
||||
FileName string `json:"FileName,omitempty"`
|
||||
CreatedAt time.Time `json:"CreationDate,omitempty"`
|
||||
ModifiedAt time.Time `json:"ClientModifiedDate,omitempty"`
|
||||
CreatedAt time.Time `json:"CreationDate"`
|
||||
ModifiedAt time.Time `json:"ClientModifiedDate"`
|
||||
IsHidden bool `json:"IsHidden,omitempty"`
|
||||
Size int64 `json:"FileSizeBytes,omitempty"`
|
||||
Type string `json:"odata.type,omitempty"`
|
||||
|
||||
@@ -610,7 +610,7 @@ func (f *Fs) findHeader(headers fs.CommaSepList, find string) bool {
|
||||
|
||||
// fetch the bearer token and set it if successful
|
||||
func (f *Fs) fetchAndSetBearerToken() error {
|
||||
_, err, _ := f.authSingleflight.Do("bearerToken", func() (interface{}, error) {
|
||||
_, err, _ := f.authSingleflight.Do("bearerToken", func() (any, error) {
|
||||
if len(f.opt.BearerTokenCommand) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ type WriteMultiMetadataRequest struct {
|
||||
|
||||
// WriteMetadata is used to write item metadata
|
||||
type WriteMetadata struct {
|
||||
Attributes WriteAttributes `json:"attributes,omitempty"`
|
||||
Attributes WriteAttributes `json:"attributes"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
@@ -92,10 +92,10 @@ func TestCountWriterConcurrent(t *testing.T) {
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(goroutines)
|
||||
for g := 0; g < goroutines; g++ {
|
||||
for range goroutines {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for i := 0; i < loops; i++ {
|
||||
for range loops {
|
||||
n, err := cw.Write(data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, chunkSize, n)
|
||||
|
||||
@@ -128,9 +128,7 @@ func (b *bisyncRun) startLockRenewal() func() {
|
||||
}
|
||||
stopLockRenewal := make(chan struct{})
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
ticker := time.NewTicker(time.Duration(b.opt.MaxLock) - time.Minute)
|
||||
for {
|
||||
select {
|
||||
@@ -141,7 +139,7 @@ func (b *bisyncRun) startLockRenewal() func() {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return func() {
|
||||
close(stopLockRenewal)
|
||||
wg.Wait()
|
||||
|
||||
+2
-4
@@ -361,9 +361,7 @@ func StartStats() func() {
|
||||
}
|
||||
stopStats := make(chan struct{})
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
ticker := time.NewTicker(*statsInterval)
|
||||
for {
|
||||
select {
|
||||
@@ -374,7 +372,7 @@ func StartStats() func() {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return func() {
|
||||
close(stopStats)
|
||||
wg.Wait()
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ func mountOptions(VFS *vfs.VFS, device string, mountpoint string, opt *mountlib.
|
||||
func waitFor(fn func() bool) (ok bool) {
|
||||
const totalWait = 10 * time.Second
|
||||
const individualWait = 10 * time.Millisecond
|
||||
for i := 0; i < int(totalWait/individualWait); i++ {
|
||||
for range int(totalWait / individualWait) {
|
||||
ok = fn()
|
||||
if ok {
|
||||
return ok
|
||||
|
||||
+2
-4
@@ -41,9 +41,7 @@ func startProgress() func() {
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
progressInterval := defaultProgressInterval
|
||||
if ShowStats() && *statsInterval > 0 {
|
||||
progressInterval = *statsInterval
|
||||
@@ -65,7 +63,7 @@ func startProgress() func() {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return func() {
|
||||
close(stopStats)
|
||||
wg.Wait()
|
||||
|
||||
@@ -66,11 +66,9 @@ func testCacheCRUD(t *testing.T, h *Handler, c Cache, fileName string) {
|
||||
func testCacheThrashDifferent(t *testing.T, h *Handler, c Cache) {
|
||||
var wg sync.WaitGroup
|
||||
for i := range 100 {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
testCacheCRUD(t, h, c, fmt.Sprintf("file-%d", i))
|
||||
}()
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
@@ -79,9 +77,7 @@ func testCacheThrashDifferent(t *testing.T, h *Handler, c Cache) {
|
||||
func testCacheThrashSame(t *testing.T, h *Handler, c Cache) {
|
||||
var wg sync.WaitGroup
|
||||
for range 100 {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
|
||||
// Write a handle
|
||||
splitPath := []string{"file"}
|
||||
@@ -108,7 +104,7 @@ func testCacheThrashSame(t *testing.T, h *Handler, c Cache) {
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, errStaleHandle, err)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ type TransferSnapshot struct {
|
||||
Checked bool `json:"checked"`
|
||||
What string `json:"what"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
CompletedAt time.Time `json:"completed_at,omitempty"`
|
||||
CompletedAt time.Time `json:"completed_at"`
|
||||
Error error `json:"-"`
|
||||
Group string `json:"group"`
|
||||
SrcFs string `json:"srcFs,omitempty"`
|
||||
|
||||
@@ -265,9 +265,7 @@ func testAsyncReaderClose(t *testing.T, writeto bool) {
|
||||
var copyErr error
|
||||
var wg sync.WaitGroup
|
||||
started := make(chan struct{})
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
close(started)
|
||||
if writeto {
|
||||
// exercise the WriteTo path
|
||||
@@ -284,7 +282,7 @@ func testAsyncReaderClose(t *testing.T, writeto bool) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
// Do some copying
|
||||
<-started
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
@@ -163,7 +163,7 @@ type Item struct {
|
||||
// struct, otherwise they will be embedded as they are.
|
||||
func Items(opt any) (items []Item, err error) {
|
||||
def := reflect.ValueOf(opt)
|
||||
if def.Kind() != reflect.Ptr {
|
||||
if def.Kind() != reflect.Pointer {
|
||||
return nil, errors.New("argument must be a pointer")
|
||||
}
|
||||
def = def.Elem() // indirect the pointer
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ func Trace(o any, format string, a ...any) func(string, ...any) {
|
||||
for i := range a {
|
||||
// read the values of the pointed to items
|
||||
typ := reflect.TypeOf(a[i])
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
if typ.Kind() == reflect.Pointer {
|
||||
value := reflect.ValueOf(a[i])
|
||||
if value.IsNil() {
|
||||
a[i] = nil
|
||||
|
||||
+10
-20
@@ -205,9 +205,7 @@ func (m *March) Run(ctx context.Context) error {
|
||||
checkers := ci.Checkers
|
||||
in := make(chan listDirJob, checkers)
|
||||
for range checkers {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
for {
|
||||
select {
|
||||
case <-m.Ctx.Done():
|
||||
@@ -244,7 +242,7 @@ func (m *March) Run(ctx context.Context) error {
|
||||
traversing.Done()
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
// Start the process
|
||||
@@ -393,9 +391,7 @@ func (m *March) processJob(job listDirJob) ([]listDirJob, error) {
|
||||
// List the src and dst directories
|
||||
if !job.noSrc {
|
||||
srcChan := srcChan // duplicate this as we may override it later
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
srcListErr = m.srcListDir(job.srcRemote, func(entries fs.DirEntries) error {
|
||||
for _, entry := range entries {
|
||||
srcChan <- entry
|
||||
@@ -403,16 +399,14 @@ func (m *March) processJob(job listDirJob) ([]listDirJob, error) {
|
||||
return nil
|
||||
})
|
||||
close(srcChan)
|
||||
}()
|
||||
})
|
||||
} else {
|
||||
close(srcChan)
|
||||
}
|
||||
startedDst := false
|
||||
if !m.NoTraverse && !job.noDst {
|
||||
startedDst = true
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
dstListErr = m.dstListDir(job.dstRemote, func(entries fs.DirEntries) error {
|
||||
for _, entry := range entries {
|
||||
dstChan <- entry
|
||||
@@ -420,7 +414,7 @@ func (m *March) processJob(job listDirJob) ([]listDirJob, error) {
|
||||
return nil
|
||||
})
|
||||
close(dstChan)
|
||||
}()
|
||||
})
|
||||
}
|
||||
// If NoTraverse is set, then try to find a matching object
|
||||
// for each item in the srcList to head dst object
|
||||
@@ -455,9 +449,7 @@ func (m *March) processJob(job listDirJob) ([]listDirJob, error) {
|
||||
// Get the tasks from the queue and find a matching object.
|
||||
var workerWg sync.WaitGroup
|
||||
for range workers {
|
||||
workerWg.Add(1)
|
||||
go func() {
|
||||
defer workerWg.Done()
|
||||
workerWg.Go(func() {
|
||||
for t := range matchTasks {
|
||||
// Can't match directories with NewObject
|
||||
if _, ok := t.src.(fs.Object); !ok {
|
||||
@@ -476,7 +468,7 @@ func (m *March) processJob(job listDirJob) ([]listDirJob, error) {
|
||||
}
|
||||
t.dstMatch <- dst
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
// Close dstResults when all the workers have finished
|
||||
@@ -486,9 +478,7 @@ func (m *March) processJob(job listDirJob) ([]listDirJob, error) {
|
||||
}()
|
||||
|
||||
// Read the matches in order and send them to dstChan if found.
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
for dstMatch := range dstMatches {
|
||||
dst := <-dstMatch
|
||||
// Note that dst may be nil here
|
||||
@@ -497,7 +487,7 @@ func (m *March) processJob(job listDirJob) ([]listDirJob, error) {
|
||||
}
|
||||
close(srcChan)
|
||||
close(dstChan)
|
||||
}()
|
||||
})
|
||||
}
|
||||
if !startedDst {
|
||||
close(dstChan)
|
||||
|
||||
@@ -508,9 +508,7 @@ func TestMatchListings(t *testing.T) {
|
||||
}
|
||||
ls, err := list.NewSorter(ctx, nil, list.SortToChan(out), key)
|
||||
require.NoError(t, err)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
for i := 0; i < len(test.input); i += 2 {
|
||||
entry := test.input[i+offset]
|
||||
if entry != nil {
|
||||
@@ -520,7 +518,7 @@ func TestMatchListings(t *testing.T) {
|
||||
require.NoError(t, ls.Send())
|
||||
ls.CleanUp()
|
||||
close(out)
|
||||
}()
|
||||
})
|
||||
return out
|
||||
}
|
||||
|
||||
|
||||
+4
-8
@@ -570,13 +570,11 @@ func (s *syncCopyMove) startTrackRenames() {
|
||||
if !s.trackRenames {
|
||||
return
|
||||
}
|
||||
s.trackRenamesWg.Add(1)
|
||||
go func() {
|
||||
defer s.trackRenamesWg.Done()
|
||||
s.trackRenamesWg.Go(func() {
|
||||
for o := range s.trackRenamesCh {
|
||||
s.renameCheck = append(s.renameCheck, o)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
// This stops the background rename collection
|
||||
@@ -593,12 +591,10 @@ func (s *syncCopyMove) startDeleters() {
|
||||
if s.deleteMode != fs.DeleteModeDuring && s.deleteMode != fs.DeleteModeOnly {
|
||||
return
|
||||
}
|
||||
s.deletersWg.Add(1)
|
||||
go func() {
|
||||
defer s.deletersWg.Done()
|
||||
s.deletersWg.Go(func() {
|
||||
err := operations.DeleteFilesWithBackupDir(s.ctx, s.deleteFilesCh, s.backupDir)
|
||||
s.processError(err)
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
// This stops the background deleters
|
||||
|
||||
+2
-4
@@ -391,9 +391,7 @@ func walk(ctx context.Context, f fs.Fs, path string, includeAll bool, maxLevel i
|
||||
})
|
||||
}
|
||||
for range ci.Checkers {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
for {
|
||||
select {
|
||||
case job, ok := <-in:
|
||||
@@ -442,7 +440,7 @@ func walk(ctx context.Context, f fs.Fs, path string, includeAll bool, maxLevel i
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
// Start the process
|
||||
traversing.Add(1)
|
||||
|
||||
@@ -44,7 +44,7 @@ func Walk(err error, f WalkFunc) {
|
||||
// *os.SyscallError and many others in the stdlib.
|
||||
errType := reflect.TypeOf(err)
|
||||
errValue := reflect.ValueOf(err)
|
||||
if errValue.IsValid() && errType.Kind() == reflect.Ptr {
|
||||
if errValue.IsValid() && errType.Kind() == reflect.Pointer {
|
||||
errType = errType.Elem()
|
||||
errValue = errValue.Elem()
|
||||
}
|
||||
|
||||
@@ -375,21 +375,17 @@ func TestCallMaxConnectionsRecursiveDeadlock2(t *testing.T) {
|
||||
|
||||
// Normal
|
||||
for range 100 {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
err := p.Call(func() (bool, error) {
|
||||
// check we have taken the connection token
|
||||
assert.Equal(t, 0, len(p.connTokens))
|
||||
return false, nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
})
|
||||
|
||||
// Now attempt a recursive call
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
err := p.Call(func() (bool, error) {
|
||||
// check we have taken the connection token
|
||||
assert.Equal(t, 0, len(p.connTokens))
|
||||
@@ -397,7 +393,7 @@ func TestCallMaxConnectionsRecursiveDeadlock2(t *testing.T) {
|
||||
return false, p.Call(dp.fn)
|
||||
})
|
||||
assert.Equal(t, errFoo, err)
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
// Tidy up
|
||||
|
||||
@@ -290,9 +290,7 @@ func TestPoolMaxBufferMemory(t *testing.T) {
|
||||
)
|
||||
const trials = 50
|
||||
for i := range trials {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
if i < trials/2 {
|
||||
n := i%4 + 1
|
||||
buf := bp.GetN(n)
|
||||
@@ -307,7 +305,7 @@ func TestPoolMaxBufferMemory(t *testing.T) {
|
||||
countBuf(-1)
|
||||
bp.Put(buf)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
@@ -563,11 +563,9 @@ func TestRWConcurrency(t *testing.T) {
|
||||
writeTo := func(rw *RW, size int64) {
|
||||
in, out := io.Pipe()
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
check(in, size, rw)
|
||||
}()
|
||||
})
|
||||
var n int64
|
||||
for n < size {
|
||||
nn, err := rw.WriteTo(out)
|
||||
|
||||
@@ -296,13 +296,11 @@ func main() {
|
||||
quit = make(chan struct{}, *iterations)
|
||||
)
|
||||
for range *number {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
t := NewTest(dir)
|
||||
defer t.Tidy()
|
||||
t.RandomTests(*iterations, quit)
|
||||
}()
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
@@ -115,9 +115,7 @@ func New(item Item, opt *vfscommon.Options, remote string, src fs.Object) (dls *
|
||||
src: src,
|
||||
remote: remote,
|
||||
}
|
||||
dls.wg.Add(1)
|
||||
go func() {
|
||||
defer dls.wg.Done()
|
||||
dls.wg.Go(func() {
|
||||
ticker := time.NewTicker(backgroundKickerInterval)
|
||||
select {
|
||||
case <-ticker.C:
|
||||
@@ -129,7 +127,7 @@ func New(item Item, opt *vfscommon.Options, remote string, src fs.Object) (dls *
|
||||
break
|
||||
}
|
||||
ticker.Stop()
|
||||
}()
|
||||
})
|
||||
|
||||
return dls
|
||||
}
|
||||
@@ -189,9 +187,7 @@ func (dls *Downloaders) _newDownloader(r ranges.Range) (dl *downloader, err erro
|
||||
|
||||
dls.dls = append(dls.dls, dl)
|
||||
|
||||
dl.wg.Add(1)
|
||||
go func() {
|
||||
defer dl.wg.Done()
|
||||
dl.wg.Go(func() {
|
||||
n, err := dl.download()
|
||||
_ = dl.close(err)
|
||||
dl.dls.countErrors(n, err)
|
||||
@@ -202,7 +198,7 @@ func (dls *Downloaders) _newDownloader(r ranges.Range) (dl *downloader, err erro
|
||||
if err != nil {
|
||||
fs.Errorf(dl.dls.src, "vfs cache: failed to kick waiters: %v", err)
|
||||
}
|
||||
}()
|
||||
})
|
||||
|
||||
return dl, nil
|
||||
}
|
||||
|
||||
@@ -542,9 +542,7 @@ func TestItemReadWrite(t *testing.T) {
|
||||
assert.False(t, item.present())
|
||||
var wg sync.WaitGroup
|
||||
for range 8 {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
in := readers.NewPatternReader(size)
|
||||
buf := make([]byte, 1024*1024)
|
||||
buf2 := make([]byte, 1024*1024)
|
||||
@@ -553,7 +551,7 @@ func TestItemReadWrite(t *testing.T) {
|
||||
offset := max(rand.Int63n(size+2*int64(blockSize))-int64(blockSize), 0)
|
||||
_, _ = readCheckBuf(t, in, buf, buf2, item, offset, blockSize)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
require.NoError(t, item.Close(nil))
|
||||
|
||||
Reference in New Issue
Block a user