Mercurial > hg-git-serve
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 |
