@@ -12,8 +12,6 @@ import (
1212 "io"
1313 "net"
1414 "strings"
15- "sync"
16- "text/template"
1715 "time"
1816
1917 "github.com/Masterminds/cookoo"
@@ -31,10 +29,8 @@ const (
3129 ServerConfig string = "ssh.ServerConfig"
3230
3331 multiplePush string = "Another git push is ongoing"
34- )
3532
36- var (
37- buildingRepos = NewInMemoryRepositoryLock ()
33+ inProgressDelete string = "This app was deleted and is being cleaned up. Please re-create it with 'deis create your_app'"
3834)
3935
4036// Serve starts a native SSH server.
5450//
5551// This puts the following variables into the context:
5652// - ssh.Closer (chan interface{}): Send a message to this to shutdown the server.
57- func Serve (reg * cookoo.Registry , router * cookoo.Router , serverCircuit * Circuit , gitHomeDir string , c cookoo.Context ) cookoo.Interrupt {
53+ func Serve (reg * cookoo.Registry , router * cookoo.Router , serverCircuit * Circuit , gitHomeDir string , concurrentPushLock RepositoryLock , concurrentDeleteLock RepositoryLock , c cookoo.Context ) cookoo.Interrupt {
5854 hostkeys := c .Get (HostKeys , []ssh.Signer {}).([]ssh.Signer )
5955 addr := c .Get (Address , "0.0.0.0:2223" ).(string )
6056 cfg := c .Get (ServerConfig , & ssh.ServerConfig {}).(* ssh.ServerConfig )
@@ -70,8 +66,10 @@ func Serve(reg *cookoo.Registry, router *cookoo.Router, serverCircuit *Circuit,
7066 }
7167
7268 srv := & server {
73- c : c ,
74- gitHome : gitHomeDir ,
69+ c : c ,
70+ gitHome : gitHomeDir ,
71+ pushLock : concurrentPushLock ,
72+ deleteLock : concurrentDeleteLock ,
7573 }
7674
7775 closer := make (chan interface {}, 1 )
@@ -88,8 +86,8 @@ func Serve(reg *cookoo.Registry, router *cookoo.Router, serverCircuit *Circuit,
8886type server struct {
8987 c cookoo.Context
9088 gitHome string
91- hookTpl * template. Template
92- createLock sync. Mutex
89+ pushLock RepositoryLock
90+ deleteLock RepositoryLock
9391}
9492
9593// listen handles accepting and managing connections. However, since closer
@@ -225,7 +223,17 @@ func (s *server) answer(channel ssh.Channel, requests <-chan *ssh.Request, sshCo
225223 }
226224
227225 repoName := parts [1 ]
228- if err := buildingRepos .Lock (repoName , time .Duration (0 )); err != nil {
226+ if err := s .deleteLock .Lock (repoName , time .Duration (0 )); err != nil {
227+ log .Errf (s .c , inProgressDelete )
228+ // The error must be in git format
229+ if err := gitPktLine (channel , fmt .Sprintf ("ERR %v\n " , inProgressDelete )); err != nil {
230+ log .Errf (s .c , "Failed to write to channel: %s" , err )
231+ }
232+ sendExitStatus (1 , channel )
233+ req .Reply (false , nil )
234+ return nil
235+ }
236+ if err := s .pushLock .Lock (repoName , time .Duration (0 )); err != nil {
229237 log .Errf (s .c , multiplePush )
230238 // The error must be in git format
231239 if err := gitPktLine (channel , fmt .Sprintf ("ERR %v\n " , multiplePush )); err != nil {
@@ -244,7 +252,16 @@ func (s *server) answer(channel ssh.Channel, requests <-chan *ssh.Request, sshCo
244252 cxt .Put ("repository" , parts [1 ])
245253 sshGitReceive := cxt .Get ("route.sshd.sshGitReceive" , "sshGitReceive" ).(string )
246254 err := router .HandleRequest (sshGitReceive , cxt , true )
247- buildingRepos .Unlock (repoName , time .Duration (0 ))
255+ if err := s .pushLock .Unlock (repoName , time .Duration (0 )); err != nil {
256+ log .Errf (s .c , "unable to unlock repository lock for %s (%s)" , repoName , err )
257+ // TODO: this is an important error case that needs to be covered
258+ // Probably the best solution is to change the lock into a lease so that even on unlock failures, RepositoryLock will eventually yield
259+ }
260+ if err := s .deleteLock .Unlock (repoName , time .Duration (0 )); err != nil {
261+ log .Errf (s .c , "unable to unlock delete lock for %s (%s)" , repoName , err )
262+ // TODO: this is an important error case that needs to be covered
263+ // Probably the best solution is to change the lock into a lease so that even on unlock failures, RepositoryLock will eventually yield
264+ }
248265 var xs uint32
249266 if err != nil {
250267 log .Errf (s .c , "Failed git receive: %v" , err )
0 commit comments