mercurial/tags.py
author Greg Ward <greg-hg@gerg.ca>
Tue, 18 Aug 2009 22:07:43 -0400
changeset 9366 9ff178e7b627
parent 9312 c5f0825c1dbb
child 9678 e2b1de5fee04
permissions -rw-r--r--
tags: don't crash if unable to write tag cache This happens with hgweb in real life, if the httpd user is unable to write in the repository directory. Another case is doing 'hg incoming' on a repository in the filesystem owned by someone else.
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
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
     9
# Currently this module only deals with reading and caching tags.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    10
# Eventually, it could take care of updating (adding/removing/moving)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    11
# tags too.
9149
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    12
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    13
import os
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    14
from node import nullid, bin, hex, short
9149
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    15
from i18n import _
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    16
import encoding
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    17
import error
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    18
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    19
def _debugalways(ui, *msg):
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    20
    ui.write(*msg)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    21
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    22
def _debugconditional(ui, *msg):
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    23
    ui.debug(*msg)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    24
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    25
def _debugnever(ui, *msg):
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    26
    pass
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    27
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    28
_debug = _debugalways
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    29
_debug = _debugnever
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    30
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    31
def findglobaltags1(ui, repo, alltags, tagtypes):
9149
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    32
    '''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
    33
    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
    34
    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
    35
    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
    36
    case).'''
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    37
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    38
    seen = set()
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    39
    fctx = None
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    40
    ctxs = []                       # list of filectx
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    41
    for node in repo.heads():
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    42
        try:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    43
            fnode = repo[node].filenode('.hgtags')
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    44
        except error.LookupError:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    45
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    46
        if fnode not in seen:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    47
            seen.add(fnode)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    48
            if not fctx:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    49
                fctx = repo.filectx('.hgtags', fileid=fnode)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    50
            else:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    51
                fctx = fctx.filectx(fnode)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    52
            ctxs.append(fctx)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    53
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    54
    # 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
    55
    for fctx in reversed(ctxs):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    56
        filetags = _readtags(
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    57
            ui, repo, fctx.data().splitlines(), fctx)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    58
        _updatetags(filetags, "global", alltags, tagtypes)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    59
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    60
def findglobaltags2(ui, repo, alltags, tagtypes):
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    61
    '''Same as findglobaltags1(), but with caching.'''
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    62
    # This is so we can be lazy and assume alltags contains only global
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    63
    # tags when we pass it to _writetagcache().
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    64
    assert len(alltags) == len(tagtypes) == 0, \
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    65
           "findglobaltags() should be called first"
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    66
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    67
    (heads, tagfnode, cachetags, shouldwrite) = _readtagcache(ui, repo)
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    68
    if cachetags is not None:
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    69
        assert not shouldwrite
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    70
        # XXX is this really 100% correct?  are there oddball special
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    71
        # cases where a global tag should outrank a local tag but won't,
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    72
        # because cachetags does not contain rank info?
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    73
        _updatetags(cachetags, 'global', alltags, tagtypes)
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    74
        return
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    75
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    76
    _debug(ui, "reading tags from %d head(s): %s\n"
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    77
           % (len(heads), map(short, reversed(heads))))
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    78
    seen = set()                    # set of fnode
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    79
    fctx = None
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    80
    for head in reversed(heads):        # oldest to newest
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    81
        assert head in repo.changelog.nodemap, \
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    82
               "tag cache returned bogus head %s" % short(head)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    83
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    84
        fnode = tagfnode.get(head)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    85
        if fnode and fnode not in seen:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    86
            seen.add(fnode)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    87
            if not fctx:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    88
                fctx = repo.filectx('.hgtags', fileid=fnode)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    89
            else:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    90
                fctx = fctx.filectx(fnode)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    91
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    92
            filetags = _readtags(ui, repo, fctx.data().splitlines(), fctx)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    93
            _updatetags(filetags, 'global', alltags, tagtypes)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    94
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    95
    # and update the cache (if necessary)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    96
    if shouldwrite:
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
    97
        _writetagcache(ui, repo, heads, tagfnode, alltags)
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    98
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
    99
