- commit
- 5a19fa8
- parent
- 9e07ba1
- author
- Eric Bower
- date
- 2024-04-28 12:13:09 -0400 EDT
progress Wow does this actually work? I wonder how we can do this.
A
cfg.go
+11,
-0
1@@ -0,0 +1,11 @@
2+package git
3+
4+type GitCfg struct {
5+ DataPath string
6+}
7+
8+func NewGitCfg() *GitCfg {
9+ return &GitCfg{
10+ DataPath: "ssh_data",
11+ }
12+}
A
db.go
+14,
-0
1@@ -0,0 +1,14 @@
2+package git
3+
4+import "time"
5+
6+type Patch struct {
7+ ID string
8+ Owner string
9+ Contents string
10+ CreatedAt *time.Time
11+}
12+
13+type GitDB interface {
14+ InsertPatch(patch *Patch) (*Patch, error)
15+}
M
go.mod
+2,
-0
1@@ -37,6 +37,7 @@ require (
2 github.com/google/uuid v1.4.0 // indirect
3 github.com/jmoiron/sqlx v1.3.5 // indirect
4 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
5+ github.com/kr/fs v0.1.0 // indirect
6 github.com/lib/pq v1.10.9 // indirect
7 github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
8 github.com/mattn/go-isatty v0.0.20 // indirect
9@@ -48,6 +49,7 @@ require (
10 github.com/muesli/cancelreader v0.2.2 // indirect
11 github.com/muesli/reflow v0.3.0 // indirect
12 github.com/muesli/termenv v0.15.2 // indirect
13+ github.com/pkg/sftp v1.13.6 // indirect
14 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
15 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
16 github.com/rivo/uniseg v0.4.7 // indirect
M
go.sum
+28,
-0
1@@ -68,6 +68,8 @@ github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
2 github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
3 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
4 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
5+github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
6+github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
7 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
8 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
9 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
10@@ -108,6 +110,8 @@ github.com/picosh/send v0.0.0-20240217194807-77b972121e63 h1:VSSbAejFzj2KBThfVnM
11 github.com/picosh/send v0.0.0-20240217194807-77b972121e63/go.mod h1:1JCq0NVOdTDenQ0/Kd8e4rP80lu06UHJJ+6dQxhcpew=
12 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
13 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
14+github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
15+github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
16 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
17 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
18 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
19@@ -133,31 +137,55 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
20 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
21 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
22 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
23+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
24 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
25 golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
26+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
27+golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
28 golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
29 golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
30 golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w=
31 golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
32+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
33 golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
34 golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
35 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
36+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
37+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
38+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
39+golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
40+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
41+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
42 golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
43 golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
44 golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
45 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
46 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
47+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
48+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
49+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
50+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
51 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
52 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
53 golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
54 golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
55+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
56+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
57+golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
58 golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
59 golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
60 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
61+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
62+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
63+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
64 golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
65 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
66+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
67+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
68+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
69 golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
70 golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
71+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
72 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
73 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
74 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
A
mdw.go
+70,
-0
1@@ -0,0 +1,70 @@
2+package git
3+
4+import (
5+ "fmt"
6+ "path/filepath"
7+
8+ "github.com/charmbracelet/soft-serve/pkg/git"
9+ "github.com/charmbracelet/soft-serve/pkg/utils"
10+ "github.com/charmbracelet/ssh"
11+ "github.com/charmbracelet/wish"
12+)
13+
14+func gitServiceCommands(sesh ssh.Session, cfg *GitCfg, cmd, repo string) error {
15+ name := utils.SanitizeRepo(repo)
16+ // git bare repositories should end in ".git"
17+ // https://git-scm.com/docs/gitrepository-layout
18+ repoDir := name + ".git"
19+ reposDir := filepath.Join(cfg.DataPath, "repos")
20+ err := git.EnsureWithin(reposDir, repoDir)
21+ if err != nil {
22+ return err
23+ }
24+ repoPath := filepath.Join(reposDir, repoDir)
25+ serviceCmd := git.ServiceCommand{
26+ Stdin: sesh,
27+ Stdout: sesh,
28+ Stderr: sesh.Stderr(),
29+ Dir: repoPath,
30+ Env: sesh.Environ(),
31+ }
32+
33+ if cmd == "git-receive-pack" {
34+ err := git.ReceivePack(sesh.Context(), serviceCmd)
35+ if err != nil {
36+ return err
37+ }
38+ } else if cmd == "git-upload-pack" {
39+ err := git.UploadPack(sesh.Context(), serviceCmd)
40+ if err != nil {
41+ return err
42+ }
43+ }
44+
45+ return nil
46+}
47+
48+func GitServerMiddleware(cfg *GitCfg) wish.Middleware {
49+ return func(next ssh.Handler) ssh.Handler {
50+ return func(sesh ssh.Session) {
51+ args := sesh.Command()
52+ cmd := args[0]
53+ fmt.Println(cmd)
54+
55+ if cmd == "git-receive-pack" || cmd == "git-upload-pack" {
56+ repoName := args[1]
57+ err := gitServiceCommands(sesh, cfg, cmd, repoName)
58+ if err != nil {
59+ wish.Fatal(sesh, err.Error())
60+ return
61+ }
62+ } else if cmd == "help" {
63+ wish.Println(sesh, "commands: [help, git-receive-pack, git-upload-pack]")
64+ } else {
65+ fmt.Println("made it here")
66+ next(sesh)
67+ return
68+ }
69+ }
70+ }
71+}
+7,
-1
1@@ -24,6 +24,7 @@ func NewUploadHandler(cfg *GitCfg, logger *slog.Logger) *UploadHandler {
2 }
3
4 func (h *UploadHandler) Read(s ssh.Session, entry *utils.FileEntry) (os.FileInfo, utils.ReaderAtCloser, error) {
5+ fmt.Println("read")
6 cleanFilename := filepath.Base(entry.Filepath)
7
8 if cleanFilename == "" || cleanFilename == "." {
9@@ -34,6 +35,7 @@ func (h *UploadHandler) Read(s ssh.Session, entry *utils.FileEntry) (os.FileInfo
10 }
11
12 func (h *UploadHandler) List(s ssh.Session, fpath string, isDir bool, recursive bool) ([]os.FileInfo, error) {
13+ fmt.Println("list")
14 var fileList []os.FileInfo
15 cleanFilename := filepath.Base(fpath)
16
17@@ -58,16 +60,20 @@ func (h *UploadHandler) GetLogger() *slog.Logger {
18 }
19
20 func (h *UploadHandler) Validate(s ssh.Session) error {
21+ fmt.Println("validate")
22 return nil
23 }
24
25 func (h *UploadHandler) Write(s ssh.Session, entry *utils.FileEntry) (string, error) {
26+ fmt.Println("write")
27 logger := h.GetLogger()
28 user := s.User()
29
30 filename := filepath.Base(entry.Filepath)
31 logger = logger.With(
32 "user", user,
33+ "filepath", entry.Filepath,
34+ "size", entry.Size,
35 "filename", filename,
36 )
37
38@@ -76,7 +82,7 @@ func (h *UploadHandler) Write(s ssh.Session, entry *utils.FileEntry) (string, er
39 text = b
40 }
41
42- fmt.Println(text)
43+ fmt.Println(string(text))
44
45 return "", nil
46 }
M
ssh.go
+8,
-73
1@@ -10,86 +10,17 @@ import (
2 "syscall"
3 "time"
4
5- "github.com/charmbracelet/soft-serve/pkg/git"
6- "github.com/charmbracelet/soft-serve/pkg/utils"
7 "github.com/charmbracelet/ssh"
8 "github.com/charmbracelet/wish"
9- "github.com/picosh/send/list"
10 wishrsync "github.com/picosh/send/send/rsync"
11 "github.com/picosh/send/send/scp"
12+ "github.com/picosh/send/send/sftp"
13 )
14
15 func authHandler(ctx ssh.Context, key ssh.PublicKey) bool {
16 return true
17 }
18
19-func gitServiceCommands(sesh ssh.Session, cfg *GitCfg, cmd, repo string) error {
20- name := utils.SanitizeRepo(repo)
21- // git bare repositories should end in ".git"
22- // https://git-scm.com/docs/gitrepository-layout
23- repoDir := name + ".git"
24- reposDir := filepath.Join(cfg.DataPath, "repos")
25- err := git.EnsureWithin(reposDir, repoDir)
26- if err != nil {
27- return err
28- }
29- repoPath := filepath.Join(reposDir, repoDir)
30- serviceCmd := git.ServiceCommand{
31- Stdin: sesh,
32- Stdout: sesh,
33- Stderr: sesh.Stderr(),
34- Dir: repoPath,
35- Env: sesh.Environ(),
36- }
37-
38- if cmd == "git-receive-pack" {
39- err := git.ReceivePack(sesh.Context(), serviceCmd)
40- if err != nil {
41- return err
42- }
43- } else if cmd == "git-upload-pack" {
44- err := git.UploadPack(sesh.Context(), serviceCmd)
45- if err != nil {
46- return err
47- }
48- }
49-
50- return nil
51-}
52-
53-func GitServerMiddleware(cfg *GitCfg) wish.Middleware {
54- return func(next ssh.Handler) ssh.Handler {
55- return func(sesh ssh.Session) {
56- args := sesh.Command()
57- cmd := args[0]
58-
59- if cmd == "git-receive-pack" || cmd == "git-upload-pack" {
60- repoName := args[1]
61- err := gitServiceCommands(sesh, cfg, cmd, repoName)
62- if err != nil {
63- wish.Fatal(sesh, err.Error())
64- return
65- }
66- } else if cmd == "help" {
67- wish.Println(sesh, "commands: [help, git-receive-pack, git-upload-pack]")
68- } else {
69- next(sesh)
70- return
71- }
72- }
73- }
74-}
75-
76-type GitCfg struct {
77- DataPath string
78-}
79-
80-func NewGitCfg() *GitCfg {
81- return &GitCfg{
82- DataPath: "ssh_data",
83- }
84-}
85-
86 func GitSshServer() {
87 host := os.Getenv("SSH_HOST")
88 if host == "" {
89@@ -105,11 +36,15 @@ func GitSshServer() {
90 handler := NewUploadHandler(cfg, logger)
91
92 s, err := wish.NewServer(
93- wish.WithAddress(fmt.Sprintf("%s:%s", host, port)),
94- wish.WithHostKeyPath(filepath.Join(cfg.DataPath, "term_info_ed25519")),
95+ wish.WithAddress(
96+ fmt.Sprintf("%s:%s", host, port),
97+ ),
98+ wish.WithHostKeyPath(
99+ filepath.Join(cfg.DataPath, "term_info_ed25519"),
100+ ),
101 wish.WithPublicKeyAuth(authHandler),
102+ sftp.SSHOption(handler),
103 wish.WithMiddleware(
104- list.Middleware(handler),
105 scp.Middleware(handler),
106 wishrsync.Middleware(handler),
107 GitServerMiddleware(cfg),