def computeunserved(repo): """compute the set of revision that should be filtered when used a server Secret and hidden changeset should not pretend to be here.""" assert not repo.changelog.filteredrevs # fast path in simple case to avoid impact of non optimised code hiddens = filterrevs(repo, 'visible') if phases.hassecret(repo): cl = repo.changelog secret = phases.secret getphase = repo._phasecache.phase first = min(cl.rev(n) for n in repo._phasecache.phaseroots[secret]) revs = cl.revs(start=first) secrets = set(r for r in revs if getphase(repo, r) >= secret) return frozenset(hiddens | secrets) else: return hiddens
def clone(ui, peeropts, source, dest=None, pull=False, rev=None, update=True, stream=False, branch=None): """Make a copy of an existing repository. Create a copy of an existing repository in a new directory. The source and destination are URLs, as passed to the repository function. Returns a pair of repository peers, the source and newly created destination. The location of the source is added to the new repository's .hg/hgrc file, as the default to be used for future pulls and pushes. If an exception is raised, the partly cloned/updated destination repository will be deleted. Arguments: source: repository object or URL dest: URL of destination repository to create (defaults to base name of source repository) pull: always pull from source repository, even in local case or if the server prefers streaming stream: stream raw data uncompressed from repository (fast over LAN, slow over WAN) rev: revision to clone up to (implies pull=True) update: update working directory after clone completes, if destination is local repository (True means update to default rev, anything else is treated as a revision) branch: branches to clone """ if isinstance(source, str): origsource = ui.expandpath(source) source, branch = parseurl(origsource, branch) srcpeer = peer(ui, peeropts, source) else: srcpeer = source.peer() # in case we were called with a localrepo branch = (None, branch or []) origsource = source = srcpeer.url() rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev) if dest is None: dest = defaultdest(source) if dest: ui.status(_("destination directory: %s\n") % dest) else: dest = ui.expandpath(dest) dest = util.urllocalpath(dest) source = util.urllocalpath(source) if not dest: raise util.Abort(_("empty destination path is not valid")) destvfs = scmutil.vfs(dest, expandpath=True) if destvfs.lexists(): if not destvfs.isdir(): raise util.Abort(_("destination '%s' already exists") % dest) elif destvfs.listdir(): raise util.Abort(_("destination '%s' is not empty") % dest) srclock = destlock = cleandir = None srcrepo = srcpeer.local() try: abspath = origsource if islocal(origsource): abspath = os.path.abspath(util.urllocalpath(origsource)) if islocal(dest): cleandir = dest copy = False if (srcrepo and srcrepo.cancopy() and islocal(dest) and not phases.hassecret(srcrepo)): copy = not pull and not rev if copy: try: # we use a lock here because if we race with commit, we # can end up with extra data in the cloned revlogs that's # not pointed to by changesets, thus causing verify to # fail srclock = srcrepo.lock(wait=False) except error.LockError: copy = False if copy: srcrepo.hook('preoutgoing', throw=True, source='clone') hgdir = os.path.realpath(os.path.join(dest, ".hg")) if not os.path.exists(dest): os.mkdir(dest) else: # only clean up directories we create ourselves cleandir = hgdir try: destpath = hgdir util.makedir(destpath, notindexed=True) except OSError, inst: if inst.errno == errno.EEXIST: cleandir = None raise util.Abort( _("destination '%s' already exists") % dest) raise destlock = copystore(ui, srcrepo, destpath) # copy bookmarks over srcbookmarks = srcrepo.join('bookmarks') dstbookmarks = os.path.join(destpath, 'bookmarks') if os.path.exists(srcbookmarks): util.copyfile(srcbookmarks, dstbookmarks) # Recomputing branch cache might be slow on big repos, # so just copy it def copybranchcache(fname): srcbranchcache = srcrepo.join('cache/%s' % fname) dstbranchcache = os.path.join(dstcachedir, fname) if os.path.exists(srcbranchcache): if not os.path.exists(dstcachedir): os.mkdir(dstcachedir) util.copyfile(srcbranchcache, dstbranchcache) dstcachedir = os.path.join(destpath, 'cache') # In local clones we're copying all nodes, not just served # ones. Therefore copy all branch caches over. copybranchcache('branch2') for cachename in repoview.filtertable: copybranchcache('branch2-%s' % cachename) # we need to re-init the repo after manually copying the data # into it destpeer = peer(srcrepo, peeropts, dest) srcrepo.hook('outgoing', source='clone', node=node.hex(node.nullid)) else:
def clone(ui, peeropts, source, dest=None, pull=False, rev=None, update=True, stream=False, branch=None): """Make a copy of an existing repository. Create a copy of an existing repository in a new directory. The source and destination are URLs, as passed to the repository function. Returns a pair of repository peers, the source and newly created destination. The location of the source is added to the new repository's .hg/hgrc file, as the default to be used for future pulls and pushes. If an exception is raised, the partly cloned/updated destination repository will be deleted. Arguments: source: repository object or URL dest: URL of destination repository to create (defaults to base name of source repository) pull: always pull from source repository, even in local case or if the server prefers streaming stream: stream raw data uncompressed from repository (fast over LAN, slow over WAN) rev: revision to clone up to (implies pull=True) update: update working directory after clone completes, if destination is local repository (True means update to default rev, anything else is treated as a revision) branch: branches to clone """ if isinstance(source, str): origsource = ui.expandpath(source) source, branch = parseurl(origsource, branch) srcpeer = peer(ui, peeropts, source) else: srcpeer = source.peer() # in case we were called with a localrepo branch = (None, branch or []) origsource = source = srcpeer.url() rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev) if dest is None: dest = defaultdest(source) if dest: ui.status(_("destination directory: %s\n") % dest) else: dest = ui.expandpath(dest) dest = util.urllocalpath(dest) source = util.urllocalpath(source) if not dest: raise util.Abort(_("empty destination path is not valid")) destvfs = scmutil.vfs(dest, expandpath=True) if destvfs.lexists(): if not destvfs.isdir(): raise util.Abort(_("destination '%s' already exists") % dest) elif destvfs.listdir(): raise util.Abort(_("destination '%s' is not empty") % dest) srclock = destlock = cleandir = None srcrepo = srcpeer.local() try: abspath = origsource if islocal(origsource): abspath = os.path.abspath(util.urllocalpath(origsource)) if islocal(dest): cleandir = dest copy = False if (srcrepo and srcrepo.cancopy() and islocal(dest) and not phases.hassecret(srcrepo)): copy = not pull and not rev if copy: try: # we use a lock here because if we race with commit, we # can end up with extra data in the cloned revlogs that's # not pointed to by changesets, thus causing verify to # fail srclock = srcrepo.lock(wait=False) except error.LockError: copy = False if copy: srcrepo.hook('preoutgoing', throw=True, source='clone') hgdir = os.path.realpath(os.path.join(dest, ".hg")) if not os.path.exists(dest): os.mkdir(dest) else: # only clean up directories we create ourselves cleandir = hgdir try: destpath = hgdir util.makedir(destpath, notindexed=True) except OSError as inst: if inst.errno == errno.EEXIST: cleandir = None raise util.Abort(_("destination '%s' already exists") % dest) raise destlock = copystore(ui, srcrepo, destpath) # copy bookmarks over srcbookmarks = srcrepo.join('bookmarks') dstbookmarks = os.path.join(destpath, 'bookmarks') if os.path.exists(srcbookmarks): util.copyfile(srcbookmarks, dstbookmarks) # Recomputing branch cache might be slow on big repos, # so just copy it def copybranchcache(fname): srcbranchcache = srcrepo.join('cache/%s' % fname) dstbranchcache = os.path.join(dstcachedir, fname) if os.path.exists(srcbranchcache): if not os.path.exists(dstcachedir): os.mkdir(dstcachedir) util.copyfile(srcbranchcache, dstbranchcache) dstcachedir = os.path.join(destpath, 'cache') # In local clones we're copying all nodes, not just served # ones. Therefore copy all branch caches over. copybranchcache('branch2') for cachename in repoview.filtertable: copybranchcache('branch2-%s' % cachename) # we need to re-init the repo after manually copying the data # into it destpeer = peer(srcrepo, peeropts, dest) srcrepo.hook('outgoing', source='clone', node=node.hex(node.nullid)) else: try: destpeer = peer(srcrepo or ui, peeropts, dest, create=True) # only pass ui when no srcrepo except OSError as inst: if inst.errno == errno.EEXIST: cleandir = None raise util.Abort(_("destination '%s' already exists") % dest) raise revs = None if rev: if not srcpeer.capable('lookup'): raise util.Abort(_("src repository does not support " "revision lookup and so doesn't " "support clone by revision")) revs = [srcpeer.lookup(r) for r in rev] checkout = revs[0] if destpeer.local(): if not stream: if pull: stream = False else: stream = None destpeer.local().clone(srcpeer, heads=revs, stream=stream) elif srcrepo: exchange.push(srcrepo, destpeer, revs=revs, bookmarks=srcrepo._bookmarks.keys()) else: raise util.Abort(_("clone from remote to remote not supported")) cleandir = None destrepo = destpeer.local() if destrepo: template = uimod.samplehgrcs['cloned'] fp = destrepo.vfs("hgrc", "w", text=True) u = util.url(abspath) u.passwd = None defaulturl = str(u) fp.write(template % defaulturl) fp.close() destrepo.ui.setconfig('paths', 'default', defaulturl, 'clone') if update: if update is not True: checkout = srcpeer.lookup(update) uprev = None status = None if checkout is not None: try: uprev = destrepo.lookup(checkout) except error.RepoLookupError: pass if uprev is None: try: uprev = destrepo._bookmarks['@'] update = '@' bn = destrepo[uprev].branch() if bn == 'default': status = _("updating to bookmark @\n") else: status = (_("updating to bookmark @ on branch %s\n") % bn) except KeyError: try: uprev = destrepo.branchtip('default') except error.RepoLookupError: uprev = destrepo.lookup('tip') if not status: bn = destrepo[uprev].branch() status = _("updating to branch %s\n") % bn destrepo.ui.status(status) _update(destrepo, uprev) if update in destrepo._bookmarks: bookmarks.activate(destrepo, update) finally: release(srclock, destlock) if cleandir is not None: shutil.rmtree(cleandir, True) if srcpeer is not None: srcpeer.close() return srcpeer, destpeer
def clone(ui, peeropts, source, dest=None, pull=False, rev=None, update=True, stream=False, branch=None): """Make a copy of an existing repository. Create a copy of an existing repository in a new directory. The source and destination are URLs, as passed to the repository function. Returns a pair of repository peers, the source and newly created destination. The location of the source is added to the new repository's .hg/hgrc file, as the default to be used for future pulls and pushes. If an exception is raised, the partly cloned/updated destination repository will be deleted. Arguments: source: repository object or URL dest: URL of destination repository to create (defaults to base name of source repository) pull: always pull from source repository, even in local case stream: stream raw data uncompressed from repository (fast over LAN, slow over WAN) rev: revision to clone up to (implies pull=True) update: update working directory after clone completes, if destination is local repository (True means update to default rev, anything else is treated as a revision) branch: branches to clone """ if isinstance(source, str): origsource = ui.expandpath(source) source, branch = parseurl(origsource, branch) srcpeer = peer(ui, peeropts, source) else: srcpeer = source.peer() # in case we were called with a localrepo branch = (None, branch or []) origsource = source = srcpeer.url() rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev) if dest is None: dest = defaultdest(source) ui.status(_("destination directory: %s\n") % dest) else: dest = ui.expandpath(dest) dest = util.urllocalpath(dest) source = util.urllocalpath(source) if not dest: raise util.Abort(_("empty destination path is not valid")) if os.path.exists(dest): if not os.path.isdir(dest): raise util.Abort(_("destination '%s' already exists") % dest) elif os.listdir(dest): raise util.Abort(_("destination '%s' is not empty") % dest) srclock = destlock = cleandir = None srcrepo = srcpeer.local() try: abspath = origsource if islocal(origsource): abspath = os.path.abspath(util.urllocalpath(origsource)) if islocal(dest): cleandir = dest copy = False if (srcrepo and srcrepo.cancopy() and islocal(dest) and not phases.hassecret(srcrepo)): copy = not pull and not rev if copy: try: # we use a lock here because if we race with commit, we # can end up with extra data in the cloned revlogs that's # not pointed to by changesets, thus causing verify to # fail srclock = srcrepo.lock(wait=False) except error.LockError: copy = False if copy: srcrepo.hook('preoutgoing', throw=True, source='clone') hgdir = os.path.realpath(os.path.join(dest, ".hg")) if not os.path.exists(dest): os.mkdir(dest) else: # only clean up directories we create ourselves cleandir = hgdir try: destpath = hgdir util.makedir(destpath, notindexed=True) except OSError, inst: if inst.errno == errno.EEXIST: cleandir = None raise util.Abort(_("destination '%s' already exists") % dest) raise destlock = copystore(ui, srcrepo, destpath) # Recomputing branch cache might be slow on big repos, # so just copy it dstcachedir = os.path.join(destpath, 'cache') srcbranchcache = srcrepo.sjoin('cache/branchheads') dstbranchcache = os.path.join(dstcachedir, 'branchheads') if os.path.exists(srcbranchcache): if not os.path.exists(dstcachedir): os.mkdir(dstcachedir) util.copyfile(srcbranchcache, dstbranchcache) # we need to re-init the repo after manually copying the data # into it destpeer = peer(srcrepo, peeropts, dest) srcrepo.hook('outgoing', source='clone', node=node.hex(node.nullid)) else:
def clone(ui, peeropts, source, dest=None, pull=False, rev=None, update=True, stream=False, branch=None): """Make a copy of an existing repository. Create a copy of an existing repository in a new directory. The source and destination are URLs, as passed to the repository function. Returns a pair of repository peers, the source and newly created destination. The location of the source is added to the new repository's .hg/hgrc file, as the default to be used for future pulls and pushes. If an exception is raised, the partly cloned/updated destination repository will be deleted. Arguments: source: repository object or URL dest: URL of destination repository to create (defaults to base name of source repository) pull: always pull from source repository, even in local case or if the server prefers streaming stream: stream raw data uncompressed from repository (fast over LAN, slow over WAN) rev: revision to clone up to (implies pull=True) update: update working directory after clone completes, if destination is local repository (True means update to default rev, anything else is treated as a revision) branch: branches to clone """ if isinstance(source, str): origsource = ui.expandpath(source) source, branch = parseurl(origsource, branch) srcpeer = peer(ui, peeropts, source) else: srcpeer = source.peer() # in case we were called with a localrepo branch = (None, branch or []) origsource = source = srcpeer.url() rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev) if dest is None: dest = defaultdest(source) if dest: ui.status(_("destination directory: %s\n") % dest) else: dest = ui.expandpath(dest) dest = util.urllocalpath(dest) source = util.urllocalpath(source) if not dest: raise util.Abort(_("empty destination path is not valid")) destvfs = scmutil.vfs(dest, expandpath=True) if destvfs.lexists(): if not destvfs.isdir(): raise util.Abort(_("destination '%s' already exists") % dest) elif destvfs.listdir(): raise util.Abort(_("destination '%s' is not empty") % dest) srclock = destlock = cleandir = None srcrepo = srcpeer.local() try: abspath = origsource if islocal(origsource): abspath = os.path.abspath(util.urllocalpath(origsource)) if islocal(dest): cleandir = dest copy = False if srcrepo and srcrepo.cancopy() and islocal(dest) and not phases.hassecret(srcrepo): copy = not pull and not rev if copy: try: # we use a lock here because if we race with commit, we # can end up with extra data in the cloned revlogs that's # not pointed to by changesets, thus causing verify to # fail srclock = srcrepo.lock(wait=False) except error.LockError: copy = False if copy: srcrepo.hook("preoutgoing", throw=True, source="clone") hgdir = os.path.realpath(os.path.join(dest, ".hg")) if not os.path.exists(dest): os.mkdir(dest) else: # only clean up directories we create ourselves cleandir = hgdir try: destpath = hgdir util.makedir(destpath, notindexed=True) except OSError as inst: if inst.errno == errno.EEXIST: cleandir = None raise util.Abort(_("destination '%s' already exists") % dest) raise destlock = copystore(ui, srcrepo, destpath) # copy bookmarks over srcbookmarks = srcrepo.join("bookmarks") dstbookmarks = os.path.join(destpath, "bookmarks") if os.path.exists(srcbookmarks): util.copyfile(srcbookmarks, dstbookmarks) # Recomputing branch cache might be slow on big repos, # so just copy it def copybranchcache(fname): srcbranchcache = srcrepo.join("cache/%s" % fname) dstbranchcache = os.path.join(dstcachedir, fname) if os.path.exists(srcbranchcache): if not os.path.exists(dstcachedir): os.mkdir(dstcachedir) util.copyfile(srcbranchcache, dstbranchcache) dstcachedir = os.path.join(destpath, "cache") # In local clones we're copying all nodes, not just served # ones. Therefore copy all branch caches over. copybranchcache("branch2") for cachename in repoview.filtertable: copybranchcache("branch2-%s" % cachename) # we need to re-init the repo after manually copying the data # into it destpeer = peer(srcrepo, peeropts, dest) srcrepo.hook("outgoing", source="clone", node=node.hex(node.nullid)) else: try: destpeer = peer(srcrepo or ui, peeropts, dest, create=True) # only pass ui when no srcrepo except OSError as inst: if inst.errno == errno.EEXIST: cleandir = None raise util.Abort(_("destination '%s' already exists") % dest) raise revs = None if rev: if not srcpeer.capable("lookup"): raise util.Abort( _( "src repository does not support " "revision lookup and so doesn't " "support clone by revision" ) ) revs = [srcpeer.lookup(r) for r in rev] checkout = revs[0] if destpeer.local(): if not stream: if pull: stream = False else: stream = None destpeer.local().clone(srcpeer, heads=revs, stream=stream) elif srcrepo: exchange.push(srcrepo, destpeer, revs=revs, bookmarks=srcrepo._bookmarks.keys()) else: raise util.Abort(_("clone from remote to remote not supported")) cleandir = None destrepo = destpeer.local() if destrepo: template = uimod.samplehgrcs["cloned"] fp = destrepo.vfs("hgrc", "w", text=True) u = util.url(abspath) u.passwd = None defaulturl = str(u) fp.write(template % defaulturl) fp.close() destrepo.ui.setconfig("paths", "default", defaulturl, "clone") if update: if update is not True: checkout = srcpeer.lookup(update) uprev = None status = None if checkout is not None: try: uprev = destrepo.lookup(checkout) except error.RepoLookupError: pass if uprev is None: try: uprev = destrepo._bookmarks["@"] update = "@" bn = destrepo[uprev].branch() if bn == "default": status = _("updating to bookmark @\n") else: status = _("updating to bookmark @ on branch %s\n") % bn except KeyError: try: uprev = destrepo.branchtip("default") except error.RepoLookupError: uprev = destrepo.lookup("tip") if not status: bn = destrepo[uprev].branch() status = _("updating to branch %s\n") % bn destrepo.ui.status(status) _update(destrepo, uprev) if update in destrepo._bookmarks: bookmarks.activate(destrepo, update) finally: release(srclock, destlock) if cleandir is not None: shutil.rmtree(cleandir, True) if srcpeer is not None: srcpeer.close() return srcpeer, destpeer