in internal/storage/fake/bucket.go [728:796]
func (b *bucket) CopyObject(
ctx context.Context,
req *gcs.CopyObjectRequest) (o *gcs.Object, err error) {
b.mu.Lock()
defer b.mu.Unlock()
// Check that the destination name is legal.
err = checkName(req.DstName)
if err != nil {
return
}
// Does the object exist?
srcIndex := b.objects.find(req.SrcName)
if srcIndex == len(b.objects) {
err = &gcs.NotFoundError{
Err: fmt.Errorf("object %q not found", req.SrcName),
}
return
}
// Does it have the correct generation?
if req.SrcGeneration != 0 &&
b.objects[srcIndex].metadata.Generation != req.SrcGeneration {
err = &gcs.NotFoundError{
Err: fmt.Errorf(
"object %s generation %d not found", req.SrcName, req.SrcGeneration),
}
return
}
// Does it have the correct meta-generation?
if req.SrcMetaGenerationPrecondition != nil {
p := *req.SrcMetaGenerationPrecondition
if b.objects[srcIndex].metadata.MetaGeneration != p {
err = &gcs.PreconditionError{
Err: fmt.Errorf(
"object %q has meta-generation %d",
req.SrcName,
b.objects[srcIndex].metadata.MetaGeneration),
}
return
}
}
// Copy it and assign a new generation number, to ensure that the generation
// number for the destination name is strictly increasing.
dst := b.objects[srcIndex]
dst.metadata.Name = req.DstName
dst.metadata.MediaLink = "http://localhost/download/storage/fake/" + req.DstName
b.prevGeneration++
dst.metadata.Generation = b.prevGeneration
// Insert into our array.
existingIndex := b.objects.find(req.DstName)
if existingIndex < len(b.objects) {
b.objects[existingIndex] = dst
} else {
b.objects = append(b.objects, dst)
sort.Sort(b.objects)
}
o = copyObject(&dst.metadata)
return
}