view mercurial/diffhelper.py @ 47507:d4c795576aeb

dirstate-entry: turn dirstate tuple into a real object (like in C) With dirstate V2, the stored information and actual format will change. This mean we need to start an a better abstraction for a dirstate entry that a tuple directly accessed. By chance, the C code is already doing this and pretend to be a tuple. So it should be fairly easy. We start with turning the tuple into an object, we will slowly migrate the dirstate code to no longer use the tuple directly in later changesets. Differential Revision: https://phab.mercurial-scm.org/D10949
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sat, 03 Jul 2021 03:48:35 +0200
parents d4ba4d51f85f
children 6000f5b25c9b
line wrap: on
line source

# diffhelper.py - helper routines for patch
#
# Copyright 2009 Olivia Mackall <olivia@selenic.com> and others
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

from __future__ import absolute_import

from .i18n import _

from . import (
    error,
    pycompat,
)

MISSING_NEWLINE_MARKER = b'\\ No newline at end of file\n'


def addlines(fp, hunk, lena, lenb, a, b):
    """Read lines from fp into the hunk

    The hunk is parsed into two arrays, a and b. a gets the old state of
    the text, b gets the new state. The control char from the hunk is saved
    when inserting into a, but not b (for performance while deleting files.)
    """
    while True:
        todoa = lena - len(a)
        todob = lenb - len(b)
        num = max(todoa, todob)
        if num == 0:
            break
        for i in pycompat.xrange(num):
            s = fp.readline()
            if not s:
                raise error.ParseError(_(b'incomplete hunk'))
            if s == MISSING_NEWLINE_MARKER:
                fixnewline(hunk, a, b)
                continue
            if s == b'\n' or s == b'\r\n':
                # Some patches may be missing the control char
                # on empty lines. Supply a leading space.
                s = b' ' + s
            hunk.append(s)
            if s.startswith(b'+'):
                b.append(s[1:])
            elif s.startswith(b'-'):
                a.append(s)
            else:
                b.append(s[1:])
                a.append(s)


def fixnewline(hunk, a, b):
    """Fix up the last lines of a and b when the patch has no newline at EOF"""
    l = hunk[-1]
    # tolerate CRLF in last line
    if l.endswith(b'\r\n'):
        hline = l[:-2]
    else:
        hline = l[:-1]

    if hline.startswith((b' ', b'+')):
        b[-1] = hline[1:]
    if hline.startswith((b' ', b'-')):
        a[-1] = hline
    hunk[-1] = hline


def testhunk(a, b, bstart):
    """Compare the lines in a with the lines in b

    a is assumed to have a control char at the start of each line, this char
    is ignored in the compare.
    """
    alen = len(a)
    blen = len(b)
    if alen > blen - bstart or bstart < 0:
        return False
    for i in pycompat.xrange(alen):
        if a[i][1:] != b[i + bstart]:
            return False
    return True