comparison src/git_serve/__init__.py @ 5:c43ce246240b

Really fix content-length for real for serious.
author Paul Fisher <paul@pfish.zone>
date Sat, 14 Feb 2026 21:39:54 -0500
parents 5ad58438318a
children 7113e0ac3662
comparison
equal deleted inserted replaced
4:5ad58438318a 5:c43ce246240b
90 # We only handle Git requests; everything else is normal. 90 # We only handle Git requests; everything else is normal.
91 return original(req_ctx, request, response, check_permission) 91 return original(req_ctx, request, response, check_permission)
92 check_permission(req_ctx, request, b'pull') 92 check_permission(req_ctx, request, b'pull')
93 # If a request is git, we assume we should be the one handling it. 93 # If a request is git, we assume we should be the one handling it.
94 cgi_env = _build_git_environ(req_ctx, request) 94 cgi_env = _build_git_environ(req_ctx, request)
95 content_length_hdr = request.headers.get(b'content-length', b'0')
96 try:
97 content_length = int(content_length_hdr)
98 except ValueError as ve:
99 raise hgerr.InputError(
100 f'Invalid content-length {content_length!r}'.encode()
101 ) from ve
95 http_backend = req_ctx.repo.ui.configlist( 102 http_backend = req_ctx.repo.ui.configlist(
96 b'git-serve', b'http-backend', default=(b'git', b'http-backend') 103 b'git-serve', b'http-backend', default=(b'git', b'http-backend')
97 ) 104 )
98 call = subprocess.Popen( 105 call = subprocess.Popen(
99 http_backend, 106 http_backend,
106 ) 113 )
107 assert call.stdout 114 assert call.stdout
108 assert call.stdin 115 assert call.stdin
109 # Git will not start writing output until stdin is fully closed. 116 # Git will not start writing output until stdin is fully closed.
110 with call.stdin: 117 with call.stdin:
111 shutil.copyfileobj(request.bodyfh, call.stdin) 118 if content_length:
119 shutil.copyfileobj(
120 request.bodyfh, call.stdin, length=content_length
121 )
112 122
113 status, headers, rest = _parse_cgi_response(call.stdout) 123 status, headers, rest = _parse_cgi_response(call.stdout)
114 response.status = status 124 response.status = status
115 for k, v in headers.items(): 125 for k, v in headers.items():
116 response.headers[k] = v 126 response.headers[k] = v
188 _set_head(repo) 198 _set_head(repo)
189 199
190 200
191 # Interfacing with Mercurial 201 # Interfacing with Mercurial
192 202
193 __version__ = '0.1.2' 203 __version__ = '0.1.3'
194 204
195 cmdtable: dict[bytes, object] = {} 205 cmdtable: dict[bytes, object] = {}
196 206
197 command = registrar.command(cmdtable) 207 command = registrar.command(cmdtable)
198 208