comparison src/hggit_serve.py @ 9:5000914da3ff default tip

simplify handling of stream copying
author Paul Fisher <paul@pfish.zone>
date Mon, 16 Feb 2026 00:12:57 -0500
parents fe3c9fae4d4d
children
comparison
equal deleted inserted replaced
8:fe3c9fae4d4d 9:5000914da3ff
143 else req_ctx.req 143 else req_ctx.req
144 ), 144 ),
145 perm, 145 perm,
146 ) 146 )
147 cgi_env = _build_git_environ(req_ctx, request) 147 cgi_env = _build_git_environ(req_ctx, request)
148 content_length_hdr = request.headers.get(b'content-length', b'0')
149 try:
150 content_length = int(content_length_hdr)
151 except ValueError as ve:
152 raise hgerr.InputError(
153 f'Invalid content-length {content_length_hdr!r}'.encode()
154 ) from ve
155 http_backend = repo.ui.configlist( 148 http_backend = repo.ui.configlist(
156 b'hggit-serve', b'http-backend', default=(b'git', b'http-backend') 149 b'hggit-serve', b'http-backend', default=(b'git', b'http-backend')
157 ) 150 )
158 call = subprocess.Popen( 151 call = subprocess.Popen(
159 http_backend, 152 http_backend,
166 ) 159 )
167 assert call.stdout 160 assert call.stdout
168 assert call.stdin 161 assert call.stdin
169 # Git will not start writing output until stdin is fully closed. 162 # Git will not start writing output until stdin is fully closed.
170 with call.stdin: 163 with call.stdin:
171 if content_length: 164 # This is how we know if there's anything to read from bodyfh.
172 shutil.copyfileobj( 165 # If we try to read from bodyfh on a request with no content,
173 request.bodyfh, call.stdin, length=content_length 166 # it hangs forever.
174 ) 167 if b'CONTENT_LENGTH' in request.rawenv:
168 shutil.copyfileobj(request.bodyfh, call.stdin)
175 169
176 status, headers, rest = _parse_cgi_response(call.stdout) 170 status, headers, rest = _parse_cgi_response(call.stdout)
177 response.status = status 171 response.status = status
178 for k, v in headers.items(): 172 for k, v in headers.items():
179 response.headers[k] = v 173 response.headers[k] = v
180 174
181 def write_the_rest() -> t.Iterator[bytes]: 175 def write_the_rest() -> t.Iterator[bytes]:
182 with call, rest: 176 with call, rest:
183 while more := rest.read(1024 * 1024): 177 # if it's good enough for shutil it's good enough for me
178 while more := rest.read(shutil.COPY_BUFSIZE):
184 yield more 179 yield more
185 if perm == _PUSH: 180 if perm == _PUSH:
186 _importing_enter(repo) 181 _importing_enter(repo)
187 try: 182 try:
188 gh = repo.githandler 183 gh = repo.githandler