mercurial/linelog.py
author Gregory Szorc <gregory.szorc@gmail.com>
Sat, 28 Jul 2018 17:42:36 -0700
changeset 38848 d99083996398
parent 38836 f956dc7217fc
child 38849 57af5ee15b35
permissions -rw-r--r--
exchange: move simple narrow changegroup generation from extension The narrow extension completely replaced the function generating the changegroup part when a narrow changegroup was requested. Previous commits have taught the in-core changegroup code how to filter files based on a matcher. This commit teaches the in-core bundle2 part generation code to construct a matcher based on arguments. It will also emit a bundle2 part describing the narrow spec. I believe the changegroup part generation code in the narrow extension is now limited to ellipsis serving mode. i.e. core is now capable of narrow changegroup generation when ellipsis mode is disabled. Differential Revision: https://phab.mercurial-scm.org/D4014
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38835
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
     1
# linelog - efficient cache for annotate data
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
     2
#
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
     3
# Copyright 2018 Google LLC.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
     4
#
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
     7
"""linelog is an efficient cache for annotate data inspired by SCCS Weaves.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
     8
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
     9
SCCS Weaves are an implementation of
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    10
https://en.wikipedia.org/wiki/Interleaved_deltas. See
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    11
mercurial/help/internals/linelog.txt for an exploration of SCCS weaves
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    12
and how linelog works in detail.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    13
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    14
Here's a hacker's summary: a linelog is a program which is executed in
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    15
the context of a revision. Executing the program emits information
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    16
about lines, including the revision that introduced them and the line
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    17
number in the file at the introducing revision. When an insertion or
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    18
deletion is performed on the file, a jump instruction is used to patch
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    19
in a new body of annotate information.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    20
"""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    21
from __future__ import absolute_import, print_function
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    22
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    23
import abc
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    24
import struct
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    25
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    26
from .thirdparty import (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    27
    attr,
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    28
)
38836
f956dc7217fc linelog: fix import statements to pass the import checker on py3
Augie Fackler <augie@google.com>
parents: 38835
diff changeset
    29
