// list lists the objects into the function supplied from // the bucket and root supplied // // If prefix is set then startFileName is used as a prefix which all // files must have // // If limit is > 0 then it limits to that many files (must be less // than 1000) // // If hidden is set then it will list the hidden (deleted) files too. func (f *Fs) list(prefix string, limit int, hidden bool, fn listFn) error { bucketID, err := f.getBucketID() if err != nil { return err } chunkSize := 1000 if limit > 0 { chunkSize = limit } var request = api.ListFileNamesRequest{ BucketID: bucketID, MaxFileCount: chunkSize, } prefix = f.root + prefix if prefix != "" { request.StartFileName = prefix } var response api.ListFileNamesResponse opts := rest.Opts{ Method: "POST", Path: "/b2_list_file_names", } if hidden { opts.Path = "/b2_list_file_versions" } for { _, err = f.srv.CallJSON(&opts, &request, &response) if err != nil { return err } for i := range response.Files { file := &response.Files[i] // Finish if file name no longer has prefix if !strings.HasPrefix(file.Name, prefix) { return nil } err = fn(file.Name[len(prefix):], file) if err != nil { return err } } // end if no NextFileName if response.NextFileName == nil { break } request.StartFileName = *response.NextFileName if response.NextFileID != nil { request.StartFileID = *response.NextFileID } } return nil }
// list lists the objects into the function supplied from // the bucket and root supplied // // dir is the starting directory, "" for root // // level is the depth to search to // // If prefix is set then startFileName is used as a prefix which all // files must have // // If limit is > 0 then it limits to that many files (must be less // than 1000) // // If hidden is set then it will list the hidden (deleted) files too. func (f *Fs) list(dir string, level int, prefix string, limit int, hidden bool, fn listFn) error { root := f.root if dir != "" { root += dir + "/" } delimiter := "" switch level { case 1: delimiter = "/" case fs.MaxLevel: default: return fs.ErrorLevelNotSupported } bucketID, err := f.getBucketID() if err != nil { return err } chunkSize := 1000 if limit > 0 { chunkSize = limit } var request = api.ListFileNamesRequest{ BucketID: bucketID, MaxFileCount: chunkSize, Prefix: root, Delimiter: delimiter, } prefix = root + prefix if prefix != "" { request.StartFileName = prefix } var response api.ListFileNamesResponse opts := rest.Opts{ Method: "POST", Path: "/b2_list_file_names", } if hidden { opts.Path = "/b2_list_file_versions" } for { err := f.pacer.Call(func() (bool, error) { resp, err := f.srv.CallJSON(&opts, &request, &response) return f.shouldRetry(resp, err) }) if err != nil { return err } for i := range response.Files { file := &response.Files[i] // Finish if file name no longer has prefix if prefix != "" && !strings.HasPrefix(file.Name, prefix) { return nil } if !strings.HasPrefix(file.Name, f.root) { fs.Log(f, "Odd name received %q", file.Name) continue } remote := file.Name[len(f.root):] // Check for directory isDirectory := level != 0 && strings.HasSuffix(remote, "/") if isDirectory { remote = remote[:len(remote)-1] } // Send object err = fn(remote, file, isDirectory) if err != nil { if err == errEndList { return nil } return err } } // end if no NextFileName if response.NextFileName == nil { break } request.StartFileName = *response.NextFileName if response.NextFileID != nil { request.StartFileID = *response.NextFileID } } return nil }
// list lists the objects into the function supplied from // the bucket and root supplied // // level is the depth to search to // // If prefix is set then startFileName is used as a prefix which all // files must have // // If limit is > 0 then it limits to that many files (must be less // than 1000) // // If hidden is set then it will list the hidden (deleted) files too. func (f *Fs) list(dir string, level int, prefix string, limit int, hidden bool, fn listFn) error { root := f.root if dir != "" { root += dir + "/" } bucketID, err := f.getBucketID() if err != nil { return err } chunkSize := 1000 if limit > 0 { chunkSize = limit } var request = api.ListFileNamesRequest{ BucketID: bucketID, MaxFileCount: chunkSize, } prefix = root + prefix if prefix != "" { request.StartFileName = prefix } var response api.ListFileNamesResponse opts := rest.Opts{ Method: "POST", Path: "/b2_list_file_names", } if hidden { opts.Path = "/b2_list_file_versions" } lastDir := dir for { err := f.pacer.Call(func() (bool, error) { resp, err := f.srv.CallJSON(&opts, &request, &response) return f.shouldRetry(resp, err) }) if err != nil { return err } for i := range response.Files { file := &response.Files[i] // Finish if file name no longer has prefix if !strings.HasPrefix(file.Name, prefix) { return nil } remote := file.Name[len(f.root):] slashes := strings.Count(remote, "/") // Check if this file makes a new directories var dirNames []string dirNames, lastDir = sendDir(lastDir, remote, level) for _, dirName := range dirNames { err = fn(dirName, nil, true) if err != nil { if err == errEndList { return nil } return err } } // Send the file if slashes < level { err = fn(remote, file, false) if err != nil { if err == errEndList { return nil } return err } } } // end if no NextFileName if response.NextFileName == nil { break } request.StartFileName = *response.NextFileName if response.NextFileID != nil { request.StartFileID = *response.NextFileID } } return nil }