/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/patches.py

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004 - 2006, 2008 Aaron Bentley, Canonical Ltd
 
1
# Copyright (C) 2005-2010 Aaron Bentley, Canonical Ltd
2
2
# <aaron.bentley@utoronto.ca>
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
17
17
import re
18
18
 
19
19
 
 
20
binary_files_re = 'Binary files (.*) and (.*) differ\n'
 
21
 
 
22
 
20
23
class BinaryFiles(Exception):
21
24
 
22
25
    def __init__(self, orig_name, mod_name):
66
69
def get_patch_names(iter_lines):
67
70
    try:
68
71
        line = iter_lines.next()
69
 
        match = re.match('Binary files (.*) and (.*) differ\n', line)
 
72
        match = re.match(binary_files_re, line)
70
73
        if match is not None:
71
74
            raise BinaryFiles(match.group(1), match.group(2))
72
75
        if not line.startswith("--- "):
247
250
        return shift
248
251
 
249
252
 
250
 
def iter_hunks(iter_lines):
 
253
def iter_hunks(iter_lines, allow_dirty=False):
 
254
    '''
 
255
    :arg iter_lines: iterable of lines to parse for hunks
 
256
    :kwarg allow_dirty: If True, when we encounter something that is not
 
257
        a hunk header when we're looking for one, assume the rest of the lines
 
258
        are not part of the patch (comments or other junk).  Default False
 
259
    '''
251
260
    hunk = None
252
261
    for line in iter_lines:
253
262
        if line == "\n":
257
266
            continue
258
267
        if hunk is not None:
259
268
            yield hunk
260
 
        hunk = hunk_from_header(line)
 
269
        try:
 
270
            hunk = hunk_from_header(line)
 
271
        except MalformedHunkHeader:
 
272
            if allow_dirty:
 
273
                # If the line isn't a hunk header, then we've reached the end
 
274
                # of this patch and there's "junk" at the end.  Ignore the
 
275
                # rest of this patch.
 
276
                return
 
277
            raise
261
278
        orig_size = 0
262
279
        mod_size = 0
263
280
        while orig_size < hunk.orig_range or mod_size < hunk.mod_range:
336
353
                    pos += 1
337
354
 
338
355
 
339
 
def parse_patch(iter_lines):
 
356
def parse_patch(iter_lines, allow_dirty=False):
 
357
    '''
 
358
    :arg iter_lines: iterable of lines to parse
 
359
    :kwarg allow_dirty: If True, allow the patch to have trailing junk.
 
360
        Default False
 
361
    '''
340
362
    iter_lines = iter_lines_handle_nl(iter_lines)
341
363
    try:
342
364
        (orig_name, mod_name) = get_patch_names(iter_lines)
344
366
        return BinaryPatch(e.orig_name, e.mod_name)
345
367
    else:
346
368
        patch = Patch(orig_name, mod_name)
347
 
        for hunk in iter_hunks(iter_lines):
 
369
        for hunk in iter_hunks(iter_lines, allow_dirty):
348
370
            patch.hunks.append(hunk)
349
371
        return patch
350
372
 
351
373
 
352
 
def iter_file_patch(iter_lines):
 
374
def iter_file_patch(iter_lines, allow_dirty=False):
 
375
    '''
 
376
    :arg iter_lines: iterable of lines to parse for patches
 
377
    :kwarg allow_dirty: If True, allow comments and other non-patch text
 
378
        before the first patch.  Note that the algorithm here can only find
 
379
        such text before any patches have been found.  Comments after the
 
380
        first patch are stripped away in iter_hunks() if it is also passed
 
381
        allow_dirty=True.  Default False.
 
382
    '''
 
383
    ### FIXME: Docstring is not quite true.  We allow certain comments no
 
384
    # matter what, If they startwith '===', '***', or '#' Someone should
 
385
    # reexamine this logic and decide if we should include those in
 
386
    # allow_dirty or restrict those to only being before the patch is found
 
387
    # (as allow_dirty does).
 
388
    regex = re.compile(binary_files_re)
353
389
    saved_lines = []
354
390
    orig_range = 0
 
391
    beginning = True
355
392
    for line in iter_lines:
356
393
        if line.startswith('=== ') or line.startswith('*** '):
357
394
            continue
360
397
        elif orig_range > 0:
361
398
            if line.startswith('-') or line.startswith(' '):
362
399
                orig_range -= 1
363
 
        elif line.startswith('--- '):
364
 
            if len(saved_lines) > 0:
 
400
        elif line.startswith('--- ') or regex.match(line):
 
401
            if allow_dirty and beginning:
 
402
                # Patches can have "junk" at the beginning
 
403
                # Stripping junk from the end of patches is handled when we
 
404
                # parse the patch
 
405
                beginning = False
 
406
            elif len(saved_lines) > 0:
365
407
                yield saved_lines
366
408
            saved_lines = []
367
409
        elif line.startswith('@@'):
393
435
        yield last_line
394
436
 
395
437
 
396
 
def parse_patches(iter_lines):
397
 
    return [parse_patch(f.__iter__()) for f in iter_file_patch(iter_lines)]
 
438
def parse_patches(iter_lines, allow_dirty=False):
 
439
    '''
 
440
    :arg iter_lines: iterable of lines to parse for patches
 
441
    :kwarg allow_dirty: If True, allow text that's not part of the patch at
 
442
        selected places.  This includes comments before and after a patch
 
443
        for instance.  Default False.
 
444
    '''
 
445
    return [parse_patch(f.__iter__(), allow_dirty) for f in
 
446
                        iter_file_patch(iter_lines, allow_dirty)]
398
447
 
399
448
 
400
449
def difference_index(atext, btext):