mercurial/context.py
author Thomas Arendsen Hein <thomas@intevation.de>
Mon, 20 Nov 2006 19:55:59 +0100
changeset 3688 d92dad355000
parent 3673 eb0b4a2d70a9
child 3712 1bd70d40ec57
permissions -rw-r--r--
Corrected "waiting for lock on repository FOO held by BAR" message. BAR was the error number and not the locker name. Use repr on BAR, so problems can be detected easier.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# context.py - changeset and file context objects for mercurial
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
2858
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2652
diff changeset
     3
# Copyright 2006 Matt Mackall <mpm@selenic.com>
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
     8
from node import *
3217
dedddde58c5b Raise LookupError in changectx.filectx if filenode can't be found
Brendan Cully <brendan@kublai.com>
parents: 3215
diff changeset
     9
from i18n import gettext as _
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
    10
from demandload import demandload
3308
192085505f6f filectx: add size method
Matt Mackall <mpm@selenic.com>
parents: 3304
diff changeset
    11
demandload(globals(), "ancestor bdiff repo revlog util os")
3130
da85145d4571 filectx: add rename traversal for parents()
Matt Mackall <mpm@selenic.com>
parents: 2858
diff changeset
    12
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
class changectx(object):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
    """A changecontext object makes access to data related to a particular
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    15
    changeset convenient."""
3127
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    16
    def __init__(self, repo, changeid=None):
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    17
        """changeid is a revision number, node, or tag"""
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    18
        self._repo = repo
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    19
3143
db25f7b80fdb context: handle fileid or changeid == 0
Brendan Cully <brendan@kublai.com>
parents: 3136
diff changeset
    20
        if not changeid and changeid != 0:
3127
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    21
            p1, p2 = self._repo.dirstate.parents()
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    22
            self._rev = self._repo.changelog.rev(p1)
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    23
            if self._rev == -1:
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    24
                changeid = 'tip'
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    25
            else:
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    26
                self._node = p1
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    27
                return
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    28
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
    29
        self._node = self._repo.lookup(changeid)
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
        self._rev = self._repo.changelog.rev(self._node)
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
3199
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
    32
    def __str__(self):
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
    33
        return short(self.node())
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
    34
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
    35
    def __repr__(self):
3238
d865390c1781 context: simplify repr methods
Matt Mackall <mpm@selenic.com>
parents: 3237
diff changeset
    36
        return "<changectx %s>" % str(self)
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
    37
3198
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
    38
    def __eq__(self, other):
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
    39
        return self._rev == other._rev
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
    40
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
    41
    def __nonzero__(self):
3578
3b4e00cba57a Define and use nullrev (revision of nullid) instead of -1.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3495
diff changeset
    42
        return self._rev != nullrev
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
    43
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    44
    def __getattr__(self, name):
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    45
        if name == '_changeset':
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
            self._changeset = self._repo.changelog.read(self.node())
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    47
            return self._changeset
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    48
        elif name == '_manifest':
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    49
            self._manifest = self._repo.manifest.read(self._changeset[0])
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    50
            return self._manifest
3335
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    51
        elif name == '_manifestdelta':
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    52
            md = self._repo.manifest.readdelta(self._changeset[0])
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    53
            self._manifestdelta = md
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    54
            return self._manifestdelta
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    55
        else:
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    56
            raise AttributeError, name
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    57
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    58
    def changeset(self): return self._changeset
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    59
    def manifest(self): return self._manifest
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    60
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    61
    def rev(self): return self._rev
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
    def node(self): return self._node
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    63
    def user(self): return self._changeset[1]
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    64
    def date(self): return self._changeset[2]
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    65
    def files(self): return self._changeset[3]
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    66
    def description(self): return self._changeset[4]
