2 files changed,
39 insertions(+),
15 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-01-21 01:49:14 +0200
Authored at:
2026-01-21 00:50:01 +0200
Change ID:
nnnnrqovvonmukovzpopkpqyvmzwkvtn
Parent:
a00560c
M
internal/git/gitservice/gitservice.go
路路路 29 29 return fmt.Errorf("start git-upload-pack: %w", err) 30 30 } 31 31 32 - if err := packLine(out, "# service=git-upload-pack\n"); err != nil { 32 + if err := PackLine(out, "# service=git-upload-pack\n"); err != nil { 33 33 return fmt.Errorf("write pack line: %w", err) 34 34 } 35 - if err := packFlush(out); err != nil { 35 + if err := PackFlush(out); err != nil { 36 36 return fmt.Errorf("flush pack: %w", err) 37 37 } 38 38 路路路 64 64 }) 65 65 } 66 66 67 -func ReceivePack(dir string, in io.Reader, out io.Writer) error { 67 +func ReceivePack(dir string, in io.Reader, out, stderr io.Writer) error { 68 68 return gitCmd("receive-pack", config{ 69 69 Dir: dir, 70 70 Stdin: in, 71 71 Stdout: out, 72 + Stderr: stderr, 72 73 }) 73 74 } 74 75 路路路 79 80 ExtraArgs []string 80 81 Stdin io.Reader 81 82 Stdout io.Writer 83 + Stderr io.Writer 82 84 } 83 85 84 86 func gitCmd(service string, c config) error { 路路路 115 117 if err != nil { 116 118 return err 117 119 } 118 - cmd.Stderr = cmd.Stdout 120 + if c.Stderr != nil { 121 + cmd.Stderr = c.Stderr 122 + } else { 123 + cmd.Stderr = cmd.Stdout 124 + } 119 125 120 126 if err := cmd.Start(); err != nil { 121 127 return fmt.Errorf("start %s: %w", service, err) 路路路 149 155 return nil 150 156 } 151 157 152 -func packLine(w io.Writer, s string) error { 158 +// PackLine writes a pkt-line formatted string. 159 +func PackLine(w io.Writer, s string) error { 153 160 _, err := fmt.Fprintf(w, "%04x%s", len(s)+4, s) 154 161 return err 155 162 } 156 163 157 -func packFlush(w io.Writer) error { 164 +// PackFlush writes a flush packet. 165 +func PackFlush(w io.Writer) error { 158 166 _, err := fmt.Fprint(w, "0000") 159 167 return err 160 168 } 169 + 170 +// PackSideband writes a message to sideband channel (displays as "remote: <msg>" in git client). 171 +// Channel 2 = progress/info, Channel 3 = error. 172 +func PackSideband(w io.Writer, channel byte, msg string) error { 173 + return PackLine(w, string(channel)+msg) 174 +} 175 + 176 +// PackError writes an ERR packet for protocol-level errors. 177 +// Git displays this as: fatal: remote error: <msg> 178 +func PackError(w io.Writer, msg string) error { 179 + return PackLine(w, "ERR "+msg) 180 +}
M
internal/ssh/server.go
路路路 81 81 repoPath = filepath.Join(s.c.Repo.Dir, filepath.Clean(repoPath)) 82 82 _, err := git.Open(repoPath, "") 83 83 if err != nil { 84 - s.error(sess, err) 84 + slog.Error("ssh: failed to open repo", "err", err) 85 + s.repoNotFound(sess) 85 86 return 86 87 } 87 - 88 - fmt.Println(repoPath) 89 88 90 89 switch gitCmd { 91 90 case "git-upload-pack": 路路路 96 95 sess.Exit(0) 97 96 case "git-receive-pack": 98 97 if !authorized { 99 - s.repoNotFound(sess) 98 + s.unauthorized(sess) 100 99 return 101 100 } 102 101 103 - if err := gitservice.ReceivePack(repoPath, sess, sess); err != nil { 102 + if err := gitservice.ReceivePack(repoPath, sess, sess, sess.Stderr()); err != nil { 104 103 s.error(sess, err) 105 104 return 106 105 } 路路路 108 107 109 108 default: 110 109 slog.Error("ssh unsupported command", "cmd", cmd) 111 - fmt.Fprintln(sess, "Unsupported command") 110 + gitservice.PackError(sess, "Unsupported command.") 112 111 sess.Exit(1) 113 112 } 114 113 } 路路路 127 126 } 128 127 129 128 func (s *Server) repoNotFound(sess ssh.Session) { 130 - fmt.Fprintln(sess, "Sorry but repo you're looking for is not found.") 129 + gitservice.PackError(sess, "Repository not found.") 130 + sess.Exit(1) 131 +} 132 + 133 +func (s *Server) unauthorized(sess ssh.Session) { 134 + gitservice.PackError(sess, "You are not authorized to push to this repository.") 131 135 sess.Exit(1) 132 136 } 133 137 134 138 func (s *Server) error(sess ssh.Session, err error) { 135 - fmt.Fprintln(sess, "unexpected server error") 136 - sess.Exit(1) 137 139 slog.Error("error on ssh side", "err", err) 140 + gitservice.PackError(sess, "Unexpected server error.") 141 + sess.Exit(1) 138 142 }