mercurial/tags.py
author Greg Ward <greg-hg@gerg.ca>
Thu, 16 Jul 2009 10:39:41 -0400
changeset 9149 abb7d4d43a5f
child 9151 f528d1a93491
permissions -rw-r--r--
Factor tags module out of localrepo (issue548). Currently only handles reading tags, and will soon grow support for tag caching. Could eventually deal with updating tags too.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9149
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     1
# tags.py - read tag info from local repository
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     2
#
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     3
# Copyright 2009 Matt Mackall <mpm@selenic.com>
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     4
# Copyright 2009 Greg Ward <greg@gerg.ca>
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     5
#
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     6
# This software may be used and distributed according to the terms of the
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     7
# GNU General Public License version 2, incorporated herein by reference.
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     8
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     9
# Currently this module only deals with reading tags.  Soon it will grow
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    10
# support for caching tag info.  Eventually, it could take care of
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    11
# updating (adding/removing/moving) tags too.
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    12
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    13
from node import bin, hex
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    14
from i18n import _
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    15
import encoding
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    16
import error
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    17
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    18
def findglobaltags(ui, repo, alltags, tagtypes):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    19
    '''Find global tags in repo by reading .hgtags from every head that
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    20
    has a distinct version of it.  Updates the dicts alltags, tagtypes
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    21
    in place: alltags maps tag name to (node, hist) pair (see _readtags()
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    22
    below), and tagtypes maps tag name to tag type ('global' in this
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    23
    case).'''
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    24
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    25
    seen = set()
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    26
    fctx = None
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    27
    ctxs = []                       # list of filectx
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    28
    for node in repo.heads():
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    29
        try:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    30
            fnode = repo[node].filenode('.hgtags')
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    31
        except error.LookupError:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    32
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    33
        if fnode not in seen:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    34
            seen.add(fnode)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    35
            if not fctx:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    36
                fctx = repo.filectx('.hgtags', fileid=fnode)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    37
            else:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    38
                fctx = fctx.filectx(fnode)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    39
            ctxs.append(fctx)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    40
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    41
    # read the tags file from each head, ending with the tip
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    42
    for fctx in reversed(ctxs):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    43
        filetags = _readtags(
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    44
            ui, repo, fctx.data().splitlines(), fctx)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    45
        _updatetags(filetags, "global", alltags, tagtypes)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    46
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    47
def readlocaltags(ui, repo, alltags, tagtypes):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    48
    '''Read local tags in repo.  Update alltags and tagtypes.'''
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    49
    try:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    50
        data = encoding.fromlocal(repo.opener("localtags").read())
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    51
        # localtags are stored in the local character set
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    52
        # while the internal tag table is stored in UTF-8
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    53
        filetags = _readtags(
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    54
            ui, repo, data.splitlines(), "localtags")
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    55
        _updatetags(filetags, "local", alltags, tagtypes)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    56
    except IOError:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    57
        pass
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    58
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    59
def _readtags(ui, repo, lines, fn):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    60
    '''Read tag definitions from a file (or any source of lines).
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    61
    Return a mapping from tag name to (node, hist): node is the node id
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    62
    from the last line read for that name, and hist is the list of node
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    63
    ids previously associated with it (in file order).  All node ids are
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    64
    binary, not hex.'''
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    65
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    66
    filetags = {}               # map tag name to (node, hist)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    67
    count = 0
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    68
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    69
    def warn(msg):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    70
        ui.warn(_("%s, line %s: %s\n") % (fn, count, msg))
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    71
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    72
    for line in lines:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    73
        count += 1
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    74
        if not line:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    75
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    76
        try:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    77
            (nodehex, name) = line.split(" ", 1)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    78
        except ValueError:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    79
            warn(_("cannot parse entry"))
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    80
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    81
        name = encoding.tolocal(name.strip()) # stored in UTF-8
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    82
        try:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    83
            nodebin = bin(nodehex)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    84
        except TypeError:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    85
            warn(_("node '%s' is not well formed") % nodehex)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    86
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    87
        if nodebin not in repo.changelog.nodemap:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    88
            # silently ignore as pull -r might cause this
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    89
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    90
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    91
        # update filetags
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    92
        hist = []
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    93
        if name in filetags:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    94
            n, hist = filetags[name]
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    95
            hist.append(n)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    96
        filetags[name] = (nodebin, hist)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    97
    return filetags
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    98
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    99
def _updatetags(filetags, tagtype, alltags, tagtypes):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   100
    '''Incorporate the tag info read from one file into the two
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   101
    dictionaries, alltags and tagtypes, that contain all tag
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   102
    info (global across all heads plus local).'''
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   103
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   104
    for name, nodehist in filetags.iteritems():
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   105
        if name not in alltags:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   106
            alltags[name] = nodehist
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   107
            tagtypes[name] = tagtype
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   108
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   109
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   110
        # we prefer alltags[name] if:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   111
        #  it supercedes us OR
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   112
        #  mutual supercedes and it has a higher rank
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   113
        # otherwise we win because we're tip-most
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   114
        anode, ahist = nodehist
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   115
        bnode, bhist = alltags[name]
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   116
        if (bnode != anode and anode in bhist and
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   117
            (bnode not in ahist or len(bhist) > len(ahist))):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   118
            anode = bnode
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   119
        ahist.extend([n for n in bhist if n not in ahist])
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   120
        alltags[name] = anode, ahist
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   121
        tagtypes[name] = tagtype
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   122