# Set this to findglobaltags1 to disable tag caching.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   100
findglobaltags = findglobaltags2
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   101
9149
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   102
def readlocaltags(ui, repo, alltags, tagtypes):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   103
    '''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
   104
    try:
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   105
        # localtags is in the local encoding; re-encode to UTF-8 on
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   106
        # input for consistency with the rest of this module.
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   107
        data = repo.opener("localtags").read()
9149
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   108
        filetags = _readtags(
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   109
            ui, repo, data.splitlines(), "localtags",
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   110
            recode=encoding.fromlocal)
9149
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   111
        _updatetags(filetags, "local", alltags, tagtypes)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   112
    except IOError:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   113
        pass
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   114
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   115
def _readtags(ui, repo, lines, fn, recode=None):
9149
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   116
    '''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
   117
    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
   118
    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
   119
    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
   120
    binary, not hex.'''
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   121
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   122
    filetags = {}               # map tag name to (node, hist)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   123
    count = 0
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   124
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   125
    def warn(msg):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   126
        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
   127
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   128
    for line in lines:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   129
        count += 1
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   130
        if not line:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   131
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   132
        try:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   133
            (nodehex, name) = line.split(" ", 1)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   134
        except ValueError:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   135
            warn(_("cannot parse entry"))
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   136
            continue
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   137
        name = name.strip()
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   138
        if recode:
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   139
            name = recode(name)
9149
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   140
        try:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   141
            nodebin = bin(nodehex)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   142
        except TypeError:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   143
            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
   144
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   145
        if nodebin not in repo.changelog.nodemap:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   146
            # 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
   147
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   148
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   149
        # update filetags
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   150
        hist = []
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   151
        if name in filetags:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   152
            n, hist = filetags[name]
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   153
            hist.append(n)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   154
        filetags[name] = (nodebin, hist)
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   155
    return filetags
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   156
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   157
def _updatetags(filetags, tagtype, alltags, tagtypes):
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   158
    '''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
   159
    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
   160
    info (global across all heads plus local).'''
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   161
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   162
    for name, nodehist in filetags.iteritems():
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   163
        if name not in alltags:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   164
            alltags[name] = nodehist
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   165
            tagtypes[name] = tagtype
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   166
            continue
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   167
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   168
        # we prefer alltags[name] if:
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   169
        #  it supercedes us OR
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   170
        #  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
   171
        # 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
   172
        anode, ahist = nodehist
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   173
        bnode, bhist = alltags[name]
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   174
        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
   175
            (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
   176
            anode = bnode
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   177
        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
   178
        alltags[name] = anode, ahist
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   179
        tagtypes[name] = tagtype
abb7d4d43a5f Factor tags module out of localrepo (issue548).
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   180
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   181
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   182
# The tag cache only stores info about heads, not the tag contents
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   183
# from each head.  I.e. it doesn't try to squeeze out the maximum
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   184
# performance, but is simpler has a better chance of actually
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   185
# working correctly.  And this gives the biggest performance win: it
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   186
# avoids looking up .hgtags in the manifest for every head, and it
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   187
# can avoid calling heads() at all if there have been no changes to
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   188
# the repo.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   189
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   190
def _readtagcache(ui, repo):
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   191
    '''Read the tag cache and return a tuple (heads, fnodes, cachetags,
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   192
    shouldwrite).  If the cache is completely up-to-date, cachetags is a
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   193
    dict of the form returned by _readtags(); otherwise, it is None and
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   194
    heads and fnodes are set.  In that case, heads is the list of all
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   195
    heads currently in the repository (ordered from tip to oldest) and
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   196
    fnodes is a mapping from head to .hgtags filenode.  If those two are
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   197
    set, caller is responsible for reading tag info from each head.'''
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   198
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   199
    try:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   200
        cachefile = repo.opener('tags.cache', 'r')
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   201
        _debug(ui, 'reading tag cache from %s\n' % cachefile.name)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   202
    except IOError:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   203
        cachefile = None
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   204
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   205
    # The cache file consists of lines like
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   206
    #   <headrev> <headnode> [<tagnode>]
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   207
    # where <headrev> and <headnode> redundantly identify a repository
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   208
    # head from the time the cache was written, and <tagnode> is the
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   209
    # filenode of .hgtags on that head.  Heads with no .hgtags file will
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   210
    # have no <tagnode>.  The cache is ordered from tip to oldest (which
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   211
    # is part of why <headrev> is there: a quick visual check is all
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   212
    # that's required to ensure correct order).
9312
c5f0825c1dbb kill trailing whitespace
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9152
diff changeset
   213
    #
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   214
    # This information is enough to let us avoid the most expensive part
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   215
    # of finding global tags, which is looking up <tagnode> in the
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   216
    # manifest for each head.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   217
    cacherevs = []                      # list of headrev
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   218
    cacheheads = []                     # list of headnode
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   219
    cachefnode = {}                     # map headnode to filenode
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   220
    if cachefile:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   221
        for line in cachefile:
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   222
            if line == "\n":
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   223
                break
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   224
            line = line.rstrip().split()
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   225
            cacherevs.append(int(line[0]))
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   226
            headnode = bin(line[1])
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   227
            cacheheads.append(headnode)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   228
            if len(line) == 3:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   229
                fnode = bin(line[2])
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   230
                cachefnode[headnode] = fnode
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   231
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   232
    tipnode = repo.changelog.tip()
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   233
    tiprev = len(repo.changelog) - 1
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   234
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   235
    # Case 1 (common): tip is the same, so nothing has changed.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   236
    # (Unchanged tip trivially means no changesets have been added.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   237
    # But, thanks to localrepository.destroyed(), it also means none
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   238
    # have been destroyed by strip or rollback.)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   239
    if cacheheads and cacheheads[0] == tipnode and cacherevs[0] == tiprev:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   240
        _debug(ui, "tag cache: tip unchanged\n")
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   241
        tags = _readtags(ui, repo, cachefile, cachefile.name)
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   242
        cachefile.close()
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   243
        return (None, None, tags, False)
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   244
    if cachefile:
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   245
        cachefile.close()               # ignore rest of file
9312
c5f0825c1dbb kill trailing whitespace
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9152
diff changeset
   246
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   247
    repoheads = repo.heads()
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   248
    # Case 2 (uncommon): empty repo; get out quickly and don't bother
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   249
    # writing an empty cache.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   250
    if repoheads == [nullid]:
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   251
        return ([], {}, {}, False)
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   252
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   253
    # Case 3 (uncommon): cache file missing or empty.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   254
    if not cacheheads:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   255
        _debug(ui, 'tag cache: cache file missing or empty\n')
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   256
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   257
    # Case 4 (uncommon): tip rev decreased.  This should only happen
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   258
    # when we're called from localrepository.destroyed().  Refresh the
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   259
    # cache so future invocations will not see disappeared heads in the
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   260
    # cache.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   261
    elif cacheheads and tiprev < cacherevs[0]:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   262
        _debug(ui,
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   263
               'tag cache: tip rev decremented (from %d to %d), '
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   264
               'so we must be destroying nodes\n'
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   265
               % (cacherevs[0], tiprev))
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   266
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   267
    # Case 5 (common): tip has changed, so we've added/replaced heads.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   268
    else:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   269
        _debug(ui,
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   270
               'tag cache: tip has changed (%d:%s); must find new heads\n'
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   271
               % (tiprev, short(tipnode)))
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   272
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   273
    # Luckily, the code to handle cases 3, 4, 5 is the same.  So the
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   274
    # above if/elif/else can disappear once we're confident this thing
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   275
    # actually works and we don't need the debug output.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   276
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   277
    # N.B. in case 4 (nodes destroyed), "new head" really means "newly
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   278
    # exposed".
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   279
    newheads = [head
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   280
                for head in repoheads
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   281
                if head not in set(cacheheads)]
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   282
    _debug(ui, 'tag cache: found %d head(s) not in cache: %s\n'
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   283
           % (len(newheads), map(short, newheads)))
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   284
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   285
    # Now we have to lookup the .hgtags filenode for every new head.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   286
    # This is the most expensive part of finding tags, so performance
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   287
    # depends primarily on the size of newheads.  Worst case: no cache
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   288
    # file, so newheads == repoheads.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   289
    for head in newheads:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   290
        cctx = repo[head]
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   291
        try:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   292
            fnode = cctx.filenode('.hgtags')
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   293
            cachefnode[head] = fnode
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   294
        except error.LookupError:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   295
            # no .hgtags file on this head
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   296
            pass
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   297
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   298
    # Caller has to iterate over all heads, but can use the filenodes in
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   299
    # cachefnode to get to each .hgtags revision quickly.
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   300
    return (repoheads, cachefnode, None, True)
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   301
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   302
def _writetagcache(ui, repo, heads, tagfnode, cachetags):
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   303
9366
9ff178e7b627 tags: don't crash if unable to write tag cache
Greg Ward <greg-hg@gerg.ca>
parents: 9312
diff changeset
   304
    try:
9ff178e7b627 tags: don't crash if unable to write tag cache
Greg Ward <greg-hg@gerg.ca>
parents: 9312
diff changeset
   305
        cachefile = repo.opener('tags.cache', 'w', atomictemp=True)
9ff178e7b627 tags: don't crash if unable to write tag cache
Greg Ward <greg-hg@gerg.ca>
parents: 9312
diff changeset
   306
    except (OSError, IOError):
9ff178e7b627 tags: don't crash if unable to write tag cache
Greg Ward <greg-hg@gerg.ca>
parents: 9312
diff changeset
   307
        return
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   308
    _debug(ui, 'writing cache file %s\n' % cachefile.name)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   309
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   310
    realheads = repo.heads()            # for sanity checks below
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   311
    for head in heads:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   312
        # temporary sanity checks; these can probably be removed
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   313
        # once this code has been in crew for a few weeks
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   314
        assert head in repo.changelog.nodemap, \
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   315
               'trying to write non-existent node %s to tag cache' % short(head)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   316
        assert head in realheads, \
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   317
               'trying to write non-head %s to tag cache' % short(head)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   318
        assert head != nullid, \
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   319
               'trying to write nullid to tag cache'
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   320
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   321
        # This can't fail because of the first assert above.  When/if we
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   322
        # remove that assert, we might want to catch LookupError here
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   323
        # and downgrade it to a warning.
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   324
        rev = repo.changelog.rev(head)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   325
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   326
        fnode = tagfnode.get(head)
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   327
        if fnode:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   328
            cachefile.write('%d %s %s\n' % (rev, hex(head), hex(fnode)))
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   329
        else:
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   330
            cachefile.write('%d %s\n' % (rev, hex(head)))
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   331
9152
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   332
    # Tag names in the cache are in UTF-8 -- which is the whole reason
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   333
    # we keep them in UTF-8 throughout this module.  If we converted
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   334
    # them local encoding on input, we would lose info writing them to
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   335
    # the cache.
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   336
    cachefile.write('\n')
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   337
    for (name, (node, hist)) in cachetags.iteritems():
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   338
        cachefile.write("%s %s\n" % (hex(node), name))
4017291c4c48 tags: support 'instant' tag retrieval (issue548)
Greg Ward <greg-hg@gerg.ca>
parents: 9151
diff changeset
   339
9151
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   340
    cachefile.rename()
f528d1a93491 tags: implement persistent tag caching (issue548).
Greg Ward <greg-hg@gerg.ca>
parents: 9149
diff changeset
   341
    cachefile.close()