mercurial/context.py
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
Fri, 17 Aug 2007 17:33:27 -0300
changeset 5189 60acf1432ee0
parent 4953 1fd7a99d98f6
child 5389 26c060922085
permissions -rw-r--r--
Move cmdtable and reposetup handling out of extensions.py A new function (extensions.extensions) allows the code that is interested in those attributes to handle them directly. This allows some cleanups of extensions.py. Notably, we can remove the extensions.commandtable hack. It also makes it easier to add standard extension attributes, like a "hgwebsetup" function or a "helptable" dict that augments the data in help.py, etc.
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
4815
8808ea7da86b merge: make test for fast-forward merge stricter (issue619)
Matt Mackall <mpm@selenic.com>
parents: 4663
diff changeset
    43
    def __ne__(self, other):
8808ea7da86b merge: make test for fast-forward merge stricter (issue619)
Matt Mackall <mpm@selenic.com>
parents: 4663
diff changeset
    44
        return not (self == other)
8808ea7da86b merge: make test for fast-forward merge stricter (issue619)
Matt Mackall <mpm@selenic.com>
parents: 4663
diff changeset
    45
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
    46
    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
    47
        return self._rev != nullrev
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
    48
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    49
    def __getattr__(self, name):
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    50
        if name == '_changeset':
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
            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
    52
            return self._changeset
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    53
        elif name == '_manifest':
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    54
            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
    55
            return self._manifest
3335
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    56
        elif name == '_manifestdelta':
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    57
            md = self._repo.manifest.readdelta(self._changeset[0])
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    58
            self._manifestdelta = md
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
    59
            return self._manifestdelta
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    60
        else:
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    61
            raise AttributeError, name
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    62
4953
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    63
    def __contains__(self, key):
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    64
        return key in self._manifest
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    65
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    66
    def __getitem__(self, key):
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    67
        return self.filectx(key)
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    68
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    69
    def __iter__(self):
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    70
        a = self._manifest.keys()
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    71
        a.sort()
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    72
        for f in a:
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    73
            return f
1fd7a99d98f6 context: add __contains__, __getitem__, and __iter__
Matt Mackall <mpm@selenic.com>
parents: 4892
diff changeset
    74
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
    75
    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
    76
    def manifest(self): return self._manifest
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
    def rev(self): return self._rev
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
    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
    80
    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
    81
    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
    82
    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
    83
    def description(self): return self._changeset[4]
4206
0b48e3985765 Minor default branch cleanups
Matt Mackall <mpm@selenic.com>
parents: 4204
diff changeset
    84
    def branch(self): return self._changeset[5].get("branch")
