@@ -23,10 +23,13 @@ type Service struct {
2323}
2424
2525type Config struct {
26- ProjectRoot string
27- GitBinPath string
28- UploadPack bool
29- ReceivePack bool
26+ AuthPassEnvVar string
27+ AuthUserEnvVar string
28+ DefaultEnv string
29+ ProjectRoot string
30+ GitBinPath string
31+ UploadPack bool
32+ ReceivePack bool
3033}
3134
3235type HandlerReq struct {
@@ -38,10 +41,13 @@ type HandlerReq struct {
3841}
3942
4043var config Config = Config {
41- ProjectRoot : "/tmp" ,
42- GitBinPath : "/usr/bin/git" ,
43- UploadPack : true ,
44- ReceivePack : true ,
44+ AuthPassEnvVar : "" ,
45+ AuthUserEnvVar : "" ,
46+ DefaultEnv : "" ,
47+ ProjectRoot : "/tmp" ,
48+ GitBinPath : "/usr/bin/git" ,
49+ UploadPack : true ,
50+ ReceivePack : true ,
4551}
4652
4753var services = map [string ]Service {
6369)
6470
6571func init () {
72+ flag .StringVar (& config .AuthPassEnvVar , "auth_pass_env_var" , config .AuthPassEnvVar , "set an env var to provide the basic auth pass as" )
73+ flag .StringVar (& config .AuthUserEnvVar , "auth_user_env_var" , config .AuthUserEnvVar , "set an env var to provide the basic auth user as" )
74+ flag .StringVar (& config .DefaultEnv , "default_env" , config .DefaultEnv , "set the default env" )
6675 flag .StringVar (& config .ProjectRoot , "project_root" , config .ProjectRoot , "set project root" )
6776 flag .StringVar (& config .GitBinPath , "git_bin_path" , config .GitBinPath , "set git bin path" )
6877 flag .StringVar (& address , "server_address" , address , "set server address" )
@@ -117,15 +126,35 @@ func serviceRpc(hr HandlerReq) {
117126 }
118127
119128 w .Header ().Set ("Content-Type" , fmt .Sprintf ("application/x-git-%s-result" , rpc ))
129+ w .Header ().Set ("Connection" , "Keep-Alive" )
130+ w .Header ().Set ("Transfer-Encoding" , "chunked" )
131+ w .Header ().Set ("X-Content-Type-Options" , "nosniff" )
120132 w .WriteHeader (http .StatusOK )
121133
134+ env := []string {}
135+
136+ if config .DefaultEnv != "" {
137+ env = append (env , config .DefaultEnv )
138+ }
139+
140+ user , password , authok := r .BasicAuth ()
141+ if authok {
142+ if config .AuthUserEnvVar != "" {
143+ env = append (env , fmt .Sprintf ("%s=%s" , config .AuthUserEnvVar , user ))
144+ }
145+ if config .AuthPassEnvVar != "" {
146+ env = append (env , fmt .Sprintf ("%s=%s" , config .AuthPassEnvVar , password ))
147+ }
148+ }
149+
122150 args := []string {rpc , "--stateless-rpc" , dir }
123151 cmd := exec .Command (config .GitBinPath , args ... )
124152 version := r .Header .Get ("Git-Protocol" )
125153 if len (version ) != 0 {
126154 cmd .Env = append (os .Environ (), fmt .Sprintf ("GIT_PROTOCOL=%s" , version ))
127155 }
128156 cmd .Dir = dir
157+ cmd .Env = env
129158 in , err := cmd .StdinPipe ()
130159 if err != nil {
131160 log .Print (err )
@@ -151,7 +180,30 @@ func serviceRpc(hr HandlerReq) {
151180 }
152181 io .Copy (in , reader )
153182 in .Close ()
154- io .Copy (w , stdout )
183+
184+ flusher , ok := w .(http.Flusher )
185+ if ! ok {
186+ panic ("expected http.ResponseWriter to be an http.Flusher" )
187+ }
188+
189+ p := make ([]byte , 1024 )
190+ for {
191+ n_read , err := stdout .Read (p )
192+ if err == io .EOF {
193+ break
194+ }
195+ n_write , err := w .Write (p [:n_read ])
196+ if err != nil {
197+ fmt .Println (err )
198+ os .Exit (1 )
199+ }
200+ if n_read != n_write {
201+ fmt .Printf ("failed to write data: %d read, %d written\n " , n_read , n_write )
202+ os .Exit (1 )
203+ }
204+ flusher .Flush ()
205+ }
206+
155207 cmd .Wait ()
156208}
157209
0 commit comments