@@ -1655,7 +1655,9 @@ func (s *Service) PushPath(server pb.APIService_PushPathServer) (err error) {
16551655 dbToken , _ := thread .TokenFromContext (server .Context ())
16561656
16571657 req , err := server .Recv ()
1658- if err != nil {
1658+ if err == io .EOF {
1659+ return nil
1660+ } else if err != nil {
16591661 return err
16601662 }
16611663 var buckKey , headerPath , root string
@@ -1946,14 +1948,18 @@ func (s *Service) PushPaths(server pb.APIService_PushPathsServer) error {
19461948 dbToken , _ := thread .TokenFromContext (ctx )
19471949
19481950 req , err := server .Recv ()
1949- if err != nil {
1951+ if err == io .EOF {
1952+ return nil
1953+ } else if err != nil {
19501954 return fmt .Errorf ("on receive: %v" , err )
19511955 }
19521956 var buckKey , buckRoot string
1957+ var buckPaths []string
19531958 switch payload := req .Payload .(type ) {
19541959 case * pb.PushPathsRequest_Header_ :
19551960 buckKey = payload .Header .Key
19561961 buckRoot = payload .Header .Root
1962+ buckPaths = payload .Header .Paths
19571963 default :
19581964 return fmt .Errorf ("push bucket path header is required" )
19591965 }
@@ -1963,17 +1969,31 @@ func (s *Service) PushPaths(server pb.APIService_PushPathsServer) error {
19631969 defer lck .Release ()
19641970
19651971 buck := & tdb.Bucket {}
1966- err = s .Buckets .GetSafe (ctx , dbID , buckKey , buck , tdb .WithToken (dbToken ))
1967- if err != nil {
1972+ if err := s .Buckets .GetSafe (ctx , dbID , buckKey , buck , tdb .WithToken (dbToken )); err != nil {
19681973 return fmt .Errorf ("getting bucket: %v" , err )
19691974 }
19701975 if buckRoot != "" && buckRoot != buck .Path {
19711976 return status .Error (codes .FailedPrecondition , buckets .ErrNonFastForward .Error ())
19721977 }
1978+
19731979 readOnlyBuck := buck .Copy ()
1980+ preVerified := make (map [string ]struct {})
1981+ if len (buckPaths ) > 0 {
1982+ readOnlyBuck .UpdatedAt = time .Now ().UnixNano ()
1983+ for _ , p := range buckPaths {
1984+ readOnlyBuck .SetMetadataAtPath (p , tdb.Metadata {
1985+ UpdatedAt : readOnlyBuck .UpdatedAt ,
1986+ })
1987+ readOnlyBuck .UnsetMetadataWithPrefix (p + "/" )
1988+ preVerified [p ] = struct {}{}
1989+ }
1990+ if err := s .Buckets .Verify (ctx , dbID , readOnlyBuck , tdb .WithToken (dbToken )); err != nil {
1991+ return status .Error (codes .PermissionDenied , fmt .Sprintf ("verifying bucket update: %v" , err ))
1992+ }
1993+ }
19741994
19751995 var wg sync.WaitGroup
1976- var ctxLock sync.RWMutex
1996+ var ctxLock , verifiedLock sync.RWMutex
19771997 addedCh := make (chan addedFile )
19781998 doneCh := make (chan struct {})
19791999 errCh := make (chan error )
@@ -2001,13 +2021,19 @@ func (s *Service) PushPaths(server pb.APIService_PushPathsServer) error {
20012021 ctxLock .RUnlock ()
20022022 fa , err := queue .add (ctx , s .IPFSClient .Unixfs (), pth , func () ([]byte , error ) {
20032023 wg .Add (1 )
2004- readOnlyBuck .UpdatedAt = time .Now ().UnixNano ()
2005- readOnlyBuck .SetMetadataAtPath (pth , tdb.Metadata {
2006- UpdatedAt : readOnlyBuck .UpdatedAt ,
2007- })
2008- readOnlyBuck .UnsetMetadataWithPrefix (pth + "/" )
2009- if err = s .Buckets .Verify (ctx , dbID , readOnlyBuck , tdb .WithToken (dbToken )); err != nil {
2010- return nil , fmt .Errorf ("verifying bucket update: %v" , err )
2024+ // Support requests that don't send all paths for pre-verification (pre v2.6.11)
2025+ verifiedLock .Lock ()
2026+ _ , ok := preVerified [pth ]
2027+ verifiedLock .Unlock ()
2028+ if ! ok {
2029+ readOnlyBuck .UpdatedAt = time .Now ().UnixNano ()
2030+ readOnlyBuck .SetMetadataAtPath (pth , tdb.Metadata {
2031+ UpdatedAt : readOnlyBuck .UpdatedAt ,
2032+ })
2033+ readOnlyBuck .UnsetMetadataWithPrefix (pth + "/" )
2034+ if err = s .Buckets .Verify (ctx , dbID , readOnlyBuck , tdb .WithToken (dbToken )); err != nil {
2035+ return nil , fmt .Errorf ("verifying bucket update: %v" , err )
2036+ }
20112037 }
20122038 key , err := readOnlyBuck .GetFileEncryptionKeyForPath (pth )
20132039 if err != nil {
0 commit comments