mercurial/context.py
author Thomas Arendsen Hein <thomas@intevation.de>
Thu, 21 Jun 2007 19:24:27 +0200
changeset 4668 e241598e956f
parent 4663 6b2e8cb39583
child 4815 8808ea7da86b
permissions -rw-r--r--
Remove useless variable assignments in util.opener. The original idea might have been to prevent circular references, but as this assignment would have created another reference, this makes no difference.
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
#
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4417
diff changeset
     3
# Copyright 2006, 2007 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 *
3893
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3886
diff changeset
     9
from i18n import _
3962
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
    10
import ancestor, bdiff, repo, revlog, util, os, errno
3130
da85145d4571 filectx: add rename traversal for parents()
Matt Mackall <mpm@selenic.com>
parents: 2858
diff changeset
    11
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
class changectx(object):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
    """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
    14
    changeset convenient."""
3127
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    15
    def __init__(self, repo, changeid=None):
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    16
        """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
    17
        self._repo = repo
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    18
3143
db25f7b80fdb context: handle fileid or changeid == 0
Brendan Cully <brendan@kublai.com>
parents: 3136
diff changeset
    19
        if not changeid and changeid != 0:
3127
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    20
            p1, p2 = self._repo.dirstate.parents()
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    21
            self._rev = self._repo.changelog.rev(p1)
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    22
            if self._rev == -1:
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    23
                changeid = 'tip'
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    24
            else:
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    25
                self._node = p1
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    26
                return
81da3c45aabd Move defaultrev into changectx
Brendan Cully <brendan@kublai.com>
parents: 2858
diff changeset
    27
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
    28
        self._node = self._repo.lookup(changeid)
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
        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
    30
3199
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
    31
    def __str__(self):
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
    32
        return short(self.node())
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
    33
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
    34
    def __repr__(self):
3238
d865390c1781 context: simplify repr methods
Matt Mackall <mpm@selenic.com>
parents: 3237
diff changeset
    35
        return "<changectx %s>" % str(self)
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
    36
3198
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
    37
    def __eq__(self, other):
3715
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
    38
        try:
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
    39
            return self._rev == other._rev
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
    40
        except AttributeError:
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
    41
            return False
3198
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
    42
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
    43
    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
    44
        return self._rev != nullrev
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
    45
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    46
    def __getattr__(self, name):
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    47
        if name == '_changeset':
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    48
            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
    49
            return self._changeset
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    50
        elif name == '_manifest':
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    51
            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
    52
            return self._manifest
3335
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    53
        elif name == '_manifestdelta':
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    54
            md = self._repo.manifest.readdelta(self._changeset[0])
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    55
            self._manifestdelta = md
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    56
            return self._manifestdelta
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    57
        else:
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    58
            raise AttributeError, name
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    59
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    60
    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
    61
    def manifest(self): return self._manifest
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
    def rev(self): return self._rev
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
    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
    65
    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
    66
    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
    67
    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
    68
    def description(self): return self._changeset[4]
4206
0b48e3985765 Minor default branch cleanups
Matt Mackall <mpm@selenic.com>
parents: 4204
diff changeset
    69
    def branch(self): return self._changeset[5].get("branch")
4663
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
    70
    def tags(self): return self._repo.nodetags(self._node)
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
    def parents(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
        """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
    74
        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
    75
        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
    76
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
    def children(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
        """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
    79
        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
    80
        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
    81
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
    def filenode(self, path):
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
    83
        if '_manifest' in self.__dict__:
3242
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    84
            try:
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    85
                return self._manifest[path]
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    86
            except KeyError:
3930
01d98d68d697 Add revlog.LookupError exception, and use it instead of RevlogError.
Brendan Cully <brendan@kublai.com>
parents: 3893
diff changeset
    87
                raise revlog.LookupError(_("'%s' not found in manifest") % path)
3335
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    88
        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
    89
            if path in self._manifestdelta:
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    90
                return self._manifestdelta[path]
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    91
        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
    92
        if not node:
3930
01d98d68d697 Add revlog.LookupError exception, and use it instead of RevlogError.
Brendan Cully <brendan@kublai.com>
parents: 3893
diff changeset
    93
            raise revlog.LookupError(_("'%s' not found in manifest") % path)
3242
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    94
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
        return node
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
3966
b4eaa68dea1b context: create a filectxt with filelog reuse
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3965
diff changeset
    97
    def filectx(self, path, fileid=None, filelog=None):
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    98
        """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
    99
        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
   100
            fileid = self.filenode(path)
3966
b4eaa68dea1b context: create a filectxt with filelog reuse
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3965
diff changeset
   101
        return filectx(self._repo, path, fileid=fileid,
b4eaa68dea1b context: create a filectxt with filelog reuse
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3965
diff changeset
   102
                       changectx=self, filelog=filelog)
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
    def filectxs(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
        """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
   106
           manifest"""
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   107
        mf = self.manifest()
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
        m = mf.keys()
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   109
        m.sort()
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   110
        for f in m:
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   111
            yield self.filectx(f, fileid=mf[f])
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
3133
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   113
    def ancestor(self, c2):
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   114
        """
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   115
        return the ancestor context of self and c2
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   116
        """
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   117
        n = self._repo.changelog.ancestor(self._node, c2._node)
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   118
        return changectx(self._repo, n)
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   119
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   120
class filectx(object):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
    """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
   122
       filerevision convenient."""
3236
696c656202a0 context: make filectx remember changectx in changectx.filectx
Matt Mackall <mpm@selenic.com>
parents: 3235
diff changeset
   123
    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
   124
                 filelog=None, changectx=None):
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
        """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
   126
           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
   127
        self._repo = repo
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   128
        self._path = path
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   129
3964
2308c39b9521 make it possible to use changectx to create a filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3962
diff changeset
   130
        assert (changeid is not None
2308c39b9521 make it possible to use changectx to create a filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3962
diff changeset
   131
                or fileid is not None
2308c39b9521 make it possible to use changectx to create a filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3962
diff changeset
   132
                or changectx is not None)
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   133
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   134
        if filelog:
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   135
            self._filelog = filelog
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   136
3143
db25f7b80fdb context: handle fileid or changeid == 0
Brendan Cully <brendan@kublai.com>
parents: 3136
diff changeset
   137
        if fileid is None:
3964
2308c39b9521 make it possible to use changectx to create a filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3962
diff changeset
   138
            if changectx is None:
2308c39b9521 make it possible to use changectx to create a filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3962
diff changeset
   139
                self._changeid = changeid
2308c39b9521 make it possible to use changectx to create a filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3962
diff changeset
   140
            else:
2308c39b9521 make it possible to use changectx to create a filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3962
diff changeset
   141
                self._changectx = changectx
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   142
        else:
3235
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   143
            self._fileid = fileid
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   144
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   145
    def __getattr__(self, name):
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   146
        if name == '_changectx':
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   147
            self._changectx = changectx(self._repo, self._changeid)
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   148
            return self._changectx
3235
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   149
        elif name == '_filelog':
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   150
            self._filelog = self._repo.file(self._path)
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   151
            return self._filelog
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   152
        elif name == '_changeid':
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   153
            self._changeid = self._filelog.linkrev(self._filenode)
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   154
            return self._changeid
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   155
        elif name == '_filenode':
3961
a4edadd807dd fix tab vs space
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3930
diff changeset
   156
            if '_fileid' in self.__dict__:
a4edadd807dd fix tab vs space
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3930
diff changeset
   157
                self._filenode = self._filelog.lookup(self._fileid)
a4edadd807dd fix tab vs space
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3930
diff changeset
   158
            else:
a4edadd807dd fix tab vs space
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3930
diff changeset
   159
                self._filenode = self._changectx.filenode(self._path)
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):
3712
1bd70d40ec57 context: None is not a valid filenode (revert from 23ede9e7ad4d)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3673
diff changeset
   168
        try:
1bd70d40ec57 context: None is not a valid filenode (revert from 23ede9e7ad4d)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3673
diff changeset
   169
            n = self._filenode
1bd70d40ec57 context: None is not a valid filenode (revert from 23ede9e7ad4d)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3673
diff changeset
   170
            return True
3930
01d98d68d697 Add revlog.LookupError exception, and use it instead of RevlogError.
Brendan Cully <brendan@kublai.com>
parents: 3893
diff changeset
   171
        except revlog.LookupError:
3712
1bd70d40ec57 context: None is not a valid filenode (revert from 23ede9e7ad4d)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3673
diff changeset
   172
            # file is missing
1bd70d40ec57 context: None is not a valid filenode (revert from 23ede9e7ad4d)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3673
diff changeset
   173
            return False
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
   174
3199
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
   175
    def __str__(self):
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
   176
        return "%s@%s" % (self.path(), short(self.node()))
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
   177
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
   178
    def __repr__(self):
3238
d865390c1781 context: simplify repr methods
Matt Mackall <mpm@selenic.com>
parents: 3237
diff changeset
   179
        return "<filectx %s>" % str(self)
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
   180
3198
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
   181
    def __eq__(self, other):
3715
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
   182
        try:
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
   183
            return (self._path == other._path
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
   184
                    and self._changeid == other._changeid)
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
   185
        except AttributeError:
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
   186
            return False
3198
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
   187
3207
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   188
    def filectx(self, fileid):
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   189
        '''opens an arbitrary revision of the file without
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   190
        opening a new filelog'''
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   191
        return filectx(self._repo, self._path, fileid=fileid,
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   192
                       filelog=self._filelog)
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   193
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   194
    def filerev(self): return self._filerev
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   195
    def filenode(self): return self._filenode
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   196
    def filelog(self): return self._filelog
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   197
3150
a5e4c8172ace filectx: lazy linkrev usage
Matt Mackall <mpm@selenic.com>
parents: 3149
diff changeset
   198
    def rev(self):
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
   199
        if '_changectx' in self.__dict__:
3150
a5e4c8172ace filectx: lazy linkrev usage
Matt Mackall <mpm@selenic.com>
parents: 3149
diff changeset
   200
            return self._changectx.rev()
3402
372999405787 Back out d8eba1c3ce9b and a004164dbeef
Brendan Cully <brendan@kublai.com>
parents: 3400
diff changeset
   201
        return self._filelog.linkrev(self._filenode)
3150
a5e4c8172ace filectx: lazy linkrev usage
Matt Mackall <mpm@selenic.com>
parents: 3149
diff changeset
   202
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   203
    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
   204
    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
   205
    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
   206
    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
   207
    def description(self): return self._changectx.description()
3428
cc9c31b07c2c Add branch method to contexts
Matt Mackall <mpm@selenic.com>
parents: 3353
diff changeset
   208
    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
   209
    def manifest(self): return self._changectx.manifest()
3149
ff1ab08e6732 restore filectx.changectx() method
Matt Mackall <mpm@selenic.com>
parents: 3146
diff changeset
   210
    def changectx(self): return self._changectx
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   211
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   212
    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
   213
    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
   214
    def path(self): return self._path
3308
192085505f6f filectx: add size method
Matt Mackall <mpm@selenic.com>
parents: 3304
diff changeset
   215
    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
   216
3316
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   217
    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
   218
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   219
    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
   220
        p = self._path
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   221
        fl = self._filelog
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   222
        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
   223
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   224
        r = self.renamed()
3130
da85145d4571 filectx: add rename traversal for parents()
Matt Mackall <mpm@selenic.com>
parents: 2858
diff changeset
   225
        if r:
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   226
            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
   227
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   228
        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
   229
                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
   230
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   231
    def children(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   232
        # hard for renames
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   233
        c = self._filelog.children(self._filenode)
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   234
        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
   235
                        filelog=self._filelog) for x in c]
2566
d8560b458f76 Convert hg annotate to context api
Matt Mackall <mpm@selenic.com>
parents: 2563
diff changeset
   236
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   237
    def annotate(self, follow=False):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   238
        '''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
   239
        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
   240
        that line was last changed'''
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   241
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   242
        def decorate(text, rev):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   243
            return ([rev] * len(text.splitlines()), text)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   244
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   245
        def pair(parent, child):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   246
            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
   247
                child[0][b1:b2] = parent[0][a1:a2]
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   248
            return child
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   249
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   250
        getlog = util.cachefunc(lambda x: self._repo.file(x))
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   251
        def getctx(path, fileid):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   252
            log = path == self._path and self._filelog or getlog(path)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   253
            return filectx(self._repo, path, fileid=fileid, filelog=log)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   254
        getctx = util.cachefunc(getctx)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   255
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   256
        def parents(f):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   257
            # we want to reuse filectx objects as much as possible
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   258
            p = f._path
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   259
            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
   260
                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
   261
            else:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   262
                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
   263
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   264
            if follow:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   265
                r = f.renamed()
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   266
                if r:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   267
                    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
   268
3578
3b4e00cba57a Define and use nullrev (revision of nullid) instead of -1.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3495
diff changeset
   269
            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
   270
3403
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   271
        # 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
   272
        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
   273
            base = self.filectx(self.filerev())
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   274
        else:
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   275
            base = self
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   276
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   277
        # find all ancestors
3403
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   278
        needed = {base: 1}
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   279
        visit = [base]
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   280
        files = [base._path]
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   281
        while visit:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   282
            f = visit.pop(0)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   283
            for p in parents(f):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   284
                if p not in needed:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   285
                    needed[p] = 1
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   286
                    visit.append(p)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   287
                    if p._path not in files:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   288
                        files.append(p._path)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   289
                else:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   290
                    # count how many times we'll use this
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   291
                    needed[p] += 1
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
        # sort by revision (per file) which is a topological order
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   294
        visit = []
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   295
        for f in files:
4638
3c7fc13c4bfa Fix issue 589: "undelete" sequence leads to crash.
Patrick Mezard <pmezard@gmail.com>
parents: 4414
diff changeset
   296
            fn = [(n.rev(), n) for n in needed.keys() if n._path == f]
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   297
            visit.extend(fn)
4638
3c7fc13c4bfa Fix issue 589: "undelete" sequence leads to crash.
Patrick Mezard <pmezard@gmail.com>
parents: 4414
diff changeset
   298
        visit.sort()
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   299
        hist = {}
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   300
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   301
        for r, f in visit:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   302
            curr = decorate(f.data(), f)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   303
            for p in parents(f):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   304
                if p != nullid:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   305
                    curr = pair(hist[p], curr)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   306
                    # trim the history of unneeded revs
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   307
                    needed[p] -= 1
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   308
                    if not needed[p]:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   309
                        del hist[p]
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   310
            hist[f] = curr
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   311
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   312
        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
   313
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   314
    def ancestor(self, fc2):
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   315
        """
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   316
        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
   317
        """
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   318
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   319
        acache = {}
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   320
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   321
        # 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
   322
        for c in (self, fc2):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   323
            if c._filerev == None:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   324
                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
   325
                acache[(c._path, None)] = pl
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   326
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   327
        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
   328
        def parents(vertex):
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   329
            if vertex in acache:
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   330
                return acache[vertex]
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   331
            f, n = vertex
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   332
            if f not in flcache:
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   333
                flcache[f] = self._repo.file(f)
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   334
            fl = flcache[f]
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   335
            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
   336
            re = fl.renamed(n)
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   337
            if re:
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   338
                pl.append(re)
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   339
            acache[vertex] = pl
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   340
            return pl
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   341
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   342
        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
   343
        v = ancestor.ancestor(a, b, parents)
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   344
        if v:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   345
            f, n = v
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   346
            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
   347
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   348
        return None
3239
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
class workingctx(changectx):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   351
    """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
   352
    the current working directory convenient."""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   353
    def __init__(self, repo):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   354
        self._repo = repo
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   355
        self._rev = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   356
        self._node = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   357
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   358
    def __str__(self):
3319
6c68bc1e7873 context: change workingctx str() from . to <node>+
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
   359
        return str(self._parents[0]) + "+"
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   360
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   361
    def __nonzero__(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   362
        return True
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   363
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   364
    def __getattr__(self, name):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   365
        if name == '_parents':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   366
            self._parents = self._repo.parents()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   367
            return self._parents
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   368
        if name == '_status':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   369
            self._status = self._repo.status()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   370
            return self._status
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   371
        if name == '_manifest':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   372
            self._buildmanifest()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   373
            return self._manifest
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   374
        else:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   375
            raise AttributeError, name
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   376
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   377
    def _buildmanifest(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   378
        """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
   379
3240
8d4855fd9d7b merge: use new working context object in update
Matt Mackall <mpm@selenic.com>
parents: 3239
diff changeset
   380
        man = self._parents[0].manifest().copy()
3996
c190df14338c exec: add execfunc to simplify exec flag support on non-exec filesystems
Matt Mackall <mpm@selenic.com>
parents: 3966
diff changeset
   381
        is_exec = util.execfunc(self._repo.root, man.execf)
4002
d7b9ec589546 symlinks: use is_link wherever is_exec is used
Matt Mackall <mpm@selenic.com>
parents: 3996
diff changeset
   382
        is_link = util.linkfunc(self._repo.root, man.linkf)
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   383
        copied = self._repo.dirstate.copies()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   384
        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
   385
        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
   386
            for f in l:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   387
                man[f] = man.get(copied.get(f, f), nullid) + i
3829
676b75547d13 context: don't spuriously raise abort when a file goes missing.
Matt Mackall <mpm@selenic.com>
parents: 3715
diff changeset
   388
                try:
4002
d7b9ec589546 symlinks: use is_link wherever is_exec is used
Matt Mackall <mpm@selenic.com>
parents: 3996
diff changeset
   389
                    man.set(f, is_exec(f), is_link(f))
3829
676b75547d13 context: don't spuriously raise abort when a file goes missing.
Matt Mackall <mpm@selenic.com>
parents: 3715
diff changeset
   390
                except OSError:
676b75547d13 context: don't spuriously raise abort when a file goes missing.
Matt Mackall <mpm@selenic.com>
parents: 3715
diff changeset
   391
                    pass
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   392
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   393
        for f in deleted + removed:
3351
50a18815e3f0 Revert changeset c67920d78248.
Giorgos Keramidas <keramida@ceid.upatras.gr>
parents: 3319
diff changeset
   394
            if f in man:
50a18815e3f0 Revert changeset c67920d78248.
Giorgos Keramidas <keramida@ceid.upatras.gr>
parents: 3319
diff changeset
   395
                del man[f]
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   396
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   397
        self._manifest = man
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   398
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   399
    def manifest(self): return self._manifest
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   400
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   401
    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
   402
    def date(self): return util.makedate()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   403
    def description(self): return ""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   404
    def files(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   405
        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
   406
        f.sort()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   407
        return f
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   408
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   409
    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
   410
    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
   411
    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
   412
    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
   413
    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
   414
    def clean(self): return self._status[5]
4207
7e1c8a565a4f Move branch read/write to dirstate where it belongs
Matt Mackall <mpm@selenic.com>
parents: 4206
diff changeset
   415
    def branch(self): return self._repo.dirstate.branch()
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   416
4663
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   417
    def tags(self):
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   418
        t = []
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   419
        [t.extend(p.tags()) for p in self.parents()]
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   420
        return t
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   421
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   422
    def parents(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   423
        """return contexts for each parent changeset"""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   424
        return self._parents
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   425
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   426
    def children(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   427
        return []
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   428
3966
b4eaa68dea1b context: create a filectxt with filelog reuse
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3965
diff changeset
   429
    def filectx(self, path, filelog=None):
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   430
        """get a file context from the working directory"""
3966
b4eaa68dea1b context: create a filectxt with filelog reuse
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3965
diff changeset
   431
        return workingfilectx(self._repo, path, workingctx=self,
b4eaa68dea1b context: create a filectxt with filelog reuse
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3965
diff changeset
   432
                              filelog=filelog)
3239
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
    def ancestor(self, c2):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   435
        """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
   436
        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
   437
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   438
class workingfilectx(filectx):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   439
    """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
   440
       file in the working directory convenient."""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   441
    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
   442
        """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
   443
           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
   444
        self._repo = repo
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   445
        self._path = path
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   446
        self._changeid = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   447
        self._filerev = self._filenode = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   448
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   449
        if filelog:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   450
            self._filelog = filelog
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   451
        if workingctx:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   452
            self._changectx = workingctx
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   453
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   454
    def __getattr__(self, name):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   455
        if name == '_changectx':
4414
b6146466b92a context: fix workingfilectx._changectx
Matt Mackall <mpm@selenic.com>
parents: 4207
diff changeset
   456
            self._changectx = workingctx(self._repo)
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   457
            return self._changectx
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   458
        elif name == '_repopath':
3304
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   459
            self._repopath = (self._repo.dirstate.copied(self._path)
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   460
                              or self._path)
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   461
            return self._repopath
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   462
        elif name == '_filelog':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   463
            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
   464
            return self._filelog
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   465
        else:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   466
            raise AttributeError, name
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   467
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   468
    def __nonzero__(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   469
        return True
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   470
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   471
    def __str__(self):
3319
6c68bc1e7873 context: change workingctx str() from . to <node>+
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
   472
        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
   473
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   474
    def filectx(self, fileid):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   475
        '''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
   476
        opening a new filelog'''
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   477
        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
   478
                       filelog=self._filelog)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   479
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   480
    def rev(self):
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
   481
        if '_changectx' in self.__dict__:
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   482
            return self._changectx.rev()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   483
        return self._filelog.linkrev(self._filenode)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   484
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   485
    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
   486
    def renamed(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   487
        rp = self._repopath
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   488
        if rp == self._path:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   489
            return None
3965
2e5161335e65 context: fix a bug in workingfilectx.renamed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3964
diff changeset
   490
        return rp, self._changectx._parents[0]._manifest.get(rp, 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 parents(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   493
        '''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
   494
        p = self._path
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   495
        rp = self._repopath
3304
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   496
        pcl = self._changectx._parents
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   497
        fl = self._filelog
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   498
        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
   499
        if len(pcl) > 1:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   500
            if rp != p:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   501
                fl = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   502
            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
   503
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   504
        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
   505
                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
   506
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   507
    def children(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   508
        return []
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   509
3308
192085505f6f filectx: add size method
Matt Mackall <mpm@selenic.com>
parents: 3304
diff changeset
   510
    def size(self): return os.stat(self._repo.wjoin(self._path)).st_size
3962
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   511
    def date(self):
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   512
        t, tz = self._changectx.date()
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   513
        try:
4115
eb0967c6e77b Use only integer part of mtime in workingfilectx.date(), fixes test-context.py
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4108
diff changeset
   514
            return (int(os.lstat(self._repo.wjoin(self._path)).st_mtime), tz)
3962
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   515
        except OSError, err:
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   516
            if err.errno != errno.ENOENT: raise
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   517
            return (t, tz)
3316
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   518
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   519
    def cmp(self, text): return self._repo.wread(self._path) == text