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: backup.go
    path of file: ./repos/lotus/cli
    
    the code of the file until where you have to start completion: package cli

import (
	"context"
	"fmt"
	"os"

	logging "github.com/ipfs/go-log/v2"
	"github.com/mitchellh/go-homedir"
	"github.com/urfave/cli/v2"
	"golang.org/x/xerrors"

	"github.com/filecoin-project/go-jsonrpc"

	"github.com/filecoin-project/lotus/lib/backupds"
	"github.com/filecoin-project/lotus/node/repo"
)

type BackupAPI interface {
	CreateBackup(ctx context.Context, fpath string) error
}

type BackupApiFn func(ctx *cli.Context) (BackupAPI, jsonrpc.ClientCloser, error)

func BackupCmd(repoFlag string, rt repo.RepoType, getApi BackupApiFn) *cli.Command {
	var offlineBackup = func(cctx *cli.Context) error {
		logging.SetLogLevel("badger", "ERROR") // nolint:errcheck

		repoPath := cctx.String(repoFlag)
		r, err := repo.NewFS(repoPath)
		if err != nil {
			return err
		}

		ok, err := r.Exists()
		if err != nil {
			return err
		}
		if !ok {
			return xerrors.Errorf("repo at '%s' is not initialized", cctx.String(repoFlag))
		}

		lr, err := r.Lock
    
func BackupCmd(repoFlag string, rt repo.RepoType, getApi BackupApiFn) *cli.Command {
	var offlineBackup = func(cctx *cli.Context) error {
		logging.SetLogLevel("badger", "ERROR") // nolint:errcheck

		repoPath := cctx.String(repoFlag)
		r, err := repo.NewFS(repoPath)
		if err != nil {
			return err
		}

		ok, err := r.Exists()
		if err != nil {
			return err
		}
		if !ok {
			return xerrors.Errorf("repo at '%s' is not initialized", cctx.String(repoFlag))
		}

		lr, err := r.LockRO(rt)
		if err != nil {
			return xerrors.Errorf("locking repo: %w", err)
		}
		defer lr.Close() // nolint:errcheck

		mds, err := lr.Datastore(context.TODO(), "/metadata")
		if err != nil {
			return xerrors.Errorf("getting metadata datastore: %w", err)
		}

		bds, err := backupds.Wrap(mds, backupds.NoLogdir)
		if err != nil {
			return err
		}

		fpath, err := homedir.Expand(cctx.Args().First())
		if err != nil {
			return xerrors.Errorf("expanding file path: %w", err)
		}

		if _, err := os.Stat(fpath); !os.IsNotExist(err) {
			return xerrors.Errorf("backup file %s already exists. Overwriting it will corrupt the file, please specify another file name", fpath)
		}

		out, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			return xerrors.Errorf("opening backup file %s: %w", fpath, err)
		}

		if err := bds.Backup(cctx.Context, out); err != nil {
			if cerr := out.Close(); cerr != nil {
				log.Errorw("error closing backup file while handling backup error", "closeErr", cerr, "backupErr", err)
			}
			return xerrors.Errorf("backup error: %w", err)
		}

		if err := out.Close(); err != nil {
			return xerrors.Errorf("closing backup file: %w", err)
		}

		return nil
	}

	var onlineBackup = func(cctx *cli.Context) error {
		api, closer, err := getApi(cctx)
		if err != nil {
			return xerrors.Errorf("getting api: %w (if the node isn't running you can use the --offline flag)", err)
		}
		defer closer()

		backupPath := cctx.Args().First()
		if _, err := os.Stat(backupPath); !os.IsNotExist(err) {
			return xerrors.Errorf("backup file %s already exists. Overwriting it will corrupt the file, please specify another file name", backupPath)
		}

		err = api.CreateBackup(ReqContext(cctx), backupPath)
		if err != nil {
			return err
		}

		fmt.Println("Success")

		return nil
	}

	return &cli.Command{
		Name:  "backup",
		Usage: "Create node metadata backup",
		Description: `The backup command writes a copy of node metadata under the specified path

Online backups:
For security reasons, the daemon must be have LOTUS_BACKUP_BASE_PATH env var set
to a path where backup files are supposed to be saved, and the path specified in
this command must be within this base path`,
		Flags: []cli.Flag{
			&cli.BoolFlag{
				Name:  "offline",
				Usage: "create backup without the node running",
			},
		},
		ArgsUsage: "[backup file path]",
		Action: func(cctx *cli.Context) error {
			if cctx.NArg() != 1 {
				return IncorrectNumArgs(cctx)
			}

			if cctx.Bool("offline") {
				return offlineBackup(cctx)
			}

			return onlineBackup(cctx)
		},
	}
}