19 import weakref, errno, os, time, inspect |
19 import weakref, errno, os, time, inspect |
20 propertycache = util.propertycache |
20 propertycache = util.propertycache |
21 |
21 |
22 class localrepository(repo.repository): |
22 class localrepository(repo.repository): |
23 capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey', |
23 capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey', |
24 'known')) |
24 'known', 'getbundle')) |
25 supportedformats = set(('revlogv1', 'parentdelta')) |
25 supportedformats = set(('revlogv1', 'parentdelta')) |
26 supported = supportedformats | set(('store', 'fncache', 'shared', |
26 supported = supportedformats | set(('store', 'fncache', 'shared', |
27 'dotencode')) |
27 'dotencode')) |
28 |
28 |
29 def __init__(self, baseui, path=None, create=0): |
29 def __init__(self, baseui, path=None, create=0): |
1441 is non-trivial. |
1441 is non-trivial. |
1442 |
1442 |
1443 Another wrinkle is doing the reverse, figuring out which changeset in |
1443 Another wrinkle is doing the reverse, figuring out which changeset in |
1444 the changegroup a particular filenode or manifestnode belongs to. |
1444 the changegroup a particular filenode or manifestnode belongs to. |
1445 """ |
1445 """ |
|
1446 cl = self.changelog |
|
1447 if not bases: |
|
1448 bases = [nullid] |
|
1449 csets, bases, heads = cl.nodesbetween(bases, heads) |
|
1450 # We assume that all ancestors of bases are known |
|
1451 common = set(cl.ancestors(*[cl.rev(n) for n in bases])) |
|
1452 return self._changegroupsubset(common, csets, heads, source) |
|
1453 |
|
1454 def getbundle(self, source, heads=None, common=None): |
|
1455 """Like changegroupsubset, but returns the set difference between the |
|
1456 ancestors of heads and the ancestors common. |
|
1457 |
|
1458 If heads is None, use the local heads. If common is None, use [nullid]. |
|
1459 |
|
1460 The nodes in common might not all be known locally due to the way the |
|
1461 current discovery protocol works. |
|
1462 """ |
|
1463 cl = self.changelog |
|
1464 if common: |
|
1465 nm = cl.nodemap |
|
1466 common = [n for n in common if n in nm] |
|
1467 else: |
|
1468 common = [nullid] |
|
1469 if not heads: |
|
1470 heads = cl.heads() |
|
1471 common, missing = cl.findcommonmissing(common, heads) |
|
1472 return self._changegroupsubset(common, missing, heads, source) |
|
1473 |
|
1474 def _changegroupsubset(self, commonrevs, csets, heads, source): |
1446 |
1475 |
1447 cl = self.changelog |
1476 cl = self.changelog |
1448 mf = self.manifest |
1477 mf = self.manifest |
1449 mfs = {} # needed manifests |
1478 mfs = {} # needed manifests |
1450 fnodes = {} # needed file nodes |
1479 fnodes = {} # needed file nodes |
1451 |
1480 |
1452 if not bases: |
|
1453 bases = [nullid] |
|
1454 csets, bases, heads = cl.nodesbetween(bases, heads) |
|
1455 |
|
1456 # can we go through the fast path ? |
1481 # can we go through the fast path ? |
1457 heads.sort() |
1482 heads.sort() |
1458 if heads == sorted(self.heads()): |
1483 if heads == sorted(self.heads()): |
1459 return self._changegroup(csets, source) |
1484 return self._changegroup(csets, source) |
1460 |
1485 |
1461 # slow path |
1486 # slow path |
1462 self.hook('preoutgoing', throw=True, source=source) |
1487 self.hook('preoutgoing', throw=True, source=source) |
1463 self.changegroupinfo(csets, source) |
1488 self.changegroupinfo(csets, source) |
1464 |
|
1465 # We assume that all ancestors of bases are known |
|
1466 commonrevs = set(cl.ancestors(*[cl.rev(n) for n in bases])) |
|
1467 |
1489 |
1468 # A function generating function that sets up the initial environment |
1490 # A function generating function that sets up the initial environment |
1469 # the inner function. |
1491 # the inner function. |
1470 def filenode_collector(changedfiles): |
1492 def filenode_collector(changedfiles): |
1471 # This gathers information from each manifestnode included in the |
1493 # This gathers information from each manifestnode included in the |