1# revlogv0 - code related to revlog format "V0"
2#
3# Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
4#
5# This software may be used and distributed according to the terms of the
6# GNU General Public License version 2 or any later version.
7from __future__ import absolute_import
8
9
10from ..node import sha1nodeconstants
11from .constants import (
12    INDEX_ENTRY_V0,
13)
14from ..i18n import _
15
16from .. import (
17    error,
18    node,
19    pycompat,
20    revlogutils,
21    util,
22)
23
24from . import (
25    nodemap as nodemaputil,
26)
27
28
29def getoffset(q):
30    return int(q >> 16)
31
32
33def gettype(q):
34    return int(q & 0xFFFF)
35
36
37class revlogoldindex(list):
38    rust_ext_compat = 0
39    entry_size = INDEX_ENTRY_V0.size
40    null_item = revlogutils.entry(
41        data_offset=0,
42        data_compressed_length=0,
43        data_delta_base=node.nullrev,
44        link_rev=node.nullrev,
45        parent_rev_1=node.nullrev,
46        parent_rev_2=node.nullrev,
47        node_id=sha1nodeconstants.nullid,
48    )
49
50    @property
51    def nodemap(self):
52        msg = b"index.nodemap is deprecated, use index.[has_node|rev|get_rev]"
53        util.nouideprecwarn(msg, b'5.3', stacklevel=2)
54        return self._nodemap
55
56    @util.propertycache
57    def _nodemap(self):
58        nodemap = nodemaputil.NodeMap({sha1nodeconstants.nullid: node.nullrev})
59        for r in range(0, len(self)):
60            n = self[r][7]
61            nodemap[n] = r
62        return nodemap
63
64    def has_node(self, node):
65        """return True if the node exist in the index"""
66        return node in self._nodemap
67
68    def rev(self, node):
69        """return a revision for a node
70
71        If the node is unknown, raise a RevlogError"""
72        return self._nodemap[node]
73
74    def get_rev(self, node):
75        """return a revision for a node
76
77        If the node is unknown, return None"""
78        return self._nodemap.get(node)
79
80    def append(self, tup):
81        self._nodemap[tup[7]] = len(self)
82        super(revlogoldindex, self).append(tup)
83
84    def __delitem__(self, i):
85        if not isinstance(i, slice) or not i.stop == -1 or i.step is not None:
86            raise ValueError(b"deleting slices only supports a:-1 with step 1")
87        for r in pycompat.xrange(i.start, len(self)):
88            del self._nodemap[self[r][7]]
89        super(revlogoldindex, self).__delitem__(i)
90
91    def clearcaches(self):
92        self.__dict__.pop('_nodemap', None)
93
94    def __getitem__(self, i):
95        if i == -1:
96            return self.null_item
97        return list.__getitem__(self, i)
98
99    def pack_header(self, header):
100        """pack header information in binary"""
101        return b''
102
103    def entry_binary(self, rev):
104        """return the raw binary string representing a revision"""
105        entry = self[rev]
106        if gettype(entry[0]):
107            raise error.RevlogError(
108                _(b'index entry flags need revlog version 1')
109            )
110        e2 = (
111            getoffset(entry[0]),
112            entry[1],
113            entry[3],
114            entry[4],
115            self[entry[5]][7],
116            self[entry[6]][7],
117            entry[7],
118        )
119        return INDEX_ENTRY_V0.pack(*e2)
120
121
122def parse_index_v0(data, inline):
123    s = INDEX_ENTRY_V0.size
124    index = []
125    nodemap = nodemaputil.NodeMap({node.nullid: node.nullrev})
126    n = off = 0
127    l = len(data)
128    while off + s <= l:
129        cur = data[off : off + s]
130        off += s
131        e = INDEX_ENTRY_V0.unpack(cur)
132        # transform to revlogv1 format
133        e2 = revlogutils.entry(
134            data_offset=e[0],
135            data_compressed_length=e[1],
136            data_delta_base=e[2],
137            link_rev=e[3],
138            parent_rev_1=nodemap.get(e[4], node.nullrev),
139            parent_rev_2=nodemap.get(e[5], node.nullrev),
140            node_id=e[6],
141        )
142        index.append(e2)
143        nodemap[e[6]] = n
144        n += 1
145
146    index = revlogoldindex(index)
147    return index, None
148