1package cmd23import (4 "fmt"56 "github.com/charmbracelet/soft-serve/git"7 "github.com/charmbracelet/soft-serve/pkg/backend"8 "github.com/charmbracelet/soft-serve/pkg/proto"9 "github.com/charmbracelet/soft-serve/pkg/ui/common"10 "github.com/dustin/go-humanize"11 "github.com/spf13/cobra"12)1314// treeCommand returns a command that list file or directory at path.15func treeCommand() *cobra.Command {16 cmd := &cobra.Command{17 Use: "tree REPOSITORY [REFERENCE] [PATH]",18 Short: "Print repository tree at path",19 Args: cobra.RangeArgs(1, 3),20 PersistentPreRunE: checkIfReadable,21 RunE: func(cmd *cobra.Command, args []string) error {22 ctx := cmd.Context()23 be := backend.FromContext(ctx)24 rn := args[0]25 path := ""26 ref := ""27 switch len(args) {28 case 2:29 path = args[1]30 case 3:31 ref = args[1]32 path = args[2]33 }34 rr, err := be.Repository(ctx, rn)35 if err != nil {36 return err37 }3839 r, err := rr.Open()40 if err != nil {41 return err42 }4344 if ref == "" {45 head, err := r.HEAD()46 if err != nil {47 if bs, err := r.Branches(); err != nil && len(bs) == 0 {48 return fmt.Errorf("repository is empty")49 }50 return err51 }5253 ref = head.ID54 }5556 tree, err := r.LsTree(ref)57 if err != nil {58 return err59 }6061 ents := git.Entries{}62 if path != "" && path != "/" {63 te, err := tree.TreeEntry(path)64 if err == git.ErrRevisionNotExist {65 return proto.ErrFileNotFound66 }67 if err != nil {68 return err69 }70 if te.Type() == "tree" {71 tree, err = tree.SubTree(path)72 if err != nil {73 return err74 }75 ents, err = tree.Entries()76 if err != nil {77 return err78 }79 } else {80 ents = append(ents, te)81 }82 } else {83 ents, err = tree.Entries()84 if err != nil {85 return err86 }87 }88 ents.Sort()89 for _, ent := range ents {90 size := ent.Size()91 ssize := ""92 if size == 0 {93 ssize = "-"94 } else {95 ssize = humanize.Bytes(uint64(size)) //nolint:gosec96 }97 cmd.Printf("%s\t%s\t %s\n", ent.Mode(), ssize, common.UnquoteFilename(ent.Name()))98 }99 return nil100 },101 }102 return cmd103}