@@ -9,10 +9,12 @@ package sshd
99
1010import (
1111 "fmt"
12+ "io"
1213 "net"
1314 "strings"
1415 "sync"
1516 "text/template"
17+ "time"
1618
1719 "github.com/Masterminds/cookoo"
1820 "github.com/Masterminds/cookoo/log"
@@ -27,6 +29,12 @@ const (
2729 Address string = "ssh.Address"
2830 // ServerConfig is the context key for ServerConfig object.
2931 ServerConfig string = "ssh.ServerConfig"
32+
33+ multiplePush string = "Another git push is ongoing"
34+ )
35+
36+ var (
37+ buildingRepos = NewInMemoryRepositoryLock ()
3038)
3139
3240// Serve starts a native SSH server.
@@ -215,6 +223,19 @@ func (s *server) answer(channel ssh.Channel, requests <-chan *ssh.Request, sshCo
215223 req .Reply (ok , nil )
216224 break
217225 }
226+
227+ repoName := parts [1 ]
228+ if err := buildingRepos .Lock (repoName , time .Duration (0 )); err != nil {
229+ log .Errf (s .c , multiplePush )
230+ // The error must be in git format
231+ if err := gitPktLine (channel , fmt .Sprintf ("ERR %v\n " , multiplePush )); err != nil {
232+ log .Errf (s .c , "Failed to write to channel: %s" , err )
233+ }
234+ sendExitStatus (1 , channel )
235+ req .Reply (false , nil )
236+ return nil
237+ }
238+
218239 req .Reply (true , nil ) // We processed. Yay.
219240
220241 cxt .Put ("channel" , channel )
@@ -223,12 +244,14 @@ func (s *server) answer(channel ssh.Channel, requests <-chan *ssh.Request, sshCo
223244 cxt .Put ("repository" , parts [1 ])
224245 sshGitReceive := cxt .Get ("route.sshd.sshGitReceive" , "sshGitReceive" ).(string )
225246 err := router .HandleRequest (sshGitReceive , cxt , true )
247+ buildingRepos .Unlock (repoName , time .Duration (0 ))
226248 var xs uint32
227249 if err != nil {
228250 log .Errf (s .c , "Failed git receive: %v" , err )
229251 xs = 1
230252 }
231253 sendExitStatus (xs , channel )
254+
232255 return nil
233256 default :
234257 log .Warnf (s .c , "Illegal command is '%s'\n " , clean )
@@ -296,3 +319,10 @@ func Ping(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
296319 req .Reply (true , nil )
297320 return nil , nil
298321}
322+
323+ // gitPktLine writes a line following the git protocol
324+ // https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt
325+ func gitPktLine (w io.Writer , s string ) error {
326+ _ , err := fmt .Fprintf (w , "%04x%s" , len (s )+ 4 , s )
327+ return err
328+ }
0 commit comments