github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/backend/union/policy/epall.go (about)

     1  package policy
     2  
     3  import (
     4  	"context"
     5  	"path"
     6  	"sync"
     7  
     8  	"github.com/rclone/rclone/backend/union/upstream"
     9  	"github.com/rclone/rclone/fs"
    10  )
    11  
    12  func init() {
    13  	registerPolicy("epall", &EpAll{})
    14  }
    15  
    16  // EpAll stands for existing path, all
    17  // Action category: apply to all found.
    18  // Create category: apply to all found.
    19  // Search category: same as epff.
    20  type EpAll struct {
    21  	EpFF
    22  }
    23  
    24  func (p *EpAll) epall(ctx context.Context, upstreams []*upstream.Fs, filePath string) ([]*upstream.Fs, error) {
    25  	var wg sync.WaitGroup
    26  	ufs := make([]*upstream.Fs, len(upstreams))
    27  	for i, u := range upstreams {
    28  		wg.Add(1)
    29  		i, u := i, u // Closure
    30  		go func() {
    31  			rfs := u.RootFs
    32  			remote := path.Join(u.RootPath, filePath)
    33  			if findEntry(ctx, rfs, remote) != nil {
    34  				ufs[i] = u
    35  			}
    36  			wg.Done()
    37  		}()
    38  	}
    39  	wg.Wait()
    40  	var results []*upstream.Fs
    41  	for _, f := range ufs {
    42  		if f != nil {
    43  			results = append(results, f)
    44  		}
    45  	}
    46  	if len(results) == 0 {
    47  		return nil, fs.ErrorObjectNotFound
    48  	}
    49  	return results, nil
    50  }
    51  
    52  // Action category policy, governing the modification of files and directories
    53  func (p *EpAll) Action(ctx context.Context, upstreams []*upstream.Fs, path string) ([]*upstream.Fs, error) {
    54  	if len(upstreams) == 0 {
    55  		return nil, fs.ErrorObjectNotFound
    56  	}
    57  	upstreams = filterRO(upstreams)
    58  	if len(upstreams) == 0 {
    59  		return nil, fs.ErrorPermissionDenied
    60  	}
    61  	return p.epall(ctx, upstreams, path)
    62  }
    63  
    64  // ActionEntries is ACTION category policy but receiving a set of candidate entries
    65  func (p *EpAll) ActionEntries(entries ...upstream.Entry) ([]upstream.Entry, error) {
    66  	if len(entries) == 0 {
    67  		return nil, fs.ErrorObjectNotFound
    68  	}
    69  	entries = filterROEntries(entries)
    70  	if len(entries) == 0 {
    71  		return nil, fs.ErrorPermissionDenied
    72  	}
    73  	return entries, nil
    74  }
    75  
    76  // Create category policy, governing the creation of files and directories
    77  func (p *EpAll) Create(ctx context.Context, upstreams []*upstream.Fs, path string) ([]*upstream.Fs, error) {
    78  	if len(upstreams) == 0 {
    79  		return nil, fs.ErrorObjectNotFound
    80  	}
    81  	upstreams = filterNC(upstreams)
    82  	if len(upstreams) == 0 {
    83  		return nil, fs.ErrorPermissionDenied
    84  	}
    85  	upstreams, err := p.epall(ctx, upstreams, path+"/..")
    86  	return upstreams, err
    87  }
    88  
    89  // CreateEntries is CREATE category policy but receiving a set of candidate entries
    90  func (p *EpAll) CreateEntries(entries ...upstream.Entry) ([]upstream.Entry, error) {
    91  	if len(entries) == 0 {
    92  		return nil, fs.ErrorObjectNotFound
    93  	}
    94  	entries = filterNCEntries(entries)
    95  	if len(entries) == 0 {
    96  		return nil, fs.ErrorPermissionDenied
    97  	}
    98  	return entries, nil
    99  }