Mercurial > python-hglib
comparison hglib/client.py @ 216:68588c652ac6
client: handle commit messages with \0 characters
Mercurial allows commit messages containing \0 characters,
but hglib does not properly handle them.
By using the json template, these characters are correctly escaped.
Note: initial change only modifies this for the 'log' command,
I'll follow-up for other commands if this is ok.
author | Mathias De Mare <mathias.de_mare@nokia.com> |
---|---|
date | Wed, 08 Mar 2023 16:22:21 +0100 |
parents | 388820908580 |
children | 2ab42323f149 |
comparison
equal
deleted
inserted
replaced
215:1e7a64588ab0 | 216:68588c652ac6 |
---|---|
1 import struct, re, datetime | 1 import struct, re, datetime, json |
2 import hglib | 2 import hglib |
3 from hglib import error, util, templates, merge, context | 3 from hglib import error, util, templates, merge, context |
4 | 4 |
5 from hglib.util import b, cmdbuilder, BytesIO, strtobytes | 5 from hglib.util import b, cmdbuilder, BytesIO, strtobytes |
6 | 6 |
170 dt = datetime.datetime.fromtimestamp(posixtime) | 170 dt = datetime.datetime.fromtimestamp(posixtime) |
171 revs.append(revision(rev[0], rev[1], rev[2], rev[3], | 171 revs.append(revision(rev[0], rev[1], rev[2], rev[3], |
172 rev[4], rev[5], dt)) | 172 rev[4], rev[5], dt)) |
173 return revs | 173 return revs |
174 | 174 |
175 @staticmethod | |
176 def _parsejsonrevs(jsonrevs): | |
177 revs = [] | |
178 for rev in jsonrevs: | |
179 # truncate the timezone and convert to a local datetime | |
180 posixtime = float(rev["date"][0]) | |
181 dt = datetime.datetime.fromtimestamp(posixtime) | |
182 revs.append(revision(str(rev["rev"]).encode(), rev["node"].encode(), | |
183 ' '.join(rev["tags"]).encode(), | |
184 rev["branch"].encode(), rev["user"].encode(), | |
185 rev["desc"].encode(), dt)) | |
186 return revs | |
187 | |
175 def runcommand(self, args, inchannels, outchannels): | 188 def runcommand(self, args, inchannels, outchannels): |
176 def writeblock(data): | 189 def writeblock(data): |
177 if self._protocoltracefn is not None: | 190 if self._protocoltracefn is not None: |
178 self._protocoltracefn('w', None, data) | 191 self._protocoltracefn('w', None, data) |
179 self.server.stdin.write(struct.pack(self.inputfmt, len(data))) | 192 self.server.stdin.write(struct.pack(self.inputfmt, len(data))) |
1092 exclude - exclude names matching the given patterns | 1105 exclude - exclude names matching the given patterns |
1093 | 1106 |
1094 """ | 1107 """ |
1095 if hidden is None: | 1108 if hidden is None: |
1096 hidden = self.hidden | 1109 hidden = self.hidden |
1097 args = cmdbuilder(b('log'), template=templates.changeset, | 1110 args = cmdbuilder(b('log'), template="json", |
1098 r=revrange, f=follow, follow_first=followfirst, | 1111 r=revrange, f=follow, follow_first=followfirst, |
1099 d=date, C=copies, k=keyword, removed=removed, | 1112 d=date, C=copies, k=keyword, removed=removed, |
1100 m=onlymerges, u=user, b=branch, P=prune, | 1113 m=onlymerges, u=user, b=branch, P=prune, |
1101 l=limit, M=nomerges, I=include, X=exclude, | 1114 l=limit, M=nomerges, I=include, X=exclude, |
1102 hidden=hidden, *files) | 1115 hidden=hidden, *files) |
1103 | 1116 |
1104 out = self.rawcommand(args) | 1117 out = self.rawcommand(args) |
1105 out = out.split(b('\0'))[:-1] | 1118 json_out = json.loads(out) |
1106 | 1119 |
1107 return self._parserevs(out) | 1120 return self._parsejsonrevs(json_out) |
1108 | 1121 |
1109 def manifest(self, rev=None, all=False): | 1122 def manifest(self, rev=None, all=False): |
1110 """Yields (nodeid, permission, executable, symlink, file path) tuples | 1123 """Yields (nodeid, permission, executable, symlink, file path) tuples |
1111 for version controlled files for the given revision. If no | 1124 for version controlled files for the given revision. If no |
1112 revision is given, the first parent of the working directory | 1125 revision is given, the first parent of the working directory |