--- a/mercurial/tags.py Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/tags.py Sun Oct 06 09:45:02 2019 -0400
@@ -30,9 +30,7 @@
scmutil,
util,
)
-from .utils import (
- stringutil,
-)
+from .utils import stringutil
# Tags computation can be expensive and caches exist to make it fast in
# the common case.
@@ -83,6 +81,7 @@
# The most recent changeset (in terms of revlog ordering for the head
# setting it) for each tag is last.
+
def fnoderevs(ui, repo, revs):
"""return the list of '.hgtags' fnodes used in a set revisions
@@ -95,6 +94,7 @@
fnodes = _filterfnodes(fnodes, nodes)
return fnodes
+
def _nulltonone(value):
"""convert nullid to None
@@ -104,6 +104,7 @@
return None
return value
+
def difftags(ui, repo, oldfnodes, newfnodes):
"""list differences between tags expressed in two set of file-nodes
@@ -134,6 +135,7 @@
entries.sort()
return entries
+
def writediff(fp, difflist):
"""write tags diff information to a file.
@@ -172,6 +174,7 @@
fp.write(updateold % (old, tag))
fp.write(updatenew % (new, tag))
+
def findglobaltags(ui, repo):
'''Find global tags in a repo: return a tagsmap
@@ -190,8 +193,9 @@
return alltags
for head in reversed(heads): # oldest to newest
- assert head in repo.changelog.nodemap, (
- "tag cache returned bogus head %s" % short(head))
+ assert (
+ head in repo.changelog.nodemap
+ ), "tag cache returned bogus head %s" % short(head)
fnodes = _filterfnodes(tagfnode, reversed(heads))
alltags = _tagsfromfnodes(ui, repo, fnodes)
@@ -200,6 +204,7 @@
_writetagcache(ui, repo, valid, alltags)
return alltags
+
def _filterfnodes(tagfnode, nodes):
"""return a list of unique fnodes
@@ -215,6 +220,7 @@
fnodes.append(fnode)
return fnodes
+
def _tagsfromfnodes(ui, repo, fnodes):
"""return a tagsmap from a list of file-node
@@ -232,6 +238,7 @@
_updatetags(filetags, alltags)
return alltags
+
def readlocaltags(ui, repo, alltags, tagtypes):
'''Read local tags in repo. Update alltags and tagtypes.'''
try:
@@ -244,8 +251,8 @@
# localtags is in the local encoding; re-encode to UTF-8 on
# input for consistency with the rest of this module.
filetags = _readtags(
- ui, repo, data.splitlines(), "localtags",
- recode=encoding.fromlocal)
+ ui, repo, data.splitlines(), "localtags", recode=encoding.fromlocal
+ )
# remove tags pointing to invalid nodes
cl = repo.changelog
@@ -257,6 +264,7 @@
_updatetags(filetags, alltags, 'local', tagtypes)
+
def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False):
'''Read tag definitions from a file (or any source of lines).
@@ -314,6 +322,7 @@
bintaghist[name].append(nodebin)
return bintaghist, hextaglines
+
def _readtags(ui, repo, lines, fn, recode=None, calcnodelines=False):
'''Read tag definitions from a file (or any source of lines).
@@ -323,8 +332,9 @@
is the list of node ids previously associated with it (in file order).
All node ids are binary, not hex.
'''
- filetags, nodelines = _readtaghist(ui, repo, lines, fn, recode=recode,
- calcnodelines=calcnodelines)
+ filetags, nodelines = _readtaghist(
+ ui, repo, lines, fn, recode=recode, calcnodelines=calcnodelines
+ )
# util.sortdict().__setitem__ is much slower at replacing then inserting
# new entries. The difference can matter if there are thousands of tags.
# Create a new sortdict to avoid the performance penalty.
@@ -333,6 +343,7 @@
newtags[tag] = (taghist[-1], taghist[:-1])
return newtags
+
def _updatetags(filetags, alltags, tagtype=None, tagtypes=None):
"""Incorporate the tag info read from one file into dictionnaries
@@ -357,14 +368,18 @@
# otherwise we win because we're tip-most
anode, ahist = nodehist
bnode, bhist = alltags[name]
- if (bnode != anode and anode in bhist and
- (bnode not in ahist or len(bhist) > len(ahist))):
+ if (
+ bnode != anode
+ and anode in bhist
+ and (bnode not in ahist or len(bhist) > len(ahist))
+ ):
anode = bnode
elif tagtype is not None:
tagtypes[name] = tagtype
ahist.extend([n for n in bhist if n not in ahist])
alltags[name] = anode, ahist
+
def _filename(repo):
"""name of a tagcache file for a given repo or repoview"""
filename = 'tags2'
@@ -372,6 +387,7 @@
filename = '%s-%s' % (filename, repo.filtername)
return filename
+
def _readtagcache(ui, repo):
'''Read the tag cache.
@@ -419,14 +435,16 @@
# (Unchanged tip trivially means no changesets have been added.
# But, thanks to localrepository.destroyed(), it also means none
# have been destroyed by strip or rollback.)
- if (cacherev == tiprev
- and cachenode == tipnode
- and cachehash == scmutil.filteredhash(repo, tiprev)):
+ if (
+ cacherev == tiprev
+ and cachenode == tipnode
+ and cachehash == scmutil.filteredhash(repo, tiprev)
+ ):
tags = _readtags(ui, repo, cachelines, cachefile.name)
cachefile.close()
return (None, None, None, tags, False)
if cachefile:
- cachefile.close() # ignore rest of file
+ cachefile.close() # ignore rest of file
valid = (tiprev, tipnode, scmutil.filteredhash(repo, tiprev))
@@ -454,7 +472,6 @@
# potentially expensive search.
return ([], {}, valid, None, True)
-
# Now we have to lookup the .hgtags filenode for every new head.
# This is the most expensive part of finding tags, so performance
# depends primarily on the size of newheads. Worst case: no cache
@@ -466,6 +483,7 @@
# cachefnode to get to each .hgtags revision quickly.
return (repoheads, cachefnode, valid, None, True)
+
def _getfnodes(ui, repo, nodes):
"""return .hgtags fnodes for a list of changeset nodes
@@ -483,11 +501,16 @@
fnodescache.write()
duration = util.timer() - starttime
- ui.log('tagscache',
- '%d/%d cache hits/lookups in %0.4f seconds\n',
- fnodescache.hitcount, fnodescache.lookupcount, duration)
+ ui.log(
+ 'tagscache',
+ '%d/%d cache hits/lookups in %0.4f seconds\n',
+ fnodescache.hitcount,
+ fnodescache.lookupcount,
+ duration,
+ )
return cachefnode
+
def _writetagcache(ui, repo, valid, cachetags):
filename = _filename(repo)
try:
@@ -495,8 +518,12 @@
except (OSError, IOError):
return
- ui.log('tagscache', 'writing .hg/cache/%s with %d tags\n',
- filename, len(cachetags))
+ ui.log(
+ 'tagscache',
+ 'writing .hg/cache/%s with %d tags\n',
+ filename,
+ len(cachetags),
+ )
if valid[2]:
cachefile.write('%d %s %s\n' % (valid[0], hex(valid[1]), hex(valid[2])))
@@ -517,6 +544,7 @@
except (OSError, IOError):
pass
+
def tag(repo, names, node, message, local, user, date, editor=False):
'''tag a revision with one or more symbolic names.
@@ -541,26 +569,30 @@
if not local:
m = matchmod.exact(['.hgtags'])
if any(repo.status(match=m, unknown=True, ignored=True)):
- raise error.Abort(_('working copy of .hgtags is changed'),
- hint=_('please commit .hgtags manually'))
+ raise error.Abort(
+ _('working copy of .hgtags is changed'),
+ hint=_('please commit .hgtags manually'),
+ )
with repo.wlock():
- repo.tags() # instantiate the cache
- _tag(repo, names, node, message, local, user, date,
- editor=editor)
+ repo.tags() # instantiate the cache
+ _tag(repo, names, node, message, local, user, date, editor=editor)
+
-def _tag(repo, names, node, message, local, user, date, extra=None,
- editor=False):
+def _tag(
+ repo, names, node, message, local, user, date, extra=None, editor=False
+):
if isinstance(names, bytes):
names = (names,)
branches = repo.branchmap()
for name in names:
- repo.hook('pretag', throw=True, node=hex(node), tag=name,
- local=local)
+ repo.hook('pretag', throw=True, node=hex(node), tag=name, local=local)
if name in branches:
- repo.ui.warn(_("warning: tag %s conflicts with existing"
- " branch name\n") % name)
+ repo.ui.warn(
+ _("warning: tag %s conflicts with existing" " branch name\n")
+ % name
+ )
def writetags(fp, names, munge, prevtags):
fp.seek(0, io.SEEK_END)
@@ -572,8 +604,7 @@
else:
m = name
- if (repo._tagscache.tagtypes and
- name in repo._tagscache.tagtypes):
+ if repo._tagscache.tagtypes and name in repo._tagscache.tagtypes:
old = repo.tags().get(name, nullid)
fp.write('%s %s\n' % (hex(old), m))
fp.write('%s %s\n' % (hex(node), m))
@@ -614,18 +645,21 @@
repo[None].add(['.hgtags'])
m = matchmod.exact(['.hgtags'])
- tagnode = repo.commit(message, user, date, extra=extra, match=m,
- editor=editor)
+ tagnode = repo.commit(
+ message, user, date, extra=extra, match=m, editor=editor
+ )
for name in names:
repo.hook('tag', node=hex(node), tag=name, local=local)
return tagnode
+
_fnodescachefile = 'hgtagsfnodes1'
-_fnodesrecsize = 4 + 20 # changeset fragment + filenode
+_fnodesrecsize = 4 + 20 # changeset fragment + filenode
_fnodesmissingrec = '\xff' * 24
+
class hgtagsfnodescache(object):
"""Persistent cache mapping revisions to .hgtags filenodes.
@@ -645,6 +679,7 @@
Instances behave like lists. ``c[i]`` works where i is a rev or
changeset node. Missing indexes are populated automatically on access.
"""
+
def __init__(self, repo):
assert repo.filtername is None
@@ -654,7 +689,6 @@
self.lookupcount = 0
self.hitcount = 0
-
try:
data = repo.cachevfs.read(_fnodescachefile)
except (OSError, IOError):
@@ -703,7 +737,7 @@
self.lookupcount += 1
offset = rev * _fnodesrecsize
- record = '%s' % self._raw[offset:offset + _fnodesrecsize]
+ record = '%s' % self._raw[offset : offset + _fnodesrecsize]
properprefix = node[0:4]
# Validate and return existing entry.
@@ -766,7 +800,7 @@
def _writeentry(self, offset, prefix, fnode):
# Slices on array instances only accept other array.
entry = bytearray(prefix + fnode)
- self._raw[offset:offset + _fnodesrecsize] = entry
+ self._raw[offset : offset + _fnodesrecsize] = entry
# self._dirtyoffset could be None.
self._dirtyoffset = min(self._dirtyoffset or 0, offset or 0)
@@ -779,7 +813,7 @@
if self._dirtyoffset is None:
return
- data = self._raw[self._dirtyoffset:]
+ data = self._raw[self._dirtyoffset :]
if not data:
return
@@ -788,8 +822,11 @@
try:
lock = repo.wlock(wait=False)
except error.LockError:
- repo.ui.log('tagscache', 'not writing .hg/cache/%s because '
- 'lock cannot be acquired\n' % (_fnodescachefile))
+ repo.ui.log(
+ 'tagscache',
+ 'not writing .hg/cache/%s because '
+ 'lock cannot be acquired\n' % _fnodescachefile,
+ )
return
try:
@@ -799,19 +836,23 @@
actualoffset = f.tell()
if actualoffset < self._dirtyoffset:
self._dirtyoffset = actualoffset
- data = self._raw[self._dirtyoffset:]
+ data = self._raw[self._dirtyoffset :]
f.seek(self._dirtyoffset)
f.truncate()
- repo.ui.log('tagscache',
- 'writing %d bytes to cache/%s\n' % (
- len(data), _fnodescachefile))
+ repo.ui.log(
+ 'tagscache',
+ 'writing %d bytes to cache/%s\n'
+ % (len(data), _fnodescachefile),
+ )
f.write(data)
self._dirtyoffset = None
finally:
f.close()
except (IOError, OSError) as inst:
- repo.ui.log('tagscache',
- "couldn't write cache/%s: %s\n" % (
- _fnodescachefile, stringutil.forcebytestr(inst)))
+ repo.ui.log(
+ 'tagscache',
+ "couldn't write cache/%s: %s\n"
+ % (_fnodescachefile, stringutil.forcebytestr(inst)),
+ )
finally:
lock.release()