4663
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
    85
    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
    86
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    87
    def parents(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
        """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
    89
        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
    90
        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
    91
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    92
    def children(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
        """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
    94
        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
    95
        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
    96
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    97
    def filenode(self, path):
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
    98
        if '_manifest' in self.__dict__:
3242
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
    99
            try:
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
   100
                return self._manifest[path]
1539f788e913 Make changectx.filenode raise repo.LookupError on failure
Brendan Cully <brendan@kublai.com>
parents: 3241
diff changeset
   101
            except KeyError:
3930
01d98d68d697 Add revlog.LookupError exception, and use it instead of RevlogError.
Brendan Cully <brendan@kublai.com>
parents: 3893
diff changeset
   102
                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
   103
        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
   104
            if path in self._manifestdelta:
b02e60097bbe changectx: search manifest delta for filenode
Brendan Cully <brendan@kublai.com>
parents: 3334
diff changeset
   105
                return self._manifestdelta[path]
3237
931288cf58a7 contexts: use __getattr__ rather than try/except in changectx
Matt Mackall <mpm@selenic.com>
parents: 3236
diff changeset
   106
        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
   107
        if not node:
3930
01d98d68d697 Add revlog.LookupError exception, and use it instead of RevlogError.
Brendan Cully <brendan@kublai.com>
parents: 3893
diff changeset
   108
            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
   109
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   110
        return node
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   111
3966
b4eaa68dea1b context: create a filectxt with filelog reuse
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3965
diff changeset
   112
    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
   113
        """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
   114
        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
   115
            fileid = self.filenode(path)
3966
b4eaa68dea1b context: create a filectxt with filelog reuse
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3965
diff changeset
   116
        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
   117
                       changectx=self, filelog=filelog)
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   118
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   119
    def filectxs(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   120
        """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
   121
           manifest"""
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   122
        mf = self.manifest()
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   123
        m = mf.keys()
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
        m.sort()
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
        for f in m:
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   126
            yield self.filectx(f, fileid=mf[f])
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   127
3133
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   128
    def ancestor(self, c2):
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   129
        """
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   130
        return the ancestor context of self and c2
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   131
        """
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   132
        n = self._repo.changelog.ancestor(self._node, c2._node)
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   133
        return changectx(self._repo, n)
02b22fefc01f changectx: add ancestor function
Matt Mackall <mpm@selenic.com>
parents: 3132
diff changeset
   134
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   135
class filectx(object):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   136
    """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
   137
       filerevision convenient."""
3236
696c656202a0 context: make filectx remember changectx in changectx.filectx
Matt Mackall <mpm@selenic.com>
parents: 3235
diff changeset
   138
    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
   139
                 filelog=None, changectx=None):
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   140
        """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
   141
           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
   142
        self._repo = repo
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   143
        self._path = path
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   144
3964
2308c39b9521 make it possible to use changectx to create a filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3962
diff changeset
   145
        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
   146
                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
   147
                or changectx is not None)
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   148
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   149
        if filelog:
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   150
            self._filelog = filelog
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   151
3143
db25f7b80fdb context: handle fileid or changeid == 0
Brendan Cully <brendan@kublai.com>
parents: 3136
diff changeset
   152
        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
   153
            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
   154
                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
   155
            else:
2308c39b9521 make it possible to use changectx to create a filectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3962
diff changeset
   156
                self._changectx = changectx
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   157
        else:
3235
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   158
            self._fileid = fileid
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   159
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   160
    def __getattr__(self, name):
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   161
        if name == '_changectx':
2652
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   162
            self._changectx = changectx(self._repo, self._changeid)
f23973ea3107 fix filectxt to really work
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2629
diff changeset
   163
            return self._changectx
3235
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   164
        elif name == '_filelog':
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   165
            self._filelog = self._repo.file(self._path)
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   166
            return self._filelog
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   167
        elif name == '_changeid':
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   168
            self._changeid = self._filelog.linkrev(self._filenode)
e8199702cf4e Make filectx lazier
Matt Mackall <mpm@selenic.com>
parents: 3209
diff changeset
   169
            return self._changeid
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   170
        elif name == '_filenode':
3961
a4edadd807dd fix tab vs space
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3930
diff changeset
   171
            if '_fileid' in self.__dict__:
a4edadd807dd fix tab vs space
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3930
diff changeset
   172
                self._filenode = self._filelog.lookup(self._fileid)
a4edadd807dd fix tab vs space
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3930
diff changeset
   173
            else:
a4edadd807dd fix tab vs space
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3930
diff changeset
   174
                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
   175
            return self._filenode
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   176
        elif name == '_filerev':
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   177
            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
   178
            return self._filerev
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   179
        else:
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   180
            raise AttributeError, name
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   181
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
   182
    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
   183
        try:
1bd70d40ec57 context: None is not a valid filenode (revert from 23ede9e7ad4d)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3673
diff changeset
   184
            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
   185
            return True
3930
01d98d68d697 Add revlog.LookupError exception, and use it instead of RevlogError.
Brendan Cully <brendan@kublai.com>
parents: 3893
diff changeset
   186
        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
   187
            # 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
   188
            return False
3201
05c588e1803d context: add __nonzero__ methods
Matt Mackall <mpm@selenic.com>
parents: 3199
diff changeset
   189
3199
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
   190
    def __str__(self):
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
   191
        return "%s@%s" % (self.path(), short(self.node()))
ebdb3f616bc0 Add str methods to contexts
Matt Mackall <mpm@selenic.com>
parents: 3198
diff changeset
   192
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
   193
    def __repr__(self):
