Mercurial > hg-git-serve
annotate src/git_serve/__init__.py @ 6:7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Sun, 15 Feb 2026 01:31:53 -0500 |
| parents | c43ce246240b |
| children |
| rev | line source |
|---|---|
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
1 from __future__ import annotations |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
2 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
3 import binascii |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
4 import email.parser |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
5 import email.policy |
|
3
189f4a0bc653
don't try to pass bytes to pathlib.Path
Paul Fisher <paul@pfish.zone>
parents:
2
diff
changeset
|
6 import os.path |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
7 import re |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
8 import shutil |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
9 import subprocess |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
10 import typing as t |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
11 |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
12 import dulwich.refs |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
13 import mercurial.error as hgerr |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
14 from mercurial import extensions |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
15 from mercurial import registrar |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
16 from mercurial import wireprotoserver |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
17 |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
18 if t.TYPE_CHECKING: |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
19 import hggit.git_handler |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
20 import mercurial.hgweb.hgweb_mod_inner as web_inner |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
21 import mercurial.hgweb.request as hgreq |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
22 import mercurial.interfaces.repository as hgrepo |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
23 import mercurial.ui as hgui |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
24 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
25 class GittyRepo(hgrepo.IRepo, t.Protocol): |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
26 githandler: hggit.git_handler.GitHandler |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
27 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
28 PermissionCheck = t.Callable[ |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
29 [web_inner.requestcontext, hgreq.parsedrequest, bytes], |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
30 None, |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
31 ] |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
32 GitPrelude = t.Sequence[bytes | str | os.PathLike] |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
33 |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
34 |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
35 def _is_gitty(repo: hgrepo.IRepo) -> t.TypeGuard[GittyRepo]: |
|
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
36 """Ensures that we have hg-git installed and active.""" |
|
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
37 return hasattr(repo, 'githandler') |
|
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
38 |
|
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
39 |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
40 _CGI_VAR = re.compile(rb'[A-Z0-9_]+$') |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
41 """Environment variables that we need to pass to git-as-cgi.""" |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
42 |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
43 |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
44 def _build_git_environ( |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
45 req_ctx: web_inner.requestcontext, |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
46 request: hgreq.parsedrequest, |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
47 ) -> dict[bytes, bytes]: |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
48 """Builds the environment to be sent to Git to serve HTTP.""" |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
49 fixed = { |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
50 k: v |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
51 for (k, v) in request.rawenv.items() |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
52 if isinstance(v, bytes) and _CGI_VAR.match(k) |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
53 } |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
54 fixed[b'GIT_HTTP_EXPORT_ALL'] = b'yes' |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
55 fixed[b'GIT_PROJECT_ROOT'] = req_ctx.repo.path |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
56 fixed[b'PATH_INFO'] = b'/git/' + request.dispatchpath |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
57 return fixed |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
58 |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
59 |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
60 def _parse_cgi_response( |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
61 output: t.IO[bytes], |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
62 ) -> tuple[bytes, dict[bytes, bytes], t.IO[bytes]]: |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
63 """Parses a CGI response into a status, headers, and everyhting else.""" |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
64 parser = email.parser.BytesFeedParser(policy=email.policy.HTTP) |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
65 while line := output.readline(): |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
66 if not line.rstrip(b'\r\n'): |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
67 # We've reached the end of the headers. |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
68 # Leave the rest in the output for later. |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
69 break |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
70 parser.feed(line) |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
71 msg = parser.close() |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
72 status = msg.get('Status', '200 OK I guess').encode('utf-8') |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
73 del msg['Status'] # this won't raise an exception |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
74 byte_headers = { |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
75 k.encode('utf-8'): v.encode('utf-8') for (k, v) in msg.items() |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
76 } |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
77 return status, byte_headers, output |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
78 |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
79 |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
80 def _handle_git_protocol( |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
81 original: t.Callable[..., bool], |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
82 req_ctx: web_inner.requestcontext, |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
83 request: hgreq.parsedrequest, |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
84 response: hgreq.wsgiresponse, |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
85 check_permission: PermissionCheck, |
|
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
86 ) -> bool: |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
87 """Intercepts requests from Git, if needed.""" |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
88 repo = req_ctx.repo |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
89 if not _is_gitty(repo) or b'git-protocol' not in request.headers: |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
90 # We only handle Git requests; everything else is normal. |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
91 return original(req_ctx, request, response, check_permission) |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
92 check_permission(req_ctx, request, b'pull') |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
93 # If a request is git, we assume we should be the one handling it. |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
94 cgi_env = _build_git_environ(req_ctx, request) |
|
5
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
95 content_length_hdr = request.headers.get(b'content-length', b'0') |
|
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
96 try: |
|
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
97 content_length = int(content_length_hdr) |
|
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
98 except ValueError as ve: |
|
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
99 raise hgerr.InputError( |
|
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
100 f'Invalid content-length {content_length!r}'.encode() |
|
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
101 ) from ve |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
102 http_backend = req_ctx.repo.ui.configlist( |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
103 b'git-serve', b'http-backend', default=(b'git', b'http-backend') |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
104 ) |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
105 call = subprocess.Popen( |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
106 http_backend, |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
107 close_fds=True, |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
108 stdin=subprocess.PIPE, |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
109 stdout=subprocess.PIPE, |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
110 stderr=subprocess.DEVNULL, |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
111 env=cgi_env, |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
112 text=False, |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
113 ) |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
114 assert call.stdout |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
115 assert call.stdin |
|
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
116 # Git will not start writing output until stdin is fully closed. |
|
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
117 with call.stdin: |
|
5
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
118 if content_length: |
|
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
119 shutil.copyfileobj( |
|
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
120 request.bodyfh, call.stdin, length=content_length |
|
c43ce246240b
Really fix content-length for real for serious.
Paul Fisher <paul@pfish.zone>
parents:
4
diff
changeset
|
121 ) |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
122 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
123 status, headers, rest = _parse_cgi_response(call.stdout) |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
124 response.status = status |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
125 for k, v in headers.items(): |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
126 response.headers[k] = v |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
127 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
128 def write_the_rest(): |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
129 with call, rest: |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
130 while more := rest.read(1024 * 1024): |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
131 yield more |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
132 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
133 response.setbodygen(write_the_rest()) |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
134 response.sendresponse() |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
135 return True |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
136 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
137 |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
138 def _clean_all_refs(refs: dulwich.refs.RefsContainer) -> None: |
|
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
139 """Removes all refs from the Git repository.""" |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
140 for ref in refs.allkeys(): |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
141 refs.remove_if_equals(ref, None) |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
142 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
143 |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
144 def _set_head(ui: hgui.ui, repo: GittyRepo, at_name: bytes) -> None: |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
145 """Creates a HEAD reference in Git referring to the current HEAD.""" |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
146 # By default, we use '@', since that's what will be auto checked out. |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
147 current = b'@' |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
148 if current not in repo._bookmarks: |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
149 current = repo._bookmarks.active or current |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
150 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
151 # We'll be moving this (possibly fake) bookmark into Git. |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
152 git_current = current |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
153 if current == b'@': |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
154 # @ is a special keyword in Git, so we can't use it as a bookmark. |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
155 git_current = at_name |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
156 git_branch = dulwich.refs.LOCAL_BRANCH_PREFIX + git_current |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
157 if not dulwich.refs.check_ref_format(git_branch): |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
158 # We can't export this ref to Git. Give up. |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
159 ui.warn(f'{git_branch!r} is not a valid branch name for Git.'.encode()) |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
160 return |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
161 try: |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
162 # Maybe this is a real bookmark? |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
163 hgsha = repo._bookmarks[current] |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
164 except KeyError: |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
165 # Not a real bookmark. Assume we want the tip of the current branch. |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
166 branch = repo.dirstate.branch() |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
167 try: |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
168 tip = repo.branchtip(branch) |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
169 except hgerr.RepoLookupError: |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
170 # This branch somehow doesn't exist??? |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
171 ui.warn(f"{branch} doesn't seem to exist?".encode()) |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
172 return |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
173 hgsha = binascii.hexlify(tip) |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
174 gitsha = repo.githandler.map_git_get(hgsha) |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
175 if not gitsha: |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
176 # No Git SHA to match this Hg sha. Give up. |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
177 ui.warn(f'revision {hgsha} was not exported to Git'.encode()) |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
178 return |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
179 refs = repo.githandler.git.refs |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
180 refs.add_packed_refs({git_branch: gitsha}) |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
181 refs.set_symbolic_ref(b'HEAD', git_branch) |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
182 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
183 |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
184 def fix_refs_hook(ui: hgui.ui, repo: hgrepo.IRepo, **__: object) -> None: |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
185 """Exports to Git and sets up for serving.""" |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
186 if not _is_gitty(repo): |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
187 return |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
188 _fix_refs(ui, repo) |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
189 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
190 |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
191 def _fix_refs(ui: hgui.ui, repo: GittyRepo) -> None: |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
192 """After a git export, fix up the refs.""" |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
193 _clean_all_refs(repo.githandler.git.refs) |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
194 repo.githandler.export_hg_tags() |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
195 repo.githandler.update_references() |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
196 default_branch_name = ui.config( |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
197 b'hggit-serve', b'default-branch', b'default' |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
198 ) |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
199 _set_head(ui, repo, default_branch_name) |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
200 |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
201 |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
202 def export_hook(ui: hgui.ui, repo: hgrepo.IRepo, **__: object) -> None: |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
203 if not _is_gitty(repo): |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
204 return |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
205 auto_export = ui.config(b'hggit-serve', b'auto-export') |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
206 if auto_export == b'never': |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
207 return |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
208 if auto_export == b'always' or os.path.isdir(repo.githandler.gitdir): |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
209 repo.githandler.export_commits() |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
210 _fix_refs(ui, repo) |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
211 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
212 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
213 # Interfacing with Mercurial |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
214 |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
215 __version__ = '0.1.4' |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
216 testedwith = b'7.1 7.2' |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
217 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
218 cmdtable: dict[bytes, object] = {} |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
219 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
220 command = registrar.command(cmdtable) |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
221 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
222 |
|
0
c1dc9d21fa57
First cut at serving hg repos with git.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
223 def uisetup(_: hgui.ui) -> None: |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
224 extensions.wrapfunction( |
|
4
5ad58438318a
Fix issue where sometimes reads would be cut off.
Paul Fisher <paul@pfish.zone>
parents:
3
diff
changeset
|
225 wireprotoserver, 'handlewsgirequest', _handle_git_protocol |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
226 ) |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
227 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
228 |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
229 def uipopulate(ui: hgui.ui) -> None: |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
230 ui.setconfig( |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
231 b'hooks', b'post-git-export.__gitserve_add_tag__', fix_refs_hook |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
232 ) |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
233 ui.setconfig(b'hooks', b'txnclose.__gitserve_export__', export_hook) |
|
1
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
234 |
|
a39dd69b8972
Create a more-or-less real package and make it work (?)
Paul Fisher <paul@pfish.zone>
parents:
0
diff
changeset
|
235 |
|
6
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
236 __all__ = ( |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
237 '__version__', |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
238 'cmdtable', |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
239 'command', |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
240 'testedwith', |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
241 'uipopulate', |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
242 'uisetup', |
|
7113e0ac3662
fix refs on git-export; clean up how gitserve export works.
Paul Fisher <paul@pfish.zone>
parents:
5
diff
changeset
|
243 ) |
