You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: compose_stack.go
    path of file: ./repos/portainer/api/exec
    
    the code of the file until where you have to start completion: package exec

import (
	"context"
	"fmt"
	"io"
	"os"
	"path"
	"strings"

	portainer "github.com/portainer/portainer/api"
	"github.com/portainer/portainer/api/http/proxy"
	"github.com/portainer/portainer/api/http/proxy/factory"
	"github.com/portainer/portainer/api/stacks/stackutils"
	"github.com/portainer/portainer/pkg/libstack"

	"github.com/pkg/errors"
)

// ComposeStackManager is a wrapper for docker-compose binary
type ComposeStackManager struct {
	deployer     libstack.Deployer
	proxyManager *proxy.Manager
}

// NewComposeStackManager returns a docker-compose wrapper if corresponding binary present, otherwise nil
func NewComposeStackManager(deployer libstack.Deployer, proxyManager *proxy.Manager) (*ComposeS
    
func (manager *ComposeStackManager) Up(ctx context.Context, stack *portainer.Stack, endpoint *portainer.Endpoint, forceRecreate bool) error {
	url, proxy, err := manager.fetchEndpointProxy(endpoint)
	if err != nil {
		return errors.Wrap(err, "failed to fetch environment proxy")
	}

	if proxy != nil {
		defer proxy.Close()
	}

	envFilePath, err := createEnvFile(stack)
	if err != nil {
		return errors.Wrap(err, "failed to create env file")
	}

	filePaths := stackutils.GetStackFilePaths(stack, true)
	err = manager.deployer.Deploy(ctx, filePaths, libstack.DeployOptions{
		Options: libstack.Options{
			WorkingDir:  stack.ProjectPath,
			EnvFilePath: envFilePath,
			Host:        url,
			ProjectName: stack.Name,
		},
		ForceRecreate: forceRecreate,
	})
	return errors.Wrap(err, "failed to deploy a stack")
}