3238
d865390c1781 context: simplify repr methods
Matt Mackall <mpm@selenic.com>
parents: 3237
diff changeset
   194
        return "<filectx %s>" % str(self)
3151
6719b3dd7d50 context: add __repr__ methods
Matt Mackall <mpm@selenic.com>
parents: 3150
diff changeset
   195
3198
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
   196
    def __eq__(self, other):
3715
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
   197
        try:
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
   198
            return (self._path == other._path
4892
3b081f2a77b2 contexts: improve filectx eq test
Matt Mackall <mpm@selenic.com>
parents: 4846
diff changeset
   199
                    and self._fileid == other._fileid)
3715
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
   200
        except AttributeError:
6cb3aca69cdc Make context __eq__ handle arbitrary RHS values
Brendan Cully <brendan@kublai.com>
parents: 3712
diff changeset
   201
            return False
3198
e78185746554 Add equality operators to changectx and filectx
Matt Mackall <mpm@selenic.com>
parents: 3154
diff changeset
   202
4815
8808ea7da86b merge: make test for fast-forward merge stricter (issue619)
Matt Mackall <mpm@selenic.com>
parents: 4663
diff changeset
   203
    def __ne__(self, other):
8808ea7da86b merge: make test for fast-forward merge stricter (issue619)
Matt Mackall <mpm@selenic.com>
parents: 4663
diff changeset
   204
        return not (self == other)
8808ea7da86b merge: make test for fast-forward merge stricter (issue619)
Matt Mackall <mpm@selenic.com>
parents: 4663
diff changeset
   205
3207
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   206
    def filectx(self, fileid):
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   207
        '''opens an arbitrary revision of the file without
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   208
        opening a new filelog'''
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   209
        return filectx(self._repo, self._path, fileid=fileid,
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   210
                       filelog=self._filelog)
0790dce2f3a8 Add lookup method to filectx
Brendan Cully <brendan@kublai.com>
parents: 3165
diff changeset
   211
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   212
    def filerev(self): return self._filerev
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   213
    def filenode(self): return self._filenode
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   214
    def filelog(self): return self._filelog
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   215
3150
a5e4c8172ace filectx: lazy linkrev usage
Matt Mackall <mpm@selenic.com>
parents: 3149
diff changeset
   216
    def rev(self):
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
   217
        if '_changectx' in self.__dict__:
3150
a5e4c8172ace filectx: lazy linkrev usage
Matt Mackall <mpm@selenic.com>
parents: 3149
diff changeset
   218
            return self._changectx.rev()
3402
372999405787 Back out d8eba1c3ce9b and a004164dbeef
Brendan Cully <brendan@kublai.com>
parents: 3400
diff changeset
   219
        return self._filelog.linkrev(self._filenode)
3150
a5e4c8172ace filectx: lazy linkrev usage
Matt Mackall <mpm@selenic.com>
parents: 3149
diff changeset
   220
3144
8342ad5abe0b Make filectx lazier - some users never use filenode
Brendan Cully <brendan@kublai.com>
parents: 3143
diff changeset
   221
    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
   222
    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
   223
    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
   224
    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
   225
    def description(self): return self._changectx.description()
3428
cc9c31b07c2c Add branch method to contexts
Matt Mackall <mpm@selenic.com>
parents: 3353
diff changeset
   226
    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
   227
    def manifest(self): return self._changectx.manifest()
3149
ff1ab08e6732 restore filectx.changectx() method
Matt Mackall <mpm@selenic.com>
parents: 3146
diff changeset
   228
    def changectx(self): return self._changectx
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   229
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   230
    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
   231
    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
   232
    def path(self): return self._path
3308
192085505f6f filectx: add size method
Matt Mackall <mpm@selenic.com>
parents: 3304
diff changeset
   233
    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
   234
3316
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   235
    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
   236
2563
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   237
    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
   238
        p = self._path
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   239
        fl = self._filelog
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   240
        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
   241
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   242
        r = self.renamed()
3130
da85145d4571 filectx: add rename traversal for parents()
Matt Mackall <mpm@selenic.com>
parents: 2858
diff changeset
   243
        if r:
