// LOCKS_EXCLUDED(b.mu) func (b *bucket) UpdateObject( ctx context.Context, req *gcs.UpdateObjectRequest) (o *gcs.Object, err error) { b.mu.Lock() defer b.mu.Unlock() // Match real GCS in not allowing the removal of ContentType. if req.ContentType != nil && *req.ContentType == "" { err = errors.New("The ContentType field is required and cannot be removed.") return } // Does the object exist? index := b.objects.find(req.Name) if index == len(b.objects) { err = &gcs.NotFoundError{ Err: fmt.Errorf("Object %s not found", req.Name), } return } var obj *gcs.Object = &b.objects[index].metadata // Update the entry's basic fields according to the request. if req.ContentType != nil { obj.ContentType = *req.ContentType } if req.ContentEncoding != nil { obj.ContentEncoding = *req.ContentEncoding } if req.ContentLanguage != nil { obj.ContentLanguage = *req.ContentLanguage } if req.CacheControl != nil { obj.CacheControl = *req.CacheControl } // Update the user metadata if necessary. if len(req.Metadata) > 0 { if obj.Metadata == nil { obj.Metadata = make(map[string]string) } for k, v := range req.Metadata { if v == nil { delete(obj.Metadata, k) continue } obj.Metadata[k] = *v } } // Bump up the entry generation number. obj.MetaGeneration++ // Make a copy to avoid handing back internal state. var objCopy gcs.Object = *obj o = &objCopy return }
// LOCKS_EXCLUDED(b.mu) func (b *bucket) UpdateObject( ctx context.Context, req *gcs.UpdateObjectRequest) (o *gcs.Object, err error) { b.mu.Lock() defer b.mu.Unlock() // Does the object exist? index := b.objects.find(req.Name) if index == len(b.objects) { err = &gcs.NotFoundError{ Err: fmt.Errorf("Object %s not found", req.Name), } return } var obj *gcs.Object = &b.objects[index].metadata // Does the generation number match the request? if req.Generation != 0 && obj.Generation != req.Generation { err = &gcs.NotFoundError{ Err: fmt.Errorf( "Object %q generation %d not found", req.Name, req.Generation), } return } // Does the meta-generation precondition check out? if req.MetaGenerationPrecondition != nil && obj.MetaGeneration != *req.MetaGenerationPrecondition { err = &gcs.PreconditionError{ Err: fmt.Errorf( "Object %q has meta-generation %d", obj.Name, obj.MetaGeneration), } return } // Update the entry's basic fields according to the request. if req.ContentType != nil { obj.ContentType = *req.ContentType } if req.ContentEncoding != nil { obj.ContentEncoding = *req.ContentEncoding } if req.ContentLanguage != nil { obj.ContentLanguage = *req.ContentLanguage } if req.CacheControl != nil { obj.CacheControl = *req.CacheControl } // Update the user metadata if necessary. if len(req.Metadata) > 0 { if obj.Metadata == nil { obj.Metadata = make(map[string]string) } for k, v := range req.Metadata { if v == nil { delete(obj.Metadata, k) continue } obj.Metadata[k] = *v } } // Bump up the entry generation number and the update time. obj.MetaGeneration++ obj.Updated = b.clock.Now() // Make a copy to avoid handing back internal state. var objCopy gcs.Object = *obj o = &objCopy return }