1package cmd
2
3import (
4 "fmt"
5 "path/filepath"
6 "strings"
7
8 "github.com/charmbracelet/soft-serve/git"
9 gm "github.com/charmbracelet/soft-serve/server/git"
10 "github.com/spf13/cobra"
11)
12
13// ListCommand returns a command that list file or directory at path.
14func ListCommand() *cobra.Command {
15 lsCmd := &cobra.Command{
16 Use: "ls PATH",
17 Aliases: []string{"list"},
18 Short: "List file or directory at path.",
19 Args: cobra.RangeArgs(0, 1),
20 RunE: func(cmd *cobra.Command, args []string) error {
21 ac, s := fromContext(cmd)
22 rn := ""
23 path := ""
24 ps := []string{}
25 if len(args) > 0 {
26 path = filepath.Clean(args[0])
27 ps = strings.Split(path, "/")
28 rn = ps[0]
29 auth := ac.AuthRepo(rn, s.PublicKey())
30 if auth < gm.ReadOnlyAccess {
31 return ErrUnauthorized
32 }
33 }
34 if path == "" || path == "." || path == "/" {
35 for _, r := range ac.Source.AllRepos() {
36 if ac.AuthRepo(r.Repo(), s.PublicKey()) >= gm.ReadOnlyAccess {
37 fmt.Fprintln(s, r.Repo())
38 }
39 }
40 return nil
41 }
42 r, err := ac.Source.GetRepo(rn)
43 if err != nil {
44 return err
45 }
46 head, err := r.HEAD()
47 if err != nil {
48 return err
49 }
50 tree, err := r.Tree(head, "")
51 if err != nil {
52 return err
53 }
54 subpath := strings.Join(ps[1:], "/")
55 ents := git.Entries{}
56 te, err := tree.TreeEntry(subpath)
57 if err == git.ErrRevisionNotExist {
58 return ErrFileNotFound
59 }
60 if err != nil {
61 return err
62 }
63 if te.Type() == "tree" {
64 tree, err = tree.SubTree(subpath)
65 if err != nil {
66 return err
67 }
68 ents, err = tree.Entries()
69 if err != nil {
70 return err
71 }
72 } else {
73 ents = append(ents, te)
74 }
75 ents.Sort()
76 for _, ent := range ents {
77 fmt.Fprintf(s, "%s\t%d\t %s\n", ent.Mode(), ent.Size(), ent.Name())
78 }
79 return nil
80 },
81 }
82 return lsCmd
83}