3132
4d021b91cb26 filectx: allow passing filelog in init to avoid opening new filelogs
Matt Mackall <mpm@selenic.com>
parents: 3131
diff changeset
   244
            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
   245
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   246
        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
   247
                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
   248
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   249
    def children(self):
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   250
        # hard for renames
482c524dd9ab Add context.py: changeset and file revision contexts
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   251
        c = self._filelog.children(self._filenode)
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   252
        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
   253
                        filelog=self._filelog) for x in c]
2566
d8560b458f76 Convert hg annotate to context api
Matt Mackall <mpm@selenic.com>
parents: 2563
diff changeset
   254
4846
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   255
    def annotate(self, follow=False, linenumber=None):
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   256
        '''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
   257
        in the file, where ctx is the filectx of the node where
4846
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   258
        that line was last changed.
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   259
        This returns tuples of ((ctx, linenumber), line) for each line,
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   260
        if "linenumber" parameter is NOT "None".
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   261
        In such tuples, linenumber means one at the first appearance
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   262
        in the managed file.
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   263
        To reduce annotation cost,
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   264
        this returns fixed value(False is used) as linenumber,
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   265
        if "linenumber" parameter is "False".'''
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   266
4846
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   267
        def decorate_compat(text, rev):
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   268
            return ([rev] * len(text.splitlines()), text)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   269
4846
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   270
        def without_linenumber(text, rev):
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   271
            return ([(rev, False)] * len(text.splitlines()), text)
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   272
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   273
        def with_linenumber(text, rev):
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   274
            size = len(text.splitlines())
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   275
            return ([(rev, i) for i in xrange(1, size + 1)], text)
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   276
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   277
        decorate = (((linenumber is None) and decorate_compat) or
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   278
                    (linenumber and with_linenumber) or
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   279
                    without_linenumber)
e45c5120ca27 Allow filectx.annotate to return the line number of first appearance.
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 4815
diff changeset
   280
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   281
        def pair(parent, child):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   282
            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
   283
                child[0][b1:b2] = parent[0][a1:a2]
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   284
            return child
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   285
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   286
        getlog = util.cachefunc(lambda x: self._repo.file(x))
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   287
        def getctx(path, fileid):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   288
            log = path == self._path and self._filelog or getlog(path)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   289
            return filectx(self._repo, path, fileid=fileid, filelog=log)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   290
        getctx = util.cachefunc(getctx)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   291
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   292
        def parents(f):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   293
            # we want to reuse filectx objects as much as possible
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   294
            p = f._path
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   295
            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
   296
                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
   297
            else:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   298
                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
   299
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   300
            if follow:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   301
                r = f.renamed()
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   302
                if r:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   303
                    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
   304
3578
3b4e00cba57a Define and use nullrev (revision of nullid) instead of -1.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3495
diff changeset
   305
            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
   306
3403
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   307
        # 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
   308
        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
   309
            base = self.filectx(self.filerev())
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   310
        else:
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   311
            base = self
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   312
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   313
        # find all ancestors
3403
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   314
        needed = {base: 1}
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   315
        visit = [base]
1a437b0f4902 Fix annotate where linkrev != rev without exporting linkrev
Brendan Cully <brendan@kublai.com>
parents: 3402
diff changeset
   316
        files = [base._path]
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   317
        while visit:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   318
            f = visit.pop(0)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   319
            for p in parents(f):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   320
                if p not in needed:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   321
                    needed[p] = 1
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   322
                    visit.append(p)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   323
                    if p._path not in files:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   324
                        files.append(p._path)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   325
                else:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   326
                    # count how many times we'll use this
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   327
                    needed[p] += 1
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   328
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   329
        # sort by revision (per file) which is a topological order
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   330
        visit = []
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   331
        for f in files:
4638
3c7fc13c4bfa Fix issue 589: "undelete" sequence leads to crash.
Patrick Mezard <pmezard@gmail.com>
parents: 4414
diff changeset
   332
            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
   333
            visit.extend(fn)
4638
3c7fc13c4bfa Fix issue 589: "undelete" sequence leads to crash.
Patrick Mezard <pmezard@gmail.com>
parents: 4414
diff changeset
   334
        visit.sort()
