Mercurial > hg
comparison hgext/remotefilelog/remotefilectx.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 041d829575ed |
children | 687b865b95ad |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
20 from . import shallowutil | 20 from . import shallowutil |
21 | 21 |
22 propertycache = util.propertycache | 22 propertycache = util.propertycache |
23 FASTLOG_TIMEOUT_IN_SECS = 0.5 | 23 FASTLOG_TIMEOUT_IN_SECS = 0.5 |
24 | 24 |
25 | |
25 class remotefilectx(context.filectx): | 26 class remotefilectx(context.filectx): |
26 def __init__(self, repo, path, changeid=None, fileid=None, | 27 def __init__( |
27 filelog=None, changectx=None, ancestormap=None): | 28 self, |
29 repo, | |
30 path, | |
31 changeid=None, | |
32 fileid=None, | |
33 filelog=None, | |
34 changectx=None, | |
35 ancestormap=None, | |
36 ): | |
28 if fileid == nullrev: | 37 if fileid == nullrev: |
29 fileid = nullid | 38 fileid = nullid |
30 if fileid and len(fileid) == 40: | 39 if fileid and len(fileid) == 40: |
31 fileid = bin(fileid) | 40 fileid = bin(fileid) |
32 super(remotefilectx, self).__init__(repo, path, changeid, | 41 super(remotefilectx, self).__init__( |
33 fileid, filelog, changectx) | 42 repo, path, changeid, fileid, filelog, changectx |
43 ) | |
34 self._ancestormap = ancestormap | 44 self._ancestormap = ancestormap |
35 | 45 |
36 def size(self): | 46 def size(self): |
37 return self._filelog.size(self._filenode) | 47 return self._filelog.size(self._filenode) |
38 | 48 |
43 elif r'_changectx' in self.__dict__: | 53 elif r'_changectx' in self.__dict__: |
44 return self._changectx.rev() | 54 return self._changectx.rev() |
45 elif r'_descendantrev' in self.__dict__: | 55 elif r'_descendantrev' in self.__dict__: |
46 # this file context was created from a revision with a known | 56 # this file context was created from a revision with a known |
47 # descendant, we can (lazily) correct for linkrev aliases | 57 # descendant, we can (lazily) correct for linkrev aliases |
48 linknode = self._adjustlinknode(self._path, self._filelog, | 58 linknode = self._adjustlinknode( |
49 self._filenode, self._descendantrev) | 59 self._path, self._filelog, self._filenode, self._descendantrev |
60 ) | |
50 return self._repo.unfiltered().changelog.rev(linknode) | 61 return self._repo.unfiltered().changelog.rev(linknode) |
51 else: | 62 else: |
52 return self.linkrev() | 63 return self.linkrev() |
53 | 64 |
54 def filectx(self, fileid, changeid=None): | 65 def filectx(self, fileid, changeid=None): |
55 '''opens an arbitrary revision of the file without | 66 '''opens an arbitrary revision of the file without |
56 opening a new filelog''' | 67 opening a new filelog''' |
57 return remotefilectx(self._repo, self._path, fileid=fileid, | 68 return remotefilectx( |
58 filelog=self._filelog, changeid=changeid) | 69 self._repo, |
70 self._path, | |
71 fileid=fileid, | |
72 filelog=self._filelog, | |
73 changeid=changeid, | |
74 ) | |
59 | 75 |
60 def linkrev(self): | 76 def linkrev(self): |
61 return self._linkrev | 77 return self._linkrev |
62 | 78 |
63 @propertycache | 79 @propertycache |
77 cl = self._repo.unfiltered().changelog | 93 cl = self._repo.unfiltered().changelog |
78 mfl = self._repo.manifestlog | 94 mfl = self._repo.manifestlog |
79 | 95 |
80 for rev in range(len(cl) - 1, 0, -1): | 96 for rev in range(len(cl) - 1, 0, -1): |
81 node = cl.node(rev) | 97 node = cl.node(rev) |
82 data = cl.read(node) # get changeset data (we avoid object creation) | 98 data = cl.read( |
83 if path in data[3]: # checking the 'files' field. | 99 node |
100 ) # get changeset data (we avoid object creation) | |
101 if path in data[3]: # checking the 'files' field. | |
84 # The file has been touched, check if the hash is what we're | 102 # The file has been touched, check if the hash is what we're |
85 # looking for. | 103 # looking for. |
86 if fileid == mfl[data[0]].readfast().get(path): | 104 if fileid == mfl[data[0]].readfast().get(path): |
87 return rev | 105 return rev |
88 | 106 |
102 lkr = self.linkrev() | 120 lkr = self.linkrev() |
103 attrs = vars(self) | 121 attrs = vars(self) |
104 noctx = not (r'_changeid' in attrs or r'_changectx' in attrs) | 122 noctx = not (r'_changeid' in attrs or r'_changectx' in attrs) |
105 if noctx or self.rev() == lkr: | 123 if noctx or self.rev() == lkr: |
106 return lkr | 124 return lkr |
107 linknode = self._adjustlinknode(self._path, self._filelog, | 125 linknode = self._adjustlinknode( |
108 self._filenode, self.rev(), | 126 self._path, |
109 inclusive=True) | 127 self._filelog, |
128 self._filenode, | |
129 self.rev(), | |
130 inclusive=True, | |
131 ) | |
110 return self._repo.changelog.rev(linknode) | 132 return self._repo.changelog.rev(linknode) |
111 | 133 |
112 def renamed(self): | 134 def renamed(self): |
113 """check if file was actually renamed in this changeset revision | 135 """check if file was actually renamed in this changeset revision |
114 | 136 |
153 p1, p2, linknode, copyfrom = ancestormap[self._filenode] | 175 p1, p2, linknode, copyfrom = ancestormap[self._filenode] |
154 results = [] | 176 results = [] |
155 if p1 != nullid: | 177 if p1 != nullid: |
156 path = copyfrom or self._path | 178 path = copyfrom or self._path |
157 flog = repo.file(path) | 179 flog = repo.file(path) |
158 p1ctx = remotefilectx(repo, path, fileid=p1, filelog=flog, | 180 p1ctx = remotefilectx( |
159 ancestormap=ancestormap) | 181 repo, path, fileid=p1, filelog=flog, ancestormap=ancestormap |
182 ) | |
160 p1ctx._descendantrev = self.rev() | 183 p1ctx._descendantrev = self.rev() |
161 results.append(p1ctx) | 184 results.append(p1ctx) |
162 | 185 |
163 if p2 != nullid: | 186 if p2 != nullid: |
164 path = self._path | 187 path = self._path |
165 flog = repo.file(path) | 188 flog = repo.file(path) |
166 p2ctx = remotefilectx(repo, path, fileid=p2, filelog=flog, | 189 p2ctx = remotefilectx( |
167 ancestormap=ancestormap) | 190 repo, path, fileid=p2, filelog=flog, ancestormap=ancestormap |
191 ) | |
168 p2ctx._descendantrev = self.rev() | 192 p2ctx._descendantrev = self.rev() |
169 results.append(p2ctx) | 193 results.append(p2ctx) |
170 | 194 |
171 return results | 195 return results |
172 | 196 |
173 def _nodefromancrev(self, ancrev, cl, mfl, path, fnode): | 197 def _nodefromancrev(self, ancrev, cl, mfl, path, fnode): |
174 """returns the node for <path> in <ancrev> if content matches <fnode>""" | 198 """returns the node for <path> in <ancrev> if content matches <fnode>""" |
175 ancctx = cl.read(ancrev) # This avoids object creation. | 199 ancctx = cl.read(ancrev) # This avoids object creation. |
176 manifestnode, files = ancctx[0], ancctx[3] | 200 manifestnode, files = ancctx[0], ancctx[3] |
177 # If the file was touched in this ancestor, and the content is similar | 201 # If the file was touched in this ancestor, and the content is similar |
178 # to the one we are searching for. | 202 # to the one we are searching for. |
179 if path in files and fnode == mfl[manifestnode].readfast().get(path): | 203 if path in files and fnode == mfl[manifestnode].readfast().get(path): |
180 return cl.node(ancrev) | 204 return cl.node(ancrev) |
212 linknode = ancestormap[fnode][2] | 236 linknode = ancestormap[fnode][2] |
213 | 237 |
214 if srcrev is None: | 238 if srcrev is None: |
215 # wctx case, used by workingfilectx during mergecopy | 239 # wctx case, used by workingfilectx during mergecopy |
216 revs = [p.rev() for p in self._repo[None].parents()] | 240 revs = [p.rev() for p in self._repo[None].parents()] |
217 inclusive = True # we skipped the real (revless) source | 241 inclusive = True # we skipped the real (revless) source |
218 else: | 242 else: |
219 revs = [srcrev] | 243 revs = [srcrev] |
220 | 244 |
221 if self._verifylinknode(revs, linknode): | 245 if self._verifylinknode(revs, linknode): |
222 return linknode | 246 return linknode |
245 # prefetch | 269 # prefetch |
246 if not seenpublic and pc.phase(repo, ancrev) == phases.public: | 270 if not seenpublic and pc.phase(repo, ancrev) == phases.public: |
247 # TODO: there used to be a codepath to fetch linknodes | 271 # TODO: there used to be a codepath to fetch linknodes |
248 # from a server as a fast path, but it appeared to | 272 # from a server as a fast path, but it appeared to |
249 # depend on an API FB added to their phabricator. | 273 # depend on an API FB added to their phabricator. |
250 lnode = self._forceprefetch(repo, path, fnode, revs, | 274 lnode = self._forceprefetch( |
251 commonlogkwargs) | 275 repo, path, fnode, revs, commonlogkwargs |
276 ) | |
252 if lnode: | 277 if lnode: |
253 return lnode | 278 return lnode |
254 seenpublic = True | 279 seenpublic = True |
255 | 280 |
256 return linknode | 281 return linknode |
257 | 282 |
258 def _forceprefetch(self, repo, path, fnode, revs, | 283 def _forceprefetch(self, repo, path, fnode, revs, commonlogkwargs): |
259 commonlogkwargs): | |
260 # This next part is super non-obvious, so big comment block time! | 284 # This next part is super non-obvious, so big comment block time! |
261 # | 285 # |
262 # It is possible to get extremely bad performance here when a fairly | 286 # It is possible to get extremely bad performance here when a fairly |
263 # common set of circumstances occur when this extension is combined | 287 # common set of circumstances occur when this extension is combined |
264 # with a server-side commit rewriting extension like pushrebase. | 288 # with a server-side commit rewriting extension like pushrebase. |
305 | 329 |
306 # Now that we've downloaded a new blob from the server, | 330 # Now that we've downloaded a new blob from the server, |
307 # we need to rebuild the ancestor map to recompute the | 331 # we need to rebuild the ancestor map to recompute the |
308 # linknodes. | 332 # linknodes. |
309 self._ancestormap = None | 333 self._ancestormap = None |
310 linknode = self.ancestormap()[fnode][2] # 2 is linknode | 334 linknode = self.ancestormap()[fnode][2] # 2 is linknode |
311 if self._verifylinknode(revs, linknode): | 335 if self._verifylinknode(revs, linknode): |
312 logmsg = 'remotefilelog prefetching succeeded' | 336 logmsg = 'remotefilelog prefetching succeeded' |
313 return linknode | 337 return linknode |
314 logmsg = 'remotefilelog prefetching not found' | 338 logmsg = 'remotefilelog prefetching not found' |
315 return None | 339 return None |
316 except Exception as e: | 340 except Exception as e: |
317 logmsg = 'remotefilelog prefetching failed (%s)' % e | 341 logmsg = 'remotefilelog prefetching failed (%s)' % e |
318 return None | 342 return None |
319 finally: | 343 finally: |
320 elapsed = time.time() - start | 344 elapsed = time.time() - start |
321 repo.ui.log('linkrevfixup', logmsg + '\n', elapsed=elapsed * 1000, | 345 repo.ui.log( |
322 **commonlogkwargs) | 346 'linkrevfixup', |
347 logmsg + '\n', | |
348 elapsed=elapsed * 1000, | |
349 **commonlogkwargs | |
350 ) | |
323 | 351 |
324 def _verifylinknode(self, revs, linknode): | 352 def _verifylinknode(self, revs, linknode): |
325 """ | 353 """ |
326 Check if a linknode is correct one for the current history. | 354 Check if a linknode is correct one for the current history. |
327 | 355 |
368 # Remove self | 396 # Remove self |
369 ancestors.pop(0) | 397 ancestors.pop(0) |
370 | 398 |
371 # Sort by linkrev | 399 # Sort by linkrev |
372 # The copy tracing algorithm depends on these coming out in order | 400 # The copy tracing algorithm depends on these coming out in order |
373 ancestors = sorted(ancestors, reverse=True, key=lambda x:x.linkrev()) | 401 ancestors = sorted(ancestors, reverse=True, key=lambda x: x.linkrev()) |
374 | 402 |
375 for ancestor in ancestors: | 403 for ancestor in ancestors: |
376 yield ancestor | 404 yield ancestor |
377 | 405 |
378 def ancestor(self, fc2, actx): | 406 def ancestor(self, fc2, actx): |
402 a = (self.path(), self.filenode()) | 430 a = (self.path(), self.filenode()) |
403 b = (fc2.path(), fc2.filenode()) | 431 b = (fc2.path(), fc2.filenode()) |
404 result = ancestor.genericancestor(a, b, parents) | 432 result = ancestor.genericancestor(a, b, parents) |
405 if result: | 433 if result: |
406 f, n = result | 434 f, n = result |
407 r = remotefilectx(self._repo, f, fileid=n, | 435 r = remotefilectx(self._repo, f, fileid=n, ancestormap=amap) |
408 ancestormap=amap) | |
409 return r | 436 return r |
410 | 437 |
411 return None | 438 return None |
412 | 439 |
413 def annotate(self, *args, **kwargs): | 440 def annotate(self, *args, **kwargs): |
415 prefetchskip = kwargs.pop(r'prefetchskip', None) | 442 prefetchskip = kwargs.pop(r'prefetchskip', None) |
416 if prefetchskip: | 443 if prefetchskip: |
417 # use introrev so prefetchskip can be accurately tested | 444 # use introrev so prefetchskip can be accurately tested |
418 introrev = self.introrev() | 445 introrev = self.introrev() |
419 if self.rev() != introrev: | 446 if self.rev() != introrev: |
420 introctx = remotefilectx(self._repo, self._path, | 447 introctx = remotefilectx( |
421 changeid=introrev, | 448 self._repo, |
422 fileid=self._filenode, | 449 self._path, |
423 filelog=self._filelog, | 450 changeid=introrev, |
424 ancestormap=self._ancestormap) | 451 fileid=self._filenode, |
452 filelog=self._filelog, | |
453 ancestormap=self._ancestormap, | |
454 ) | |
425 | 455 |
426 # like self.ancestors, but append to "fetch" and skip visiting parents | 456 # like self.ancestors, but append to "fetch" and skip visiting parents |
427 # of nodes in "prefetchskip". | 457 # of nodes in "prefetchskip". |
428 fetch = [] | 458 fetch = [] |
429 seen = set() | 459 seen = set() |
440 for parent in current.parents(): | 470 for parent in current.parents(): |
441 if parent.node() not in seen: | 471 if parent.node() not in seen: |
442 seen.add(parent.node()) | 472 seen.add(parent.node()) |
443 queue.append(parent) | 473 queue.append(parent) |
444 | 474 |
445 self._repo.ui.debug('remotefilelog: prefetching %d files ' | 475 self._repo.ui.debug( |
446 'for annotate\n' % len(fetch)) | 476 'remotefilelog: prefetching %d files ' 'for annotate\n' % len(fetch) |
477 ) | |
447 if fetch: | 478 if fetch: |
448 self._repo.fileservice.prefetch(fetch) | 479 self._repo.fileservice.prefetch(fetch) |
449 return super(remotefilectx, self).annotate(*args, **kwargs) | 480 return super(remotefilectx, self).annotate(*args, **kwargs) |
450 | 481 |
451 # Return empty set so that the hg serve and thg don't stack trace | 482 # Return empty set so that the hg serve and thg don't stack trace |
452 def children(self): | 483 def children(self): |
453 return [] | 484 return [] |
454 | 485 |
486 | |
455 class remoteworkingfilectx(context.workingfilectx, remotefilectx): | 487 class remoteworkingfilectx(context.workingfilectx, remotefilectx): |
456 def __init__(self, repo, path, filelog=None, workingctx=None): | 488 def __init__(self, repo, path, filelog=None, workingctx=None): |
457 self._ancestormap = None | 489 self._ancestormap = None |
458 super(remoteworkingfilectx, self).__init__(repo, path, filelog, | 490 super(remoteworkingfilectx, self).__init__( |
459 workingctx) | 491 repo, path, filelog, workingctx |
492 ) | |
460 | 493 |
461 def parents(self): | 494 def parents(self): |
462 return remotefilectx.parents(self) | 495 return remotefilectx.parents(self) |
463 | 496 |
464 def ancestormap(self): | 497 def ancestormap(self): |