3428
cc9c31b07c2c Add branch method to contexts
Matt Mackall <mpm@selenic.com>
parents: 3353
diff changeset
    67
    def branch(self): return self._changeset[5].get("branch", "")
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
    def parents(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
        """return contexts for each parent changeset"""
2627
b779319a532b context.py: self.repo is not defined, change to self._repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2566
diff changeset
    71
        p = self._repo.changelog.parents(self._node)
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
    72
        return [changectx(self._repo, x) for x in p]
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
    def children(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
        """return contexts for each child changeset"""
2627
b779319a532b context.py: self.repo is not defined, change to self._repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2566
diff changeset
    76
        c = self._repo.changelog.children(self._node)
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
    77
        return [changectx(self._repo, x) for x in c]
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
    def filenode(self, path):
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
    80
        if '_manifest' in self.__dict__:
3242
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    81
            try:
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    82
                return self._manifest[path]
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    83
            except KeyError:
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    84
                raise repo.LookupError(_("'%s' not found in manifest") % path)
3335
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    85
        if '_manifestdelta' in self.__dict__ or path in self.files():
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    86
            if path in self._manifestdelta:
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    87
                return self._manifestdelta[path]
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    88
        node, flag = self._repo.manifest.find(self._changeset[0], path)
3242
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    89
        if not node:
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    90
            raise repo.LookupError(_("'%s' not found in manifest") % path)
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    91
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    92
        return node
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
2628
9999a796d389 context.py: filectxs was using a keyword arg, add it to filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2627
diff changeset
    94
    def filectx(self, path, fileid=None):
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
        """get a file context from this changeset"""
2628
9999a796d389 context.py: filectxs was using a keyword arg, add it to filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2627
diff changeset
    96
        if fileid is None:
9999a796d389 context.py: filectxs was using a keyword arg, add it to filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2627
diff changeset
    97
            fileid = self.filenode(path)
3236
696c656202a0 context: make filectx remember changectx in changectx.filectx
Matt Mackall <mpm@selenic.com>
parents: 3235
diff changeset
    98
        return filectx(self._repo, path, fileid=fileid, changectx=self)
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    99
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
    def filectxs(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
        """generate a file context for each file in this changeset's
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
           manifest"""
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
        mf = self.manifest()
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
        m = mf.keys()
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
        m.sort()
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   106
        for f in m:
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   107
            yield self.filectx(f, fileid=mf[f])
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
3133
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   109
    def ancestor(self, c2):
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   110
        """
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   111
        return the ancestor context of self and c2
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   112
        """
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   113
        n = self._repo.changelog.ancestor(self._node, c2._node)
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   114
        return changectx(self._repo, n)
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   115
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   116
class filectx(object):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
    """A filecontext object makes access to data related to a particular
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   118
       filerevision convenient."""
3236
696c656202a0 context: make filectx remember changectx in changectx.filectx
Matt Mackall <mpm@selenic.com>
parents: 3235
diff changeset
   119
    def __init__(self, repo, path, changeid=None, fileid=None,
696c656202a0 context: make filectx remember changectx in changectx.filectx
Matt Mackall <mpm@selenic.com>
parents: 3235
diff changeset
   120
                 filelog=None, changectx=None):
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
        """changeid can be a changeset revision, node, or tag.
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   122
           fileid can be a file revision or node."""
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   123
        self._repo = repo
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
        self._path = path
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
3143
db25f7b80fdb context: handle fileid or changeid == 0
Brendan Cully <brendan@kublai.com>
parents: 3136
diff changeset
   126
        assert changeid is not None or fileid is not None
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   127
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   128
        if filelog:
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   129
            self._filelog = filelog
3236
696c656202a0 context: make filectx remember changectx in changectx.filectx
Matt Mackall <mpm@selenic.com>
parents: 3235
diff changeset
   130
        if changectx:
696c656202a0 context: make filectx remember changectx in changectx.filectx
Matt Mackall <mpm@selenic.com>
parents: 3235
diff changeset
   131
            self._changectx = changectx
696c656202a0 context: make filectx remember changectx in changectx.filectx
Matt Mackall <mpm@selenic.com>
parents: 3235
diff changeset
   132
            self._changeid = changectx.node()
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   133
3143
db25f7b80fdb context: handle fileid or changeid == 0
Brendan Cully <brendan@kublai.com>
parents: 3136
diff changeset
   134
        if fileid is None:
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   135
            self._changeid = changeid
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   136
        else:
3235
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   137
            self._fileid = fileid
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   138
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   139
    def __getattr__(self, name):
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   140
        if name == '_changectx':
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   141
            self._changectx = changectx(self._repo, self._changeid)
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   142
            return self._changectx
3235
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   143
        elif name == '_filelog':
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   144
            self._filelog = self._repo.file(self._path)
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   145
            return self._filelog
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   146
        elif name == '_changeid':
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   147
            self._changeid = self._filelog.linkrev(self._filenode)
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   148
            return self._changeid
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   149
        elif name == '_filenode':
3241
a184cd0c2db9 Merge with upstream
Brendan Cully <brendan@kublai.com>
parents: 3229 3240
diff changeset
   150
            try:
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
   151
                if '_fileid' in self.__dict__:
3241
a184cd0c2db9 Merge with upstream
Brendan Cully <brendan@kublai.com>
parents: 3229 3240
diff changeset
   152
                    self._filenode = self._filelog.lookup(self._fileid)
a184cd0c2db9 Merge with upstream
Brendan Cully <brendan@kublai.com>
parents: 3229 3240
diff changeset
   153
                else:
3495
23ede9e7ad4d filecontext: report False for missing files
Matt Mackall <mpm@selenic.com>
parents: 3436
diff changeset
   154
                    try:
23ede9e7ad4d filecontext: report False for missing files
Matt Mackall <mpm@selenic.com>
parents: 3436
diff changeset
   155
                        self._filenode = self._changectx.filenode(self._path)
23ede9e7ad4d filecontext: report False for missing files
Matt Mackall <mpm@selenic.com>
parents: 3436
diff changeset
   156
                    except:
23ede9e7ad4d filecontext: report False for missing files
Matt Mackall <mpm@selenic.com>
parents: 3436
diff changeset
   157
                        self._filenode = self._filerev = None
3241
a184cd0c2db9 Merge with upstream
Brendan Cully <brendan@kublai.com>
parents: 3229 3240
diff changeset
   158
            except revlog.RevlogError, inst:
a184cd0c2db9 Merge with upstream
Brendan Cully <brendan@kublai.com>
parents: 3229 3240
diff changeset
   159
                raise repo.LookupError(str(inst))
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   160
            return self._filenode
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   161
        elif name == '_filerev':
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   162
            self._filerev = self._filelog.rev(self._filenode)
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   163
            return self._filerev
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   164
        else:
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   165
            raise AttributeError, name
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   166
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
   167
    def __nonzero__(self):
3495
23ede9e7ad4d filecontext: report False for missing files
Matt Mackall <mpm@selenic.com>
parents: 3436
diff changeset
   168
        return self._filenode != None
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
   169
3199
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
   170
    def __str__(self):
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
   171
        return "%s@%s" % (self.path(), short(self.node()))
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
   172
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
   173
    def __repr__(self):
3238
d865390c1781 context: simplify repr methods
Matt Mackall <mpm@selenic.com>
parents: 3237
diff changeset
   174
        return "<filectx %s>" % str(self)
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
   175
3198
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
   176
    def __eq__(self, other):
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
   177
        return self._path == other._path and self._changeid == other._changeid
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
   178
3207
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   179
    def filectx(self, fileid):
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   180
        '''opens an arbitrary revision of the file without
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   181
        opening a new filelog'''
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   182
        return filectx(self._repo, self._path, fileid=fileid,
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   183
                       filelog=self._filelog)
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   184
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   185
    def filerev(self): return self._filerev
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   186
    def filenode(self): return self._filenode
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   187
    def filelog(self): return self._filelog
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   188
3150
a5e4c8172ace filectx: lazy linkrev usage
Matt Mackall <mpm@selenic.com>
parents: 3149
diff changeset
   189
    def rev(self):
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
   190
        if '_changectx' in self.__dict__:
3150
a5e4c8172ace filectx: lazy linkrev usage
Matt Mackall <mpm@selenic.com>
parents: 3149
diff changeset
   191
            return self._changectx.rev()
3402
372999405787 Back out d8eba1c3ce9b and a004164dbeef
Brendan Cully <brendan@kublai.com>
parents: 3400
diff changeset
   192
        return self._filelog.linkrev(self._filenode)
3150
a5e4c8172ace filectx: lazy linkrev usage
Matt Mackall <mpm@selenic.com>
parents: 3149
diff changeset
   193
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   194
    def node(self): return self._changectx.node()
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   195
    def user(self): return self._changectx.user()
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   196
    def date(self): return self._changectx.date()
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   197
    def files(self): return self._changectx.files()
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   198
    def description(self): return self._changectx.description()
3428
cc9c31b07c2c Add branch method to contexts
Matt Mackall <mpm@selenic.com>
parents: 3353
diff changeset
   199
    def branch(self): return self._changectx.branch()
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   200
    def manifest(self): return self._changectx.manifest()
3149
ff1ab08e6732 restore filectx.changectx() method
Matt Mackall <mpm@selenic.com>
parents: 3146
diff changeset
   201
    def changectx(self): return self._changectx
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   202
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   203
    def data(self): return self._filelog.read(self._filenode)
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   204
    def renamed(self): return self._filelog.renamed(self._filenode)
3130
da85145d4571 filectx: add rename traversal for parents()
Matt Mackall <mpm@selenic.com>
parents: 2858
diff changeset
   205
    def path(self): return self._path
3308
192085505f6f filectx: add size method
Matt Mackall <mpm@selenic.com>
parents: 3304
diff changeset
   206
    def size(self): return self._filelog.size(self._filerev)
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   207
3316
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   208
    def cmp(self, text): return self._filelog.cmp(self._filenode, text)
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   209
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   210
    def parents(self):
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   211
        p = self._path
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   212
        fl = self._filelog
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   213
        pl = [(p, n, fl) for n in self._filelog.parents(self._filenode)]
3131
4ea58eb3f0c9 filelog: make metadata method private
Matt Mackall <mpm@selenic.com>
parents: 3130
diff changeset
   214
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   215
        r = self.renamed()
3130
da85145d4571 filectx: add rename traversal for parents()
Matt Mackall <mpm@selenic.com>
parents: 2858
diff changeset
   216
        if r:
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   217
            pl[0] = (r[0], r[1], None)
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   218
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   219
        return [filectx(self._repo, p, fileid=n, filelog=l)
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   220
                for p,n,l in pl if n != nullid]
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   221
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   222
    def children(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   223
        # hard for renames
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   224
        c = self._filelog.children(self._filenode)
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   225
        return [filectx(self._repo, self._path, fileid=x,
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   226
                        filelog=self._filelog) for x in c]
2566
d8560b458f76 Convert hg annotate to context api
Matt Mackall <mpm@selenic.com>
parents: 2563
diff changeset
   227
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   228
    def annotate(self, follow=False):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   229
        '''returns a list of tuples of (ctx, line) for each line
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   230
        in the file, where ctx is the filectx of the node where
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   231
        that line was last changed'''
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   232
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   233
        def decorate(text, rev):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   234
            return ([rev] * len(text.splitlines()), text)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   235
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   236
        def pair(parent, child):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   237
            for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   238
                child[0][b1:b2] = parent[0][a1:a2]
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   239
            return child
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   240
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   241
        getlog = util.cachefunc(lambda x: self._repo.file(x))
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   242
        def getctx(path, fileid):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   243
            log = path == self._path and self._filelog or getlog(path)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   244
            return filectx(self._repo, path, fileid=fileid, filelog=log)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   245
        getctx = util.cachefunc(getctx)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   246
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   247
        def parents(f):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   248
            # we want to reuse filectx objects as much as possible
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   249
            p = f._path
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   250
            if f._filerev is None: # working dir
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   251
                pl = [(n.path(), n.filerev()) for n in f.parents()]
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   252
            else:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   253
                pl = [(p, n) for n in f._filelog.parentrevs(f._filerev)]
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   254
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   255
            if follow:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   256
                r = f.renamed()
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   257
                if r:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   258
                    pl[0] = (r[0], getlog(r[0]).rev(r[1]))
3146
e69a0cbe268e filectx.annotate: return filectx for each line instead of rev
Brendan Cully <brendan@kublai.com>
parents: 3144
diff changeset
   259
3578
3b4e00cba57a Define and use nullrev (revision of nullid) instead of -1.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3495
diff changeset
   260
            return [getctx(p, n) for p, n in pl if n != nullrev]
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   261
3403
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   262
        # use linkrev to find the first changeset where self appeared
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   263
        if self.rev() != self._filelog.linkrev(self._filenode):
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   264
            base = self.filectx(self.filerev())
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   265
        else:
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   266
            base = self
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   267
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   268
        # find all ancestors
3403
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   269
        needed = {base: 1}
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   270
        visit = [base]
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   271
        files = [base._path]
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   272
        while visit:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   273
            f = visit.pop(0)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   274
            for p in parents(f):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   275
                if p not in needed:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   276
                    needed[p] = 1
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   277
                    visit.append(p)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   278
                    if p._path not in files:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   279
                        files.append(p._path)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   280
                else:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   281
                    # count how many times we'll use this
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   282
                    needed[p] += 1
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   283
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   284
        # sort by revision (per file) which is a topological order
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   285
        visit = []
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   286
        files.reverse()
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   287
        for f in files:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   288
            fn = [(n._filerev, n) for n in needed.keys() if n._path == f]
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   289
            fn.sort()
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   290
            visit.extend(fn)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   291
        hist = {}
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   292
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   293
        for r, f in visit:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   294
            curr = decorate(f.data(), f)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   295
            for p in parents(f):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   296
                if p != nullid:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   297
                    curr = pair(hist[p], curr)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   298
                    # trim the history of unneeded revs
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   299
                    needed[p] -= 1
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   300
                    if not needed[p]:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   301
                        del hist[p]
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   302
            hist[f] = curr
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   303
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   304
        return zip(hist[f][0], hist[f][1].splitlines(1))
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   305
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   306
    def ancestor(self, fc2):
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   307
        """
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   308
        find the common ancestor file context, if any, of self, and fc2
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   309
        """
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   310
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   311
        acache = {}
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   312
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   313
        # prime the ancestor cache for the working directory
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   314
        for c in (self, fc2):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   315
            if c._filerev == None:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   316
                pl = [(n.path(), n.filenode()) for n in c.parents()]
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   317
                acache[(c._path, None)] = pl
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   318
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   319
        flcache = {self._path:self._filelog, fc2._path:fc2._filelog}
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   320
        def parents(vertex):
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   321
            if vertex in acache:
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   322
                return acache[vertex]
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   323
            f, n = vertex
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   324
            if f not in flcache:
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   325
                flcache[f] = self._repo.file(f)
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   326
            fl = flcache[f]
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   327
            pl = [(f, p) for p in fl.parents(n) if p != nullid]
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   328
            re = fl.renamed(n)
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   329
            if re:
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   330
                pl.append(re)
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   331
            acache[vertex] = pl
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   332
            return pl
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   333
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   334
        a, b = (self._path, self._filenode), (fc2._path, fc2._filenode)
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   335
        v = ancestor.ancestor(a, b, parents)
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   336
        if v:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   337
            f, n = v
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   338
            return filectx(self._repo, f, fileid=n, filelog=flcache[f])
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   339
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   340
        return None
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   341
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   342
class workingctx(changectx):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   343
    """A workingctx object makes access to data related to
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   344
    the current working directory convenient."""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   345
    def __init__(self, repo):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   346
        self._repo = repo
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   347
        self._rev = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   348
        self._node = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   349
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   350
    def __str__(self):
3319
6c68bc1e7873 context: change workingctx str() from . to <node>+
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
   351
        return str(self._parents[0]) + "+"
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   352
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   353
    def __nonzero__(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   354
        return True
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   355
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   356
    def __getattr__(self, name):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   357
        if name == '_parents':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   358
            self._parents = self._repo.parents()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   359
            return self._parents
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   360
        if name == '_status':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   361
            self._status = self._repo.status()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   362
            return self._status
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   363
        if name == '_manifest':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   364
            self._buildmanifest()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   365
            return self._manifest
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   366
        else:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   367
            raise AttributeError, name
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   368
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   369
    def _buildmanifest(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   370
        """generate a manifest corresponding to the working directory"""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   371
3240
8d4855fd9d7b merge: use new working context object in update
Matt Mackall <mpm@selenic.com>
parents: 3239
diff changeset
   372
        man = self._parents[0].manifest().copy()
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   373
        copied = self._repo.dirstate.copies()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   374
        modified, added, removed, deleted, unknown = self._status[:5]
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   375
        for i, l in (("a", added), ("m", modified), ("u", unknown)):
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   376
            for f in l:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   377
                man[f] = man.get(copied.get(f, f), nullid) + i
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   378
                man.set(f, util.is_exec(self._repo.wjoin(f), man.execf(f)))
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   379
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   380
        for f in deleted + removed:
3351
50a18815e3f0 Revert changeset c67920d78248.
Giorgos Keramidas <keramida@ceid.upatras.gr>
parents: 3319
diff changeset
   381
            if f in man:
50a18815e3f0 Revert changeset c67920d78248.
Giorgos Keramidas <keramida@ceid.upatras.gr>
parents: 3319
diff changeset
   382
                del man[f]
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   383
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   384
        self._manifest = man
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   385
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   386
    def manifest(self): return self._manifest
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   387
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   388
    def user(self): return self._repo.ui.username()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   389
    def date(self): return util.makedate()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   390
    def description(self): return ""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   391
    def files(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   392
        f = self.modified() + self.added() + self.removed()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   393
        f.sort()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   394
        return f
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   395
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   396
    def modified(self): return self._status[0]
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   397
    def added(self): return self._status[1]
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   398
    def removed(self): return self._status[2]
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   399
    def deleted(self): return self._status[3]
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   400
    def unknown(self): return self._status[4]
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   401
    def clean(self): return self._status[5]
3428
cc9c31b07c2c Add branch method to contexts
Matt Mackall <mpm@selenic.com>
parents: 3353
diff changeset
   402
    def branch(self):
cc9c31b07c2c Add branch method to contexts
Matt Mackall <mpm@selenic.com>
parents: 3353
diff changeset
   403
        try:
cc9c31b07c2c Add branch method to contexts
Matt Mackall <mpm@selenic.com>
parents: 3353
diff changeset
   404
            return self._repo.opener("branch").read().strip()
cc9c31b07c2c Add branch method to contexts
Matt Mackall <mpm@selenic.com>
parents: 3353
diff changeset
   405
        except IOError:
cc9c31b07c2c Add branch method to contexts
Matt Mackall <mpm@selenic.com>
parents: 3353
diff changeset
   406
            return ""
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   407
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   408
    def parents(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   409
        """return contexts for each parent changeset"""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   410
        return self._parents
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   411
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   412
    def children(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   413
        return []
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   414
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   415
    def filectx(self, path):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   416
        """get a file context from the working directory"""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   417
        return workingfilectx(self._repo, path, workingctx=self)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   418
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   419
    def ancestor(self, c2):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   420
        """return the ancestor context of self and c2"""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   421
        return self._parents[0].ancestor(c2) # punt on two parents for now
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   422
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   423
class workingfilectx(filectx):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   424
    """A workingfilectx object makes access to data related to a particular
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   425
       file in the working directory convenient."""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   426
    def __init__(self, repo, path, filelog=None, workingctx=None):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   427
        """changeid can be a changeset revision, node, or tag.
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   428
           fileid can be a file revision or node."""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   429
        self._repo = repo
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   430
        self._path = path
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   431
        self._changeid = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   432
        self._filerev = self._filenode = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   433
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   434
        if filelog:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   435
            self._filelog = filelog
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   436
        if workingctx:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   437
            self._changectx = workingctx
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   438
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   439
    def __getattr__(self, name):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   440
        if name == '_changectx':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   441
            self._changectx = workingctx(repo)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   442
            return self._changectx
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   443
        elif name == '_repopath':
3304
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   444
            self._repopath = (self._repo.dirstate.copied(self._path)
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   445
                              or self._path)
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   446
            return self._repopath
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   447
        elif name == '_filelog':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   448
            self._filelog = self._repo.file(self._repopath)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   449
            return self._filelog
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   450
        else:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   451
            raise AttributeError, name
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   452
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   453
    def __nonzero__(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   454
        return True
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   455
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   456
    def __str__(self):
3319
6c68bc1e7873 context: change workingctx str() from . to <node>+
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
   457
        return "%s@%s" % (self.path(), self._changectx)
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   458
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   459
    def filectx(self, fileid):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   460
        '''opens an arbitrary revision of the file without
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   461
        opening a new filelog'''
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   462
        return filectx(self._repo, self._repopath, fileid=fileid,
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   463
                       filelog=self._filelog)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   464
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   465
    def rev(self):
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
   466
        if '_changectx' in self.__dict__:
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   467
            return self._changectx.rev()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   468
        return self._filelog.linkrev(self._filenode)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   469
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   470
    def data(self): return self._repo.wread(self._path)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   471
    def renamed(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   472
        rp = self._repopath
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   473
        if rp == self._path:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   474
            return None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   475
        return rp, self._workingctx._parents._manifest.get(rp, nullid)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   476
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   477
    def parents(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   478
        '''return parent filectxs, following copies if necessary'''
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   479
        p = self._path
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   480
        rp = self._repopath
3304
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   481
        pcl = self._changectx._parents
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   482
        fl = self._filelog
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   483
        pl = [(rp, pcl[0]._manifest.get(rp, nullid), fl)]
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   484
        if len(pcl) > 1:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   485
            if rp != p:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   486
                fl = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   487
            pl.append((p, pcl[1]._manifest.get(p, nullid), fl))
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   488
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   489
        return [filectx(self._repo, p, fileid=n, filelog=l)
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   490
                for p,n,l in pl if n != nullid]
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   491
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   492
    def children(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   493
        return []
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   494
3308
192085505f6f filectx: add size method
Matt Mackall <mpm@selenic.com>
parents: 3304
diff changeset
   495
    def size(self): return os.stat(self._repo.wjoin(self._path)).st_size
3316
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   496
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   497
    def cmp(self, text): return self._repo.wread(self._path) == text