1package cmd
2
3import (
4 "fmt"
5
6 "github.com/charmbracelet/soft-serve/git"
7 "github.com/charmbracelet/soft-serve/server/errors"
8 "github.com/dustin/go-humanize"
9 "github.com/spf13/cobra"
10)
11
12// treeCommand returns a command that list file or directory at path.
13func treeCommand() *cobra.Command {
14 cmd := &cobra.Command{
15 Use: "tree REPOSITORY [REFERENCE] [PATH]",
16 Short: "Print repository tree at path",
17 Args: cobra.RangeArgs(1, 3),
18 PersistentPreRunE: checkIfReadable,
19 RunE: func(cmd *cobra.Command, args []string) error {
20 cfg, _ := fromContext(cmd)
21 rn := args[0]
22 path := ""
23 ref := ""
24 switch len(args) {
25 case 2:
26 path = args[1]
27 case 3:
28 ref = args[1]
29 path = args[2]
30 }
31 rr, err := cfg.Backend.Repository(rn)
32 if err != nil {
33 return err
34 }
35
36 r, err := rr.Open()
37 if err != nil {
38 return err
39 }
40
41 if ref == "" {
42 head, err := r.HEAD()
43 if err != nil {
44 if bs, err := r.Branches(); err != nil && len(bs) == 0 {
45 return fmt.Errorf("repository is empty")
46 }
47 return err
48 }
49
50 ref = head.Hash.String()
51 }
52
53 tree, err := r.LsTree(ref)
54 if err != nil {
55 return err
56 }
57
58 ents := git.Entries{}
59 if path != "" && path != "/" {
60 te, err := tree.TreeEntry(path)
61 if err == git.ErrRevisionNotExist {
62 return errors.ErrFileNotFound
63 }
64 if err != nil {
65 return err
66 }
67 if te.Type() == "tree" {
68 tree, err = tree.SubTree(path)
69 if err != nil {
70 return err
71 }
72 ents, err = tree.Entries()
73 if err != nil {
74 return err
75 }
76 } else {
77 ents = append(ents, te)
78 }
79 } else {
80 ents, err = tree.Entries()
81 if err != nil {
82 return err
83 }
84 }
85 ents.Sort()
86 for _, ent := range ents {
87 size := ent.Size()
88 ssize := ""
89 if size == 0 {
90 ssize = "-"
91 } else {
92 ssize = humanize.Bytes(uint64(size))
93 }
94 cmd.Printf("%s\t%s\t %s\n", ent.Mode(), ssize, ent.Name())
95 }
96 return nil
97 },
98 }
99 return cmd
100}