mercurial/diffhelper.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Fri, 20 Nov 2020 10:38:46 +0100
changeset 45985 b6b7626d3e06
parent 45154 10f48720ef95
child 46819 d4ba4d51f85f
permissions -rw-r--r--
copies: avoid unwanted side effect from one branch to another Without this copy, change in a one descendant branch (With "remove" change only) could affect computation on another descendant branches. This was not caugh by the test because the test graph are "too simple". I started writing more test in that regards, but I a submitting this changes earlier because I want to get more code landed to allow other optimisation work to happens. Differential Revision: https://phab.mercurial-scm.org/D9416
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
37803
72f6498c040b diffhelper: rename module to avoid conflicts with ancient C module (issue5846)
Yuya Nishihara <yuya@tcha.org>
parents: 37802
diff changeset
     1
# diffhelper.py - helper routines for patch
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
     2
#
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
     3
# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7702
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 8225
diff changeset
     6
# GNU General Public License version 2 or any later version.
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
     7
27336
80214358ac88 diffhelpers: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 12387
diff changeset
     8
from __future__ import absolute_import
80214358ac88 diffhelpers: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 12387
diff changeset
     9
37573
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
    10
from .i18n import _
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
    11
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
    12
from . import (
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
    13
    error,
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37836
diff changeset
    14
    pycompat,
37573
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
    15
)
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
    16
45154
10f48720ef95 diff: move no-eol text constant to a common location
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43077
diff changeset
    17
MISSING_NEWLINE_MARKER = b'\\ No newline at end of file\n'
10f48720ef95 diff: move no-eol text constant to a common location
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43077
diff changeset
    18
43075
57875cf423c9 style: run a patched black on a subset of mercurial
Augie Fackler <augie@google.com>
parents: 38783
diff changeset
    19
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    20
def addlines(fp, hunk, lena, lenb, a, b):
37567
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    21
    """Read lines from fp into the hunk
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    22
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    23
    The hunk is parsed into two arrays, a and b. a gets the old state of
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    24
    the text, b gets the new state. The control char from the hunk is saved
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    25
    when inserting into a, but not b (for performance while deleting files.)
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    26
    """
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    27
    while True:
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    28
        todoa = lena - len(a)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    29
        todob = lenb - len(b)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    30
        num = max(todoa, todob)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    31
        if num == 0:
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    32
            break
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37836
diff changeset
    33
        for i in pycompat.xrange(num):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    34
            s = fp.readline()
37573
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37572
diff changeset
    35
            if not s:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43075
diff changeset
    36
                raise error.ParseError(_(b'incomplete hunk'))
45154
10f48720ef95 diff: move no-eol text constant to a common location
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43077
diff changeset
    37
            if s == MISSING_NEWLINE_MARKER:
37570
c4c8d0d1267f diffhelpers: naming and whitespace cleanup
Yuya Nishihara <yuya@tcha.org>
parents: 37567
diff changeset
    38
                fixnewline(hunk, a, b)
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    39
                continue
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43075
diff changeset
    40
            if s == b'\n' or s == b'\r\n':
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    41
                # Some patches may be missing the control char
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    42
                # on empty lines. Supply a leading space.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43075
diff changeset
    43
                s = b' ' + s
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    44
            hunk.append(s)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43075
diff changeset
    45
            if s.startswith(b'+'):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    46
                b.append(s[1:])
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43075
diff changeset
    47
            elif s.startswith(b'-'):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    48
                a.append(s)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    49
            else:
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    50
                b.append(s[1:])
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    51
                a.append(s)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    52
43075
57875cf423c9 style: run a patched black on a subset of mercurial
Augie Fackler <augie@google.com>
parents: 38783
diff changeset
    53
37570
c4c8d0d1267f diffhelpers: naming and whitespace cleanup
Yuya Nishihara <yuya@tcha.org>
parents: 37567
diff changeset
    54
def fixnewline(hunk, a, b):
37567
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    55
    """Fix up the last lines of a and b when the patch has no newline at EOF"""
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    56
    l = hunk[-1]
10551
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
    57
    # tolerate CRLF in last line
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43075
diff changeset
    58
    if l.endswith(b'\r\n'):
10551
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
    59
        hline = l[:-2]
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
    60
    else:
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
    61
        hline = l[:-1]
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    62
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43075
diff changeset
    63
    if hline.startswith((b' ', b'+')):
10551
f61dced1367a fix test-mq-eol under --pure (mimic diffhelper.c behaviour)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10263
diff changeset
    64
        b[-1] = hline[1:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43075
diff changeset
    65
    if hline.startswith((b' ', b'-')):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    66
        a[-1] = hline
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    67
    hunk[-1] = hline
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    68
43075
57875cf423c9 style: run a patched black on a subset of mercurial
Augie Fackler <augie@google.com>
parents: 38783
diff changeset
    69
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    70
def testhunk(a, b, bstart):
37567
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    71
    """Compare the lines in a with the lines in b
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    72
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    73
    a is assumed to have a control char at the start of each line, this char
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    74
    is ignored in the compare.
53021c4ef0b2 diffhelpers: port docstrings from cext to pure
Yuya Nishihara <yuya@tcha.org>
parents: 37566
diff changeset
    75
    """
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    76
    alen = len(a)
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    77
    blen = len(b)
37802
090c89a8db32 diffhelpers: backport 9e40bc4c1bde from C implementation
Yuya Nishihara <yuya@tcha.org>
parents: 37575
diff changeset
    78
    if alen > blen - bstart or bstart < 0:
37574
a1bcc7ff0eac diffhelpers: make return value of testhunk() more Pythonic
Yuya Nishihara <yuya@tcha.org>
parents: 37573
diff changeset
    79
        return False
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37836
diff changeset
    80
    for i in pycompat.xrange(alen):
7702
f6bb40554e34 pure Python implementation of diffhelpers.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    81
        if a[i][1:] != b[i + bstart]:
37574
a1bcc7ff0eac diffhelpers: make return value of testhunk() more Pythonic
Yuya Nishihara <yuya@tcha.org>
parents: 37573
diff changeset
    82
            return False
a1bcc7ff0eac diffhelpers: make return value of testhunk() more Pythonic
Yuya Nishihara <yuya@tcha.org>
parents: 37573
diff changeset
    83
    return True