3165
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   335
        hist = {}
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   336
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   337
        for r, f in visit:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   338
            curr = decorate(f.data(), f)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   339
            for p in parents(f):
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   340
                if p != nullid:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   341
                    curr = pair(hist[p], curr)
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   342
                    # trim the history of unneeded revs
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   343
                    needed[p] -= 1
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   344
                    if not needed[p]:
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   345
                        del hist[p]
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   346
            hist[f] = curr
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   347
5c93dd0ae413 Refactor annotate copy support.
Brendan Cully <brendan@kublai.com>
parents: 3154
diff changeset
   348
        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
   349
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   350
    def ancestor(self, fc2):
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   351
        """
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   352
        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
   353
        """
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   354
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   355
        acache = {}
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   356
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   357
        # 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
   358
        for c in (self, fc2):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   359
            if c._filerev == None:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   360
                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
   361
                acache[(c._path, None)] = pl
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   362
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   363
        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
   364
        def parents(vertex):
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   365
            if vertex in acache:
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   366
                return acache[vertex]
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   367
            f, n = vertex
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   368
            if f not in flcache:
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   369
                flcache[f] = self._repo.file(f)
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   370
            fl = flcache[f]
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   371
            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
   372
            re = fl.renamed(n)
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   373
            if re:
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   374
                pl.append(re)
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   375
            acache[vertex] = pl
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   376
            return pl
3134
4bf2e895cf86 filectx: add rename-aware ancestor algorithm
Matt Mackall <mpm@selenic.com>
parents: 3133
diff changeset
   377
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   378
        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
   379
        v = ancestor.ancestor(a, b, parents)
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   380
        if v:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   381
            f, n = v
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   382
            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
   383
3136
b1db258e875c Abstract ancestor algorithm into generic function
Matt Mackall <mpm@selenic.com>
parents: 3135
diff changeset
   384
        return None
3239
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
class workingctx(changectx):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   387
    """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
   388
    the current working directory convenient."""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   389
    def __init__(self, repo):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   390
        self._repo = repo
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   391
        self._rev = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   392
        self._node = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   393
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   394
    def __str__(self):
