This file is indexed.

/usr/lib/python2.7/dist-packages/cvs2svn_lib/rcs_stream.py is in cvs2svn 2.4.0-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# (Be in -*- python -*- mode.)
#
# ====================================================================
# Copyright (c) 2007 CollabNet.  All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.  The terms
# are also available at http://subversion.tigris.org/license-1.html.
# If newer versions of this license are posted there, you may use a
# newer version instead, at your option.
#
# This software consists of voluntary contributions made by many
# individuals.  For exact contribution history, see the revision
# history and logs, available at http://cvs2svn.tigris.org/.
# ====================================================================

"""This module processes RCS diffs (deltas)."""


from cStringIO import StringIO
import re


def msplit(s):
  """Split S into an array of lines.

  Only \n is a line separator. The line endings are part of the lines."""

  # return s.splitlines(True) clobbers \r
  re = [ i + "\n" for i in s.split("\n") ]
  re[-1] = re[-1][:-1]
  if not re[-1]:
    del re[-1]
  return re


class MalformedDeltaException(Exception):
  """A malformed RCS delta was encountered."""

  pass


ed_command_re = re.compile(r'^([ad])(\d+)\s(\d+)\n$')


def generate_edits(diff):
  """Generate edit commands from an RCS diff block.

  DIFF is a string holding an entire RCS file delta.  Generate a tuple
  (COMMAND, INPUT_POS, ARG) for each block implied by DIFF.  Tuples
  describe the ed commands:

      ('a', INPUT_POS, LINES) : add LINES at INPUT_POS.  LINES is a
          list of strings.

      ('d', INPUT_POS, COUNT) : delete COUNT input lines starting at
          line INPUT_POS.

  In all cases, INPUT_POS is expressed as a zero-offset line number
  within the input revision."""

  diff = msplit(diff)
  i = 0

  while i < len(diff):
    m = ed_command_re.match(diff[i])
    if not m:
      raise MalformedDeltaException('Bad ed command')
    i += 1
    command = m.group(1)
    start = int(m.group(2))
    count = int(m.group(3))
    if command == 'd':
      # "d" - Delete command
      yield ('d', start - 1, count)
    else:
      # "a" - Add command
      if i + count > len(diff):
        raise MalformedDeltaException('Add block truncated')
      yield ('a', start, diff[i:i + count])
      i += count


def merge_blocks(blocks):
  """Merge adjacent 'r'eplace or 'c'opy blocks."""

  i = iter(blocks)

  try:
    (command1, old_lines1, new_lines1) = i.next()
  except StopIteration:
    return

  for (command2, old_lines2, new_lines2) in i:
    if command1 == 'r' and command2 == 'r':
      old_lines1 += old_lines2
      new_lines1 += new_lines2
    elif command1 == 'c' and command2 == 'c':
      old_lines1 += old_lines2
      new_lines1 = old_lines1
    else:
      yield (command1, old_lines1, new_lines1)
      (command1, old_lines1, new_lines1) = (command2, old_lines2, new_lines2)

  yield (command1, old_lines1, new_lines1)


def invert_blocks(blocks):
  """Invert the blocks in BLOCKS.

  BLOCKS is an iterable over blocks.  Invert them, in the sense that
  the input becomes the output and the output the input."""

  for (command, old_lines, new_lines) in blocks:
    yield (command, new_lines, old_lines)


def generate_edits_from_blocks(blocks):
  """Convert BLOCKS into an equivalent series of RCS edits.

  The edits are generated as tuples in the format described in the
  docstring for generate_edits().

  It is important that deletes are emitted before adds in the output
  for two reasons:

  1. The last line in the last 'add' block might end in a line that is
     not terminated with a newline, in which case no other command is
     allowed to follow it.

  2. This is the canonical order used by RCS; this ensures that
     inverting twice gives back the original delta."""

  # Merge adjacent 'r'eplace blocks to ensure that we emit adds and
  # deletes in the right order:
  blocks = merge_blocks(blocks)

  input_position = 0
  for (command, old_lines, new_lines) in blocks:
    if command == 'c':
      input_position += len(old_lines)
    elif command == 'r':
      if old_lines:
        yield ('d', input_position, len(old_lines))
        input_position += len(old_lines)
      if new_lines:
        yield ('a', input_position, new_lines)


def write_edits(f, edits):
  """Write EDITS to file-like object f as an RCS diff."""

  for (command, input_position, arg) in edits:
    if command == 'd':
      f.write('d%d %d\n' % (input_position + 1, arg,))
    elif command == 'a':
      lines = arg
      f.write('a%d %d\n' % (input_position, len(lines),))
      f.writelines(lines)
      del lines
    else:
      raise MalformedDeltaException('Unknown command %r' % (command,))


