@@ -23,10 +23,13 @@ type Service struct {
23
23
}
24
24
25
25
type 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
30
33
}
31
34
32
35
type HandlerReq struct {
@@ -38,10 +41,13 @@ type HandlerReq struct {
38
41
}
39
42
40
43
var 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 ,
45
51
}
46
52
47
53
var services = map [string ]Service {
63
69
)
64
70
65
71
func 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" )
66
75
flag .StringVar (& config .ProjectRoot , "project_root" , config .ProjectRoot , "set project root" )
67
76
flag .StringVar (& config .GitBinPath , "git_bin_path" , config .GitBinPath , "set git bin path" )
68
77
flag .StringVar (& address , "server_address" , address , "set server address" )
@@ -117,15 +126,35 @@ func serviceRpc(hr HandlerReq) {
117
126
}
118
127
119
128
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" )
120
132
w .WriteHeader (http .StatusOK )
121
133
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
+
122
150
args := []string {rpc , "--stateless-rpc" , dir }
123
151
cmd := exec .Command (config .GitBinPath , args ... )
124
152
version := r .Header .Get ("Git-Protocol" )
125
153
if len (version ) != 0 {
126
154
cmd .Env = append (os .Environ (), fmt .Sprintf ("GIT_PROTOCOL=%s" , version ))
127
155
}
128
156
cmd .Dir = dir
157
+ cmd .Env = env
129
158
in , err := cmd .StdinPipe ()
130
159
if err != nil {
131
160
log .Print (err )
@@ -151,7 +180,30 @@ func serviceRpc(hr HandlerReq) {
151
180
}
152
181
io .Copy (in , reader )
153
182
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
+
155
207
cmd .Wait ()
156
208
}
157
209
0 commit comments