Mercurial > hg
comparison hgext/convert/p4.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | be8552f25cab |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
22 | 22 |
23 from . import common | 23 from . import common |
24 | 24 |
25 | 25 |
26 def loaditer(f): | 26 def loaditer(f): |
27 "Yield the dictionary objects generated by p4" | 27 b"Yield the dictionary objects generated by p4" |
28 try: | 28 try: |
29 while True: | 29 while True: |
30 d = marshal.load(f) | 30 d = marshal.load(f) |
31 if not d: | 31 if not d: |
32 break | 32 break |
42 >>> decodefilename(b'portable-net45%252Bnetcore45%252Bwp8%252BMonoAndroid') | 42 >>> decodefilename(b'portable-net45%252Bnetcore45%252Bwp8%252BMonoAndroid') |
43 'portable-net45%2Bnetcore45%2Bwp8%2BMonoAndroid' | 43 'portable-net45%2Bnetcore45%2Bwp8%2BMonoAndroid' |
44 >>> decodefilename(b'//Depot/Directory/%2525/%2523/%23%40.%2A') | 44 >>> decodefilename(b'//Depot/Directory/%2525/%2523/%23%40.%2A') |
45 '//Depot/Directory/%25/%23/#@.*' | 45 '//Depot/Directory/%25/%23/#@.*' |
46 """ | 46 """ |
47 replacements = [('%2A', '*'), ('%23', '#'), ('%40', '@'), ('%25', '%')] | 47 replacements = [ |
48 (b'%2A', b'*'), | |
49 (b'%23', b'#'), | |
50 (b'%40', b'@'), | |
51 (b'%25', b'%'), | |
52 ] | |
48 for k, v in replacements: | 53 for k, v in replacements: |
49 filename = filename.replace(k, v) | 54 filename = filename.replace(k, v) |
50 return filename | 55 return filename |
51 | 56 |
52 | 57 |
55 # avoid import cycle | 60 # avoid import cycle |
56 from . import convcmd | 61 from . import convcmd |
57 | 62 |
58 super(p4_source, self).__init__(ui, repotype, path, revs=revs) | 63 super(p4_source, self).__init__(ui, repotype, path, revs=revs) |
59 | 64 |
60 if "/" in path and not path.startswith('//'): | 65 if b"/" in path and not path.startswith(b'//'): |
61 raise common.NoRepo( | 66 raise common.NoRepo( |
62 _('%s does not look like a P4 repository') % path | 67 _(b'%s does not look like a P4 repository') % path |
63 ) | 68 ) |
64 | 69 |
65 common.checktool('p4', abort=False) | 70 common.checktool(b'p4', abort=False) |
66 | 71 |
67 self.revmap = {} | 72 self.revmap = {} |
68 self.encoding = self.ui.config( | 73 self.encoding = self.ui.config( |
69 'convert', 'p4.encoding', convcmd.orig_encoding | 74 b'convert', b'p4.encoding', convcmd.orig_encoding |
70 ) | 75 ) |
71 self.re_type = re.compile( | 76 self.re_type = re.compile( |
72 br"([a-z]+)?(text|binary|symlink|apple|resource|unicode|utf\d+)" | 77 br"([a-z]+)?(text|binary|symlink|apple|resource|unicode|utf\d+)" |
73 br"(\+\w+)?$" | 78 br"(\+\w+)?$" |
74 ) | 79 ) |
78 ) | 83 ) |
79 self.re_keywords_old = re.compile(br"\$(Id|Header):[^$\n]*\$") | 84 self.re_keywords_old = re.compile(br"\$(Id|Header):[^$\n]*\$") |
80 | 85 |
81 if revs and len(revs) > 1: | 86 if revs and len(revs) > 1: |
82 raise error.Abort( | 87 raise error.Abort( |
83 _("p4 source does not support specifying " "multiple revisions") | 88 _( |
89 b"p4 source does not support specifying " | |
90 b"multiple revisions" | |
91 ) | |
84 ) | 92 ) |
85 | 93 |
86 def setrevmap(self, revmap): | 94 def setrevmap(self, revmap): |
87 """Sets the parsed revmap dictionary. | 95 """Sets the parsed revmap dictionary. |
88 | 96 |
95 imports if a revmap is provided. | 103 imports if a revmap is provided. |
96 """ | 104 """ |
97 self.revmap = revmap | 105 self.revmap = revmap |
98 | 106 |
99 def _parse_view(self, path): | 107 def _parse_view(self, path): |
100 "Read changes affecting the path" | 108 b"Read changes affecting the path" |
101 cmd = 'p4 -G changes -s submitted %s' % procutil.shellquote(path) | 109 cmd = b'p4 -G changes -s submitted %s' % procutil.shellquote(path) |
102 stdout = procutil.popen(cmd, mode='rb') | 110 stdout = procutil.popen(cmd, mode=b'rb') |
103 p4changes = {} | 111 p4changes = {} |
104 for d in loaditer(stdout): | 112 for d in loaditer(stdout): |
105 c = d.get("change", None) | 113 c = d.get(b"change", None) |
106 if c: | 114 if c: |
107 p4changes[c] = True | 115 p4changes[c] = True |
108 return p4changes | 116 return p4changes |
109 | 117 |
110 def _parse(self, ui, path): | 118 def _parse(self, ui, path): |
111 "Prepare list of P4 filenames and revisions to import" | 119 b"Prepare list of P4 filenames and revisions to import" |
112 p4changes = {} | 120 p4changes = {} |
113 changeset = {} | 121 changeset = {} |
114 files_map = {} | 122 files_map = {} |
115 copies_map = {} | 123 copies_map = {} |
116 localname = {} | 124 localname = {} |
117 depotname = {} | 125 depotname = {} |
118 heads = [] | 126 heads = [] |
119 | 127 |
120 ui.status(_('reading p4 views\n')) | 128 ui.status(_(b'reading p4 views\n')) |
121 | 129 |
122 # read client spec or view | 130 # read client spec or view |
123 if "/" in path: | 131 if b"/" in path: |
124 p4changes.update(self._parse_view(path)) | 132 p4changes.update(self._parse_view(path)) |
125 if path.startswith("//") and path.endswith("/..."): | 133 if path.startswith(b"//") and path.endswith(b"/..."): |
126 views = {path[:-3]: ""} | 134 views = {path[:-3]: b""} |
127 else: | 135 else: |
128 views = {"//": ""} | 136 views = {b"//": b""} |
129 else: | 137 else: |
130 cmd = 'p4 -G client -o %s' % procutil.shellquote(path) | 138 cmd = b'p4 -G client -o %s' % procutil.shellquote(path) |
131 clientspec = marshal.load(procutil.popen(cmd, mode='rb')) | 139 clientspec = marshal.load(procutil.popen(cmd, mode=b'rb')) |
132 | 140 |
133 views = {} | 141 views = {} |
134 for client in clientspec: | 142 for client in clientspec: |
135 if client.startswith("View"): | 143 if client.startswith(b"View"): |
136 sview, cview = clientspec[client].split() | 144 sview, cview = clientspec[client].split() |
137 p4changes.update(self._parse_view(sview)) | 145 p4changes.update(self._parse_view(sview)) |
138 if sview.endswith("...") and cview.endswith("..."): | 146 if sview.endswith(b"...") and cview.endswith(b"..."): |
139 sview = sview[:-3] | 147 sview = sview[:-3] |
140 cview = cview[:-3] | 148 cview = cview[:-3] |
141 cview = cview[2:] | 149 cview = cview[2:] |
142 cview = cview[cview.find("/") + 1 :] | 150 cview = cview[cview.find(b"/") + 1 :] |
143 views[sview] = cview | 151 views[sview] = cview |
144 | 152 |
145 # list of changes that affect our source files | 153 # list of changes that affect our source files |
146 p4changes = p4changes.keys() | 154 p4changes = p4changes.keys() |
147 p4changes.sort(key=int) | 155 p4changes.sort(key=int) |
149 # list with depot pathnames, longest first | 157 # list with depot pathnames, longest first |
150 vieworder = views.keys() | 158 vieworder = views.keys() |
151 vieworder.sort(key=len, reverse=True) | 159 vieworder.sort(key=len, reverse=True) |
152 | 160 |
153 # handle revision limiting | 161 # handle revision limiting |
154 startrev = self.ui.config('convert', 'p4.startrev') | 162 startrev = self.ui.config(b'convert', b'p4.startrev') |
155 | 163 |
156 # now read the full changelists to get the list of file revisions | 164 # now read the full changelists to get the list of file revisions |
157 ui.status(_('collecting p4 changelists\n')) | 165 ui.status(_(b'collecting p4 changelists\n')) |
158 lastid = None | 166 lastid = None |
159 for change in p4changes: | 167 for change in p4changes: |
160 if startrev and int(change) < int(startrev): | 168 if startrev and int(change) < int(startrev): |
161 continue | 169 continue |
162 if self.revs and int(change) > int(self.revs[0]): | 170 if self.revs and int(change) > int(self.revs[0]): |
174 d = self._fetch_revision(change) | 182 d = self._fetch_revision(change) |
175 c = self._construct_commit(d, parents) | 183 c = self._construct_commit(d, parents) |
176 | 184 |
177 descarr = c.desc.splitlines(True) | 185 descarr = c.desc.splitlines(True) |
178 if len(descarr) > 0: | 186 if len(descarr) > 0: |
179 shortdesc = descarr[0].rstrip('\r\n') | 187 shortdesc = descarr[0].rstrip(b'\r\n') |
180 else: | 188 else: |
181 shortdesc = '**empty changelist description**' | 189 shortdesc = b'**empty changelist description**' |
182 | 190 |
183 t = '%s %s' % (c.rev, repr(shortdesc)[1:-1]) | 191 t = b'%s %s' % (c.rev, repr(shortdesc)[1:-1]) |
184 ui.status(stringutil.ellipsis(t, 80) + '\n') | 192 ui.status(stringutil.ellipsis(t, 80) + b'\n') |
185 | 193 |
186 files = [] | 194 files = [] |
187 copies = {} | 195 copies = {} |
188 copiedfiles = [] | 196 copiedfiles = [] |
189 i = 0 | 197 i = 0 |
190 while ("depotFile%d" % i) in d and ("rev%d" % i) in d: | 198 while (b"depotFile%d" % i) in d and (b"rev%d" % i) in d: |
191 oldname = d["depotFile%d" % i] | 199 oldname = d[b"depotFile%d" % i] |
192 filename = None | 200 filename = None |
193 for v in vieworder: | 201 for v in vieworder: |
194 if oldname.lower().startswith(v.lower()): | 202 if oldname.lower().startswith(v.lower()): |
195 filename = decodefilename(views[v] + oldname[len(v) :]) | 203 filename = decodefilename(views[v] + oldname[len(v) :]) |
196 break | 204 break |
197 if filename: | 205 if filename: |
198 files.append((filename, d["rev%d" % i])) | 206 files.append((filename, d[b"rev%d" % i])) |
199 depotname[filename] = oldname | 207 depotname[filename] = oldname |
200 if d.get("action%d" % i) == "move/add": | 208 if d.get(b"action%d" % i) == b"move/add": |
201 copiedfiles.append(filename) | 209 copiedfiles.append(filename) |
202 localname[oldname] = filename | 210 localname[oldname] = filename |
203 i += 1 | 211 i += 1 |
204 | 212 |
205 # Collect information about copied files | 213 # Collect information about copied files |
206 for filename in copiedfiles: | 214 for filename in copiedfiles: |
207 oldname = depotname[filename] | 215 oldname = depotname[filename] |
208 | 216 |
209 flcmd = 'p4 -G filelog %s' % procutil.shellquote(oldname) | 217 flcmd = b'p4 -G filelog %s' % procutil.shellquote(oldname) |
210 flstdout = procutil.popen(flcmd, mode='rb') | 218 flstdout = procutil.popen(flcmd, mode=b'rb') |
211 | 219 |
212 copiedfilename = None | 220 copiedfilename = None |
213 for d in loaditer(flstdout): | 221 for d in loaditer(flstdout): |
214 copiedoldname = None | 222 copiedoldname = None |
215 | 223 |
216 i = 0 | 224 i = 0 |
217 while ("change%d" % i) in d: | 225 while (b"change%d" % i) in d: |
218 if ( | 226 if ( |
219 d["change%d" % i] == change | 227 d[b"change%d" % i] == change |
220 and d["action%d" % i] == "move/add" | 228 and d[b"action%d" % i] == b"move/add" |
221 ): | 229 ): |
222 j = 0 | 230 j = 0 |
223 while ("file%d,%d" % (i, j)) in d: | 231 while (b"file%d,%d" % (i, j)) in d: |
224 if d["how%d,%d" % (i, j)] == "moved from": | 232 if d[b"how%d,%d" % (i, j)] == b"moved from": |
225 copiedoldname = d["file%d,%d" % (i, j)] | 233 copiedoldname = d[b"file%d,%d" % (i, j)] |
226 break | 234 break |
227 j += 1 | 235 j += 1 |
228 i += 1 | 236 i += 1 |
229 | 237 |
230 if copiedoldname and copiedoldname in localname: | 238 if copiedoldname and copiedoldname in localname: |
233 | 241 |
234 if copiedfilename: | 242 if copiedfilename: |
235 copies[filename] = copiedfilename | 243 copies[filename] = copiedfilename |
236 else: | 244 else: |
237 ui.warn( | 245 ui.warn( |
238 _("cannot find source for copied file: %s@%s\n") | 246 _(b"cannot find source for copied file: %s@%s\n") |
239 % (filename, change) | 247 % (filename, change) |
240 ) | 248 ) |
241 | 249 |
242 changeset[change] = c | 250 changeset[change] = c |
243 files_map[change] = files | 251 files_map[change] = files |
246 | 254 |
247 if lastid and len(changeset) > 0: | 255 if lastid and len(changeset) > 0: |
248 heads = [lastid] | 256 heads = [lastid] |
249 | 257 |
250 return { | 258 return { |
251 'changeset': changeset, | 259 b'changeset': changeset, |
252 'files': files_map, | 260 b'files': files_map, |
253 'copies': copies_map, | 261 b'copies': copies_map, |
254 'heads': heads, | 262 b'heads': heads, |
255 'depotname': depotname, | 263 b'depotname': depotname, |
256 } | 264 } |
257 | 265 |
258 @util.propertycache | 266 @util.propertycache |
259 def _parse_once(self): | 267 def _parse_once(self): |
260 return self._parse(self.ui, self.path) | 268 return self._parse(self.ui, self.path) |
261 | 269 |
262 @util.propertycache | 270 @util.propertycache |
263 def copies(self): | 271 def copies(self): |
264 return self._parse_once['copies'] | 272 return self._parse_once[b'copies'] |
265 | 273 |
266 @util.propertycache | 274 @util.propertycache |
267 def files(self): | 275 def files(self): |
268 return self._parse_once['files'] | 276 return self._parse_once[b'files'] |
269 | 277 |
270 @util.propertycache | 278 @util.propertycache |
271 def changeset(self): | 279 def changeset(self): |
272 return self._parse_once['changeset'] | 280 return self._parse_once[b'changeset'] |
273 | 281 |
274 @util.propertycache | 282 @util.propertycache |
275 def heads(self): | 283 def heads(self): |
276 return self._parse_once['heads'] | 284 return self._parse_once[b'heads'] |
277 | 285 |
278 @util.propertycache | 286 @util.propertycache |
279 def depotname(self): | 287 def depotname(self): |
280 return self._parse_once['depotname'] | 288 return self._parse_once[b'depotname'] |
281 | 289 |
282 def getheads(self): | 290 def getheads(self): |
283 return self.heads | 291 return self.heads |
284 | 292 |
285 def getfile(self, name, rev): | 293 def getfile(self, name, rev): |
286 cmd = 'p4 -G print %s' % procutil.shellquote( | 294 cmd = b'p4 -G print %s' % procutil.shellquote( |
287 "%s#%s" % (self.depotname[name], rev) | 295 b"%s#%s" % (self.depotname[name], rev) |
288 ) | 296 ) |
289 | 297 |
290 lasterror = None | 298 lasterror = None |
291 while True: | 299 while True: |
292 stdout = procutil.popen(cmd, mode='rb') | 300 stdout = procutil.popen(cmd, mode=b'rb') |
293 | 301 |
294 mode = None | 302 mode = None |
295 contents = [] | 303 contents = [] |
296 keywords = None | 304 keywords = None |
297 | 305 |
298 for d in loaditer(stdout): | 306 for d in loaditer(stdout): |
299 code = d["code"] | 307 code = d[b"code"] |
300 data = d.get("data") | 308 data = d.get(b"data") |
301 | 309 |
302 if code == "error": | 310 if code == b"error": |
303 # if this is the first time error happened | 311 # if this is the first time error happened |
304 # re-attempt getting the file | 312 # re-attempt getting the file |
305 if not lasterror: | 313 if not lasterror: |
306 lasterror = IOError(d["generic"], data) | 314 lasterror = IOError(d[b"generic"], data) |
307 # this will exit inner-most for-loop | 315 # this will exit inner-most for-loop |
308 break | 316 break |
309 else: | 317 else: |
310 raise lasterror | 318 raise lasterror |
311 | 319 |
312 elif code == "stat": | 320 elif code == b"stat": |
313 action = d.get("action") | 321 action = d.get(b"action") |
314 if action in ["purge", "delete", "move/delete"]: | 322 if action in [b"purge", b"delete", b"move/delete"]: |
315 return None, None | 323 return None, None |
316 p4type = self.re_type.match(d["type"]) | 324 p4type = self.re_type.match(d[b"type"]) |
317 if p4type: | 325 if p4type: |
318 mode = "" | 326 mode = b"" |
319 flags = (p4type.group(1) or "") + ( | 327 flags = (p4type.group(1) or b"") + ( |
320 p4type.group(3) or "" | 328 p4type.group(3) or b"" |
321 ) | 329 ) |
322 if "x" in flags: | 330 if b"x" in flags: |
323 mode = "x" | 331 mode = b"x" |
324 if p4type.group(2) == "symlink": | 332 if p4type.group(2) == b"symlink": |
325 mode = "l" | 333 mode = b"l" |
326 if "ko" in flags: | 334 if b"ko" in flags: |
327 keywords = self.re_keywords_old | 335 keywords = self.re_keywords_old |
328 elif "k" in flags: | 336 elif b"k" in flags: |
329 keywords = self.re_keywords | 337 keywords = self.re_keywords |
330 | 338 |
331 elif code == "text" or code == "binary": | 339 elif code == b"text" or code == b"binary": |
332 contents.append(data) | 340 contents.append(data) |
333 | 341 |
334 lasterror = None | 342 lasterror = None |
335 | 343 |
336 if not lasterror: | 344 if not lasterror: |
337 break | 345 break |
338 | 346 |
339 if mode is None: | 347 if mode is None: |
340 return None, None | 348 return None, None |
341 | 349 |
342 contents = ''.join(contents) | 350 contents = b''.join(contents) |
343 | 351 |
344 if keywords: | 352 if keywords: |
345 contents = keywords.sub("$\\1$", contents) | 353 contents = keywords.sub(b"$\\1$", contents) |
346 if mode == "l" and contents.endswith("\n"): | 354 if mode == b"l" and contents.endswith(b"\n"): |
347 contents = contents[:-1] | 355 contents = contents[:-1] |
348 | 356 |
349 return contents, mode | 357 return contents, mode |
350 | 358 |
351 def getchanges(self, rev, full): | 359 def getchanges(self, rev, full): |
352 if full: | 360 if full: |
353 raise error.Abort(_("convert from p4 does not support --full")) | 361 raise error.Abort(_(b"convert from p4 does not support --full")) |
354 return self.files[rev], self.copies[rev], set() | 362 return self.files[rev], self.copies[rev], set() |
355 | 363 |
356 def _construct_commit(self, obj, parents=None): | 364 def _construct_commit(self, obj, parents=None): |
357 """ | 365 """ |
358 Constructs a common.commit object from an unmarshalled | 366 Constructs a common.commit object from an unmarshalled |
359 `p4 describe` output | 367 `p4 describe` output |
360 """ | 368 """ |
361 desc = self.recode(obj.get("desc", "")) | 369 desc = self.recode(obj.get(b"desc", b"")) |
362 date = (int(obj["time"]), 0) # timezone not set | 370 date = (int(obj[b"time"]), 0) # timezone not set |
363 if parents is None: | 371 if parents is None: |
364 parents = [] | 372 parents = [] |
365 | 373 |
366 return common.commit( | 374 return common.commit( |
367 author=self.recode(obj["user"]), | 375 author=self.recode(obj[b"user"]), |
368 date=dateutil.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'), | 376 date=dateutil.datestr(date, b'%Y-%m-%d %H:%M:%S %1%2'), |
369 parents=parents, | 377 parents=parents, |
370 desc=desc, | 378 desc=desc, |
371 branch=None, | 379 branch=None, |
372 rev=obj['change'], | 380 rev=obj[b'change'], |
373 extra={"p4": obj['change'], "convert_revision": obj['change']}, | 381 extra={b"p4": obj[b'change'], b"convert_revision": obj[b'change']}, |
374 ) | 382 ) |
375 | 383 |
376 def _fetch_revision(self, rev): | 384 def _fetch_revision(self, rev): |
377 """Return an output of `p4 describe` including author, commit date as | 385 """Return an output of `p4 describe` including author, commit date as |
378 a dictionary.""" | 386 a dictionary.""" |
379 cmd = "p4 -G describe -s %s" % rev | 387 cmd = b"p4 -G describe -s %s" % rev |
380 stdout = procutil.popen(cmd, mode='rb') | 388 stdout = procutil.popen(cmd, mode=b'rb') |
381 return marshal.load(stdout) | 389 return marshal.load(stdout) |
382 | 390 |
383 def getcommit(self, rev): | 391 def getcommit(self, rev): |
384 if rev in self.changeset: | 392 if rev in self.changeset: |
385 return self.changeset[rev] | 393 return self.changeset[rev] |
386 elif rev in self.revmap: | 394 elif rev in self.revmap: |
387 d = self._fetch_revision(rev) | 395 d = self._fetch_revision(rev) |
388 return self._construct_commit(d, parents=None) | 396 return self._construct_commit(d, parents=None) |
389 raise error.Abort( | 397 raise error.Abort( |
390 _("cannot find %s in the revmap or parsed changesets") % rev | 398 _(b"cannot find %s in the revmap or parsed changesets") % rev |
391 ) | 399 ) |
392 | 400 |
393 def gettags(self): | 401 def gettags(self): |
394 return {} | 402 return {} |
395 | 403 |