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: upload.go
    path of file: ./repos/glab/commands/release/upload
    
    the code of the file until where you have to start completion: package upload

import (
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/MakeNowJust/heredoc"
	"github.com/profclems/glab/commands/cmdutils"
	"github.com/profclems/glab/commands/release/releaseutils"
	"github.com/profclems/glab/commands/release/releaseutils/upload"
	"github.com/profclems/glab/internal/config"
	"github.com/profclems/glab/internal/glrepo"
	"github.com/profclems/glab/pkg/iostreams"
	"github.com/spf13/cobra"
	"github.com/xanzy/go-gitlab"
)

type UploadOpts struct {
	TagName          string
	AssetLinksAsJson string

	AssetLinks []*upload.ReleaseAsset
	AssetFiles []*upload.ReleaseFile

	IO         *iostreams.IOStreams
	HTTPClient func() (*gitlab.Client, error)
	BaseRepo   func() (glrepo.Interface, error)
	Config     func() (config.Config, error)
}

func NewCmdUpload(f *cmdutils.Factory, runE func(opts *UploadOpts) error) *cobra.Command {
	opts := &UploadOpts{
		IO:     f.IO,
		Config: f.Config,
	}

	cmd := &cobra.Command{
		Use:   "upload <tag> [<files>...]",
		Short: "Upload release asset files or links to GitLab Release",
		Long: heredoc.Doc(`Upload release assets to GitLab Release

				
    
func deleteRun(opts *UploadOpts) error {
	start := time.Now()

	client, err := opts.HTTPClient()
	if err != nil {
		return err
	}

	repo, err := opts.BaseRepo()
	if err != nil {
		return err
	}
	color := opts.IO.Color()
	var resp *gitlab.Response

	opts.IO.Logf("%s validating tag %s=%s %s=%s\n",
		color.ProgressIcon(),
		color.Blue("repo"), repo.FullName(),
		color.Blue("tag"), opts.TagName)

	release, resp, err := client.Releases.GetRelease(repo.FullName(), opts.TagName)
	if err != nil {
		if resp != nil && (resp.StatusCode == 404 || resp.StatusCode == 403) {
			return cmdutils.WrapError(err, "release does not exist. Create a new release with `glab release create "+opts.TagName+"`")
		}
		return cmdutils.WrapError(err, "failed to fetch release")
	}

	opts.IO.Logf("%s uploading release assets %s=%s %s=%s\n",
		color.ProgressIcon(),
		color.Blue("repo"), repo.FullName(),
		color.Blue("tag"), opts.TagName)
	// upload files and create asset link
	if opts.AssetFiles != nil || opts.AssetLinks != nil {
		uploadCtx := upload.Context{
			IO:          opts.IO,
			Client:      client,
			AssetsLinks: opts.AssetLinks,
			AssetFiles:  opts.AssetFiles,
		}
		if err = uploadCtx.UploadFiles(repo.FullName(), release.TagName); err != nil {
			return cmdutils.WrapError(err, "upload failed")
		}

		// create asset link for assets provided as json
		if err = uploadCtx.CreateReleaseAssetLinks(repo.FullName(), release.TagName); err != nil {
			return cmdutils.WrapError(err, "failed to create release link")
		}
	}

	opts.IO.Logf(color.Bold("%s upload succeeded after %0.2fs\n"), color.GreenCheck(), time.Since(start).Seconds())
	return nil
}