##// END OF EJS Templates
copies: split the combination of the copies mapping in its own function...
copies: split the combination of the copies mapping in its own function In some case, this part take up to 95% of the copy tracing that take about a hundred second. This poor performance comes from the fact we keep duplciating and merging dictionary that are mostly similar. I want to experiment with smarter native code to do this, so I need to isolate the function first.

File last commit:

r43376:d783f945 default
r44178:0cc91600 default
Show More
logexchange.py
163 lines | 4.9 KiB | text/x-python | PythonLexer
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 # logexchange.py
#
# Copyright 2017 Augie Fackler <raf@durin42.com>
# Copyright 2017 Sean Farley <sean@farley.io>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
from .node import hex
from . import (
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 pycompat,
Pulkit Goyal
logexchange: introduce helper function to get remote path name...
r36076 util,
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 vfs as vfsmod,
)
# directory name in .hg/ in which remotenames files will be present
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 remotenamedir = b'logexchange'
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 def readremotenamefile(repo, filename):
"""
reads a file from .hg/logexchange/ directory and yields it's content
filename: the file to be read
yield a tuple (node, remotepath, name)
"""
vfs = vfsmod.vfs(repo.vfs.join(remotenamedir))
if not vfs.exists(filename):
return
f = vfs(filename)
lineno = 0
for line in f:
line = line.strip()
if not line:
continue
# contains the version number
if lineno == 0:
lineno += 1
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 node, remote, rname = line.split(b'\0')
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 yield node, remote, rname
except ValueError:
pass
f.close()
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 def readremotenames(repo):
"""
read the details about the remotenames stored in .hg/logexchange/ and
yields a tuple (node, remotepath, name). It does not yields information
about whether an entry yielded is branch or bookmark. To get that
information, call the respective functions.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for bmentry in readremotenamefile(repo, b'bookmarks'):
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 yield bmentry
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for branchentry in readremotenamefile(repo, b'branches'):
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 yield branchentry
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 def writeremotenamefile(repo, remotepath, names, nametype):
vfs = vfsmod.vfs(repo.vfs.join(remotenamedir))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = vfs(nametype, b'w', atomictemp=True)
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 # write the storage version info on top of file
# version '0' represents the very initial version of the storage format
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(b'0\n\n')
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348
olddata = set(readremotenamefile(repo, nametype))
# re-save the data from a different remote than this one.
for node, oldpath, rname in sorted(olddata):
if oldpath != remotepath:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(b'%s\0%s\0%s\n' % (node, oldpath, rname))
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for name, node in sorted(pycompat.iteritems(names)):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if nametype == b"branches":
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 for n in node:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(b'%s\0%s\0%s\n' % (n, remotepath, name))
elif nametype == b"bookmarks":
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 if node:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(b'%s\0%s\0%s\n' % (node, remotepath, name))
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348
f.close()
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 def saveremotenames(repo, remotepath, branches=None, bookmarks=None):
"""
save remotenames i.e. remotebookmarks and remotebranches in their
respective files under ".hg/logexchange/" directory.
"""
wlock = repo.wlock()
try:
if bookmarks:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 writeremotenamefile(repo, remotepath, bookmarks, b'bookmarks')
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 if branches:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 writeremotenamefile(repo, remotepath, branches, b'branches')
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 finally:
wlock.release()
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
logexchange: introduce helper function to get remote path name...
r36076 def activepath(repo, remote):
"""returns remote path"""
# is the remote a local peer
local = remote.local()
# determine the remote path from the repo, if possible; else just
# use the string given to us
rpath = remote
if local:
Matt Harbison
logexchange: convert paths to unix when detecting the active path...
r40471 rpath = util.pconvert(remote._repo.root)
Pulkit Goyal
py3: use bytes instead of str in instance()...
r37383 elif not isinstance(remote, bytes):
Pulkit Goyal
logexchange: introduce helper function to get remote path name...
r36076 rpath = remote._url
# represent the remotepath with user defined path name if exists
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for path, url in repo.ui.configitems(b'paths'):
Pulkit Goyal
logexchange: introduce helper function to get remote path name...
r36076 # remove auth info from user defined url
Pulkit Goyal
remotenames: check the remotepath with url containing user information too...
r38001 noauthurl = util.removeauth(url)
Matt Harbison
logexchange: convert paths to unix when detecting the active path...
r40471
# Standardize on unix style paths, otherwise some {remotenames} end up
# being an absolute path on Windows.
url = util.pconvert(bytes(url))
noauthurl = util.pconvert(noauthurl)
Pulkit Goyal
remotenames: check the remotepath with url containing user information too...
r38001 if url == rpath or noauthurl == rpath:
Pulkit Goyal
logexchange: introduce helper function to get remote path name...
r36076 rpath = path
break
return rpath
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 def pullremotenames(localrepo, remoterepo):
"""
pulls bookmarks and branches information of the remote repo during a
pull or clone operation.
localrepo is our local repository
remoterepo is the peer instance
"""
Pulkit Goyal
logexchange: introduce helper function to get remote path name...
r36076 remotepath = activepath(localrepo, remoterepo)
Gregory Szorc
logexchange: use command executor for wire protocol commands...
r37657
with remoterepo.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 bookmarks = e.callcommand(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'listkeys', {b'namespace': b'bookmarks',}
Augie Fackler
formatting: blacken the codebase...
r43346 ).result()
Gregory Szorc
logexchange: use command executor for wire protocol commands...
r37657
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 # on a push, we don't want to keep obsolete heads since
# they won't show up as heads on the next pull, so we
# remove them here otherwise we would require the user
# to issue a pull to refresh the storage
bmap = {}
repo = localrepo.unfiltered()
Gregory Szorc
logexchange: use command executor for wire protocol commands...
r37657
with remoterepo.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 branchmap = e.callcommand(b'branchmap', {}).result()
Gregory Szorc
logexchange: use command executor for wire protocol commands...
r37657
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for branch, nodes in pycompat.iteritems(branchmap):
Pulkit Goyal
remotenames: rename related file and storage dir to logexchange...
r35348 bmap[branch] = []
for node in nodes:
if node in repo and not repo[node].obsolete():
bmap[branch].append(hex(node))
saveremotenames(localrepo, remotepath, bmap, bookmarks)