class RCSStream:
  """This class allows RCS deltas to be accumulated.

  This file holds the contents of a single RCS version in memory as an
  array of lines.  It is able to apply an RCS delta to the version,
  thereby transforming the stored text into the following RCS version.
  While doing so, it can optionally also return the inverted delta.

  This class holds revisions in memory.  It uses temporary memory
  space of a few times the size of a single revision plus a few times
  the size of a single delta."""

  def __init__(self, text):
    """Instantiate and initialize the file content with TEXT."""

    self.set_text(text)

  def get_text(self):
    """Return the current file content."""

    return "".join(self._lines)

  def set_lines(self, lines):
    """Set the current contents to the specified LINES.

    LINES is an iterable over well-formed lines; i.e., each line
    contains exactly one LF as its last character, except that the
    list line can be unterminated.  LINES will be consumed
    immediately; if it is a sequence, it will be copied."""

    self._lines = list(lines)

  def set_text(self, text):
    """Set the current file content."""

    self._lines = msplit(text)

  def generate_blocks(self, edits):
    """Generate edit blocks from an iterable of RCS edits.

    EDITS is an iterable over RCS edits, as generated by
    generate_edits().  Generate a tuple (COMMAND, OLD_LINES,
    NEW_LINES) for each block implied by EDITS when applied to the
    current contents of SELF.  OLD_LINES and NEW_LINES are lists of
    strings, where each string is one line.  OLD_LINES and NEW_LINES
    are newly-allocated lists, though they might both point at the
    same list.  Blocks consist of copy and replace commands:

        ('c', OLD_LINES, NEW_LINES) : copy the lines from one version
            to the other, unaltered.  In this case
            OLD_LINES==NEW_LINES.

        ('r', OLD_LINES, NEW_LINES) : replace OLD_LINES with
            NEW_LINES.  Either OLD_LINES or NEW_LINES (or both) might
            be empty."""

    # The number of lines from the old version that have been processed
    # so far:
    input_pos = 0

    for (command, start, arg) in edits:
      if command == 'd':
        # "d" - Delete command
        count = arg
        if start < input_pos:
          raise MalformedDeltaException('Deletion before last edit')
        if start > len(self._lines):
          raise MalformedDeltaException('Deletion past file end')
        if start + count > len(self._lines):
          raise MalformedDeltaException('Deletion beyond file end')

        if input_pos < start:
          copied_lines = self._lines[input_pos:start]
          yield ('c', copied_lines, copied_lines)
          del copied_lines
        yield ('r', self._lines[start:start + count], [])
        input_pos = start + count
      else:
        # "a" - Add command
        lines = arg
        if start < input_pos:
          raise MalformedDeltaException('Insertion before last edit')
        if start > len(self._lines):
          raise MalformedDeltaException('Insertion past file end')

        if input_pos < start:
          copied_lines = self._lines[input_pos:start]
          yield ('c', copied_lines, copied_lines)
          del copied_lines
          input_pos = start
        yield ('r', [], lines)

    # Pass along the part of the input that follows all of the delta
    # blocks:
    copied_lines = self._lines[input_pos:]
    if copied_lines:
      yield ('c', copied_lines, copied_lines)

  def apply_diff(self, diff):
    """Apply the RCS diff DIFF to the current file content."""

    lines = []

    blocks = self.generate_blocks(generate_edits(diff))
    for (command, old_lines, new_lines) in blocks:
      lines += new_lines

    self._lines = lines

  def apply_and_invert_edits(self, edits):
    """Apply EDITS and generate their inverse.

    Apply EDITS to the current file content.  Simultaneously generate
    edits suitable for reverting the change."""

    blocks = self.generate_blocks(edits)

    # Blocks have to be merged so that adjacent delete,add edits are
    # generated in that order:
    blocks = merge_blocks(blocks)

    # Convert the iterable into a list (1) so that we can modify
    # self._lines in-place, (2) because we need it twice.
    blocks = list(blocks)

    self._lines = []
    for (command, old_lines, new_lines) in blocks:
      self._lines += new_lines

    return generate_edits_from_blocks(invert_blocks(blocks))

  def invert_diff(self, diff):
    """Apply DIFF and generate its inverse.

    Apply the RCS diff DIFF to the current file content.
    Simultaneously generate an RCS diff suitable for reverting the
    change, and return it as a string."""

    inverse_diff = StringIO()
    write_edits(
        inverse_diff, self.apply_and_invert_edits(generate_edits(diff))
        )
    return inverse_diff.getvalue()