comparison mercurial/localrepo.py @ 20933:d3775db748a0

localrepo: move the addchangegroup method in changegroup module This is a gratuitous code move aimed at reducing the localrepo bloatness. The method had few callers, not enough to be kept in local repo.
author Pierre-Yves David <pierre-yves.david@fb.com>
date Tue, 01 Apr 2014 15:27:53 -0700
parents 0ac83e4e4f7c
children 8d853cad6b14
comparison
equal deleted inserted replaced
20932:0ac83e4e4f7c 20933:d3775db748a0
112 112
113 def lock(self): 113 def lock(self):
114 return self._repo.lock() 114 return self._repo.lock()
115 115
116 def addchangegroup(self, cg, source, url): 116 def addchangegroup(self, cg, source, url):
117 return self._repo.addchangegroup(cg, source, url) 117 return changegroup.addchangegroup(self._repo, cg, source, url)
118 118
119 def pushkey(self, namespace, key, old, new): 119 def pushkey(self, namespace, key, old, new):
120 return self._repo.pushkey(namespace, key, old, new) 120 return self._repo.pushkey(namespace, key, old, new)
121 121
122 def listkeys(self, namespace): 122 def listkeys(self, namespace):
1681 pass 1681 pass
1682 1682
1683 def push(self, remote, force=False, revs=None, newbranch=False): 1683 def push(self, remote, force=False, revs=None, newbranch=False):
1684 return exchange.push(self, remote, force, revs, newbranch) 1684 return exchange.push(self, remote, force, revs, newbranch)
1685 1685
1686 @unfilteredmethod
1687 def addchangegroup(self, source, srctype, url, emptyok=False):
1688 """Add the changegroup returned by source.read() to this repo.
1689 srctype is a string like 'push', 'pull', or 'unbundle'. url is
1690 the URL of the repo where this changegroup is coming from.
1691
1692 Return an integer summarizing the change to this repo:
1693 - nothing changed or no source: 0
1694 - more heads than before: 1+added heads (2..n)
1695 - fewer heads than before: -1-removed heads (-2..-n)
1696 - number of heads stays the same: 1
1697 """
1698 def csmap(x):
1699 self.ui.debug("add changeset %s\n" % short(x))
1700 return len(cl)
1701
1702 def revmap(x):
1703 return cl.rev(x)
1704
1705 if not source:
1706 return 0
1707
1708 self.hook('prechangegroup', throw=True, source=srctype, url=url)
1709
1710 changesets = files = revisions = 0
1711 efiles = set()
1712
1713 # write changelog data to temp files so concurrent readers will not see
1714 # inconsistent view
1715 cl = self.changelog
1716 cl.delayupdate()
1717 oldheads = cl.heads()
1718
1719 tr = self.transaction("\n".join([srctype, util.hidepassword(url)]))
1720 try:
1721 trp = weakref.proxy(tr)
1722 # pull off the changeset group
1723 self.ui.status(_("adding changesets\n"))
1724 clstart = len(cl)
1725 class prog(object):
1726 step = _('changesets')
1727 count = 1
1728 ui = self.ui
1729 total = None
1730 def __call__(self):
1731 self.ui.progress(self.step, self.count, unit=_('chunks'),
1732 total=self.total)
1733 self.count += 1
1734 pr = prog()
1735 source.callback = pr
1736
1737 source.changelogheader()
1738 srccontent = cl.addgroup(source, csmap, trp)
1739 if not (srccontent or emptyok):
1740 raise util.Abort(_("received changelog group is empty"))
1741 clend = len(cl)
1742 changesets = clend - clstart
1743 for c in xrange(clstart, clend):
1744 efiles.update(self[c].files())
1745 efiles = len(efiles)
1746 self.ui.progress(_('changesets'), None)
1747
1748 # pull off the manifest group
1749 self.ui.status(_("adding manifests\n"))
1750 pr.step = _('manifests')
1751 pr.count = 1
1752 pr.total = changesets # manifests <= changesets
1753 # no need to check for empty manifest group here:
1754 # if the result of the merge of 1 and 2 is the same in 3 and 4,
1755 # no new manifest will be created and the manifest group will
1756 # be empty during the pull
1757 source.manifestheader()
1758 self.manifest.addgroup(source, revmap, trp)
1759 self.ui.progress(_('manifests'), None)
1760
1761 needfiles = {}
1762 if self.ui.configbool('server', 'validate', default=False):
1763 # validate incoming csets have their manifests
1764 for cset in xrange(clstart, clend):
1765 mfest = self.changelog.read(self.changelog.node(cset))[0]
1766 mfest = self.manifest.readdelta(mfest)
1767 # store file nodes we must see
1768 for f, n in mfest.iteritems():
1769 needfiles.setdefault(f, set()).add(n)
1770
1771 # process the files
1772 self.ui.status(_("adding file changes\n"))
1773 pr.step = _('files')
1774 pr.count = 1
1775 pr.total = efiles
1776 source.callback = None
1777
1778 newrevs, newfiles = changegroup.addchangegroupfiles(self,
1779 source,
1780 revmap,
1781 trp,
1782 pr,
1783 needfiles)
1784 revisions += newrevs
1785 files += newfiles
1786
1787 dh = 0
1788 if oldheads:
1789 heads = cl.heads()
1790 dh = len(heads) - len(oldheads)
1791 for h in heads:
1792 if h not in oldheads and self[h].closesbranch():
1793 dh -= 1
1794 htext = ""
1795 if dh:
1796 htext = _(" (%+d heads)") % dh
1797
1798 self.ui.status(_("added %d changesets"
1799 " with %d changes to %d files%s\n")
1800 % (changesets, revisions, files, htext))
1801 self.invalidatevolatilesets()
1802
1803 if changesets > 0:
1804 p = lambda: cl.writepending() and self.root or ""
1805 self.hook('pretxnchangegroup', throw=True,
1806 node=hex(cl.node(clstart)), source=srctype,
1807 url=url, pending=p)
1808
1809 added = [cl.node(r) for r in xrange(clstart, clend)]
1810 publishing = self.ui.configbool('phases', 'publish', True)
1811 if srctype == 'push':
1812 # Old servers can not push the boundary themselves.
1813 # New servers won't push the boundary if changeset already
1814 # exists locally as secret
1815 #
1816 # We should not use added here but the list of all change in
1817 # the bundle
1818 if publishing:
1819 phases.advanceboundary(self, phases.public, srccontent)
1820 else:
1821 phases.advanceboundary(self, phases.draft, srccontent)
1822 phases.retractboundary(self, phases.draft, added)
1823 elif srctype != 'strip':
1824 # publishing only alter behavior during push
1825 #
1826 # strip should not touch boundary at all
1827 phases.retractboundary(self, phases.draft, added)
1828
1829 # make changelog see real files again
1830 cl.finalize(trp)
1831
1832 tr.close()
1833
1834 if changesets > 0:
1835 if srctype != 'strip':
1836 # During strip, branchcache is invalid but coming call to
1837 # `destroyed` will repair it.
1838 # In other case we can safely update cache on disk.
1839 branchmap.updatecache(self.filtered('served'))
1840 def runhooks():
1841 # These hooks run when the lock releases, not when the
1842 # transaction closes. So it's possible for the changelog
1843 # to have changed since we last saw it.
1844 if clstart >= len(self):
1845 return
1846
1847 # forcefully update the on-disk branch cache
1848 self.ui.debug("updating the branch cache\n")
1849 self.hook("changegroup", node=hex(cl.node(clstart)),
1850 source=srctype, url=url)
1851
1852 for n in added:
1853 self.hook("incoming", node=hex(n), source=srctype,
1854 url=url)
1855
1856 newheads = [h for h in self.heads() if h not in oldheads]
1857 self.ui.log("incoming",
1858 "%s incoming changes - new heads: %s\n",
1859 len(added),
1860 ', '.join([hex(c[:6]) for c in newheads]))
1861 self._afterlock(runhooks)
1862
1863 finally:
1864 tr.release()
1865 # never return 0 here:
1866 if dh < 0:
1867 return dh - 1
1868 else:
1869 return dh + 1
1870
1871
1872 def stream_in(self, remote, requirements): 1686 def stream_in(self, remote, requirements):
1873 lock = self.lock() 1687 lock = self.lock()
1874 try: 1688 try:
1875 # Save remote branchmap. We will use it later 1689 # Save remote branchmap. We will use it later
1876 # to speed up branchcache creation 1690 # to speed up branchcache creation