mercurial/linelog.py
author Georges Racinet <georges.racinet@octobus.net>
Tue, 18 Feb 2020 19:11:15 +0100
changeset 44386 8f7c6656ac79
parent 44247 c443b9ba6f63
child 48875 6000f5b25c9b
permissions -rw-r--r--
rust-nodemap: pure Rust example To run, use `cargo run --release --example nodemap` This demonstrates that simple scenarios entirely written in Rust can content themselves with `NodeTree<T>`. The example mmaps both the nodemap file and the changelog index. We had of course to include an implementation of `RevlogIndex` directly, which isn't much at this stage. It felt a bit prematurate to include it in the lib. Here are some first performance measurements, obtained with this example, on a clone of mozilla-central with 440000 changesets: (create) Nodemap constructed in RAM in 153.638305ms (query CAE63161B68962) found in 22.362us: Ok(Some(269489)) (bench) Did 3 queries in 36.418µs (mean 12.139µs) (bench) Did 50 queries in 184.318µs (mean 3.686µs) (bench) Did 100000 queries in 31.053461ms (mean 310ns) To be fair, even between bench runs, results tend to depend whether the file is still in kernel caches, and it's not so easy to get back to a real cold start. The worst we've seen was in the 50us ballpark. In any busy server setting, the pages would always be in RAM. We hope it's good enough not to be significantly slower on any concrete Mercurial operation than the C nodetree when fully in RAM, and of course this implementation has the serious headstart advantage of persistence. Differential Revision: https://phab.mercurial-scm.org/D7797
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38795
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
43736
640bae94f2f3 cleanup: update references to /help/ that should now be /helptext/
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
    11
mercurial/helptext/internals/linelog.txt for an exploration of SCCS weaves
38795
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
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
    26
from .thirdparty import attr
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
    27
from . import pycompat
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    28
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    29
_llentry = struct.Struct(b'>II')
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    30
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
    31
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    32
class LineLogError(Exception):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    33
    """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
    34
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
    35
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    36
@attr.s
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    37
class lineinfo(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    38
    # Introducing revision of this line.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
    rev = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    40
    # 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
    41
    linenum = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
    # 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
    43
    _offset = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
    45
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
@attr.s
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    47
class annotateresult(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    48
    rev = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    49
    lines = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    50
    _eof = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    51
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    52
    def __iter__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
        return iter(self.lines)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    54
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
    55
43472
acc4047c2194 linelog: suppress annoying pytype warning about an ignored metaclass
Augie Fackler <augie@google.com>
parents: 43077
diff changeset
    56
class _llinstruction(object):  # pytype: disable=ignored-metaclass
38795
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
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
    93
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    94
class _jge(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    95
    """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
    96
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    97
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    98
        self._cmprev = op1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
    99
        self._target = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   100
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   101
    def __str__(self):
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43473
diff changeset
   102
        return 'JGE %d %d' % (self._cmprev, self._target)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   103
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   104
    def __eq__(self, other):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   105
        return (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   106
            type(self) == type(other)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   107
            and self._cmprev == other._cmprev
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   108
            and self._target == other._target
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   109
        )
