func()

in internal/gcsx/compose_object_creator.go [84:175]


func (oc *composeObjectCreator) Create(
	ctx context.Context,
	objectName string,
	srcObject *gcs.Object,
	mtime *time.Time,
	chunkTransferTimeoutSecs int64,
	r io.Reader) (o *gcs.Object, err error) {
	// Choose a name for a temporary object.
	tmpName, err := oc.chooseName()
	if err != nil {
		err = fmt.Errorf("chooseName: %w", err)
		return
	}

	// Create a temporary object containing the additional contents.
	req := gcs.NewCreateObjectRequest(nil, tmpName, nil, chunkTransferTimeoutSecs)
	req.Contents = r
	tmp, err := oc.bucket.CreateObject(ctx, req)
	if err != nil {
		err = fmt.Errorf("CreateObject: %w", err)
		return
	}

	// Attempt to delete the temporary object when we're done.
	defer func() {
		deleteErr := oc.bucket.DeleteObject(
			ctx,
			&gcs.DeleteObjectRequest{
				Name:       tmp.Name,
				Generation: 0, // Delete the latest generation of temporary object.
			})

		if err == nil && deleteErr != nil {
			err = fmt.Errorf("DeleteObject: %w", deleteErr)
		}
	}()

	MetadataMap := make(map[string]string)

	/* Copy Metadata fields from src object to new object generated by compose. */
	for key, value := range srcObject.Metadata {
		MetadataMap[key] = value
	}

	if mtime != nil {
		MetadataMap[gcs.MtimeMetadataKey] = mtime.UTC().Format(time.RFC3339Nano)
	}

	// Compose the old contents plus the new over the old.
	o, err = oc.bucket.ComposeObjects(
		ctx,
		&gcs.ComposeObjectsRequest{
			DstName:                       srcObject.Name,
			DstGenerationPrecondition:     &srcObject.Generation,
			DstMetaGenerationPrecondition: &srcObject.MetaGeneration,
			Sources: []gcs.ComposeSource{
				gcs.ComposeSource{
					Name:       srcObject.Name,
					Generation: srcObject.Generation,
				},

				gcs.ComposeSource{
					Name:       tmp.Name,
					Generation: tmp.Generation,
				},
			},
			Metadata:           MetadataMap,
			CacheControl:       srcObject.CacheControl,
			ContentDisposition: srcObject.ContentDisposition,
			ContentEncoding:    srcObject.ContentEncoding,
			ContentType:        srcObject.ContentType,
			CustomTime:         srcObject.CustomTime,
			EventBasedHold:     srcObject.EventBasedHold,
			StorageClass:       srcObject.StorageClass,
		})
	if err != nil {
		// A not found error means that either the source object was clobbered or the
		// temporary object was. The latter is unlikely, so we signal a precondition
		// error.
		var notFoundErr *gcs.NotFoundError
		if errors.As(err, &notFoundErr) {
			err = &gcs.PreconditionError{
				Err: err,
			}
		}

		err = fmt.Errorf("ComposeObjects: %w", err)
		return
	}

	return
}