build: modernize Go code with go fix for go1.25

This commit is contained in:
Nick Craig-Wood
2026-02-18 12:11:52 +00:00
parent cf97f250df
commit b2866f0291
36 changed files with 118 additions and 176 deletions
+7 -14
View File
@@ -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
+7 -7
View File
@@ -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
+2 -2
View File
@@ -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"`
}
+2 -4
View File
@@ -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] == '/'
+4 -4
View File
@@ -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"`
+2 -4
View File
@@ -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)
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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"`
+12 -12
View File
@@ -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
View File
@@ -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
}
+2 -2
View File
@@ -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
+2 -3
View File
@@ -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) {
+2 -2
View File
@@ -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"`
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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"`
}
+2 -2
View File
@@ -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)
+2 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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()
+4 -8
View File
@@ -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()
}
+1 -1
View File
@@ -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"`
+2 -4
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+2 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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()
}
+4 -8
View File
@@ -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
+2 -4
View File
@@ -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()
+2 -4
View File
@@ -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)
+2 -4
View File
@@ -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()
}
+4 -8
View File
@@ -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
}
+2 -4
View File
@@ -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))