3319
6c68bc1e7873 context: change workingctx str() from . to <node>+
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
   395
        return str(self._parents[0]) + "+"
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
    def __nonzero__(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   398
        return True
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   399
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   400
    def __getattr__(self, name):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   401
        if name == '_parents':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   402
            self._parents = self._repo.parents()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   403
            return self._parents
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   404
        if name == '_status':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   405
            self._status = self._repo.status()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   406
            return self._status
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   407
        if name == '_manifest':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   408
            self._buildmanifest()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   409
            return self._manifest
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   410
        else:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   411
            raise AttributeError, name
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   412
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   413
    def _buildmanifest(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   414
        """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
   415
3240
8d4855fd9d7b merge: use new working context object in update
Matt Mackall <mpm@selenic.com>
parents: 3239
diff changeset
   416
        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
   417
        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
   418
        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
   419
        copied = self._repo.dirstate.copies()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   420
        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
   421
        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
   422
            for f in l:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   423
                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
   424
                try:
4002
d7b9ec589546 symlinks: use is_link wherever is_exec is used
Matt Mackall <mpm@selenic.com>
parents: 3996
diff changeset
   425
                    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
   426
                except OSError:
676b75547d13 context: don't spuriously raise abort when a file goes missing.
Matt Mackall <mpm@selenic.com>
parents: 3715
diff changeset
   427
                    pass
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   428
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   429
        for f in deleted + removed:
3351
50a18815e3f0 Revert changeset c67920d78248.
Giorgos Keramidas <keramida@ceid.upatras.gr>
parents: 3319
diff changeset
   430
            if f in man:
50a18815e3f0 Revert changeset c67920d78248.
Giorgos Keramidas <keramida@ceid.upatras.gr>
parents: 3319
diff changeset
   431
                del man[f]
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   432
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   433
        self._manifest = man
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   434
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   435
    def manifest(self): return self._manifest
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   436
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   437
    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
   438
    def date(self): return util.makedate()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   439
    def description(self): return ""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   440
    def files(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   441
        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
   442
        f.sort()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   443
        return f
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   444
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   445
    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
   446
    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
   447
    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
   448
    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
   449
    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
   450
    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
   451
    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
   452
4663
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   453
    def tags(self):
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   454
        t = []
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   455
        [t.extend(p.tags()) for p in self.parents()]
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   456
        return t
6b2e8cb39583 context: add tags() method
Matt Mackall <mpm@selenic.com>
parents: 4640
diff changeset
   457
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   458
    def parents(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   459
        """return contexts for each parent changeset"""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   460
        return self._parents
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   461
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   462
    def children(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   463
        return []
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   464
3966
b4eaa68dea1b context: create a filectxt with filelog reuse
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3965
diff changeset
   465
    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
   466
        """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
   467
        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
   468
                              filelog=filelog)
3239
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 ancestor(self, c2):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   471
        """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
   472
        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
   473
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   474
class workingfilectx(filectx):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   475
    """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
   476
       file in the working directory convenient."""
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   477
    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
   478
        """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
   479
           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
   480
        self._repo = repo
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   481
        self._path = path
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   482
        self._changeid = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   483
        self._filerev = self._filenode = None
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
        if filelog:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   486
            self._filelog = filelog
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   487
        if workingctx:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   488
            self._changectx = workingctx
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   489
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   490
    def __getattr__(self, name):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   491
        if name == '_changectx':
4414
b6146466b92a context: fix workingfilectx._changectx
Matt Mackall <mpm@selenic.com>
parents: 4207
diff changeset
   492
            self._changectx = workingctx(self._repo)
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   493
            return self._changectx
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   494
        elif name == '_repopath':
3304
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   495
            self._repopath = (self._repo.dirstate.copied(self._path)
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   496
                              or self._path)
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   497
            return self._repopath
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   498
        elif name == '_filelog':
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   499
            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
   500
            return self._filelog
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   501
        else:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   502
            raise AttributeError, name
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   503
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   504
    def __nonzero__(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   505
        return True
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 __str__(self):
3319
6c68bc1e7873 context: change workingctx str() from . to <node>+
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
   508
        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
   509
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   510
    def filectx(self, fileid):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   511
        '''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
   512
        opening a new filelog'''
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   513
        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
   514
                       filelog=self._filelog)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   515
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   516
    def rev(self):
3334
e44eadc92ec4 context: check self.__dict__ instead of using hasattr
Brendan Cully <brendan@kublai.com>
parents: 3319
diff changeset
   517
        if '_changectx' in self.__dict__:
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   518
            return self._changectx.rev()
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   519
        return self._filelog.linkrev(self._filenode)
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   520
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   521
    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
   522
    def renamed(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   523
        rp = self._repopath
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   524
        if rp == self._path:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   525
            return None
3965
2e5161335e65 context: fix a bug in workingfilectx.renamed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3964
diff changeset
   526
        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
   527
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   528
    def parents(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   529
        '''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
   530
        p = self._path
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   531
        rp = self._repopath
3304
45f0c49f0449 fix workingfilectx parents and ancestor functions
Matt Mackall <mpm@selenic.com>
parents: 3242
diff changeset
   532
        pcl = self._changectx._parents
3239
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   533
        fl = self._filelog
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   534
        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
   535
        if len(pcl) > 1:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   536
            if rp != p:
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   537
                fl = None
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   538
            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
   539
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3578
diff changeset
   540
        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
   541
                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
   542
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   543
    def children(self):
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   544
        return []
6d98149d70fe contexts: add working dir and working file contexts
Matt Mackall <mpm@selenic.com>
parents: 3238
diff changeset
   545
3308
192085505f6f filectx: add size method
Matt Mackall <mpm@selenic.com>
parents: 3304
diff changeset
   546
    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
   547
    def date(self):
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   548
        t, tz = self._changectx.date()
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   549
        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
   550
            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
   551
        except OSError, err:
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   552
            if err.errno != errno.ENOENT: raise
2b8825c94c5a add date attribute to workingfilectx
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3961
diff changeset
   553
            return (t, tz)
3316
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   554
0e370798eebf context: add cmp for filectxs
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   555
    def cmp(self, text): return self._repo.wread(self._path) == text