38795
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 encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   112
        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
   113
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   114
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   115
        if rev >= self._cmprev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   116
            return self._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   117
        return pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   118
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   119
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   120
class _jump(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   121
    """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
   122
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   123
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   124
        if op1 != 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   125
            raise LineLogError(b"malformed JUMP, op1 must be 0, got %d" % op1)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   126
        self._target = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   127
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   128
    def __str__(self):
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43473
diff changeset
   129
        return 'JUMP %d' % (self._target)
38795
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 __eq__(self, other):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   132
        return type(self) == type(other) and self._target == other._target
38795
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 encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   135
        return _llentry.pack(0, 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
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   138
        return self._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   139
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   140
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   141
class _eof(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   142
    """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
   143
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   144
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   145
        if op1 != 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   146
            raise LineLogError(b"malformed EOF, op1 must be 0, got %d" % op1)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   147
        if op2 != 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   148
            raise LineLogError(b"malformed EOF, op2 must be 0, got %d" % op2)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   149
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   150
    def __str__(self):
38809
57af5ee15b35 linelog: port to Python 3
Augie Fackler <augie@google.com>
parents: 38796
diff changeset
   151
        return r'EOF'
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   152
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   153
    def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   154
        return type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   155
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   156
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   157
        return _llentry.pack(0, 0)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   158
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   159
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   160
        return None
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   161
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   162
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   163
class _jl(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   164
    """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
   165
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   166
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   167
        self._cmprev = op1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   168
        self._target = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   169
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   170
    def __str__(self):
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43473
diff changeset
   171
        return 'JL %d %d' % (self._cmprev, self._target)
38795
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 __eq__(self, other):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   174
        return (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   175
            type(self) == type(other)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   176
            and self._cmprev == other._cmprev
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   177
            and self._target == other._target
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   178
        )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   179
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   180
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   181
        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
   182
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   183
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   184
        if rev < self._cmprev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   185
            return self._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   186
        return pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   187
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   188
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   189
class _line(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   190
    """Emit a line."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   191
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   192
    def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   193
        # 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
   194
        self._rev = op1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   195
        # 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
   196
        self._origlineno = op2
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 __str__(self):
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43473
diff changeset
   199
        return 'LINE %d %d' % (self._rev, self._origlineno)
38795
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 __eq__(self, other):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   202
        return (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   203
            type(self) == type(other)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   204
            and self._rev == other._rev
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   205
            and self._origlineno == other._origlineno
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   206
        )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   207
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   208
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   209
        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
   210
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   211
    def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   212
        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
   213
        return pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   214
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   215
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   216
def _decodeone(data, offset):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   217
    """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
   218
    try:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   219
        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
   220
    except struct.error as e:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   221
        raise LineLogError(b'reading an instruction failed: %r' % e)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   222
    opcode = op1 & 0b11
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   223
    op1 = op1 >> 2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   224
    if opcode == 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   225
        if op1 == 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   226
            if op2 == 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   227
                return _eof(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   228
            return _jump(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   229
        return _jge(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   230
    elif opcode == 1:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   231
        return _jl(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   232
    elif opcode == 2:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   233
        return _line(op1, op2)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   234
    raise NotImplementedError(b'Unimplemented opcode %r' % opcode)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   235
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   236
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   237
class linelog(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   238
    """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
   239
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   240
    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
   241
        if program is None:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   242
            # 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
   243
            # 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
   244
            # interoperate with the C code.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   245
            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
   246
        self._program = program
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   247
        self._lastannotate = None
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   248
        self._maxrev = maxrev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   249
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   250
    def __eq__(self, other):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   251
        return (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   252
            type(self) == type(other)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   253
            and self._program == other._program
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   254
            and self._maxrev == other._maxrev
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   255
        )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   256
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   257
    def __repr__(self):
44247
c443b9ba6f63 py3: __repr__ needs to return str, not bytes
Kyle Lippincott <spectral@google.com>
parents: 43736
diff changeset
   258
        return '<linelog at %s: maxrev=%d size=%d>' % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   259
            hex(id(self)),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   260
            self._maxrev,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   261
            len(self._program),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   262
        )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   263
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   264
    def debugstr(self):
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43473
diff changeset
   265
        fmt = '%%%dd %%s' % len(str(len(self._program)))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   266
        return pycompat.sysstr(b'\n').join(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   267
            fmt % (idx, i) for idx, i in enumerate(self._program[1:], 1)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   268
        )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   269
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   270
    @classmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   271
    def fromdata(cls, buf):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   272
        if len(buf) % _llentry.size != 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   273
            raise LineLogError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   274
                b"invalid linelog buffer size %d (must be a multiple of %d)"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   275
                % (len(buf), _llentry.size)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   276
            )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   277
        expected = len(buf) / _llentry.size
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   278
        fakejge = _decodeone(buf, 0)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   279
        if isinstance(fakejge, _jump):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   280
            maxrev = 0
43473
14e374d4c9ee linelog: be more careful about types before looking for _target attribute
Augie Fackler <augie@google.com>
parents: 43472
diff changeset
   281
        elif isinstance(fakejge, (_jge, _jl)):
14e374d4c9ee linelog: be more careful about types before looking for _target attribute
Augie Fackler <augie@google.com>
parents: 43472
diff changeset
   282
            maxrev = fakejge._cmprev
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   283
        else:
43473
14e374d4c9ee linelog: be more careful about types before looking for _target attribute
Augie Fackler <augie@google.com>
parents: 43472
diff changeset
   284
            raise LineLogError(
14e374d4c9ee linelog: be more careful about types before looking for _target attribute
Augie Fackler <augie@google.com>
parents: 43472
diff changeset
   285
                'Expected one of _jump, _jge, or _jl. Got %s.'
14e374d4c9ee linelog: be more careful about types before looking for _target attribute
Augie Fackler <augie@google.com>
parents: 43472
diff changeset
   286
                % type(fakejge).__name__
14e374d4c9ee linelog: be more careful about types before looking for _target attribute
Augie Fackler <augie@google.com>
parents: 43472
diff changeset
   287
            )
14e374d4c9ee linelog: be more careful about types before looking for _target attribute
Augie Fackler <augie@google.com>
parents: 43472
diff changeset
   288
        assert isinstance(fakejge, (_jump, _jge, _jl))  # help pytype
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   289
        numentries = fakejge._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   290
        if expected != numentries:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   291
            raise LineLogError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   292
                b"corrupt linelog data: claimed"
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   293
                b" %d entries but given data for %d entries"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   294
                % (expected, numentries)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   295
            )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   296
        instructions = [_eof(0, 0)]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   297
        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
   298
            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
   299
        return cls(instructions, maxrev=maxrev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   300
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   301
    def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   302
        hdr = _jge(self._maxrev, len(self._program)).encode()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   303
        return hdr + b''.join(i.encode() for i in self._program[1:])
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   304
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   305
    def clear(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   306
        self._program = []
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   307
        self._maxrev = 0
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   308
        self._lastannotate = None
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   309
38924
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
   310
    def replacelines_vec(self, rev, a1, a2, blines):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   311
        return self.replacelines(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   312
            rev, a1, a2, 0, len(blines), _internal_blines=blines
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   313
        )
38924
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
   314
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
   315
    def replacelines(self, rev, a1, a2, b1, b2, _internal_blines=None):
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   316
        """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
   317
        if self._lastannotate:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   318
            # 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
   319
            # 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
   320
            # 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
   321
            # 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
   322
            # 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
   323
            ar = self._lastannotate
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   324
        else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   325
            ar = self.annotate(rev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   326
            #        ar = self.annotate(self._maxrev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   327
        if a1 > len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   328
            raise LineLogError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   329
                b'%d contains %d lines, tried to access line %d'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   330
                % (rev, len(ar.lines), a1)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   331
            )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   332
        elif a1 == len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   333
            # 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
   334
            # doesn't have a "real" line.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   335
            a1inst = _eof(0, 0)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   336
            a1info = lineinfo(0, 0, ar._eof)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   337
        else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   338
            a1info = ar.lines[a1]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   339
            a1inst = self._program[a1info._offset]
38970
32b1967b8734 linelog: extract `len(self._program)` to a local function
Jun Wu <quark@fb.com>
parents: 38962
diff changeset
   340
        programlen = self._program.__len__
32b1967b8734 linelog: extract `len(self._program)` to a local function
Jun Wu <quark@fb.com>
parents: 38962
diff changeset
   341
        oldproglen = programlen()
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   342
        appendinst = self._program.append
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   343
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   344
        # insert
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   345
        blineinfos = []
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   346
        bappend = blineinfos.append
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   347
        if b1 < b2:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   348
            # 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
   349
            # the new block.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   350
            tgt = oldproglen + (b2 - b1 + 1)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   351
            # 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
   352
            appendinst(_jl(rev, tgt))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   353
            for linenum in pycompat.xrange(b1, b2):
38924
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
   354
                if _internal_blines is None:
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   355
                    bappend(lineinfo(rev, linenum, programlen()))
38924
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
   356
                    appendinst(_line(rev, linenum))
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
   357
                else:
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   358
                    newrev, newlinenum = _internal_blines[linenum]
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   359
                    bappend(lineinfo(newrev, newlinenum, programlen()))
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   360
                    appendinst(_line(newrev, newlinenum))
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   361
        # delete
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   362
        if a1 < a2:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   363
            if a2 > len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   364
                raise LineLogError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   365
                    b'%d contains %d lines, tried to access line %d'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   366
                    % (rev, len(ar.lines), a2)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   367
                )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   368
            elif a2 == len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   369
                endaddr = ar._eof
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   370
            else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   371
                endaddr = ar.lines[a2]._offset
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   372
            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
   373
                # 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
   374
                # 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
   375
                # 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
   376
                # are added later).
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   377
                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
   378
            appendinst(_jge(rev, endaddr))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   379
        # copy instruction from a1
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   380
        a1instpc = programlen()
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   381
        appendinst(a1inst)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   382
        # 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
   383
        # jump back into the program here.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   384
        if not isinstance(a1inst, (_jump, _eof)):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   385
            appendinst(_jump(0, a1info._offset + 1))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   386
        # 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
   387
        self._program[a1info._offset] = _jump(0, oldproglen)
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   388
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   389
        # Update self._lastannotate in place. This serves as a cache to avoid
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   390
        # expensive "self.annotate" in this function, when "replacelines" is
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   391
        # used continuously.
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   392
        if len(self._lastannotate.lines) > a1:
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   393
            self._lastannotate.lines[a1]._offset = a1instpc
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   394
        else:
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   395
            assert isinstance(a1inst, _eof)
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   396
            self._lastannotate._eof = a1instpc
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   397
        self._lastannotate.lines[a1:a2] = blineinfos
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   398
        self._lastannotate.rev = max(self._lastannotate.rev, rev)
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
   399
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   400
        if rev > self._maxrev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   401
            self._maxrev = rev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   402
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   403
    def annotate(self, rev):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   404
        pc = 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   405
        lines = []
38935
27a54096c92e linelog: fix infinite loop vulnerability
Jun Wu <quark@fb.com>
parents: 38924
diff changeset
   406
        executed = 0
27a54096c92e linelog: fix infinite loop vulnerability
Jun Wu <quark@fb.com>
parents: 38924
diff changeset
   407
        # Sanity check: if instructions executed exceeds len(program), we
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   408
        # 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
   409
        # should stop.
38935
27a54096c92e linelog: fix infinite loop vulnerability
Jun Wu <quark@fb.com>
parents: 38924
diff changeset
   410
        while pc is not None and executed < len(self._program):
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   411
            inst = self._program[pc]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   412
            lastpc = pc
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   413
            pc = inst.execute(rev, pc, lines.append)
38935
27a54096c92e linelog: fix infinite loop vulnerability
Jun Wu <quark@fb.com>
parents: 38924
diff changeset
   414
            executed += 1
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   415
        if pc is not None:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   416
            raise LineLogError(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   417
                r'Probably hit an infinite loop in linelog. Program:\n'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   418
                + self.debugstr()
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38971
diff changeset
   419
            )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   420
        ar = annotateresult(rev, lines, lastpc)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   421
        self._lastannotate = ar
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   422
        return ar
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   423
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   424
    @property
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   425
    def maxrev(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   426
        return self._maxrev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   427
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   428
    # 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
   429
    # 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
   430
    # 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
   431
    @property
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   432
    def annotateresult(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   433
        """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
   434
        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
   435
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   436
    def getoffset(self, line):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   437
        return self._lastannotate.lines[line]._offset
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   438
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   439
    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
   440
        """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
   441
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   442
        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
   443
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   444
        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
   445
        """
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   446
        pc = start or 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   447
        lines = []
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   448
        # 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
   449
        # 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
   450
        # then, something is badly broken.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   451
        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
   452
            inst = self._program[pc]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   453
            nextpc = pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   454
            if isinstance(inst, _jump):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   455
                nextpc = inst._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   456
            elif isinstance(inst, _eof):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   457
                return lines
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   458
            elif isinstance(inst, (_jl, _jge)):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   459
                pass
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   460
            elif isinstance(inst, _line):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   461
                lines.append((inst._rev, inst._origlineno))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   462
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   463
                raise LineLogError(b"Illegal instruction %r" % inst)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   464
            if nextpc == end:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   465
                return lines
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
   466
            pc = nextpc
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   467
        raise LineLogError(b"Failed to perform getalllines")