##// END OF EJS Templates
share: make it possible to control the working copy format variant...
share: make it possible to control the working copy format variant A share will use the same format as its source for the store, but there are no reason to not lets it control the working copy variant at creation time. So we make it so. Differential Revision: https://phab.mercurial-scm.org/D11892

File last commit:

r49055:7d1e6024 default
r49297:bf2738e0 default
Show More
hg.py
1591 lines | 51.2 KiB | text/x-python | PythonLexer
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 # hg.py - repository classes for mercurial
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
Vadim Gelfer
update copyrights.
r2859 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Gregory Szorc
hg: use absolute_import
r25939 from __future__ import absolute_import
import errno
import os
import shutil
Augie Fackler
cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime...
r36799 import stat
Gregory Szorc
hg: use absolute_import
r25939
from .i18n import _
Joerg Sonnenberger
node: import symbols explicitly...
r46729 from .node import (
hex,
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 sha1nodeconstants,
Joerg Sonnenberger
node: import symbols explicitly...
r46729 short,
)
Gregory Szorc
py3: manually import getattr where it is needed...
r43359 from .pycompat import getattr
Jordi Gutiérrez Hermoso
config: use the same hgrc for a cloned repo as for an uninitted repo...
r22837
Gregory Szorc
hg: use absolute_import
r25939 from . import (
bookmarks,
bundlerepo,
cmdutil,
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501 destutil,
Gregory Szorc
hg: use absolute_import
r25939 discovery,
error,
exchange,
extensions,
outgoing: merge the code handling --graph with the main one...
r47677 graphmod,
Gregory Szorc
hg: use absolute_import
r25939 httppeer,
localrepo,
lock,
Yuya Nishihara
cmdutil: drop aliases for logcmdutil functions (API)...
r35906 logcmdutil,
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 logexchange,
Gregory Szorc
hg: use absolute_import
r25939 merge as mergemod,
Augie Fackler
mergestate: split out merge state handling code from main merge module...
r45383 mergestate as mergestatemod,
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586 narrowspec,
Gregory Szorc
hg: use absolute_import
r25939 phases,
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 requirements,
Gregory Szorc
hg: use absolute_import
r25939 scmutil,
sshpeer,
statichttprepo,
ui as uimod,
unionrepo,
url,
util,
verify as verifymod,
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.hg'...
r31218 vfs as vfsmod,
Gregory Szorc
hg: use absolute_import
r25939 )
updatecaches: use the `caches` argument instead of a special `full` value...
r48079 from .interfaces import repository as repositorymod
Matt Harbison
hg: convert an exception to bytes in the repo creation exception handler...
r47518 from .utils import (
hashutil,
stringutil,
urlutil: extract `url` related code from `util` into the new module...
r47669 urlutil,
Matt Harbison
hg: convert an exception to bytes in the repo creation exception handler...
r47518 )
Pulkit Goyal
interfaces: create a new folder for interfaces and move repository.py in it...
r43078
Gregory Szorc
hg: use absolute_import
r25939 release = lock.release
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Martijn Pieters
share: move magic string to a constant
r29424 # shared features
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 sharedbookmarks = b'bookmarks'
Martijn Pieters
share: move magic string to a constant
r29424
Augie Fackler
formatting: blacken the codebase...
r43346
Vadim Gelfer
clean up hg.py: move repo constructor code into each repo module
r2740 def _local(path):
urlutil: extract `url` related code from `util` into the new module...
r47669 path = util.expandpath(urlutil.urllocalpath(path))
Gregory Szorc
hg: raise Abort on invalid path...
r41625
try:
Augie Fackler
hg: make _local() behave consistently on Python 3.8 (issue6287)...
r45061 # we use os.stat() directly here instead of os.path.isfile()
# because the latter started returning `False` on invalid path
# exceptions starting in 3.8 and we care about handling
# invalid paths specially here.
st = os.stat(path)
isfile = stat.S_ISREG(st.st_mode)
Gregory Szorc
hg: raise Abort on invalid path...
r41625 # Python 2 raises TypeError, Python 3 ValueError.
except (TypeError, ValueError) as e:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Matt Harbison
hg: convert an exception to bytes in the repo creation exception handler...
r47518 _(b'invalid path %s: %s') % (path, stringutil.forcebytestr(e))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
hg: make _local() behave consistently on Python 3.8 (issue6287)...
r45061 except OSError:
isfile = False
Gregory Szorc
hg: raise Abort on invalid path...
r41625
return isfile and bundlerepo or localrepo
Vadim Gelfer
hg.repository: make protocol table driven....
r2469
Augie Fackler
formatting: blacken the codebase...
r43346
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 def addbranchrevs(lrepo, other, branches, revs):
Augie Fackler
formatting: blacken the codebase...
r43346 peer = other.peer() # a courtesy to callers using a localrepo for other
Sune Foldager
improve --branch processing (and differentiate from # syntax)...
r11322 hashbranch, branches = branches
if not hashbranch and not branches:
Pierre-Yves David
repair: use `first` instead of direct indexing...
r22818 x = revs or None
Martin von Zweigbergk
addbranchrevs: no longer accept revset as "revs" (API)...
r37499 if revs:
Pierre-Yves David
repair: use `first` instead of direct indexing...
r22818 y = revs[0]
else:
y = None
return x, y
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if revs:
revs = list(revs)
else:
revs = []
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not peer.capable(b'branchmap'):
Sune Foldager
improve --branch processing (and differentiate from # syntax)...
r11322 if branches:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"remote branch lookup not supported"))
Sune Foldager
improve --branch processing (and differentiate from # syntax)...
r11322 revs.append(hashbranch)
Sune Foldager
addbranchrevs: fallback for older servers
r10380 return revs, revs[0]
Gregory Szorc
hg: use command executor for wire protocol commands...
r37658
with peer.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 branchmap = e.callcommand(b'branchmap', {}).result()
Sune Foldager
improve --branch processing (and differentiate from # syntax)...
r11322
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 def primary(branch):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if branch == b'.':
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 if not lrepo:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"dirstate branch not accessible"))
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 branch = lrepo.dirstate.branch()
if branch in branchmap:
Joerg Sonnenberger
node: import symbols explicitly...
r46729 revs.extend(hex(r) for r in reversed(branchmap[branch]))
Sune Foldager
improve --branch processing (and differentiate from # syntax)...
r11322 return True
Sune Foldager
interpret repo#name url syntax as branch instead of revision...
r10365 else:
Sune Foldager
improve --branch processing (and differentiate from # syntax)...
r11322 return False
for branch in branches:
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 if not primary(branch):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.RepoLookupError(_(b"unknown branch '%s'") % branch)
Sune Foldager
improve --branch processing (and differentiate from # syntax)...
r11322 if hashbranch:
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 if not primary(hashbranch):
Sune Foldager
improve --branch processing (and differentiate from # syntax)...
r11322 revs.append(hashbranch)
Sune Foldager
interpret repo#name url syntax as branch instead of revision...
r10365 return revs, revs[0]
Augie Fackler
formatting: blacken the codebase...
r43346
Brodie Rao
hg: use url.url to parse branch names in parseurl()
r13824 def parseurl(path, branches=None):
Sune Foldager
improve --branch processing (and differentiate from # syntax)...
r11322 '''parse url#branch, returning (url, (branch, branches))'''
urlutil: extract `parseurl` from `hg` into the new module...
r47670 msg = b'parseurl(...) moved to mercurial.utils.urlutil'
util.nouideprecwarn(msg, b'6.0', stacklevel=2)
return urlutil.parseurl(path, branches=branches)
Matt Mackall
move parseurl from cmdutil to hg
r5177
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
hg: move peerschemes back to schemes...
r14606 schemes = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'bundle': bundlerepo,
b'union': unionrepo,
b'file': _local,
b'http': httppeer,
b'https': httppeer,
b'ssh': sshpeer,
b'static-http': statichttprepo,
Matt Mackall
hg: split peer and repo lookup tables
r14568 }
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
hg: split peer and repo lookup tables
r14568 def _peerlookup(path):
urlutil: extract `url` related code from `util` into the new module...
r47669 u = urlutil.url(path)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 scheme = u.scheme or b'file'
thing = schemes.get(scheme) or schemes[b'file']
Matt Mackall
hg: split peer and repo lookup tables
r14568 try:
return thing(path)
except TypeError:
Yuya Nishihara
hg: explicitly check that peer lookup object has instance() if call failed...
r25365 # we can't test callable(thing) because 'thing' can be an unloaded
# module that implements __call__
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not util.safehasattr(thing, b'instance'):
Yuya Nishihara
hg: explicitly check that peer lookup object has instance() if call failed...
r25365 raise
Matt Mackall
hg: split peer and repo lookup tables
r14568 return thing
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
hg: rearrange peer scheme lookup...
r14605 def islocal(repo):
Siddharth Agarwal
hg: note that islocal only accepts paths pointing to repos...
r20355 '''return true if repo (or path pointing to repo) is local'''
Pulkit Goyal
py3: check for bytes instead of str in isinstance
r33018 if isinstance(repo, bytes):
Matt Mackall
hg: rearrange peer scheme lookup...
r14605 try:
return _peerlookup(repo).islocal(repo)
except AttributeError:
return False
return repo.local()
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
import: suppress accept: header...
r42278 def openpath(ui, path, sendaccept=True):
Siddharth Agarwal
url: use open and not url.open for local files (issue3624)
r17887 '''open path with open if local, url.open if remote'''
urlutil: extract `url` related code from `util` into the new module...
r47669 pathurl = urlutil.url(path, parsequery=False, parsefragment=False)
Siddharth Agarwal
hg.openpath: use url.islocal to tell if the path is local (issue3624)...
r20354 if pathurl.islocal():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return util.posixfile(pathurl.localpath(), b'rb')
Siddharth Agarwal
url: use open and not url.open for local files (issue3624)
r17887 else:
timeless
import: suppress accept: header...
r42278 return url.open(ui, path, sendaccept=sendaccept)
Siddharth Agarwal
url: use open and not url.open for local files (issue3624)
r17887
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
hg: introduce "wirepeersetupfuncs" to setup wire peer by extensions (issue4109)...
r20858 # a list of (ui, repo) functions called for wire peer initialization
wirepeersetupfuncs = []
Augie Fackler
formatting: blacken the codebase...
r43346
def _peerorrepo(
ui, path, create=False, presetupfuncs=None, intents=None, createopts=None
):
Matt Mackall
hg: rearrange peer scheme lookup...
r14605 """return a repository object for the specified path"""
Augie Fackler
formatting: blacken the codebase...
r43346 obj = _peerlookup(path).instance(
ui, path, create, intents=intents, createopts=createopts
)
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 ui = getattr(obj, "ui", ui)
Jun Wu
dispatch: make request accept additional reposetups...
r32379 for f in presetupfuncs or []:
f(ui, obj)
Yuya Nishihara
extensions: use ui.log() interface to provide detailed loading information...
r41032 ui.log(b'extension', b'- executing reposetup hooks\n')
Augie Fackler
cleanup: hgdemandimport.tracing accepts strings, not bytes...
r43532 with util.timedcm('all reposetup') as allreposetupstats:
Boris Feld
extensions: trace the total time of running all reposetup callbacks...
r39546 for name, module in extensions.extensions(ui):
Yuya Nishihara
extensions: use ui.log() interface to provide detailed loading information...
r41032 ui.log(b'extension', b' - running reposetup for %s\n', name)
Boris Feld
extensions: trace the total time of running all reposetup callbacks...
r39546 hook = getattr(module, 'reposetup', None)
if hook:
Augie Fackler
cleanup: hgdemandimport.tracing accepts strings, not bytes...
r43532 with util.timedcm('reposetup %r', name) as stats:
Boris Feld
extensions: trace the total time of running all reposetup callbacks...
r39546 hook(ui, obj)
Augie Fackler
formatting: blacken the codebase...
r43346 ui.log(
b'extension', b' > reposetup for %s took %s\n', name, stats
)
Yuya Nishihara
extensions: use ui.log() interface to provide detailed loading information...
r41032 ui.log(b'extension', b'> all reposetup took %s\n', allreposetupstats)
FUJIWARA Katsunori
hg: introduce "wirepeersetupfuncs" to setup wire peer by extensions (issue4109)...
r20858 if not obj.local():
for f in wirepeersetupfuncs:
f(ui, obj)
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 return obj
Augie Fackler
formatting: blacken the codebase...
r43346
def repository(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui,
path=b'',
create=False,
presetupfuncs=None,
intents=None,
createopts=None,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 """return a repository object for the specified path"""
Augie Fackler
formatting: blacken the codebase...
r43346 peer = _peerorrepo(
ui,
path,
create,
presetupfuncs=presetupfuncs,
intents=intents,
createopts=createopts,
)
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 repo = peer.local()
if not repo:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"repository '%s' is not local") % (path or peer.url())
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return repo.filtered(b'visible')
Matt Mackall
hg: rearrange peer scheme lookup...
r14605
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hg: allow extra arguments to be passed to repo creation (API)...
r39585 def peer(uiorrepo, opts, path, create=False, intents=None, createopts=None):
Matt Mackall
hg: add peer method
r14554 '''return a repository peer for the specified path'''
Idan Kamara
peer: change arg name to convey it can be a repo as well
r14839 rui = remoteui(uiorrepo, opts)
Augie Fackler
formatting: blacken the codebase...
r43346 return _peerorrepo(
rui, path, create, intents=intents, createopts=createopts
).peer()
Matt Mackall
hg: add peer method
r14554
Vadim Gelfer
hg.py: add islocal() and defaultdest() functions, refactor...
r2719 def defaultdest(source):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """return default destination of clone if none is given
Yuya Nishihara
clone: add doctest for default destination
r20799
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> defaultdest(b'foo')
Yuya Nishihara
clone: add doctest for default destination
r20799 'foo'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> defaultdest(b'/foo/bar')
Yuya Nishihara
clone: add doctest for default destination
r20799 'bar'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> defaultdest(b'/')
Yuya Nishihara
clone: add doctest for default destination
r20799 ''
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> defaultdest(b'')
Yuya Nishihara
clone: abort if default destination has no meaningful name (BC)...
r20800 ''
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> defaultdest(b'http://example.org/')
Yuya Nishihara
clone: abort if default destination has no meaningful name (BC)...
r20800 ''
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> defaultdest(b'http://example.org/foo/')
Yuya Nishihara
clone: add doctest for default destination
r20799 'foo'
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
urlutil: extract `url` related code from `util` into the new module...
r47669 path = urlutil.url(source).path
Yuya Nishihara
clone: abort if default destination has no meaningful name (BC)...
r20800 if not path:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''
Yuya Nishihara
clone: abort if default destination has no meaningful name (BC)...
r20800 return os.path.basename(os.path.normpath(path))
Matt Mackall
Add a doc string
r2774
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hg: move share._getsrcrepo into core...
r36177 def sharedreposource(repo):
"""Returns repository object for source repository of a shared repo.
If repo is not a shared repository, returns None.
"""
if repo.sharedpath == repo.path:
return None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if util.safehasattr(repo, b'srcrepo') and repo.srcrepo:
Gregory Szorc
hg: move share._getsrcrepo into core...
r36177 return repo.srcrepo
# the sharedpath always ends in the .hg; we want the path to the repo
source = repo.vfs.split(repo.sharedpath)[0]
urlutil: extract `parseurl` from `hg` into the new module...
r47670 srcurl, branches = urlutil.parseurl(source)
Gregory Szorc
hg: move share._getsrcrepo into core...
r36177 srcrepo = repository(repo.ui, srcurl)
repo.srcrepo = srcrepo
return srcrepo
Augie Fackler
formatting: blacken the codebase...
r43346
def share(
ui,
source,
dest=None,
update=True,
bookmarks=True,
defaultpath=None,
relative=False,
):
Matt Mackall
add helper function to create shared repos
r8800 '''create a shared repository'''
if not islocal(source):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'can only share local repositories'))
Matt Mackall
add helper function to create shared repos
r8800
Matt Mackall
share: allow dest to default to the basename of source
r8807 if not dest:
Brendan Cully
share: use defaultdest to compute unspecified destination...
r10099 dest = defaultdest(source)
Matt Mackall
Merge with i18n-stable
r9344 else:
share: use `get_clone_path`...
r47715 dest = urlutil.get_clone_path(ui, dest)[1]
Matt Mackall
share: allow dest to default to the basename of source
r8807
Gregory Szorc
py3: check for bytes instead of str in hg.share()...
r36066 if isinstance(source, bytes):
share: use `get_clone_path`...
r47715 origsource, source, branches = urlutil.get_clone_path(ui, source)
Matt Mackall
add helper function to create shared repos
r8800 srcrepo = repository(ui, source)
Sune Foldager
interpret repo#name url syntax as branch instead of revision...
r10365 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
Matt Mackall
add helper function to create shared repos
r8800 else:
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 srcrepo = source.local()
Matt Mackall
add helper function to create shared repos
r8800 checkout = None
Gregory Szorc
localrepo: support writing shared file (API)...
r39885 shareditems = set()
if bookmarks:
shareditems.add(sharedbookmarks)
Augie Fackler
formatting: blacken the codebase...
r43346 r = repository(
ui,
dest,
create=True,
createopts={
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'sharedrepo': srcrepo,
b'sharedrelative': relative,
b'shareditems': shareditems,
Augie Fackler
formatting: blacken the codebase...
r43346 },
)
Matt Mackall
add helper function to create shared repos
r8800
Gregory Szorc
localrepo: support writing shared file (API)...
r39885 postshare(srcrepo, r, defaultpath=defaultpath)
Martin von Zweigbergk
share: reload repo after adjusting it in postshare()...
r40609 r = repository(ui, dest)
Gregory Szorc
hg: perform update after pulling during clone with share (issue5103)...
r28632 _postshareupdate(r, update, checkout=checkout)
Matt Harbison
subrepo: share instead of clone if the parent repo is shared (issue5675) (BC)...
r34816 return r
Matt Mackall
add helper function to create shared repos
r8800
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
localrepo: load the share source .hg/hgrc also in share-safe mode (API)...
r46057 def _prependsourcehgrc(repo):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """copies the source repo config and prepend it in current repo .hg/hgrc
Pulkit Goyal
localrepo: load the share source .hg/hgrc also in share-safe mode (API)...
r46057 on unshare. This is only done if the share was perfomed using share safe
method where we share config of source in shares"""
srcvfs = vfsmod.vfs(repo.sharedpath)
dstvfs = vfsmod.vfs(repo.path)
if not srcvfs.exists(b'hgrc'):
return
currentconfig = b''
if dstvfs.exists(b'hgrc'):
currentconfig = dstvfs.read(b'hgrc')
with dstvfs(b'hgrc', b'wb') as fp:
sourceconfig = srcvfs.read(b'hgrc')
fp.write(b"# Config copied from shared source\n")
fp.write(sourceconfig)
fp.write(b'\n')
fp.write(currentconfig)
Matt Harbison
share: move the implementation of 'unshare' to the 'hg' module...
r34879 def unshare(ui, repo):
"""convert a shared repository to a normal one
Copy the store data to the repo and remove the sharedpath data.
Gregory Szorc
hg: don't reuse repo instance after unshare()...
r39642
Returns a new repository object representing the unshared repository.
The passed repository object is not usable after this function is
called.
Matt Harbison
share: move the implementation of 'unshare' to the 'hg' module...
r34879 """
Martin von Zweigbergk
unshare: use context manager for locks...
r41436 with repo.lock():
Matt Harbison
share: move the implementation of 'unshare' to the 'hg' module...
r34879 # we use locks 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
destlock = copystore(ui, repo, repo.path)
Martin von Zweigbergk
unshare: use context manager for locks...
r41436 with destlock or util.nullcontextmanager():
Pulkit Goyal
localrepo: load the share source .hg/hgrc also in share-safe mode (API)...
r46057 if requirements.SHARESAFE_REQUIREMENT in repo.requirements:
# we were sharing .hg/hgrc of the share source with the current
# repo. We need to copy that while unsharing otherwise it can
# disable hooks and other checks
_prependsourcehgrc(repo)
Matt Harbison
share: move the implementation of 'unshare' to the 'hg' module...
r34879
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 sharefile = repo.vfs.join(b'sharedpath')
util.rename(sharefile, sharefile + b'.old')
Martin von Zweigbergk
unshare: use context manager for locks...
r41436
Pulkit Goyal
requirements: introduce constants for `shared` and `relshared` requirements...
r45946 repo.requirements.discard(requirements.SHARED_REQUIREMENT)
repo.requirements.discard(requirements.RELATIVE_SHARED_REQUIREMENT)
Pulkit Goyal
scmutil: add writereporequirements() and route requires writing through it...
r45666 scmutil.writereporequirements(repo)
Matt Harbison
share: move the implementation of 'unshare' to the 'hg' module...
r34879
Gregory Szorc
hg: don't reuse repo instance after unshare()...
r39642 # Removing share changes some fundamental properties of the repo instance.
# So we instantiate a new repo object and operate on it rather than
# try to keep the existing repo usable.
newrepo = repository(repo.baseui, repo.root, create=False)
Matt Harbison
share: move the implementation of 'unshare' to the 'hg' module...
r34879
Matt Harbison
subrepo: implement 'unshare' for Mercurial subrepos...
r34880 # TODO: figure out how to access subrepos that exist, but were previously
# removed from .hgsub
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 c = newrepo[b'.']
Matt Harbison
subrepo: implement 'unshare' for Mercurial subrepos...
r34880 subs = c.substate
for s in sorted(subs):
c.sub(s).unshare()
Gregory Szorc
hg: don't reuse repo instance after unshare()...
r39642 localrepo.poisonrepository(repo)
return newrepo
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: support writing shared file (API)...
r39885 def postshare(sourcerepo, destrepo, defaultpath=None):
Gregory Szorc
hg: establish function for performing post-share actions...
r27354 """Called after a new shared repo is created.
The new repo only has a requirements file and pointer to the source.
This function configures additional shared data.
Extensions can wrap this function and write additional entries to
destrepo/.hg/shared to indicate additional pieces of data to be shared.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 default = defaultpath or sourcerepo.ui.config(b'paths', b'default')
Gregory Szorc
hg: establish function for performing post-share actions...
r27354 if default:
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 template = b'[paths]\ndefault = %s\n'
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 destrepo.vfs.write(b'hgrc', util.tonativeeol(template % default))
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 if requirements.NARROW_REQUIREMENT in sourcerepo.requirements:
Martin von Zweigbergk
narrow: detect if narrowspec was changed in a different share...
r41072 with destrepo.wlock():
Martin von Zweigbergk
narrow: copy store narrowspec to working copy immediately...
r41265 narrowspec.copytoworkingcopy(destrepo)
Gregory Szorc
hg: establish function for performing post-share actions...
r27354
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hg: perform update after pulling during clone with share (issue5103)...
r28632 def _postshareupdate(repo, update, checkout=None):
"""Maybe perform a working directory update after a shared repo is created.
``update`` can be a boolean or a revision to update to.
"""
if not update:
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.status(_(b"updating working directory\n"))
Gregory Szorc
hg: perform update after pulling during clone with share (issue5103)...
r28632 if update is not True:
checkout = update
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for test in (checkout, b'default', b'tip'):
Gregory Szorc
hg: perform update after pulling during clone with share (issue5103)...
r28632 if test is None:
continue
try:
uprev = repo.lookup(test)
break
except error.RepoLookupError:
continue
_update(repo, uprev)
Augie Fackler
formatting: blacken the codebase...
r43346
Simon Heimberg
hg: extract copying the store out of clone
r15078 def copystore(ui, srcrepo, destpath):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """copy files from store of srcrepo in destpath
Simon Heimberg
hg: extract copying the store out of clone
r15078
returns destlock
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Simon Heimberg
hg: extract copying the store out of clone
r15078 destlock = None
try:
hardlink = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 topic = _(b'linking') if hardlink else _(b'copying')
with ui.makeprogress(topic, unit=_(b'files')) as progress:
Matt Harbison
hg: ensure the progress bar is completed when copying the store...
r39425 num = 0
srcpublishing = srcrepo.publishing()
srcvfs = vfsmod.vfs(srcrepo.sharedpath)
dstvfs = vfsmod.vfs(destpath)
for f in srcrepo.store.copylist():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if srcpublishing and f.endswith(b'phaseroots'):
Matt Harbison
hg: ensure the progress bar is completed when copying the store...
r39425 continue
dstbase = os.path.dirname(f)
if dstbase and not dstvfs.exists(dstbase):
dstvfs.mkdir(dstbase)
if srcvfs.exists(f):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if f.endswith(b'data'):
Matt Harbison
hg: ensure the progress bar is completed when copying the store...
r39425 # 'dstbase' may be empty (e.g. revlog format 0)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lockfile = os.path.join(dstbase, b"lock")
Matt Harbison
hg: ensure the progress bar is completed when copying the store...
r39425 # lock to avoid premature writing to the target
destlock = lock.lock(dstvfs, lockfile)
Augie Fackler
formatting: blacken the codebase...
r43346 hardlink, n = util.copyfiles(
srcvfs.join(f), dstvfs.join(f), hardlink, progress
)
Matt Harbison
hg: ensure the progress bar is completed when copying the store...
r39425 num += n
if hardlink:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.debug(b"linked %d files\n" % num)
Matt Harbison
hg: ensure the progress bar is completed when copying the store...
r39425 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.debug(b"copied %d files\n" % num)
Simon Heimberg
hg: extract copying the store out of clone
r15078 return destlock
Augie Fackler
formatting: blacken the codebase...
r43346 except: # re-raises
Simon Heimberg
hg: extract copying the store out of clone
r15078 release(destlock)
raise
Augie Fackler
formatting: blacken the codebase...
r43346
def clonewithshare(
ui,
peeropts,
sharepath,
source,
srcpeer,
dest,
pull=False,
rev=None,
update=True,
stream=False,
):
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761 """Perform a clone using a shared repo.
The store for the repository will be located at <sharepath>/.hg. The
specified revisions will be cloned or pulled from "source". A shared repo
will be created at "dest" and a working copy will be created if "update" is
True.
"""
revs = None
if rev:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not srcpeer.capable(b'lookup'):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"src repository does not support "
b"revision lookup and so doesn't "
b"support clone by revision"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Gregory Szorc
hg: use command executor for wire protocol commands...
r37658
# TODO this is batchable.
remoterevs = []
for r in rev:
with srcpeer.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 remoterevs.append(
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 e.callcommand(
b'lookup',
{
b'key': r,
},
).result()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 )
Gregory Szorc
hg: use command executor for wire protocol commands...
r37658 revs = remoterevs
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761
Gregory Szorc
hg: obtain lock when creating share from pooled repo (issue5104)...
r28289 # Obtain a lock before checking for or cloning the pooled repo otherwise
# 2 clients may race creating or populating it.
pooldir = os.path.dirname(sharepath)
# lock class requires the directory to exist.
try:
util.makedir(pooldir, False)
except OSError as e:
if e.errno != errno.EEXIST:
raise
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.hg'...
r31218 poolvfs = vfsmod.vfs(pooldir)
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761 basename = os.path.basename(sharepath)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with lock.lock(poolvfs, b'%s.lock' % basename):
Gregory Szorc
hg: obtain lock when creating share from pooled repo (issue5104)...
r28289 if os.path.exists(sharepath):
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'(sharing from existing pooled repository %s)\n') % basename
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
hg: obtain lock when creating share from pooled repo (issue5104)...
r28289 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(
_(b'(sharing from new pooled repository %s)\n') % basename
)
Gregory Szorc
hg: obtain lock when creating share from pooled repo (issue5104)...
r28289 # Always use pull mode because hardlinks in share mode don't work
# well. Never update because working copies aren't necessary in
# share mode.
Augie Fackler
formatting: blacken the codebase...
r43346 clone(
ui,
peeropts,
source,
dest=sharepath,
pull=True,
revs=rev,
update=False,
stream=stream,
)
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761
Gregory Szorc
hg: set default path correctly when doing a clone+share (issue5378)...
r30041 # Resolve the value to put in [paths] section for the source.
if islocal(source):
windows: use abspath in mercurial/hg.py...
r48426 defaultpath = util.abspath(urlutil.urllocalpath(source))
Gregory Szorc
hg: set default path correctly when doing a clone+share (issue5378)...
r30041 else:
defaultpath = source
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761 sharerepo = repository(ui, path=sharepath)
Augie Fackler
formatting: blacken the codebase...
r43346 destrepo = share(
ui,
sharerepo,
dest=dest,
update=False,
bookmarks=False,
defaultpath=defaultpath,
)
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761
# We need to perform a pull against the dest repo to fetch bookmarks
# and other non-store data that isn't shared by default. In the case of
# non-existing shared repo, this means we pull from the remote twice. This
# is a bit weird. But at the time it was implemented, there wasn't an easy
# way to pull just non-changegroup data.
exchange.pull(destrepo, srcpeer, heads=revs)
Gregory Szorc
hg: perform update after pulling during clone with share (issue5103)...
r28632 _postshareupdate(destrepo, update)
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761 return srcpeer, peer(ui, peeropts, dest)
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
share: properly copy cache files when cloning from a share...
r46739 # Recomputing caches is often slow on big repos, so copy them.
local-clone: extract the closure copying caches...
r32492 def _copycache(srcrepo, dstcachedir, fname):
"""copy a cache from srcrepo to destcachedir (if it exists)"""
Joerg Sonnenberger
share: properly copy cache files when cloning from a share...
r46739 srcfname = srcrepo.cachevfs.join(fname)
dstfname = os.path.join(dstcachedir, fname)
if os.path.exists(srcfname):
local-clone: extract the closure copying caches...
r32492 if not os.path.exists(dstcachedir):
os.mkdir(dstcachedir)
Joerg Sonnenberger
share: properly copy cache files when cloning from a share...
r46739 util.copyfile(srcfname, dstfname)
local-clone: extract the closure copying caches...
r32492
Augie Fackler
formatting: blacken the codebase...
r43346
def clone(
ui,
peeropts,
source,
dest=None,
pull=False,
revs=None,
update=True,
stream=False,
branch=None,
shareopts=None,
storeincludepats=None,
storeexcludepats=None,
depth=None,
):
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597 """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
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 function. Returns a pair of repository peers, the source and
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597 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.
Vadim Gelfer
clean up trailing white space.
r2600
Vadim Gelfer
hg.py: add islocal() and defaultdest() functions, refactor...
r2719 Arguments:
source: repository object or URL
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
dest: URL of destination repository to create (defaults to base
name of source repository)
Siddharth Agarwal
hg.clone: set 'stream' depending on whether --pull was requested or not...
r23545 pull: always pull from source repository, even in local case or if the
server prefers streaming
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
Vadim Gelfer
clone: disable stream support on server side by default....
r2621 stream: stream raw data uncompressed from repository (fast over
LAN, slow over WAN)
Vadim Gelfer
clone: do not make streaming default. add --stream option instead.
r2613
Martin von Zweigbergk
clone: rename "rev" to "revs" since there can be many...
r37279 revs: revision to clone up to (implies pull=True)
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
update: update working directory after clone completes, if
Bryan O'Sullivan
repo: add rjoin method
r6526 destination is local repository (True means update to default rev,
anything else is treated as a revision)
Sune Foldager
add -b/--branch option to clone, bundle, incoming, outgoing, pull, push
r10379
branch: branches to clone
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761
shareopts: dict of options to control auto sharing behavior. The "pool" key
activates auto sharing mode and defines the directory for stores. The
"mode" key determines how to construct the directory name of the shared
repository. "identity" means the name is derived from the node of the first
changeset in the repository. "remote" means the name is derived from the
remote's path/URL. Defaults to "identity."
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586
storeincludepats and storeexcludepats: sets of file patterns to include and
exclude in the repository copy, respectively. If not defined, all files
will be included (a "full" clone). Otherwise a "narrow" clone containing
only the requested files will be performed. If ``storeincludepats`` is not
defined but ``storeexcludepats`` is, ``storeincludepats`` is assumed to be
``path:.``. If both are empty sets, no files will be cloned.
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597 """
Matt Mackall
Add support for url#id syntax...
r4478
Pulkit Goyal
py3: replace str with bytes in isinstance()...
r32970 if isinstance(source, bytes):
urlutil: add a `get_clone_path` function...
r47696 src = urlutil.get_clone_path(ui, source, branch)
origsource, source, branches = src
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 srcpeer = peer(ui, peeropts, source)
Vadim Gelfer
hg.py: add islocal() and defaultdest() functions, refactor...
r2719 else:
Augie Fackler
formatting: blacken the codebase...
r43346 srcpeer = source.peer() # in case we were called with a localrepo
Martin von Zweigbergk
parseurl: consistently call second output "branches"...
r37278 branches = (None, branch or [])
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 origsource = source = srcpeer.url()
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 srclock = destlock = cleandir = None
destpeer = None
try:
revs, checkout = addbranchrevs(srcpeer, srcpeer, branches, revs)
Vadim Gelfer
hg.py: add islocal() and defaultdest() functions, refactor...
r2719
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if dest is None:
dest = defaultdest(source)
if dest:
ui.status(_(b"destination directory: %s\n") % dest)
else:
clone: use `get_clone_path`...
r47713 dest = urlutil.get_clone_path(ui, dest)[0]
Vadim Gelfer
hg.py: add islocal() and defaultdest() functions, refactor...
r2719
urlutil: extract `url` related code from `util` into the new module...
r47669 dest = urlutil.urllocalpath(dest)
source = urlutil.urllocalpath(source)
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if not dest:
raise error.InputError(_(b"empty destination path is not valid"))
Chinmay Joshi
hg: use vfs functions in clone...
r21803
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 destvfs = vfsmod.vfs(dest, expandpath=True)
if destvfs.lexists():
if not destvfs.isdir():
raise error.InputError(
_(b"destination '%s' already exists") % dest
)
elif destvfs.listdir():
raise error.InputError(
_(b"destination '%s' is not empty") % dest
)
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 createopts = {}
narrow = False
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if storeincludepats is not None:
narrowspec.validatepatterns(storeincludepats)
narrow = True
if storeexcludepats is not None:
narrowspec.validatepatterns(storeexcludepats)
narrow = True
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if narrow:
# Include everything by default if only exclusion patterns defined.
if storeexcludepats and not storeincludepats:
storeincludepats = {b'path:.'}
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 createopts[b'narrowfiles'] = True
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if depth:
createopts[b'shallowfilestore'] = True
Gregory Szorc
localrepo: support marking repos as having shallow file storage...
r40426
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if srcpeer.capable(b'lfs-serve'):
# Repository creation honors the config if it disabled the extension, so
# we can't just announce that lfs will be enabled. This check avoids
# saying that lfs will be enabled, and then saying it's an unknown
# feature. The lfs creation option is set in either case so that a
# requirement is added. If the extension is explicitly disabled but the
# requirement is set, the clone aborts early, before transferring any
# data.
createopts[b'lfs'] = True
Matt Harbison
lfs: autoload the extension when cloning from repo with lfs enabled...
r40360
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if extensions.disabled_help(b'lfs'):
ui.status(
_(
b'(remote is using large file support (lfs), but it is '
b'explicitly disabled in the local configuration)\n'
)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 else:
ui.status(
_(
b'(remote is using large file support (lfs); lfs will '
b'be enabled for this repository)\n'
)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Harbison
lfs: autoload the extension when cloning from repo with lfs enabled...
r40360
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 shareopts = shareopts or {}
sharepool = shareopts.get(b'pool')
sharenamemode = shareopts.get(b'mode')
if sharepool and islocal(dest):
sharepath = None
if sharenamemode == b'identity':
# Resolve the name from the initial changeset in the remote
# repository. This returns nullid when the remote is empty. It
# raises RepoLookupError if revision 0 is filtered or otherwise
# not available. If we fail to resolve, sharing is not enabled.
try:
with srcpeer.commandexecutor() as e:
rootnode = e.callcommand(
b'lookup',
{
b'key': b'0',
},
).result()
Gregory Szorc
hg: use command executor for wire protocol commands...
r37658
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if rootnode != sha1nodeconstants.nullid:
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 sharepath = os.path.join(sharepool, hex(rootnode))
else:
ui.status(
_(
b'(not using pooled storage: '
b'remote appears to be empty)\n'
)
)
except error.RepoLookupError:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'(not using pooled storage: '
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 b'unable to resolve identity of remote)\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 elif sharenamemode == b'remote':
sharepath = os.path.join(
sharepool, hex(hashutil.sha1(source).digest())
)
else:
raise error.Abort(
_(b'unknown share naming mode: %s') % sharenamemode
Augie Fackler
formatting: blacken the codebase...
r43346 )
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419
# TODO this is a somewhat arbitrary restriction.
if narrow:
ui.status(
_(b'(pooled storage not supported for narrow clones)\n')
)
sharepath = None
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if sharepath:
return clonewithshare(
ui,
peeropts,
sharepath,
source,
srcpeer,
dest,
pull=pull,
rev=revs,
update=update,
stream=stream,
)
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 srcrepo = srcpeer.local()
Gregory Szorc
hg: support for auto sharing stores when cloning...
r25761
Brendan Cully
clone: make default path absolute for all local paths...
r14377 abspath = origsource
if islocal(origsource):
windows: use abspath in mercurial/hg.py...
r48426 abspath = util.abspath(urlutil.urllocalpath(origsource))
Brendan Cully
clone: make default path absolute for all local paths...
r14377
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if islocal(dest):
clone: cleanup the "cleanup dir" logic used during local clone...
r48209 if os.path.exists(dest):
# only clean up directories we create ourselves
hgdir = os.path.realpath(os.path.join(dest, b".hg"))
cleandir = hgdir
else:
cleandir = dest
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 copy = False
Augie Fackler
formatting: blacken the codebase...
r43346 if (
srcrepo
and srcrepo.cancopy()
and islocal(dest)
and not phases.hassecret(srcrepo)
):
Martin von Zweigbergk
clone: rename "rev" to "revs" since there can be many...
r37279 copy = not pull and not revs
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586 # TODO this is a somewhat arbitrary restriction.
if narrow:
copy = False
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 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
Martin Geisler
hg: remove underscores in clone function
r14463 srclock = srcrepo.lock(wait=False)
Matt Mackall
error: move lock errors...
r7640 except error.LockError:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 copy = False
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if copy:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 srcrepo.hook(b'preoutgoing', throw=True, source=b'clone')
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
clone: use "official" API to create local clone destination...
r48235 destrootpath = urlutil.urllocalpath(dest)
dest_reqs = localrepo.clone_requirements(ui, createopts, srcrepo)
localrepo.createrepository(
ui,
destrootpath,
requirements=dest_reqs,
)
destrepo = localrepo.makelocalrepository(ui, destrootpath)
clone: reuse the stream clone logic for local clone...
r48240 destlock = destrepo.lock()
from . import streamclone # avoid cycle
clone: use "official" API to create local clone destination...
r48235
clone: reuse the stream clone logic for local clone...
r48240 streamclone.local_copy(srcrepo, destrepo)
Tomasz Kleczek
branchcache: fetch source branchcache during clone (issue3378)...
r17740
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 # we need to re-init the repo after manually copying the data
# into it
Simon Heimberg
peer: subrepo isolation, pass repo instead of repo.ui to hg.peer...
r17874 destpeer = peer(srcrepo, peeropts, dest)
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 srcrepo.hook(
b'outgoing', source=b'clone', node=srcrepo.nodeconstants.nullhex
)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 else:
Matt Mackall
clone: fix race with same target directory (issue716)...
r5569 try:
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586 # only pass ui when no srcrepo
Augie Fackler
formatting: blacken the codebase...
r43346 destpeer = peer(
srcrepo or ui,
peeropts,
dest,
create=True,
createopts=createopts,
)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as inst:
Matt Mackall
clone: fix race with same target directory (issue716)...
r5569 if inst.errno == errno.EEXIST:
Augie Fackler
hg: replace DirCleanup class with normal try/finally use
r18441 cleandir = None
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"destination '%s' already exists") % dest
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
clone: fix race with same target directory (issue716)...
r5569 raise
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
Martin von Zweigbergk
clone: rename "rev" to "revs" since there can be many...
r37279 if revs:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not srcpeer.capable(b'lookup'):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"src repository does not support "
b"revision lookup and so doesn't "
b"support clone by revision"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Gregory Szorc
hg: use command executor for wire protocol commands...
r37658
# TODO this is batchable.
remoterevs = []
for rev in revs:
with srcpeer.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 remoterevs.append(
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 e.callcommand(
b'lookup',
{
b'key': rev,
},
).result()
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
hg: use command executor for wire protocol commands...
r37658 revs = remoterevs
Brett Carter
clone: try updating to the actual changeset specified in options...
r8417 checkout = revs[0]
Martin von Zweigbergk
clone: rename "rev" to "revs" since there can be many...
r37279 else:
revs = None
Augie Fackler
localrepo: remove clone method by hoisting into hg.py...
r27165 local = destpeer.local()
if local:
Gregory Szorc
hg: write narrow patterns after repo creation...
r39591 if narrow:
Martin von Zweigbergk
narrow: detect if narrowspec was changed in a different share...
r41072 with local.wlock(), local.lock():
Gregory Szorc
hg: write narrow patterns after repo creation...
r39591 local.setnarrowpats(storeincludepats, storeexcludepats)
Martin von Zweigbergk
narrow: move copytonarrowspec() out of setnarrowpats()...
r41272 narrowspec.copytoworkingcopy(local)
Gregory Szorc
hg: write narrow patterns after repo creation...
r39591
urlutil: extract `url` related code from `util` into the new module...
r47669 u = urlutil.url(abspath)
Boris Feld
clonebundle: make it possible to retrieve the initial bundle through largefile...
r35581 defaulturl = bytes(u)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 local.ui.setconfig(b'paths', b'default', defaulturl, b'clone')
Siddharth Agarwal
hg.clone: set 'stream' depending on whether --pull was requested or not...
r23545 if not stream:
if pull:
stream = False
else:
stream = None
Augie Fackler
localrepo: remove clone method by hoisting into hg.py...
r27165 # internal config: ui.quietbookmarkmove
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 overrides = {(b'ui', b'quietbookmarkmove'): True}
with local.ui.configoverride(overrides, b'clone'):
Augie Fackler
formatting: blacken the codebase...
r43346 exchange.pull(
local,
srcpeer,
path: keep the path instance in the `pulloperation`...
r49055 heads=revs,
Augie Fackler
formatting: blacken the codebase...
r43346 streamclonerequested=stream,
includepats=storeincludepats,
excludepats=storeexcludepats,
depth=depth,
)
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 elif srcrepo:
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586 # TODO lift restriction once exchange.push() accepts narrow
# push.
if narrow:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'narrow clone not available for '
b'remote destinations'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Gregory Szorc
hg: recognize include and exclude patterns when cloning...
r39586
Augie Fackler
formatting: blacken the codebase...
r43346 exchange.push(
srcrepo,
destpeer,
revs=revs,
bookmarks=srcrepo._bookmarks.keys(),
)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"clone from remote to remote not supported")
Augie Fackler
formatting: blacken the codebase...
r43346 )
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
Augie Fackler
hg: replace DirCleanup class with normal try/finally use
r18441 cleandir = None
Vadim Gelfer
clone: move code into hg module. make doc better....
r2597
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 destrepo = destpeer.local()
if destrepo:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 template = uimod.samplehgrcs[b'cloned']
urlutil: extract `url` related code from `util` into the new module...
r47669 u = urlutil.url(abspath)
Augie Fackler
clone: don't save user's password in .hg/hgrc (Issue3122)
r15552 u.passwd = None
Yuya Nishihara
py3: use bytes IO to write sample hgrc...
r33650 defaulturl = bytes(u)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 destrepo.vfs.write(b'hgrc', util.tonativeeol(template % defaulturl))
destrepo.ui.setconfig(b'paths', b'default', defaulturl, b'clone')
Matt Mackall
subrepo: add update/merge logic
r8814
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if ui.configbool(b'experimental', b'remotenames'):
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 logexchange.pullremotenames(destrepo, srcpeer)
Pulkit Goyal
clone: add support for storing remotenames while cloning...
r35332
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if update:
Bryan O'Sullivan
repo: add rjoin method
r6526 if update is not True:
Gregory Szorc
hg: use command executor for wire protocol commands...
r37658 with srcpeer.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 checkout = e.callcommand(
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 b'lookup',
{
b'key': update,
},
Augie Fackler
formatting: blacken the codebase...
r43346 ).result()
Gregory Szorc
hg: use command executor for wire protocol commands...
r37658
Thomas Arendsen Hein
clone: make sure to use "@" as bookmark and "default" as branch (issue3677)...
r17867 uprev = None
Adrian Buehlmann
clone: show status "updating to bookmark @"...
r17882 status = None
Thomas Arendsen Hein
clone: make sure to use "@" as bookmark and "default" as branch (issue3677)...
r17867 if checkout is not None:
Boris Feld
clone: process 'lookup' return as an arbitrary symbol...
r38776 # Some extensions (at least hg-git and hg-subversion) have
# a peer.lookup() implementation that returns a name instead
# of a nodeid. We work around it here until we've figured
# out a better solution.
if len(checkout) == 20 and checkout in destrepo:
Martin von Zweigbergk
clone: avoid using repo.lookup() with binary nodeid...
r37498 uprev = checkout
Boris Feld
clone: process 'lookup' return as an arbitrary symbol...
r38776 elif scmutil.isrevsymbol(destrepo, checkout):
uprev = scmutil.revsymbol(destrepo, checkout).node()
Martin von Zweigbergk
clone: avoid using repo.lookup() with binary nodeid...
r37498 else:
Sean Farley
clone: check update rev for being True...
r26354 if update is not True:
try:
uprev = destrepo.lookup(update)
except error.RepoLookupError:
pass
Thomas Arendsen Hein
clone: make sure to use "@" as bookmark and "default" as branch (issue3677)...
r17867 if uprev is None:
try:
Dan Villiom Podlaski Christiansen
clone: update to active bookmark, if set...
r46814 if destrepo._activebookmark:
uprev = destrepo.lookup(destrepo._activebookmark)
update = destrepo._activebookmark
else:
uprev = destrepo._bookmarks[b'@']
update = b'@'
Adrian Buehlmann
clone: show status "updating to bookmark @"...
r17882 bn = destrepo[uprev].branch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if bn == b'default':
Dan Villiom Podlaski Christiansen
clone: update to active bookmark, if set...
r46814 status = _(b"updating to bookmark %s\n" % update)
Adrian Buehlmann
clone: show status "updating to bookmark @"...
r17882 else:
Augie Fackler
formatting: blacken the codebase...
r43346 status = (
Dan Villiom Podlaski Christiansen
clone: update to active bookmark, if set...
r46814 _(b"updating to bookmark %s on branch %s\n")
) % (update, bn)
Thomas Arendsen Hein
clone: make sure to use "@" as bookmark and "default" as branch (issue3677)...
r17867 except KeyError:
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 uprev = destrepo.branchtip(b'default')
Thomas Arendsen Hein
clone: make sure to use "@" as bookmark and "default" as branch (issue3677)...
r17867 except error.RepoLookupError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 uprev = destrepo.lookup(b'tip')
Adrian Buehlmann
clone: show status "updating to bookmark @"...
r17882 if not status:
bn = destrepo[uprev].branch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 status = _(b"updating to branch %s\n") % bn
Adrian Buehlmann
clone: show status "updating to bookmark @"...
r17882 destrepo.ui.status(status)
Martin Geisler
hg: remove underscores in clone function
r14463 _update(destrepo, uprev)
Thomas Arendsen Hein
clone: activate bookmark specified with --updaterev
r17703 if update in destrepo._bookmarks:
Ryan McElroy
bookmarks: rename setcurrent to activate (API)...
r24945 bookmarks.activate(destrepo, update)
clone: make sure we warm the cache after a clone...
r47032 if destlock is not None:
release(destlock)
# here is a tiny windows were someone could end up writing the
# repository before the cache are sure to be warm. This is "fine"
# as the only "bad" outcome would be some slowness. That potential
# slowness already affect reader.
with destrepo.lock():
updatecaches: use the `caches` argument instead of a special `full` value...
r48079 destrepo.updatecaches(caches=repositorymod.CACHES_POST_CLONE)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 finally:
Matt Mackall
bookmarks: backout locking change in 12dea4d998ec...
r15908 release(srclock, destlock)
Augie Fackler
hg: replace DirCleanup class with normal try/finally use
r18441 if cleandir is not None:
shutil.rmtree(cleandir, True)
Sune Foldager
peer: introduce peer methods to prepare for peer classes...
r17191 if srcpeer is not None:
srcpeer.close()
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if destpeer and destpeer.local() is None:
destpeer.close()
simon@laptop-tosh
hg: move return statement after finally block...
r19313 return srcpeer, destpeer
Matt Mackall
Move merge code to its own module...
r2775
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hg: add quietempty flag to _showstats...
r27402 def _showstats(repo, stats, quietempty=False):
Gregory Szorc
merge: deprecate accessing update results by index...
r37143 if quietempty and stats.isempty():
timeless
hg: add quietempty flag to _showstats...
r27402 return
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"%d files updated, %d files merged, "
b"%d files removed, %d files unresolved\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% (
stats.updatedcount,
stats.mergedcount,
stats.removedcount,
stats.unresolvedcount,
)
)
Matt Mackall
merge: pull user messages out to hg.py...
r3316
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166 def updaterepo(repo, node, overwrite, updatecheck=None):
Simon Heimberg
subrepo: only do clean update when overwrite is set (issue3276)...
r17895 """Update the working directory to node.
When overwrite is set, changes are clobbered, merged else
returns stats (see pydoc mercurial.merge.applyupdates)"""
Martin von Zweigbergk
updaterepo: add deprecation warning...
r46180 repo.ui.deprecwarn(
b'prefer merge.update() or merge.clean_update() over hg.updaterepo()',
b'5.7',
)
Martin von Zweigbergk
merge: make low-level update() private (API)...
r46134 return mergemod._update(
Augie Fackler
formatting: blacken the codebase...
r43346 repo,
node,
branchmerge=False,
force=overwrite,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 labels=[b'working copy', b'destination'],
Augie Fackler
formatting: blacken the codebase...
r43346 updatecheck=updatecheck,
)
Simon Heimberg
subrepo: only do clean update when overwrite is set (issue3276)...
r17895
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166 def update(repo, node, quietempty=False, updatecheck=None):
"""update the working directory to node"""
Martin von Zweigbergk
merge: replace calls to hg.updaterepo() by merge.update()...
r46151 stats = mergemod.update(repo[node], updatecheck=updatecheck)
timeless
update: add quietempty flag to _showstats...
r27404 _showstats(repo, stats, quietempty)
Gregory Szorc
merge: deprecate accessing update results by index...
r37143 if stats.unresolvedcount:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.status(_(b"use 'hg resolve' to retry unresolved file merges\n"))
Gregory Szorc
merge: deprecate accessing update results by index...
r37143 return stats.unresolvedcount > 0
Matt Mackall
Move merge code to its own module...
r2775
Augie Fackler
formatting: blacken the codebase...
r43346
Benoit Boissinot
add a comment about the need of hg._update()
r7546 # naming conflict in clone()
_update = update
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
histedit: omit useless message from abort...
r27403 def clean(repo, node, show_stats=True, quietempty=False):
Matt Mackall
Introduce update helper functions: update, merge, clean, and revert
r2808 """forcibly switch the working directory to node, clobbering changes"""
Martin von Zweigbergk
merge: use merge.clean_update() when applicable...
r46133 stats = mergemod.clean_update(repo[node])
Martin von Zweigbergk
clean: check that there are no conflicts after...
r44620 assert stats.unresolvedcount == 0
Matt Mackall
many, many trivial check-code fixups
r10282 if show_stats:
timeless
histedit: omit useless message from abort...
r27403 _showstats(repo, stats, quietempty)
hg: make `clean` return consistent with the `update` function...
r47495 return False
Matt Mackall
Move merge code to its own module...
r2775
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501 # naming conflict in updatetotally()
_clean = clean
Augie Fackler
formatting: blacken the codebase...
r43346 _VALID_UPDATECHECKS = {
mergemod.UPDATECHECK_ABORT,
mergemod.UPDATECHECK_NONE,
mergemod.UPDATECHECK_LINEAR,
mergemod.UPDATECHECK_NO_CONFLICT,
Augie Fackler
hg: have `updatetotally` more thoroughly check updatecheck argument (API)...
r43241 }
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166 def updatetotally(ui, repo, checkout, brev, clean=False, updatecheck=None):
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501 """Update the working directory with extra care for non-file components
This takes care of non-file components below:
:bookmark: might be advanced or (in)activated
This takes arguments below:
:checkout: to which revision the working directory is updated
:brev: a name, which might be a bookmark to be activated after updating
:clean: whether changes in the working directory can be discarded
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166 :updatecheck: how to deal with a dirty working directory
Augie Fackler
merge: replace magic strings with NAMED_CONSTANTS (API)...
r43240 Valid values for updatecheck are the UPDATECHECK_* constants
defined in the merge module. Passing `None` will result in using the
configured default.
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166
Augie Fackler
merge: replace magic strings with NAMED_CONSTANTS (API)...
r43240 * ABORT: abort if the working directory is dirty
* NONE: don't check (merge working directory changes into destination)
* LINEAR: check that update is linear before merging working directory
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166 changes into destination
Augie Fackler
merge: replace magic strings with NAMED_CONSTANTS (API)...
r43240 * NO_CONFLICT: check that the update does not result in file merges
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501
This returns whether conflict is detected at updating or not.
"""
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166 if updatecheck is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 updatecheck = ui.config(b'commands', b'update.check')
Augie Fackler
hg: have `updatetotally` more thoroughly check updatecheck argument (API)...
r43241 if updatecheck not in _VALID_UPDATECHECKS:
Martin von Zweigbergk
update: add experimental config for default way of handling dirty wdir...
r31167 # If not configured, or invalid value configured
Augie Fackler
merge: replace magic strings with NAMED_CONSTANTS (API)...
r43240 updatecheck = mergemod.UPDATECHECK_LINEAR
Augie Fackler
hg: have `updatetotally` more thoroughly check updatecheck argument (API)...
r43241 if updatecheck not in _VALID_UPDATECHECKS:
Augie Fackler
formatting: blacken the codebase...
r43346 raise ValueError(
r'Invalid updatecheck value %r (can accept %r)'
% (updatecheck, _VALID_UPDATECHECKS)
)
FUJIWARA Katsunori
hg: acquire wlock while updating the working directory via updatetotally...
r28503 with repo.wlock():
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501 movemarkfrom = None
warndest = False
if checkout is None:
Martin von Zweigbergk
destutil: drop now-unused "check" parameter from destupdate()
r30962 updata = destutil.destupdate(repo, clean=clean)
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501 checkout, movemarkfrom, brev = updata
warndest = True
if clean:
ret = _clean(repo, checkout)
else:
Augie Fackler
merge: replace magic strings with NAMED_CONSTANTS (API)...
r43240 if updatecheck == mergemod.UPDATECHECK_ABORT:
Martin von Zweigbergk
update: move check for dirty wdir into hg.updatetotally()...
r30963 cmdutil.bailifchanged(repo, merge=False)
Augie Fackler
merge: replace magic strings with NAMED_CONSTANTS (API)...
r43240 updatecheck = mergemod.UPDATECHECK_NONE
Martin von Zweigbergk
update: accept --merge to allow merging across topo branches (issue5125)
r31166 ret = _update(repo, checkout, updatecheck=updatecheck)
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501
if not ret and movemarkfrom:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if movemarkfrom == repo[b'.'].node():
Augie Fackler
formatting: blacken the codebase...
r43346 pass # no-op update
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif bookmarks.update(repo, [movemarkfrom], repo[b'.'].node()):
b = ui.label(repo._activebookmark, b'bookmarks.active')
ui.status(_(b"updating bookmark %s\n") % b)
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501 else:
# this can happen with a non-linear update
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b = ui.label(repo._activebookmark, b'bookmarks')
ui.status(_(b"(leaving bookmark %s)\n") % b)
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501 bookmarks.deactivate(repo)
elif brev in repo._bookmarks:
if brev != repo._activebookmark:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b = ui.label(brev, b'bookmarks.active')
ui.status(_(b"(activating bookmark %s)\n") % b)
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501 bookmarks.activate(repo, brev)
elif brev:
if repo._activebookmark:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b = ui.label(repo._activebookmark, b'bookmarks')
ui.status(_(b"(leaving bookmark %s)\n") % b)
FUJIWARA Katsunori
commands: centralize code to update with extra care for non-file components...
r28501 bookmarks.deactivate(repo)
if warndest:
destutil.statusotherdests(ui, repo)
return ret
Augie Fackler
formatting: blacken the codebase...
r43346
def merge(
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 ctx,
force=False,
remind=True,
labels=None,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Greg Ward
merge: document some internal return values.
r13162 """Branch merge with node, resolving changes. Return true if any
unresolved conflicts."""
Martin von Zweigbergk
merge: make hg.merge() take a context instead of a node...
r44916 repo = ctx.repo()
stats = mergemod.merge(ctx, force=force, labels=labels)
Matt Mackall
merge: pull user messages out to hg.py...
r3316 _showstats(repo, stats)
Gregory Szorc
merge: deprecate accessing update results by index...
r37143 if stats.unresolvedcount:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"use 'hg resolve' to retry unresolved file merges "
b"or 'hg merge --abort' to abandon\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Taapas Agrawal
abort: added support for merge...
r42803 elif remind:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.status(_(b"(branch merge, don't forget to commit)\n"))
Gregory Szorc
merge: deprecate accessing update results by index...
r37143 return stats.unresolvedcount > 0
Matt Mackall
Introduce update helper functions: update, merge, clean, and revert
r2808
Augie Fackler
formatting: blacken the codebase...
r43346
Taapas Agrawal
abort: removed labels argument from abortmerge()...
r42810 def abortmerge(ui, repo):
Augie Fackler
mergestate: split out merge state handling code from main merge module...
r45383 ms = mergestatemod.mergestate.read(repo)
Taapas Agrawal
abort: added support for merge...
r42803 if ms.active():
# there were conflicts
node = ms.localctx.hex()
else:
# there were no conficts, mergestate was not stored
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 node = repo[b'.'].hex()
Taapas Agrawal
abort: added support for merge...
r42803
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 repo.ui.status(_(b"aborting the merge, updating back to %s\n") % node[:12])
Martin von Zweigbergk
merge: introduce a clean_update() for that use-case...
r44743 stats = mergemod.clean_update(repo[node])
Martin von Zweigbergk
merge: check that there are no conflicts after --abort...
r44636 assert stats.unresolvedcount == 0
Taapas Agrawal
abort: added support for merge...
r42803 _showstats(repo, stats)
Augie Fackler
formatting: blacken the codebase...
r43346
def _incoming(
incoming: kill the `repo._subtoppath =` hack...
r47712 displaychlist,
subreporecurse,
ui,
repo,
source,
opts,
buffered=False,
subpath=None,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Nicolas Dumazet
incoming: unify code for incoming and graphlog.incoming
r12730 """
Helper for incoming / gincoming.
displaychlist gets called with
(remoterepo, incomingchangesetlist, displayer) parameters,
and is supposed to contain only code that can't be unified.
"""
path: return path instance directly from get_pull_paths...
r49054 srcs = urlutil.get_pull_paths(repo, ui, [source])
incoming: use `urlutil.get_pull_paths`...
r47694 srcs = list(srcs)
if len(srcs) != 1:
Matt Harbison
incoming: use bytes for an error message...
r47768 msg = _(b'for now, incoming supports only a single source, %d provided')
incoming: use `urlutil.get_pull_paths`...
r47694 msg %= len(srcs)
raise error.Abort(msg)
path: return path instance directly from get_pull_paths...
r49054 path = srcs[0]
source, branches = urlutil.parseurl(path.rawloc, opts.get(b'branch'))
incoming: kill the `repo._subtoppath =` hack...
r47712 if subpath is not None:
subpath = urlutil.url(subpath)
if subpath.isabs():
source = bytes(subpath)
else:
p = urlutil.url(source)
p.path = os.path.normpath(b'%s/%s' % (p.path, subpath))
source = bytes(p)
Matt Mackall
hg: change various repository() users to use peer() where appropriate...
r14556 other = peer(repo, opts, source)
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 cleanupfn = other.close
try:
urlutil: extract `url` related code from `util` into the new module...
r47669 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(source))
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 revs, checkout = addbranchrevs(repo, other, branches, opts.get(b'rev'))
Nicolas Dumazet
incoming: unify code for incoming and graphlog.incoming
r12730
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 if revs:
revs = [other.lookup(rev) for rev in revs]
other, chlist, cleanupfn = bundlerepo.getremotechanges(
Sushil khanchi
hg: let extensions call the func without populating opts keys...
r48987 ui, repo, other, revs, opts.get(b"bundle"), opts.get(b"force")
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 )
Peter Arrenbrecht
bundlerepo: fix and improve getremotechanges...
r14161 if not chlist:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b"no changes found\n"))
Peter Arrenbrecht
bundlerepo: fix and improve getremotechanges...
r14161 return subreporecurse()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.pager(b'incoming')
Augie Fackler
formatting: blacken the codebase...
r43346 displayer = logcmdutil.changesetdisplayer(
ui, other, opts, buffered=buffered
)
Nicolas Dumazet
incoming: unify code for incoming and graphlog.incoming
r12730 displaychlist(other, chlist, displayer)
displayer.close()
finally:
Peter Arrenbrecht
bundlerepo: fix and improve getremotechanges...
r14161 cleanupfn()
Nicolas Dumazet
incoming: unify code for incoming and graphlog.incoming
r12730 subreporecurse()
Augie Fackler
formatting: blacken the codebase...
r43346 return 0 # exit code is zero since we found incoming changes
Nicolas Dumazet
incoming: unify code for incoming and graphlog.incoming
r12730
incoming: kill the `repo._subtoppath =` hack...
r47712 def incoming(ui, repo, source, opts, subpath=None):
Nicolas Dumazet
incoming: unify code for incoming and graphlog.incoming
r12730 def subreporecurse():
Erik Zielke
incoming/outgoing: Fix recursion on sub repositories...
r12400 ret = 1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts.get(b'subrepos'):
Erik Zielke
incoming/outgoing: Fix recursion on sub repositories...
r12400 ctx = repo[None]
for subpath in sorted(ctx.substate):
sub = ctx.sub(subpath)
ret = min(ret, sub.incoming(ui, source, opts))
return ret
Nicolas Dumazet
incoming: unify code for incoming and graphlog.incoming
r12730 def display(other, chlist, displayer):
Yuya Nishihara
cmdutil: drop aliases for logcmdutil functions (API)...
r35906 limit = logcmdutil.getlimit(opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts.get(b'newest_first'):
Nicolas Dumazet
incoming: rename variable...
r12729 chlist.reverse()
Martin Geisler
incoming: move code from commands to cmdutil...
r12273 count = 0
Nicolas Dumazet
incoming: rename variable...
r12729 for n in chlist:
Martin Geisler
incoming: move code from commands to cmdutil...
r12273 if limit is not None and count >= limit:
break
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 parents = [
p for p in other.changelog.parents(n) if p != repo.nullid
]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts.get(b'no_merges') and len(parents) == 2:
Martin Geisler
incoming: move code from commands to cmdutil...
r12273 continue
count += 1
displayer.show(other[n])
Augie Fackler
formatting: blacken the codebase...
r43346
incoming: kill the `repo._subtoppath =` hack...
r47712 return _incoming(
display, subreporecurse, ui, repo, source, opts, subpath=subpath
)
Martin Geisler
incoming: move code from commands to cmdutil...
r12273
Augie Fackler
formatting: blacken the codebase...
r43346
outgoing: accept multiple destinations...
r47693 def _outgoing(ui, repo, dests, opts, subpath=None):
out = set()
others = []
for path in urlutil.get_push_paths(repo, ui, dests):
dest = path.pushloc or path.loc
if subpath is not None:
subpath = urlutil.url(subpath)
if subpath.isabs():
dest = bytes(subpath)
else:
p = urlutil.url(dest)
p.path = os.path.normpath(b'%s/%s' % (p.path, subpath))
dest = bytes(p)
branches = path.branch, opts.get(b'branch') or []
outgoing: pass subrepo path using function argument instead of abssource hack...
r47692
outgoing: accept multiple destinations...
r47693 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(dest))
revs, checkout = addbranchrevs(repo, repo, branches, opts.get(b'rev'))
if revs:
Martin von Zweigbergk
errors: raise InputError on bad revset to revrange() iff provided by the user...
r48928 revs = [repo[rev].node() for rev in logcmdutil.revrange(repo, revs)]
Nicolas Dumazet
outgoing: unify common graphlog.outgoing and hg.outgoing code
r12735
outgoing: accept multiple destinations...
r47693 other = peer(repo, opts, dest)
try:
outgoing = discovery.findcommonoutgoing(
repo, other, revs, force=opts.get(b'force')
)
o = outgoing.missing
out.update(o)
if not o:
scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
others.append(other)
except: # re-raises
other.close()
raise
# make sure this is ordered by revision number
outgoing_revs = list(out)
cl = repo.changelog
outgoing_revs.sort(key=cl.rev)
return outgoing_revs, others
Nicolas Dumazet
outgoing: unify common graphlog.outgoing and hg.outgoing code
r12735
Augie Fackler
formatting: blacken the codebase...
r43346
outgoing: accept multiple destinations...
r47693 def _outgoing_recurse(ui, repo, dests, opts):
outgoing: make `recurse` a real function...
r47675 ret = 1
if opts.get(b'subrepos'):
ctx = repo[None]
for subpath in sorted(ctx.substate):
sub = ctx.sub(subpath)
outgoing: accept multiple destinations...
r47693 ret = min(ret, sub.outgoing(ui, dests, opts))
outgoing: make `recurse` a real function...
r47675 return ret
outgoing: move filtering logic in its own function...
r47676 def _outgoing_filter(repo, revs, opts):
"""apply revision filtering/ordering option for outgoing"""
limit = logcmdutil.getlimit(opts)
no_merges = opts.get(b'no_merges')
if opts.get(b'newest_first'):
revs.reverse()
if limit is None and not no_merges:
for r in revs:
yield r
return
count = 0
cl = repo.changelog
for n in revs:
if limit is not None and count >= limit:
break
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 parents = [p for p in cl.parents(n) if p != repo.nullid]
outgoing: move filtering logic in its own function...
r47676 if no_merges and len(parents) == 2:
continue
count += 1
yield n
outgoing: accept multiple destinations...
r47693 def outgoing(ui, repo, dests, opts, subpath=None):
outgoing: merge the code handling --graph with the main one...
r47677 if opts.get(b'graph'):
logcmdutil.checkunsupportedgraphflags([], opts)
outgoing: accept multiple destinations...
r47693 o, others = _outgoing(ui, repo, dests, opts, subpath=subpath)
outgoing: remove some early return...
r47674 ret = 1
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 try:
outgoing: remove some early return...
r47674 if o:
ret = 0
Erik Zielke
incoming/outgoing: Fix recursion on sub repositories...
r12400
outgoing: merge the code handling --graph with the main one...
r47677 if opts.get(b'graph'):
revdag = logcmdutil.graphrevs(repo, o, opts)
ui.pager(b'outgoing')
displayer = logcmdutil.changesetdisplayer(
ui, repo, opts, buffered=True
)
logcmdutil.displaygraph(
ui, repo, revdag, displayer, graphmod.asciiedges
)
else:
ui.pager(b'outgoing')
displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
for n in _outgoing_filter(repo, o, opts):
displayer.show(repo[n])
displayer.close()
outgoing: accept multiple destinations...
r47693 for oth in others:
cmdutil.outgoinghooks(ui, repo, oth, opts, o)
ret = min(ret, _outgoing_recurse(ui, repo, dests, opts))
outgoing: remove some early return...
r47674 return ret # exit code is zero since we found outgoing changes
Valentin Gatien-Baron
sshpeer: enable+fix warning about sshpeers not being closed explicitly...
r47419 finally:
outgoing: accept multiple destinations...
r47693 for oth in others:
oth.close()
Augie Fackler
formatting: blacken the codebase...
r43346
Martin Geisler
outgoing: move code from commands to cmdutil...
r12271
verify: introduce a notion of "level"...
r42331 def verify(repo, level=None):
Matt Mackall
Move repo.verify
r2778 """verify the consistency of a repository"""
verify: introduce a notion of "level"...
r42331 ret = verifymod.verify(repo, level=level)
Matt Harbison
verify: check the subrepository references in .hgsubstate...
r25591
# Broken subrepo references in hidden csets don't seem worth worrying about,
# since they can't be pushed/pulled, and --hidden can be used if they are a
# concern.
# pathto() is needed for -R case
Augie Fackler
formatting: blacken the codebase...
r43346 revs = repo.revs(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"filelog(%s)", util.pathto(repo.root, repo.getcwd(), b'.hgsubstate')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Harbison
verify: check the subrepository references in .hgsubstate...
r25591
if revs:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.status(_(b'checking subrepo links\n'))
Matt Harbison
verify: check the subrepository references in .hgsubstate...
r25591 for rev in revs:
ctx = repo[rev]
try:
for subpath in ctx.substate:
Matt Harbison
verify: don't init subrepo when missing one is referenced (issue5128) (API)...
r29021 try:
Augie Fackler
formatting: blacken the codebase...
r43346 ret = (
ctx.sub(subpath, allowcreate=False).verify() or ret
)
Matt Harbison
verify: don't init subrepo when missing one is referenced (issue5128) (API)...
r29021 except error.RepoError as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(b'%d: %s\n' % (rev, e))
Matt Harbison
verify: check the subrepository references in .hgsubstate...
r25591 except Exception:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'.hgsubstate is corrupt in revision %s\n')
Joerg Sonnenberger
node: import symbols explicitly...
r46729 % short(ctx.node())
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Harbison
verify: check the subrepository references in .hgsubstate...
r25591
return ret
Matt Mackall
remoteui: move from cmdutil to hg
r11273
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
remoteui: move from cmdutil to hg
r11273 def remoteui(src, opts):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """build a remote ui from ui or repo and opts"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if util.safehasattr(src, b'baseui'): # looks like a repository
Augie Fackler
formatting: blacken the codebase...
r43346 dst = src.baseui.copy() # drop repo-specific config
src = src.ui # copy target options from repo
else: # assume it's a global ui object
dst = src.copy() # keep all global options
Matt Mackall
remoteui: move from cmdutil to hg
r11273
# copy ssh-specific options
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for o in b'ssh', b'remotecmd':
v = opts.get(o) or src.config(b'ui', o)
Matt Mackall
remoteui: move from cmdutil to hg
r11273 if v:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dst.setconfig(b"ui", o, v, b'copied')
Matt Mackall
remoteui: move from cmdutil to hg
r11273
# copy bundle-specific options
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 r = src.config(b'bundle', b'mainreporoot')
Matt Mackall
remoteui: move from cmdutil to hg
r11273 if r:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dst.setconfig(b'bundle', b'mainreporoot', r, b'copied')
Matt Mackall
remoteui: move from cmdutil to hg
r11273
Mads Kiilerich
https: use web.cacerts configuration from local repo to validate remote repo
r13192 # copy selected local settings to the remote ui
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for sect in (b'auth', b'hostfingerprints', b'hostsecurity', b'http_proxy'):
Matt Mackall
remoteui: move from cmdutil to hg
r11273 for key, val in src.configitems(sect):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dst.setconfig(sect, key, val, b'copied')
v = src.config(b'web', b'cacerts')
Yuya Nishihara
ssl: remove special case of web.cacerts=! from remoteui()...
r29594 if v:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dst.setconfig(b'web', b'cacerts', util.expandpath(v), b'copied')
Matt Mackall
remoteui: move from cmdutil to hg
r11273
return dst
Gregory Szorc
hg: establish a cache for localrepository instances...
r26219
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hg: establish a cache for localrepository instances...
r26219 # Files of interest
# Used to check if the repository has changed looking at mtime and size of
Mads Kiilerich
spelling: trivial spell checking
r26781 # these files.
Augie Fackler
formatting: blacken the codebase...
r43346 foi = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b'spath', b'00changelog.i'),
(b'spath', b'phaseroots'), # ! phase can change content at the same size
(b'spath', b'obsstore'),
(b'path', b'bookmarks'), # ! bookmark can change content at the same size
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Gregory Szorc
hg: establish a cache for localrepository instances...
r26219
class cachedlocalrepo(object):
"""Holds a localrepository that can be cached and reused."""
def __init__(self, repo):
"""Create a new cached repo from an existing repo.
We assume the passed in repo was recently created. If the
repo has changed between when it was created and when it was
turned into a cache, it may not refresh properly.
"""
assert isinstance(repo, localrepo.localrepository)
self._repo = repo
self._state, self.mtime = self._repostate()
FUJIWARA Katsunori
hg: make cachedlocalrepo cache appropriate repoview object...
r28119 self._filtername = repo.filtername
Gregory Szorc
hg: establish a cache for localrepository instances...
r26219
def fetch(self):
"""Refresh (if necessary) and return a repository.
If the cached instance is out of date, it will be recreated
automatically and returned.
Returns a tuple of the repo and a boolean indicating whether a new
repo instance was created.
"""
# We compare the mtimes and sizes of some well-known files to
# determine if the repo changed. This is not precise, as mtimes
# are susceptible to clock skew and imprecise filesystems and
# file content can change while maintaining the same size.
state, mtime = self._repostate()
if state == self._state:
return self._repo, False
FUJIWARA Katsunori
hg: make cachedlocalrepo cache appropriate repoview object...
r28119 repo = repository(self._repo.baseui, self._repo.url())
if self._filtername:
self._repo = repo.filtered(self._filtername)
else:
self._repo = repo.unfiltered()
Gregory Szorc
hg: establish a cache for localrepository instances...
r26219 self._state = state
self.mtime = mtime
return self._repo, True
def _repostate(self):
state = []
maxmtime = -1
for attr, fname in foi:
prefix = getattr(self._repo, attr)
p = os.path.join(prefix, fname)
try:
st = os.stat(p)
except OSError:
st = os.stat(prefix)
Augie Fackler
cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime...
r36799 state.append((st[stat.ST_MTIME], st.st_size))
maxmtime = max(maxmtime, st[stat.ST_MTIME])
Gregory Szorc
hg: establish a cache for localrepository instances...
r26219
return tuple(state), maxmtime
def copy(self):
Gregory Szorc
hg: always create new localrepository instance...
r26240 """Obtain a copy of this class instance.
A new localrepository instance is obtained. The new instance should be
completely independent of the original.
"""
repo = repository(self._repo.baseui, self._repo.origroot)
FUJIWARA Katsunori
hg: make cachedlocalrepo cache appropriate repoview object...
r28119 if self._filtername:
repo = repo.filtered(self._filtername)
else:
repo = repo.unfiltered()
Gregory Szorc
hg: always create new localrepository instance...
r26240 c = cachedlocalrepo(repo)
Gregory Szorc
hg: establish a cache for localrepository instances...
r26219 c._state = self._state
c.mtime = self.mtime
return c