repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

commit
92b854a
parent
17217e6
author
Antonio Mika
date
2025-03-12 16:30:59 -0400 EDT
Remove charm
4 files changed,  +113, -142
M go.mod
M go.sum
M go.mod
+0, -8
 1@@ -20,15 +20,12 @@ replace github.com/picosh/pobj => ../pobj
 2 
 3 // replace git.sr.ht/~rockorager/vaxis => ../../vaxis
 4 
 5-// replace github.com/charmbracelet/wish => ../../wish
 6-
 7 require (
 8 	git.sr.ht/~delthas/senpai v0.3.1-0.20250311003540-18f699aaf9b0
 9 	git.sr.ht/~rockorager/vaxis v0.12.1-0.20250312161844-81636f76af83
10 	github.com/alecthomas/chroma/v2 v2.14.0
11 	github.com/antoniomika/syncmap v1.0.0
12 	github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
13-	github.com/charmbracelet/lipgloss v1.0.0
14 	github.com/containerd/console v1.0.4
15 	github.com/darkweak/souin v1.7.5
16 	github.com/darkweak/souin/plugins/souin/storages v1.7.5
17@@ -102,7 +99,6 @@ require (
18 	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.15 // indirect
19 	github.com/aws/aws-sdk-go-v2/service/sts v1.33.15 // indirect
20 	github.com/aws/smithy-go v1.22.3 // indirect
21-	github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
22 	github.com/aymerick/douceur v0.2.0 // indirect
23 	github.com/beorn7/perks v1.0.1 // indirect
24 	github.com/bits-and-blooms/bitset v1.5.0 // indirect
25@@ -114,8 +110,6 @@ require (
26 	github.com/caddyserver/zerossl v0.1.3 // indirect
27 	github.com/cespare/xxhash v1.1.0 // indirect
28 	github.com/cespare/xxhash/v2 v2.3.0 // indirect
29-	github.com/charmbracelet/x/ansi v0.8.0 // indirect
30-	github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b // indirect
31 	github.com/chzyer/readline v1.5.1 // indirect
32 	github.com/coreos/go-semver v0.3.1 // indirect
33 	github.com/coreos/go-systemd/v22 v22.5.0 // indirect
34@@ -203,7 +197,6 @@ require (
35 	github.com/kr/pretty v0.3.1 // indirect
36 	github.com/kr/text v0.2.0 // indirect
37 	github.com/libdns/libdns v0.2.2 // indirect
38-	github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
39 	github.com/lufia/plan9stats v0.0.0-20250224150550-a661cff19cfb // indirect
40 	github.com/manifoldco/promptui v0.9.0 // indirect
41 	github.com/maruel/natural v1.1.1 // indirect
42@@ -227,7 +220,6 @@ require (
43 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
44 	github.com/modern-go/reflect2 v1.0.2 // indirect
45 	github.com/mschoch/smat v0.2.0 // indirect
46-	github.com/muesli/termenv v0.16.0 // indirect
47 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
48 	github.com/nats-io/nats.go v1.36.0 // indirect
49 	github.com/nats-io/nkeys v0.4.7 // indirect
M go.sum
+0, -14
 1@@ -117,10 +117,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.33.15 h1:ht1jVmeeo2anR7zDiYJLSnRYnO/
 2 github.com/aws/aws-sdk-go-v2/service/sts v1.33.15/go.mod h1:xWZ5cOiFe3czngChE4LhCBqUxNwgfwndEF7XlYP/yD8=
 3 github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
 4 github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
 5-github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
 6-github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
 7-github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
 8-github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
 9 github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
10 github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
11 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
12@@ -150,12 +146,6 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
13 github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
14 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
15 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
16-github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
17-github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
18-github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
19-github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
20-github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q=
21-github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
22 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
23 github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
24 github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
25@@ -550,8 +540,6 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
26 github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
27 github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
28 github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
29-github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
30-github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
31 github.com/lufia/plan9stats v0.0.0-20250224150550-a661cff19cfb h1:YU0XAr3+rMpM8fP80KEesn32Qa9qkbquokvuwzWyYuA=
32 github.com/lufia/plan9stats v0.0.0-20250224150550-a661cff19cfb/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
33 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
34@@ -630,8 +618,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
35 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
36 github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
37 github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
38-github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
39-github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
40 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
41 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
42 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
M pgs/cli.go
+93, -113
  1@@ -4,13 +4,13 @@ import (
  2 	"context"
  3 	"errors"
  4 	"fmt"
  5+	"io"
  6 	"log/slog"
  7 	"path/filepath"
  8 	"strings"
  9+	"text/tabwriter"
 10 	"time"
 11 
 12-	"github.com/charmbracelet/lipgloss"
 13-	"github.com/charmbracelet/lipgloss/table"
 14 	"github.com/picosh/pico/db"
 15 	pgsdb "github.com/picosh/pico/pgs/db"
 16 	"github.com/picosh/pico/shared"
 17@@ -18,106 +18,31 @@ import (
 18 	"github.com/picosh/utils"
 19 )
 20 
 21-func projectTable(projects []*db.Project, width int) *table.Table {
 22-	headers := []string{
 23-		"Name",
 24-		"Last Updated",
 25-		"Links To",
 26-		"ACL Type",
 27-		"ACL",
 28-		"Blocked",
 29-	}
 30-	data := [][]string{}
 31+func NewTabWriter(out io.Writer) *tabwriter.Writer {
 32+	return tabwriter.NewWriter(out, 0, 0, 1, ' ', tabwriter.TabIndent)
 33+}
 34+
 35+func projectTable(sesh io.Writer, projects []*db.Project) {
 36+	writer := NewTabWriter(sesh)
 37+	fmt.Fprintln(writer, "Name\tLast Updated\tLinks To\tACL Type\tACL\tBlocked")
 38+
 39 	for _, project := range projects {
 40-		row := []string{
 41-			project.Name,
 42-			project.UpdatedAt.Format("2006-01-02 15:04:05"),
 43-		}
 44 		links := ""
 45 		if project.ProjectDir != project.Name {
 46 			links = project.ProjectDir
 47 		}
 48-		row = append(row, links)
 49-		row = append(row,
 50+		fmt.Fprintf(
 51+			writer,
 52+			"%s\t%s\t%s\t%s\t%s\t%s\n",
 53+			project.Name,
 54+			project.UpdatedAt.Format("2006-01-02 15:04:05"),
 55+			links,
 56 			project.Acl.Type,
 57 			strings.Join(project.Acl.Data, " "),
 58+			project.Blocked,
 59 		)
 60-		row = append(row, project.Blocked)
 61-		data = append(data, row)
 62-	}
 63-
 64-	t := table.New().
 65-		Width(width).
 66-		Headers(headers...).
 67-		Rows(data...)
 68-	return t
 69-}
 70-
 71-func getHelpText(width int) string {
 72-	helpStr := "Commands: [help, stats, ls, fzf, rm, link, unlink, prune, retain, depends, acl, cache]\n"
 73-	helpStr += "NOTICE:" + " *must* append with `--write` for the changes to persist.\n"
 74-
 75-	projectName := "projA"
 76-	headers := []string{"Cmd", "Description"}
 77-	data := [][]string{
 78-		{
 79-			"help",
 80-			"prints this screen",
 81-		},
 82-		{
 83-			"stats",
 84-			"usage statistics",
 85-		},
 86-		{
 87-			"ls",
 88-			"lists projects",
 89-		},
 90-		{
 91-			fmt.Sprintf("fzf %s", projectName),
 92-			fmt.Sprintf("lists urls of all assets in %s", projectName),
 93-		},
 94-		{
 95-			fmt.Sprintf("rm %s", projectName),
 96-			fmt.Sprintf("delete %s", projectName),
 97-		},
 98-		{
 99-			fmt.Sprintf("link %s --to projB", projectName),
100-			fmt.Sprintf("symbolic link `%s` to `projB`", projectName),
101-		},
102-		{
103-			fmt.Sprintf("unlink %s", projectName),
104-			fmt.Sprintf("removes symbolic link for `%s`", projectName),
105-		},
106-		{
107-			fmt.Sprintf("prune %s", projectName),
108-			fmt.Sprintf("removes projects that match prefix `%s`", projectName),
109-		},
110-		{
111-			fmt.Sprintf("retain %s", projectName),
112-			"alias to `prune` but keeps last N projects",
113-		},
114-		{
115-			fmt.Sprintf("depends %s", projectName),
116-			fmt.Sprintf("lists all projects linked to `%s`", projectName),
117-		},
118-		{
119-			fmt.Sprintf("acl %s", projectName),
120-			fmt.Sprintf("access control for `%s`", projectName),
121-		},
122-		{
123-			fmt.Sprintf("cache %s", projectName),
124-			fmt.Sprintf("clear http cache for `%s`", projectName),
125-		},
126 	}
127-
128-	t := table.New().
129-		Width(width).
130-		Border(lipgloss.RoundedBorder()).
131-		Headers(headers...).
132-		Rows(data...)
133-
134-	helpStr += t.String()
135-	return helpStr
136+	writer.Flush()
137 }
138 
139 type Cmd struct {
140@@ -201,7 +126,68 @@ func (c *Cmd) RmProjectAssets(projectName string) error {
141 }
142 
143 func (c *Cmd) help() {
144-	c.output(getHelpText(c.Width))
145+	helpStr := "Commands: [help, stats, ls, fzf, rm, link, unlink, prune, retain, depends, acl, cache]\n"
146+	helpStr += "NOTICE:" + " *must* append with `--write` for the changes to persist.\n"
147+	c.output(helpStr)
148+	projectName := "projA"
149+
150+	data := [][]string{
151+		{
152+			"help",
153+			"prints this screen",
154+		},
155+		{
156+			"stats",
157+			"usage statistics",
158+		},
159+		{
160+			"ls",
161+			"lists projects",
162+		},
163+		{
164+			fmt.Sprintf("fzf %s", projectName),
165+			fmt.Sprintf("lists urls of all assets in %s", projectName),
166+		},
167+		{
168+			fmt.Sprintf("rm %s", projectName),
169+			fmt.Sprintf("delete %s", projectName),
170+		},
171+		{
172+			fmt.Sprintf("link %s --to projB", projectName),
173+			fmt.Sprintf("symbolic link `%s` to `projB`", projectName),
174+		},
175+		{
176+			fmt.Sprintf("unlink %s", projectName),
177+			fmt.Sprintf("removes symbolic link for `%s`", projectName),
178+		},
179+		{
180+			fmt.Sprintf("prune %s", projectName),
181+			fmt.Sprintf("removes projects that match prefix `%s`", projectName),
182+		},
183+		{
184+			fmt.Sprintf("retain %s", projectName),
185+			"alias to `prune` but keeps last N projects",
186+		},
187+		{
188+			fmt.Sprintf("depends %s", projectName),
189+			fmt.Sprintf("lists all projects linked to `%s`", projectName),
190+		},
191+		{
192+			fmt.Sprintf("acl %s", projectName),
193+			fmt.Sprintf("access control for `%s`", projectName),
194+		},
195+		{
196+			fmt.Sprintf("cache %s", projectName),
197+			fmt.Sprintf("clear http cache for `%s`", projectName),
198+		},
199+	}
200+
201+	writer := NewTabWriter(c.Session)
202+	fmt.Fprintln(writer, "Cmd\tDescription")
203+	for _, dat := range data {
204+		fmt.Fprintf(writer, "%s\t%s\n", dat[0], dat[1])
205+	}
206+	writer.Flush()
207 }
208 
209 func (c *Cmd) stats(cfgMaxSize uint64) error {
210@@ -229,20 +215,17 @@ func (c *Cmd) stats(cfgMaxSize uint64) error {
211 		return err
212 	}
213 
214-	headers := []string{"Used (GB)", "Quota (GB)", "Used (%)", "Projects (#)"}
215-	data := []string{
216-		fmt.Sprintf("%.4f", utils.BytesToGB(int(totalFileSize))),
217-		fmt.Sprintf("%.4f", utils.BytesToGB(int(storageMax))),
218-		fmt.Sprintf("%.4f", (float32(totalFileSize)/float32(storageMax))*100),
219-		fmt.Sprintf("%d", len(projects)),
220-	}
221-
222-	t := table.New().
223-		Width(c.Width).
224-		Border(lipgloss.RoundedBorder()).
225-		Headers(headers...).
226-		Rows(data)
227-	c.output(t.String())
228+	writer := NewTabWriter(c.Session)
229+	fmt.Fprintln(writer, "Used (GB)\tQuota (GB)\tUsed (%)\tProjects (#)")
230+	fmt.Fprintf(
231+		writer,
232+		"%.4f\t%.4f\t%.4f\t%d\n",
233+		utils.BytesToGB(int(totalFileSize)),
234+		utils.BytesToGB(int(storageMax)),
235+		(float32(totalFileSize)/float32(storageMax))*100,
236+		len(projects),
237+	)
238+	writer.Flush()
239 
240 	return nil
241 }
242@@ -257,8 +240,7 @@ func (c *Cmd) ls() error {
243 		c.output("no projects found")
244 	}
245 
246-	t := projectTable(projects, c.Width)
247-	c.output(t.String())
248+	projectTable(c.Session, projects)
249 
250 	return nil
251 }
252@@ -374,9 +356,7 @@ func (c *Cmd) depends(projectName string) error {
253 		return nil
254 	}
255 
256-	t := projectTable(projects, c.Width)
257-	c.output(t.String())
258-
259+	projectTable(c.Session, projects)
260 	return nil
261 }
262 
M pssh/server.go
+20, -7
 1@@ -118,7 +118,8 @@ func (s *SSHServerConnSession) Close() error {
 2 }
 3 
 4 func (s *SSHServerConnSession) Exit(code int) error {
 5-	_, err := s.Channel.SendRequest("exit-status", false, ssh.Marshal(struct{ C int }{code}))
 6+	status := struct{ Status uint32 }{uint32(code)}
 7+	_, err := s.Channel.SendRequest("exit-status", false, ssh.Marshal(&status))
 8 	return err
 9 }
10 
11@@ -265,6 +266,10 @@ func (s *SSHServer) ListenAndServe() error {
12 		}()
13 	}
14 
15+	if errors.Is(retErr, net.ErrClosed) {
16+		return nil
17+	}
18+
19 	return retErr
20 }
21 
22@@ -358,13 +363,17 @@ func NewSSHServer(ctx context.Context, logger *slog.Logger, config *SSHServerCon
23 								SSHServerConn: sc,
24 							}
25 
26+							req.Reply(true, nil)
27+
28 							if err := h(sesh); err != nil {
29-								req.Reply(false, nil)
30-								sesh.Close()
31+								sc.Logger.Error("subsystem middleware", "err", err)
32+								sesh.Fatal(err)
33+								return
34 							}
35 
36-							req.Reply(true, nil)
37+							sesh.Exit(0)
38 							sesh.Close()
39+							return
40 						} else if req.Type == "exec" {
41 							if len(sc.SSHServer.Config.Middleware) == 0 {
42 								req.Reply(false, nil)
43@@ -382,13 +391,17 @@ func NewSSHServer(ctx context.Context, logger *slog.Logger, config *SSHServerCon
44 								h = m(h)
45 							}
46 
47+							req.Reply(true, nil)
48+
49 							if err := h(sesh); err != nil {
50-								req.Reply(false, nil)
51-								sesh.Close()
52+								sc.Logger.Error("exec middleware", "err", err)
53+								sesh.Fatal(err)
54+								return
55 							}
56 
57-							req.Reply(true, nil)
58+							sesh.Exit(0)
59 							sesh.Close()
60+							return
61 						}
62 					}()
63 				}