from . import (
f956dc7217fc linelog: fix import statements to pass the import checker on py3
Augie Fackler <augie@google.com>
parents: 38835
diff changeset
    30
    pycompat,
f956dc7217fc linelog: fix import statements to pass the import checker on py3
Augie Fackler <augie@google.com>
parents: 38835
diff changeset
    31
)
38835
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    32
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    33
_llentry = struct.Struct('>II')
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    34
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    35
class LineLogError(Exception):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    36
    """Error raised when something bad happens internally in linelog."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    37
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    38
@attr.s
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
class lineinfo(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    40
    # Introducing revision of this line.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    41
    rev = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
    # Line number for this line in its introducing revision.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    43
    linenum = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
    # Private. Offset in the linelog program of this line. Used internally.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    45
    _offset = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    47
@attr.s
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    48
class annotateresult(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    49
    rev = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    50
    lines = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    51
    _eof = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    52
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
    def __iter__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    54
        return iter(self.lines)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    55
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    56
class _llinstruction(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    57
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    58
    __metaclass__ = abc.ABCMeta
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    59
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    60
    @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    61
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    62
        pass
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    63
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    64
    @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    65
    def __str__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    66
        pass
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    67
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    68
    def __repr__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    69
        return str(self)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    70
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    71
    @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    72
    def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    73
        pass
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    74
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    75
    @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    76
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    77
        """Encode this instruction to the binary linelog format."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    78
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    79
    @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    80
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    81
        """Execute this instruction.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    82
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    83
        Args:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    84
          rev: The revision we're annotating.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    85
          pc: The current offset in the linelog program.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    86
          emit: A function that accepts a single lineinfo object.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    87
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    88
        Returns:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    89
          The new value of pc. Returns None if exeuction should stop
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    90
          (that is, we've found the end of the file.)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    91
        """
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    92
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    93
class _jge(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    94
    """If the current rev is greater than or equal to op1, jump to op2."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    95
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    96
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    97
        self._cmprev = op1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    98
        self._target = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    99
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   100
    def __str__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   101
        return 'JGE %d %d' % (self._cmprev, self._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   102
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   103
    def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   104
        return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   105
                and self._cmprev == other._cmprev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   106
                and self._target == other._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   107
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   108
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   109
        return _llentry.pack(self._cmprev << 2, self._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   110
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   111
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   112
        if rev >= self._cmprev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   113
            return self._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   114
        return pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   115
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   116
class _jump(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   117
    """Unconditional jumps are expressed as a JGE with op1 set to 0."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   118
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   119
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   120
        if op1 != 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   121
            raise LineLogError("malformed JUMP, op1 must be 0, got %d" % op1)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   122
        self._target = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   123
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   124
    def __str__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   125
        return 'JUMP %d' % (self._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   126
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   127
    def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   128
        return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   129
                and self._target == other._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   130
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   131
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   132
        return _llentry.pack(0, self._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   133
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   134
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   135
        return self._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   136
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   137
class _eof(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   138
    """EOF is expressed as a JGE that always jumps to 0."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   139
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   140
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   141
        if op1 != 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   142
            raise LineLogError("malformed EOF, op1 must be 0, got %d" % op1)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   143
        if op2 != 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   144
            raise LineLogError("malformed EOF, op2 must be 0, got %d" % op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   145
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   146
    def __str__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   147
        return 'EOF'
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   148
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   149
    def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   150
        return type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   151
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   152
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   153
        return _llentry.pack(0, 0)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   154
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   155
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   156
        return None
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   157
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   158
class _jl(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   159
    """If the current rev is less than op1, jump to op2."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   160
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   161
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   162
        self._cmprev = op1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   163
        self._target = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   164
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   165
    def __str__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   166
        return 'JL %d %d' % (self._cmprev, self._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   167
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   168
    def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   169
        return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   170
                and self._cmprev == other._cmprev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   171
                and self._target == other._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   172
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   173
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   174
        return _llentry.pack(1 | (self._cmprev << 2), self._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   175
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   176
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   177
        if rev < self._cmprev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   178
            return self._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   179
        return pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   180
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   181
class _line(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   182
    """Emit a line."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   183
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   184
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   185
        # This line was introduced by this revision number.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   186
        self._rev = op1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   187
        # This line had the specified line number in the introducing revision.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   188
        self._origlineno = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   189
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   190
    def __str__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   191
        return 'LINE %d %d' % (self._rev, self._origlineno)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   192
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   193
    def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   194
        return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   195
                and self._rev == other._rev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   196
                and self._origlineno == other._origlineno)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   197
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   198
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   199
        return _llentry.pack(2 | (self._rev << 2), self._origlineno)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   200
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   201
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   202
        emit(lineinfo(self._rev, self._origlineno, pc))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   203
        return pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   204
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   205
def _decodeone(data, offset):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   206
    """Decode a single linelog instruction from an offset in a buffer."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   207
    try:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   208
        op1, op2 = _llentry.unpack_from(data, offset)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   209
    except struct.error as e:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   210
        raise LineLogError('reading an instruction failed: %r' % e)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   211
    opcode = op1 & 0b11
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   212
    op1 = op1 >> 2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   213
    if opcode == 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   214
        if op1 == 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   215
            if op2 == 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   216
                return _eof(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   217
            return _jump(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   218
        return _jge(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   219
    elif opcode == 1:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   220
        return _jl(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   221
    elif opcode == 2:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   222
        return _line(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   223
    raise NotImplementedError('Unimplemented opcode %r' % opcode)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   224
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   225
class linelog(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   226
    """Efficient cache for per-line history information."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   227
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   228
    def __init__(self, program=None, maxrev=0):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   229
        if program is None:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   230
            # We pad the program with an extra leading EOF so that our
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   231
            # offsets will match the C code exactly. This means we can
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   232
            # interoperate with the C code.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   233
            program = [_eof(0, 0), _eof(0, 0)]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   234
        self._program = program
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   235
        self._lastannotate = None
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   236
        self._maxrev = maxrev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   237
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   238
    def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   239
        return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   240
                and self._program == other._program
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   241
                and self._maxrev == other._maxrev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   242
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   243
    def __repr__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   244
        return '<linelog at %s: maxrev=%d size=%d>' % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   245
            hex(id(self)), self._maxrev, len(self._program))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   246
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   247
    def debugstr(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   248
        fmt = '%%%dd %%s' % len(str(len(self._program)))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   249
        return '\n'.join(
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   250
            fmt % (idx, i) for idx, i in enumerate(self._program[1:], 1))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   251
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   252
    @classmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   253
    def fromdata(cls, buf):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   254
        if len(buf) % _llentry.size != 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   255
            raise LineLogError(
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   256
                "invalid linelog buffer size %d (must be a multiple of %d)" % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   257
                    len(buf), _llentry.size))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   258
        expected = len(buf) / _llentry.size
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   259
        fakejge = _decodeone(buf, 0)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   260
        if isinstance(fakejge, _jump):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   261
            maxrev = 0
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   262
        else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   263
            maxrev = fakejge._cmprev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   264
        numentries = fakejge._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   265
        if expected != numentries:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   266
            raise LineLogError("corrupt linelog data: claimed"
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   267
                               " %d entries but given data for %d entries" % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   268
                                   expected, numentries))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   269
        instructions = [_eof(0, 0)]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   270
        for offset in pycompat.xrange(1, numentries):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   271
            instructions.append(_decodeone(buf, offset * _llentry.size))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   272
        return cls(instructions, maxrev=maxrev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   273
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   274
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   275
        hdr = _jge(self._maxrev, len(self._program)).encode()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   276
        return hdr + ''.join(i.encode() for i in self._program[1:])
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   277
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   278
    def clear(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   279
        self._program = []
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   280
        self._maxrev = 0
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   281
        self._lastannotate = None
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   282
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   283
    def replacelines(self, rev, a1, a2, b1, b2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   284
        """Replace lines [a1, a2) with lines [b1, b2)."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   285
        if self._lastannotate:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   286
            # TODO(augie): make replacelines() accept a revision at
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   287
            # which we're editing as well as a revision to mark
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   288
            # responsible for the edits. In hg-experimental it's
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   289
            # stateful like this, so we're doing the same thing to
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   290
            # retain compatibility with absorb until that's imported.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   291
            ar = self._lastannotate
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   292
        else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   293
            ar = self.annotate(rev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   294
            #        ar = self.annotate(self._maxrev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   295
        if a1 > len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   296
            raise LineLogError(
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   297
                '%d contains %d lines, tried to access line %d' % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   298
                    rev, len(ar.lines), a1))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   299
        elif a1 == len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   300
            # Simulated EOF instruction since we're at EOF, which
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   301
            # doesn't have a "real" line.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   302
            a1inst = _eof(0, 0)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   303
            a1info = lineinfo(0, 0, ar._eof)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   304
        else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   305
            a1info = ar.lines[a1]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   306
            a1inst = self._program[a1info._offset]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   307
        oldproglen = len(self._program)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   308
        appendinst = self._program.append
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   309
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   310
        # insert
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   311
        if b1 < b2:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   312
            # Determine the jump target for the JGE at the start of
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   313
            # the new block.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   314
            tgt = oldproglen + (b2 - b1 + 1)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   315
            # Jump to skip the insert if we're at an older revision.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   316
            appendinst(_jl(rev, tgt))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   317
            for linenum in pycompat.xrange(b1, b2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   318
                appendinst(_line(rev, linenum))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   319
        # delete
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   320
        if a1 < a2:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   321
            if a2 > len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   322
                raise LineLogError(
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   323
                    '%d contains %d lines, tried to access line %d' % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   324
                        rev, len(ar.lines), a2))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   325
            elif a2 == len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   326
                endaddr = ar._eof
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   327
            else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   328
                endaddr = ar.lines[a2]._offset
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   329
            if a2 > 0 and rev < self._maxrev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   330
                # If we're here, we're deleting a chunk of an old
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   331
                # commit, so we need to be careful and not touch
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   332
                # invisible lines between a2-1 and a2 (IOW, lines that
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   333
                # are added later).
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   334
                endaddr = ar.lines[a2 - 1]._offset + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   335
            appendinst(_jge(rev, endaddr))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   336
        # copy instruction from a1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   337
        appendinst(a1inst)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   338
        # if a1inst isn't a jump or EOF, then we need to add an unconditional
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   339
        # jump back into the program here.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   340
        if not isinstance(a1inst, (_jump, _eof)):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   341
            appendinst(_jump(0, a1info._offset + 1))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   342
        # Patch instruction at a1, which makes our patch live.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   343
        self._program[a1info._offset] = _jump(0, oldproglen)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   344
        # For compat with the C version, re-annotate rev so that
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   345
        # self.annotateresult is cromulent.. We could fix up the
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   346
        # annotateresult in place (which is how the C version works),
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   347
        # but for now we'll pass on that and see if it matters in
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   348
        # practice.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   349
        self.annotate(max(self._lastannotate.rev, rev))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   350
        if rev > self._maxrev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   351
            self._maxrev = rev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   352
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   353
    def annotate(self, rev):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   354
        pc = 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   355
        lines = []
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   356
        # Sanity check: if len(lines) is longer than len(program), we
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   357
        # hit an infinite loop in the linelog program somehow and we
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   358
        # should stop.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   359
        while pc is not None and len(lines) < len(self._program):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   360
            inst = self._program[pc]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   361
            lastpc = pc
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   362
            pc = inst.execute(rev, pc, lines.append)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   363
        if pc is not None:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   364
            raise LineLogError(
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   365
                'Probably hit an infinite loop in linelog. Program:\n' +
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   366
                self.debugstr())
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   367
        ar = annotateresult(rev, lines, lastpc)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   368
        self._lastannotate = ar
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   369
        return ar
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   370
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   371
    @property
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   372
    def maxrev(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   373
        return self._maxrev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   374
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   375
    # Stateful methods which depend on the value of the last
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   376
    # annotation run. This API is for compatiblity with the original
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   377
    # linelog, and we should probably consider refactoring it.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   378
    @property
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   379
    def annotateresult(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   380
        """Return the last annotation result. C linelog code exposed this."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   381
        return [(l.rev, l.linenum) for l in self._lastannotate.lines]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   382
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   383
    def getoffset(self, line):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   384
        return self._lastannotate.lines[line]._offset
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   385
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   386
    def getalllines(self, start=0, end=0):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   387
        """Get all lines that ever occurred in [start, end).
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   388
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   389
        Passing start == end == 0 means "all lines ever".
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   390
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   391
        This works in terms of *internal* program offsets, not line numbers.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   392
        """
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   393
        pc = start or 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   394
        lines = []
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   395
        # only take as many steps as there are instructions in the
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   396
        # program - if we don't find an EOF or our stop-line before
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   397
        # then, something is badly broken.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   398
        for step in pycompat.xrange(len(self._program)):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   399
            inst = self._program[pc]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   400
            nextpc = pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   401
            if isinstance(inst, _jump):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   402
                nextpc = inst._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   403
            elif isinstance(inst, _eof):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   404
                return lines
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   405
            elif isinstance(inst, (_jl, _jge)):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   406
                pass
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   407
            elif isinstance(inst, _line):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   408
                lines.append((inst._rev, inst._origlineno))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   409
            else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   410
                raise LineLogError("Illegal instruction %r" % inst)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   411
            if nextpc == end:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   412
                return lines
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   413
            pc = nextpc
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   414
        raise LineLogError("Failed to perform getalllines")