blob.go

  1package repo
  2
  3import (
  4	"fmt"
  5
  6	"github.com/charmbracelet/soft-serve/cmd"
  7	"github.com/charmbracelet/soft-serve/git"
  8	"github.com/charmbracelet/soft-serve/pkg/access"
  9	"github.com/charmbracelet/soft-serve/pkg/backend"
 10	"github.com/charmbracelet/soft-serve/pkg/proto"
 11	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 12	"github.com/charmbracelet/soft-serve/pkg/ui/styles"
 13	"github.com/spf13/cobra"
 14)
 15
 16// blobCommand returns a command that prints the contents of a file.
 17func blobCommand() *cobra.Command {
 18	var linenumber bool
 19	var color bool
 20	var raw bool
 21
 22	styles := styles.DefaultStyles()
 23	cmd := &cobra.Command{
 24		Use:     "blob REPOSITORY [REFERENCE] [PATH]",
 25		Aliases: []string{"cat", "show"},
 26		Short:   "Print out the contents of file at path",
 27		Args:    cobra.RangeArgs(1, 3),
 28		RunE: func(co *cobra.Command, args []string) error {
 29			ctx := co.Context()
 30			be := backend.FromContext(ctx)
 31			rn := args[0]
 32			ref := ""
 33			fp := ""
 34			switch len(args) {
 35			case 2:
 36				fp = args[1]
 37			case 3:
 38				ref = args[1]
 39				fp = args[2]
 40			}
 41
 42			repo, err := be.Repository(ctx, rn)
 43			if err != nil {
 44				return err
 45			}
 46
 47			if !cmd.CheckUserHasAccess(co, repo.Name(), access.ReadOnlyAccess) {
 48				return proto.ErrUnauthorized
 49			}
 50
 51			r, err := repo.Open()
 52			if err != nil {
 53				return err
 54			}
 55
 56			if ref == "" {
 57				head, err := r.HEAD()
 58				if err != nil {
 59					return err
 60				}
 61				ref = head.ID
 62			}
 63
 64			tree, err := r.LsTree(ref)
 65			if err != nil {
 66				return err
 67			}
 68
 69			te, err := tree.TreeEntry(fp)
 70			if err != nil {
 71				return err
 72			}
 73
 74			if te.Type() != "blob" {
 75				return git.ErrFileNotFound
 76			}
 77
 78			bts, err := te.Contents()
 79			if err != nil {
 80				return err
 81			}
 82
 83			c := string(bts)
 84			isBin, _ := te.File().IsBinary()
 85			if isBin {
 86				if raw {
 87					co.Println(c)
 88				} else {
 89					return fmt.Errorf("binary file: use --raw to print")
 90				}
 91			} else {
 92				if color {
 93					c, err = common.FormatHighlight(fp, c)
 94					if err != nil {
 95						return err
 96					}
 97				}
 98
 99				if linenumber {
100					c, _ = common.FormatLineNumber(styles, c, color)
101				}
102
103				co.Println(c)
104			}
105			return nil
106		},
107	}
108
109	cmd.Flags().BoolVarP(&raw, "raw", "r", false, "Print raw contents")
110	cmd.Flags().BoolVarP(&linenumber, "linenumber", "l", false, "Print line numbers")
111	cmd.Flags().BoolVarP(&color, "color", "c", false, "Colorize output")
112
113	return cmd
114}