mercurial/patch.py
author Yuya Nishihara <yuya@tcha.org>
Tue, 03 Nov 2020 11:15:50 +0900
branchstable
changeset 45850 9534de20358f
parent 45154 10f48720ef95
child 45877 ac362d5a7893
child 46020 210f9b8d7bbd
permissions -rw-r--r--
chg: do not close dir fd while iterating It works so long as the dp is the last entry, but readdir(dp) would fail with EBADF. Let's not do that and close the dir fd explicitly.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     1
# patch.py - patch file parsing routines
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     2
#
2865
71e78f2ca5ae merge git patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2863
diff changeset
     3
# Copyright 2006 Brendan Cully <brendan@kublai.com>
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
     4
# Copyright 2007 Chris Mason <chris.mason@oracle.com>
2865
71e78f2ca5ae merge git patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2863
diff changeset
     5
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8209
diff changeset
     6
# 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: 10203
diff changeset
     7
# GNU General Public License version 2 or any later version.
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     8
34137
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
     9
from __future__ import absolute_import, print_function
27485
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    10
25113
0ca8410ea345 util: drop alias for collections.deque
Martin von Zweigbergk <martinvonz@google.com>
parents: 24845
diff changeset
    11
import collections
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
    12
import contextlib
27485
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    13
import copy
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    14
import errno
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    15
import os
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    16
import re
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    17
import shutil
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    18
import zlib
10965
7faef79a89c7 patch: move mercurial-specific imports after stdlib imports
Augie Fackler <durin42@gmail.com>
parents: 10905
diff changeset
    19
27485
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    20
from .i18n import _
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    21
from .node import (
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    22
    hex,
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    23
    short,
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    24
)
43085
eef9a2d67051 py3: manually import pycompat.open into files that need it
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43077
diff changeset
    25
from .pycompat import open
27485
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    26
from . import (
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    27
    copies,
37803
72f6498c040b diffhelper: rename module to avoid conflicts with ancient C module (issue5846)
Yuya Nishihara <yuya@tcha.org>
parents: 37764
diff changeset
    28
    diffhelper,
38588
1c93e0237a24 diffutil: move the module out of utils package
Yuya Nishihara <yuya@tcha.org>
parents: 38587
diff changeset
    29
    diffutil,
27485
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    30
    encoding,
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    31
    error,
28341
8286f551b7ee patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents: 27902
diff changeset
    32
    mail,
27485
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    33
    mdiff,
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    34
    pathutil,
30924
48dea083f66d py3: convert the mode argument of os.fdopen to unicodes (1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30819
diff changeset
    35
    pycompat,
27485
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    36
    scmutil,
30807
6381a6dbc325 patch: use opt.showsimilarity to calculate and show the similarity
Sean Farley <sean@farley.io>
parents: 30806
diff changeset
    37
    similar,
27485
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    38
    util,
31233
067f2a95e32c vfs: use 'vfs' module directly in 'mercurial.patch'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31216
diff changeset
    39
    vfs as vfsmod,
27485
60183975b5bc patch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27412
diff changeset
    40
)
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36838
diff changeset
    41
from .utils import (
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36838
diff changeset
    42
    dateutil,
44060
a61287a95dc3 core: migrate uses of hashlib.sha1 to hashutil.sha1
Augie Fackler <augie@google.com>
parents: 43943
diff changeset
    43
    hashutil,
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
    44
    procutil,
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36838
diff changeset
    45
    stringutil,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36838
diff changeset
    46
)
32370
017ad85e5ac8 diffhelpers: switch to policy importer
Yuya Nishihara <yuya@tcha.org>
parents: 32320
diff changeset
    47
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28341
diff changeset
    48
stringio = util.stringio
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
    49
31630
451c980a8b57 patch: make regular expressions bytes by adding b''
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31274
diff changeset
    50
gitre = re.compile(br'diff --git a/(.*) b/(.*)')
451c980a8b57 patch: make regular expressions bytes by adding b''
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31274
diff changeset
    51
tabsplitter = re.compile(br'(\t+|[^\t]+)')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
    52
wordsplitter = re.compile(
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43106
diff changeset
    53
    br'(\t+| +|[a-zA-Z0-9_\x80-\xff]+|[^ \ta-zA-Z0-9_\x80-\xff])'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
    54
)
7199
dd891d0d97a3 patch: consolidate two different regexes for parsing of git diffs
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7198
diff changeset
    55
34251
61714510220d error: move patch.PatchError so it can easily implement __bytes__ (API)
Yuya Nishihara <yuya@tcha.org>
parents: 34137
diff changeset
    56
PatchError = error.PatchError
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    57
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    58
# public functions
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    59
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
    60
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    61
def split(stream):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    62
    '''return an iterator of individual patches from a stream'''
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
    63
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    64
    def isheader(line, inheader):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    65
        if inheader and line.startswith((b' ', b'\t')):
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    66
            # continuation
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    67
            return True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    68
        if line.startswith((b' ', b'-', b'+')):
10883
196908117c27 patch: don't look for headers in diff lines
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 10748
diff changeset
    69
            # diff line - don't check for header pattern in there
196908117c27 patch: don't look for headers in diff lines
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 10748
diff changeset
    70
            return False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    71
        l = line.split(b': ', 1)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    72
        return len(l) == 2 and b' ' not in l[0]
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    73
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    74
    def chunk(lines):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    75
        return stringio(b''.join(lines))
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    76
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    77
    def hgsplit(stream, cur):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    78
        inheader = True
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    79
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    80
        for line in stream:
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    81
            if not line.strip():
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    82
                inheader = False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    83
            if not inheader and line.startswith(b'# HG changeset patch'):
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    84
                yield chunk(cur)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    85
                cur = []
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    86
                inheader = True
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    87
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    88
            cur.append(line)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    89
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    90
        if cur:
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    91
            yield chunk(cur)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    92
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    93
    def mboxsplit(stream, cur):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    94
        for line in stream:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    95
            if line.startswith(b'From '):
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    96
                for c in split(chunk(cur[1:])):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    97
                    yield c
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    98
                cur = []
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
    99
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   100
            cur.append(line)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   101
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   102
        if cur:
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   103
            for c in split(chunk(cur[1:])):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   104
                yield c
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   105
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   106
    def mimesplit(stream, cur):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   107
        def msgfp(m):
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28341
diff changeset
   108
            fp = stringio()
43156
0e6a7ce81dde py3: use email.generator.BytesGenerator in patch.split()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 43155
diff changeset
   109
            g = mail.Generator(fp, mangle_from_=False)
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   110
            g.flatten(m)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   111
            fp.seek(0)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   112
            return fp
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   113
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   114
        for line in stream:
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   115
            cur.append(line)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   116
        c = chunk(cur)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   117
38332
7b12a2d2eedc py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents: 38329
diff changeset
   118
        m = mail.parse(c)
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   119
        if not m.is_multipart():
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   120
            yield msgfp(m)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   121
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   122
            ok_types = (b'text/plain', b'text/x-diff', b'text/x-patch')
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   123
            for part in m.walk():
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   124
                ct = part.get_content_type()
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   125
                if ct not in ok_types:
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   126
                    continue
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   127
                yield msgfp(part)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   128
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   129
    def headersplit(stream, cur):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   130
        inheader = False
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   131
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   132
        for line in stream:
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   133
            if not inheader and isheader(line, inheader):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   134
                yield chunk(cur)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   135
                cur = []
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   136
                inheader = True
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   137
            if inheader and not isheader(line, inheader):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   138
                inheader = False
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   139
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   140
            cur.append(line)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   141
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   142
        if cur:
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   143
            yield chunk(cur)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   144
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   145
    def remainder(cur):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   146
        yield chunk(cur)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   147
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   148
    class fiter(object):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   149
        def __init__(self, fp):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   150
            self.fp = fp
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   151
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   152
        def __iter__(self):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   153
            return self
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   154
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   155
        def next(self):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   156
            l = self.fp.readline()
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   157
            if not l:
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   158
                raise StopIteration
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   159
            return l
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   160
35191
a1d2fc32bb99 py3: define __next__ in patch.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35062
diff changeset
   161
        __next__ = next
a1d2fc32bb99 py3: define __next__ in patch.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35062
diff changeset
   162
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   163
    inheader = False
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   164
    cur = []
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   165
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   166
    mimeheaders = [b'content-type']
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   167
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   168
    if not util.safehasattr(stream, b'next'):
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   169
        # http responses, for example, have readline but not next
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   170
        stream = fiter(stream)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   171
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   172
    for line in stream:
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   173
        cur.append(line)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   174
        if line.startswith(b'# HG changeset patch'):
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   175
            return hgsplit(stream, cur)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   176
        elif line.startswith(b'From '):
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   177
            return mboxsplit(stream, cur)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   178
        elif isheader(line, inheader):
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   179
            inheader = True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   180
            if line.split(b':', 1)[0].lower() in mimeheaders:
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   181
                # let email parser handle this
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   182
                return mimesplit(stream, cur)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   183
        elif line.startswith(b'--- ') and inheader:
10501
a27af7229850 import: if in doubt, consume stream until start of diff
Brendan Cully <brendan@kublai.com>
parents: 10467
diff changeset
   184
            # No evil headers seen by diff start, split by hand
10384
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   185
            return headersplit(stream, cur)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   186
        # Not enough info, keep reading
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   187
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   188
    # if we are here, we have a very plain patch
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   189
    return remainder(cur)
832f35386067 import: import each patch in a file or stream as a separate change
Brendan Cully <brendan@kublai.com>
parents: 10282
diff changeset
   190
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   191
26557
23f3f1cbd53b extract: add some facility for extensible header parsing
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26556
diff changeset
   192
## Some facility for extensible patch parsing:
23f3f1cbd53b extract: add some facility for extensible header parsing
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26556
diff changeset
   193
# list of pairs ("header to match", "data key")
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   194
patchheadermap = [
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   195
    (b'Date', b'date'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   196
    (b'Branch', b'branch'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   197
    (b'Node ID', b'nodeid'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   198
]
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   199
26557
23f3f1cbd53b extract: add some facility for extensible header parsing
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26556
diff changeset
   200
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   201
@contextlib.contextmanager
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   202
def extract(ui, fileobj):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   203
    '''extract patch from data read from fileobj.
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   204
4263
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
   205
    patch can be a normal patch or contained in an email message.
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   206
26781
1aee2ab0f902 spelling: trivial spell checking
Mads Kiilerich <madski@unity3d.com>
parents: 26587
diff changeset
   207
    return a dictionary. Standard keys are:
26547
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   208
      - filename,
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   209
      - message,
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   210
      - user,
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   211
      - date,
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   212
      - branch,
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   213
      - node,
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   214
      - p1,
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   215
      - p2.
26781
1aee2ab0f902 spelling: trivial spell checking
Mads Kiilerich <madski@unity3d.com>
parents: 26587
diff changeset
   216
    Any item can be missing from the dictionary. If filename is missing,
4263
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
   217
    fileobj did not contain a patch. Caller must unlink filename when done.'''
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   218
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   219
    fd, tmpname = pycompat.mkstemp(prefix=b'hg-patch-')
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
   220
    tmpfp = os.fdopen(fd, 'wb')
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   221
    try:
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   222
        yield _extract(ui, fileobj, tmpname, tmpfp)
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   223
    finally:
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   224
        tmpfp.close()
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   225
        os.unlink(tmpname)
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   226
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   227
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   228
def _extract(ui, fileobj, tmpname, tmpfp):
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   229
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   230
    # attempt to detect the start of a patch
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   231
    # (this heuristic is borrowed from quilt)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   232
    diffre = re.compile(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   233
        br'^(?:Index:[ \t]|diff[ \t]-|RCS file: |'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   234
        br'retrieving revision [0-9]+(\.[0-9]+)*$|'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   235
        br'---[ \t].*?^\+\+\+[ \t]|'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   236
        br'\*\*\*[ \t].*?^---[ \t])',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   237
        re.MULTILINE | re.DOTALL,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   238
    )
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   239
26547
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   240
    data = {}
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   241
38332
7b12a2d2eedc py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents: 38329
diff changeset
   242
    msg = mail.parse(fileobj)
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   243
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
   244
    subject = msg['Subject'] and mail.headdecode(msg['Subject'])
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
   245
    data[b'user'] = msg['From'] and mail.headdecode(msg['From'])
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   246
    if not subject and not data[b'user']:
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   247
        # Not an email, restore parsed headers if any
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   248
        subject = (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   249
            b'\n'.join(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   250
                b': '.join(map(encoding.strtolocal, h)) for h in msg.items()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   251
            )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   252
            + b'\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   253
        )
9573
b8352a3617f3 patch: do not swallow header-like patch first line (issue1859)
Patrick Mezard <pmezard@gmail.com>
parents: 9243
diff changeset
   254
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   255
    # should try to parse msg['Date']
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   256
    parents = []
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   257
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
   258
    nodeid = msg['X-Mercurial-Node']
43097
27c4f93d07a9 import: read X-Mercurial-Node email header to determine nodeid
Denis Laxalde <denis@laxalde.org>
parents: 43085
diff changeset
   259
    if nodeid:
27c4f93d07a9 import: read X-Mercurial-Node email header to determine nodeid
Denis Laxalde <denis@laxalde.org>
parents: 43085
diff changeset
   260
        data[b'nodeid'] = nodeid = mail.headdecode(nodeid)
27c4f93d07a9 import: read X-Mercurial-Node email header to determine nodeid
Denis Laxalde <denis@laxalde.org>
parents: 43085
diff changeset
   261
        ui.debug(b'Node ID: %s\n' % nodeid)
27c4f93d07a9 import: read X-Mercurial-Node email header to determine nodeid
Denis Laxalde <denis@laxalde.org>
parents: 43085
diff changeset
   262
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   263
    if subject:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   264
        if subject.startswith(b'[PATCH'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   265
            pend = subject.find(b']')
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   266
            if pend >= 0:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   267
                subject = subject[pend + 1 :].lstrip()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   268
        subject = re.sub(br'\n[ \t]+', b' ', subject)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   269
        ui.debug(b'Subject: %s\n' % subject)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   270
    if data[b'user']:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   271
        ui.debug(b'From: %s\n' % data[b'user'])
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   272
    diffs_seen = 0
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   273
    ok_types = (b'text/plain', b'text/x-diff', b'text/x-patch')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   274
    message = b''
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   275
    for part in msg.walk():
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   276
        content_type = pycompat.bytestr(part.get_content_type())
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   277
        ui.debug(b'Content-Type: %s\n' % content_type)
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   278
        if content_type not in ok_types:
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   279
            continue
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   280
        payload = part.get_payload(decode=True)
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   281
        m = diffre.search(payload)
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   282
        if m:
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   283
            hgpatch = False
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   284
            hgpatchheader = False
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   285
            ignoretext = False
4220
1253703853a8 git-send-email compatibility: stop reading changelog after ^---$
Brendan Cully <brendan@kublai.com>
parents: 4208
diff changeset
   286
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   287
            ui.debug(b'found patch at byte %d\n' % m.start(0))
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   288
            diffs_seen += 1
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   289
            cfp = stringio()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   290
            for line in payload[: m.start(0)].splitlines():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   291
                if line.startswith(b'# HG changeset patch') and not hgpatch:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   292
                    ui.debug(b'patch generated by hg export\n')
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   293
                    hgpatch = True
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   294
                    hgpatchheader = True
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   295
                    # drop earlier commit message content
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   296
                    cfp.seek(0)
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   297
                    cfp.truncate()
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   298
                    subject = None
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   299
                elif hgpatchheader:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   300
                    if line.startswith(b'# User '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   301
                        data[b'user'] = line[7:]
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   302
                        ui.debug(b'From: %s\n' % data[b'user'])
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   303
                    elif line.startswith(b"# Parent "):
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   304
                        parents.append(line[9:].lstrip())
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   305
                    elif line.startswith(b"# "):
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   306
                        for header, key in patchheadermap:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   307
                            prefix = b'# %s ' % header
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   308
                            if line.startswith(prefix):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   309
                                data[key] = line[len(prefix) :]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   310
                                ui.debug(b'%s: %s\n' % (header, data[key]))
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   311
                    else:
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   312
                        hgpatchheader = False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   313
                elif line == b'---':
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   314
                    ignoretext = True
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   315
                if not hgpatchheader and not ignoretext:
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   316
                    cfp.write(line)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   317
                    cfp.write(b'\n')
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   318
            message = cfp.getvalue()
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   319
            if tmpfp:
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   320
                tmpfp.write(payload)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   321
                if not payload.endswith(b'\n'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   322
                    tmpfp.write(b'\n')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   323
        elif not diffs_seen and message and content_type == b'text/plain':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   324
            message += b'\n' + payload
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   325
4777
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
   326
    if subject and not message.startswith(subject):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   327
        message = b'%s\n%s' % (subject, message)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   328
    data[b'message'] = message
2866
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   329
    tmpfp.close()
24306
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
   330
    if parents:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   331
        data[b'p1'] = parents.pop(0)
26548
25a58881efdd extract: simplify parents assignement
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26547
diff changeset
   332
        if parents:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   333
            data[b'p2'] = parents.pop(0)
24306
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
   334
26555
1e33384ff2ed extract: use a single return
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26554
diff changeset
   335
    if diffs_seen:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   336
        data[b'filename'] = tmpname
37621
5537d8f5e989 patch: make extract() a context manager (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37574
diff changeset
   337
26547
b9be8ab6e628 patch: move 'extract' return to a dictionnary
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26421
diff changeset
   338
    return data
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   339
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   340
8778
c5f36402daad use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8761
diff changeset
   341
class patchmeta(object):
7148
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   342
    """Patched file metadata
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   343
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   344
    'op' is the performed operation within ADD, DELETE, RENAME, MODIFY
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   345
    or COPY.  'path' is patched file path. 'oldpath' is set to the
7149
01a056c54385 patch: patchmeta gives (islink, isexec) tuple instead of int mode
Patrick Mezard <pmezard@gmail.com>
parents: 7148
diff changeset
   346
    origin file when 'op' is either COPY or RENAME, None otherwise. If
01a056c54385 patch: patchmeta gives (islink, isexec) tuple instead of int mode
Patrick Mezard <pmezard@gmail.com>
parents: 7148
diff changeset
   347
    file mode is changed, 'mode' is a tuple (islink, isexec) where
01a056c54385 patch: patchmeta gives (islink, isexec) tuple instead of int mode
Patrick Mezard <pmezard@gmail.com>
parents: 7148
diff changeset
   348
    'islink' is True if the file is a symlink and 'isexec' is True if
01a056c54385 patch: patchmeta gives (islink, isexec) tuple instead of int mode
Patrick Mezard <pmezard@gmail.com>
parents: 7148
diff changeset
   349
    the file is executable. Otherwise, 'mode' is None.
7148
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   350
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   351
7148
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   352
    def __init__(self, path):
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   353
        self.path = path
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   354
        self.oldpath = None
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   355
        self.mode = None
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   356
        self.op = b'MODIFY'
7148
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   357
        self.binary = False
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   358
7149
01a056c54385 patch: patchmeta gives (islink, isexec) tuple instead of int mode
Patrick Mezard <pmezard@gmail.com>
parents: 7148
diff changeset
   359
    def setmode(self, mode):
25658
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25644
diff changeset
   360
        islink = mode & 0o20000
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25644
diff changeset
   361
        isexec = mode & 0o100
7149
01a056c54385 patch: patchmeta gives (islink, isexec) tuple instead of int mode
Patrick Mezard <pmezard@gmail.com>
parents: 7148
diff changeset
   362
        self.mode = (islink, isexec)
01a056c54385 patch: patchmeta gives (islink, isexec) tuple instead of int mode
Patrick Mezard <pmezard@gmail.com>
parents: 7148
diff changeset
   363
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   364
    def copy(self):
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   365
        other = patchmeta(self.path)
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   366
        other.oldpath = self.oldpath
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   367
        other.mode = self.mode
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   368
        other.op = self.op
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   369
        other.binary = self.binary
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   370
        return other
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   371
16506
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
   372
    def _ispatchinga(self, afile):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   373
        if afile == b'/dev/null':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   374
            return self.op == b'ADD'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   375
        return afile == b'a/' + (self.oldpath or self.path)
16506
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
   376
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
   377
    def _ispatchingb(self, bfile):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   378
        if bfile == b'/dev/null':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   379
            return self.op == b'DELETE'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   380
        return bfile == b'b/' + self.path
16506
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
   381
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
   382
    def ispatching(self, afile, bfile):
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
   383
        return self._ispatchinga(afile) and self._ispatchingb(bfile)
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
   384
11018
17cf756ba25d patch: descriptive patchmeta.__repr__ to help debugging
Mads Kiilerich <mads@kiilerich.com>
parents: 10966
diff changeset
   385
    def __repr__(self):
43503
313e3a279828 cleanup: remove pointless r-prefixes on double-quoted strings
Augie Fackler <augie@google.com>
parents: 43166
diff changeset
   386
        return "<patchmeta %s %r>" % (self.op, self.path)
11018
17cf756ba25d patch: descriptive patchmeta.__repr__ to help debugging
Mads Kiilerich <mads@kiilerich.com>
parents: 10966
diff changeset
   387
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   388
7152
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
   389
def readgitpatch(lr):
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   390
    """extract git-style metadata about patches from <patchname>"""
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3199
diff changeset
   391
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   392
    # Filter patch for git information
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   393
    gp = None
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   394
    gitpatches = []
7152
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
   395
    for line in lr:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   396
        line = line.rstrip(b' \r\n')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   397
        if line.startswith(b'diff --git a/'):
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   398
            m = gitre.match(line)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   399
            if m:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   400
                if gp:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   401
                    gitpatches.append(gp)
9392
039bce1b505f patch: readgitpatch: remove unused variable 'src'
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9331
diff changeset
   402
                dst = m.group(2)
7148
7d84e5b00e29 patch: extract and rename gitpatch into patchmeta, document
Patrick Mezard <pmezard@gmail.com>
parents: 7147
diff changeset
   403
                gp = patchmeta(dst)
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   404
        elif gp:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   405
            if line.startswith(b'--- '):
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   406
                gitpatches.append(gp)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   407
                gp = None
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   408
                continue
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   409
            if line.startswith(b'rename from '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   410
                gp.op = b'RENAME'
9243
df21a009c9c4 fix issue 1763: strip chars from end of line when parsing gitpatch lines
Bill Barry <after.fallout@gmail.com>
parents: 9123
diff changeset
   411
                gp.oldpath = line[12:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   412
            elif line.startswith(b'rename to '):
9243
df21a009c9c4 fix issue 1763: strip chars from end of line when parsing gitpatch lines
Bill Barry <after.fallout@gmail.com>
parents: 9123
diff changeset
   413
                gp.path = line[10:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   414
            elif line.startswith(b'copy from '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   415
                gp.op = b'COPY'
9243
df21a009c9c4 fix issue 1763: strip chars from end of line when parsing gitpatch lines
Bill Barry <after.fallout@gmail.com>
parents: 9123
diff changeset
   416
                gp.oldpath = line[10:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   417
            elif line.startswith(b'copy to '):
9243
df21a009c9c4 fix issue 1763: strip chars from end of line when parsing gitpatch lines
Bill Barry <after.fallout@gmail.com>
parents: 9123
diff changeset
   418
                gp.path = line[8:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   419
            elif line.startswith(b'deleted file'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   420
                gp.op = b'DELETE'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   421
            elif line.startswith(b'new file mode '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   422
                gp.op = b'ADD'
9243
df21a009c9c4 fix issue 1763: strip chars from end of line when parsing gitpatch lines
Bill Barry <after.fallout@gmail.com>
parents: 9123
diff changeset
   423
                gp.setmode(int(line[-6:], 8))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   424
            elif line.startswith(b'new mode '):
9243
df21a009c9c4 fix issue 1763: strip chars from end of line when parsing gitpatch lines
Bill Barry <after.fallout@gmail.com>
parents: 9123
diff changeset
   425
                gp.setmode(int(line[-6:], 8))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   426
            elif line.startswith(b'GIT binary patch'):
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3329
diff changeset
   427
                gp.binary = True
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   428
    if gp:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   429
        gitpatches.append(gp)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   430
12669
b0fa39c68370 patch: remove unused flags from readgitpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 12645
diff changeset
   431
    return gitpatches
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   432
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   433
8891
5fe8dc75aa4a patch: use new style class in linereader
Simon Heimberg <simohe@besonet.ch>
parents: 8843
diff changeset
   434
class linereader(object):
8810
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   435
    # simple class to allow pushing lines back into the input stream
14418
0174d1f79280 patch: remove EOL support from linereader class
Patrick Mezard <pmezard@gmail.com>
parents: 14402
diff changeset
   436
    def __init__(self, fp):
8810
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   437
        self.fp = fp
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   438
        self.buf = []
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   439
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   440
    def push(self, line):
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   441
        if line is not None:
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   442
            self.buf.append(line)
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   443
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   444
    def readline(self):
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   445
        if self.buf:
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   446
            l = self.buf[0]
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   447
            del self.buf[0]
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   448
            return l
14418
0174d1f79280 patch: remove EOL support from linereader class
Patrick Mezard <pmezard@gmail.com>
parents: 14402
diff changeset
   449
        return self.fp.readline()
8810
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   450
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   451
    def __iter__(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   452
        return iter(self.readline, b'')
8810
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
   453
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   454
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   455
class abstractbackend(object):
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   456
    def __init__(self, ui):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   457
        self.ui = ui
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   458
14391
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   459
    def getfile(self, fname):
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   460
        """Return target file data and flags as a (data, (islink,
22296
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   461
        isexec)) tuple. Data is None if file is missing/deleted.
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   462
        """
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   463
        raise NotImplementedError
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   464
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   465
    def setfile(self, fname, data, mode, copysource):
14391
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   466
        """Write data to target file fname and set its mode. mode is a
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   467
        (islink, isexec) tuple. If data is None, the file content should
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   468
        be left unchanged. If the file is modified after being copied,
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   469
        copysource is set to the original file name.
14367
468d7d1744b4 patch: set desired mode when patching, not in updatedir()
Patrick Mezard <pmezard@gmail.com>
parents: 14366
diff changeset
   470
        """
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   471
        raise NotImplementedError
5652
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
   472
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   473
    def unlink(self, fname):
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   474
        """Unlink target file."""
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   475
        raise NotImplementedError
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   476
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   477
    def writerej(self, fname, failed, total, lines):
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   478
        """Write rejected lines for fname. total is the number of hunks
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   479
        which failed to apply and total the total number of hunks for this
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   480
        files.
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   481
        """
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   482
14351
d54f9bbcc640 patch: add lexists() to backends, use it in selectfile()
Patrick Mezard <pmezard@gmail.com>
parents: 14350
diff changeset
   483
    def exists(self, fname):
d54f9bbcc640 patch: add lexists() to backends, use it in selectfile()
Patrick Mezard <pmezard@gmail.com>
parents: 14350
diff changeset
   484
        raise NotImplementedError
d54f9bbcc640 patch: add lexists() to backends, use it in selectfile()
Patrick Mezard <pmezard@gmail.com>
parents: 14350
diff changeset
   485
33155
b8ae289a7707 patch: add close() to abstractbackend
Martin von Zweigbergk <martinvonz@google.com>
parents: 33104
diff changeset
   486
    def close(self):
b8ae289a7707 patch: add close() to abstractbackend
Martin von Zweigbergk <martinvonz@google.com>
parents: 33104
diff changeset
   487
        raise NotImplementedError
b8ae289a7707 patch: add close() to abstractbackend
Martin von Zweigbergk <martinvonz@google.com>
parents: 33104
diff changeset
   488
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   489
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   490
class fsbackend(abstractbackend):
14350
00da6624e167 patch: move copyfile() into backends, abstract basedir
Patrick Mezard <pmezard@gmail.com>
parents: 14349
diff changeset
   491
    def __init__(self, ui, basedir):
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   492
        super(fsbackend, self).__init__(ui)
31233
067f2a95e32c vfs: use 'vfs' module directly in 'mercurial.patch'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31216
diff changeset
   493
        self.opener = vfsmod.vfs(basedir)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   494
14391
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   495
    def getfile(self, fname):
21717
2a095d3442e0 patch: replace functions in fsbackend to use vfs
Chinmay Joshi <c@chinmayjoshi.com>
parents: 21553
diff changeset
   496
        if self.opener.islink(fname):
2a095d3442e0 patch: replace functions in fsbackend to use vfs
Chinmay Joshi <c@chinmayjoshi.com>
parents: 21553
diff changeset
   497
            return (self.opener.readlink(fname), (True, False))
2a095d3442e0 patch: replace functions in fsbackend to use vfs
Chinmay Joshi <c@chinmayjoshi.com>
parents: 21553
diff changeset
   498
14531
b88368a3ade4 patch: remove redundant islink() call
Patrick Mezard <pmezard@gmail.com>
parents: 14494
diff changeset
   499
        isexec = False
7392
564326a6ef9c patch: isolate patchfile filesystem calls into methods
Patrick Mezard <pmezard@gmail.com>
parents: 7391
diff changeset
   500
        try:
25658
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25644
diff changeset
   501
            isexec = self.opener.lstat(fname).st_mode & 0o100 != 0
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25658
diff changeset
   502
        except OSError as e:
14391
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   503
            if e.errno != errno.ENOENT:
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   504
                raise
22296
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   505
        try:
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   506
            return (self.opener.read(fname), (False, isexec))
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25658
diff changeset
   507
        except IOError as e:
22296
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   508
            if e.errno != errno.ENOENT:
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   509
                raise
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   510
            return None, None
7392
564326a6ef9c patch: isolate patchfile filesystem calls into methods
Patrick Mezard <pmezard@gmail.com>
parents: 7391
diff changeset
   511
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   512
    def setfile(self, fname, data, mode, copysource):
14391
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   513
        islink, isexec = mode
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   514
        if data is None:
21717
2a095d3442e0 patch: replace functions in fsbackend to use vfs
Chinmay Joshi <c@chinmayjoshi.com>
parents: 21553
diff changeset
   515
            self.opener.setflags(fname, islink, isexec)
14390
ce77c275bec3 patch: merge backend setmode() into writelines()
Patrick Mezard <pmezard@gmail.com>
parents: 14389
diff changeset
   516
            return
14391
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   517
        if islink:
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   518
            self.opener.symlink(data, fname)
14367
468d7d1744b4 patch: set desired mode when patching, not in updatedir()
Patrick Mezard <pmezard@gmail.com>
parents: 14366
diff changeset
   519
        else:
14391
1e64e1e12195 patch: unify backend file access interface
Patrick Mezard <pmezard@gmail.com>
parents: 14390
diff changeset
   520
            self.opener.write(fname, data)
14367
468d7d1744b4 patch: set desired mode when patching, not in updatedir()
Patrick Mezard <pmezard@gmail.com>
parents: 14366
diff changeset
   521
            if isexec:
21717
2a095d3442e0 patch: replace functions in fsbackend to use vfs
Chinmay Joshi <c@chinmayjoshi.com>
parents: 21553
diff changeset
   522
                self.opener.setflags(fname, False, True)
7392
564326a6ef9c patch: isolate patchfile filesystem calls into methods
Patrick Mezard <pmezard@gmail.com>
parents: 7391
diff changeset
   523
564326a6ef9c patch: isolate patchfile filesystem calls into methods
Patrick Mezard <pmezard@gmail.com>
parents: 7391
diff changeset
   524
    def unlink(self, fname):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   525
        rmdir = self.ui.configbool(b'experimental', b'removeemptydirs')
38493
da2a7d8354b2 unlinkpath: make empty directory removal optional (issue5901) (issue5826)
Kyle Lippincott <spectral@google.com>
parents: 38332
diff changeset
   526
        self.opener.unlinkpath(fname, ignoremissing=True, rmdir=rmdir)
7392
564326a6ef9c patch: isolate patchfile filesystem calls into methods
Patrick Mezard <pmezard@gmail.com>
parents: 7391
diff changeset
   527
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   528
    def writerej(self, fname, failed, total, lines):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   529
        fname = fname + b".rej"
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   530
        self.ui.warn(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   531
            _(b"%d out of %d hunks FAILED -- saving rejects to file %s\n")
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   532
            % (failed, total, fname)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   533
        )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   534
        fp = self.opener(fname, b'w')
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   535
        fp.writelines(lines)
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   536
        fp.close()
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   537
14351
d54f9bbcc640 patch: add lexists() to backends, use it in selectfile()
Patrick Mezard <pmezard@gmail.com>
parents: 14350
diff changeset
   538
    def exists(self, fname):
21717
2a095d3442e0 patch: replace functions in fsbackend to use vfs
Chinmay Joshi <c@chinmayjoshi.com>
parents: 21553
diff changeset
   539
        return self.opener.lexists(fname)
14351
d54f9bbcc640 patch: add lexists() to backends, use it in selectfile()
Patrick Mezard <pmezard@gmail.com>
parents: 14350
diff changeset
   540
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   541
14370
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   542
class workingbackend(fsbackend):
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   543
    def __init__(self, ui, repo, similarity):
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   544
        super(workingbackend, self).__init__(ui, repo.root)
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   545
        self.repo = repo
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   546
        self.similarity = similarity
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   547
        self.removed = set()
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   548
        self.changed = set()
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   549
        self.copied = []
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   550
14453
ea3d548132cc patch: do not patch unknown files (issue752)
Patrick Mezard <pmezard@gmail.com>
parents: 14452
diff changeset
   551
    def _checkknown(self, fname):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   552
        if self.repo.dirstate[fname] == b'?' and self.exists(fname):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   553
            raise PatchError(_(b'cannot patch %s: file is not tracked') % fname)
14453
ea3d548132cc patch: do not patch unknown files (issue752)
Patrick Mezard <pmezard@gmail.com>
parents: 14452
diff changeset
   554
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   555
    def setfile(self, fname, data, mode, copysource):
14453
ea3d548132cc patch: do not patch unknown files (issue752)
Patrick Mezard <pmezard@gmail.com>
parents: 14452
diff changeset
   556
        self._checkknown(fname)
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   557
        super(workingbackend, self).setfile(fname, data, mode, copysource)
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   558
        if copysource is not None:
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   559
            self.copied.append((copysource, fname))
14370
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   560
        self.changed.add(fname)
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   561
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   562
    def unlink(self, fname):
14453
ea3d548132cc patch: do not patch unknown files (issue752)
Patrick Mezard <pmezard@gmail.com>
parents: 14452
diff changeset
   563
        self._checkknown(fname)
14370
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   564
        super(workingbackend, self).unlink(fname)
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   565
        self.removed.add(fname)
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   566
        self.changed.add(fname)
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   567
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   568
    def close(self):
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   569
        wctx = self.repo[None]
19155
0b3689a08df5 patch: use scmutil.marktouched instead of scmutil.addremove
Siddharth Agarwal <sid0@fb.com>
parents: 18830
diff changeset
   570
        changed = set(self.changed)
14370
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   571
        for src, dst in self.copied:
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   572
            scmutil.dirstatecopy(self.ui, self.repo, wctx, src, dst)
16112
d7829b2ecf32 import: handle git renames and --similarity (issue3187)
Patrick Mezard <patrick@mezard.eu>
parents: 15971
diff changeset
   573
        if self.removed:
14435
5f6090e559fa context: make forget work like commands.forget
Matt Mackall <mpm@selenic.com>
parents: 14418
diff changeset
   574
            wctx.forget(sorted(self.removed))
16112
d7829b2ecf32 import: handle git renames and --similarity (issue3187)
Patrick Mezard <patrick@mezard.eu>
parents: 15971
diff changeset
   575
            for f in self.removed:
d7829b2ecf32 import: handle git renames and --similarity (issue3187)
Patrick Mezard <patrick@mezard.eu>
parents: 15971
diff changeset
   576
                if f not in self.repo.dirstate:
d7829b2ecf32 import: handle git renames and --similarity (issue3187)
Patrick Mezard <patrick@mezard.eu>
parents: 15971
diff changeset
   577
                    # File was deleted and no longer belongs to the
d7829b2ecf32 import: handle git renames and --similarity (issue3187)
Patrick Mezard <patrick@mezard.eu>
parents: 15971
diff changeset
   578
                    # dirstate, it was probably marked added then
d7829b2ecf32 import: handle git renames and --similarity (issue3187)
Patrick Mezard <patrick@mezard.eu>
parents: 15971
diff changeset
   579
                    # deleted, and should not be considered by
19155
0b3689a08df5 patch: use scmutil.marktouched instead of scmutil.addremove
Siddharth Agarwal <sid0@fb.com>
parents: 18830
diff changeset
   580
                    # marktouched().
0b3689a08df5 patch: use scmutil.marktouched instead of scmutil.addremove
Siddharth Agarwal <sid0@fb.com>
parents: 18830
diff changeset
   581
                    changed.discard(f)
0b3689a08df5 patch: use scmutil.marktouched instead of scmutil.addremove
Siddharth Agarwal <sid0@fb.com>
parents: 18830
diff changeset
   582
        if changed:
0b3689a08df5 patch: use scmutil.marktouched instead of scmutil.addremove
Siddharth Agarwal <sid0@fb.com>
parents: 18830
diff changeset
   583
            scmutil.marktouched(self.repo, changed, self.similarity)
14370
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   584
        return sorted(self.changed)
17cea10c343e patch: add a workingbackend dirstate layer on top of fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14369
diff changeset
   585
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   586
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   587
class filestore(object):
14658
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   588
    def __init__(self, maxsize=None):
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   589
        self.opener = None
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   590
        self.files = {}
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   591
        self.created = 0
14658
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   592
        self.maxsize = maxsize
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   593
        if self.maxsize is None:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   594
            self.maxsize = 4 * (2 ** 20)
14658
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   595
        self.size = 0
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   596
        self.data = {}
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   597
14609
f53dc0787424 patch: extend filtestore to store an optional copy source
Patrick Mezard <pmezard@gmail.com>
parents: 14566
diff changeset
   598
    def setfile(self, fname, data, mode, copied=None):
14658
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   599
        if self.maxsize < 0 or (len(data) + self.size) <= self.maxsize:
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   600
            self.data[fname] = (data, mode, copied)
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   601
            self.size += len(data)
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   602
        else:
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   603
            if self.opener is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   604
                root = pycompat.mkdtemp(prefix=b'hg-patch-')
31233
067f2a95e32c vfs: use 'vfs' module directly in 'mercurial.patch'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31216
diff changeset
   605
                self.opener = vfsmod.vfs(root)
14658
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   606
            # Avoid filename issues with these simple names
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   607
            fn = b'%d' % self.created
14658
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   608
            self.opener.write(fn, data)
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   609
            self.created += 1
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   610
            self.files[fname] = (fn, mode, copied)
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   611
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   612
    def getfile(self, fname):
14658
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   613
        if fname in self.data:
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   614
            return self.data[fname]
7ddf9a607b75 patch: make filestore store data in memory and fallback to fs
Patrick Mezard <pmezard@gmail.com>
parents: 14611
diff changeset
   615
        if not self.opener or fname not in self.files:
22296
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   616
            return None, None, None
14609
f53dc0787424 patch: extend filtestore to store an optional copy source
Patrick Mezard <pmezard@gmail.com>
parents: 14566
diff changeset
   617
        fn, mode, copied = self.files[fname]
f53dc0787424 patch: extend filtestore to store an optional copy source
Patrick Mezard <pmezard@gmail.com>
parents: 14566
diff changeset
   618
        return self.opener.read(fn), mode, copied
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   619
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   620
    def close(self):
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   621
        if self.opener:
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   622
            shutil.rmtree(self.opener.base)
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   623
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   624
14611
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   625
class repobackend(abstractbackend):
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   626
    def __init__(self, ui, repo, ctx, store):
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   627
        super(repobackend, self).__init__(ui)
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   628
        self.repo = repo
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   629
        self.ctx = ctx
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   630
        self.store = store
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   631
        self.changed = set()
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   632
        self.removed = set()
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   633
        self.copied = {}
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   634
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   635
    def _checkknown(self, fname):
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   636
        if fname not in self.ctx:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   637
            raise PatchError(_(b'cannot patch %s: file is not tracked') % fname)
14611
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   638
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   639
    def getfile(self, fname):
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   640
        try:
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   641
            fctx = self.ctx[fname]
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   642
        except error.LookupError:
22296
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   643
            return None, None
14611
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   644
        flags = fctx.flags()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   645
        return fctx.data(), (b'l' in flags, b'x' in flags)
14611
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   646
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   647
    def setfile(self, fname, data, mode, copysource):
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   648
        if copysource:
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   649
            self._checkknown(copysource)
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   650
        if data is None:
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   651
            data = self.ctx[fname].data()
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   652
        self.store.setfile(fname, data, mode, copysource)
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   653
        self.changed.add(fname)
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   654
        if copysource:
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   655
            self.copied[fname] = copysource
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   656
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   657
    def unlink(self, fname):
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   658
        self._checkknown(fname)
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   659
        self.removed.add(fname)
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   660
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   661
    def exists(self, fname):
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   662
        return fname in self.ctx
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   663
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   664
    def close(self):
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   665
        return self.changed | self.removed
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
   666
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   667
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   668
# @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
41532
bd3f03d8cc9f global: use raw strings for regular expressions with escapes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41499
diff changeset
   669
unidesc = re.compile(br'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@')
bd3f03d8cc9f global: use raw strings for regular expressions with escapes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41499
diff changeset
   670
contextdesc = re.compile(br'(?:---|\*\*\*) (\d+)(?:,(\d+))? (?:---|\*\*\*)')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   671
eolmodes = [b'strict', b'crlf', b'lf', b'auto']
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   672
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   673
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   674
class patchfile(object):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   675
    def __init__(self, ui, gp, backend, store, eolmode=b'strict'):
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   676
        self.fname = gp.path
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   677
        self.eolmode = eolmode
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   678
        self.eol = None
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   679
        self.backend = backend
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   680
        self.ui = ui
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   681
        self.lines = []
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   682
        self.exists = False
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   683
        self.missing = True
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   684
        self.mode = gp.mode
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   685
        self.copysource = gp.oldpath
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   686
        self.create = gp.op in (b'ADD', b'COPY', b'RENAME')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   687
        self.remove = gp.op == b'DELETE'
22296
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   688
        if self.copysource is None:
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   689
            data, mode = backend.getfile(self.fname)
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   690
        else:
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   691
            data, mode = store.getfile(self.copysource)[:2]
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   692
        if data is not None:
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   693
            self.exists = self.copysource is None or backend.exists(self.fname)
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   694
            self.missing = False
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   695
            if data:
14832
d60e4f227d75 patch: fix parsing patch files containing CRs not followed by LFs
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 14764
diff changeset
   696
                self.lines = mdiff.splitnewlines(data)
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   697
            if self.mode is None:
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   698
                self.mode = mode
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   699
            if self.lines:
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   700
                # Normalize line endings
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   701
                if self.lines[0].endswith(b'\r\n'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   702
                    self.eol = b'\r\n'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   703
                elif self.lines[0].endswith(b'\n'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   704
                    self.eol = b'\n'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   705
                if eolmode != b'strict':
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   706
                    nlines = []
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   707
                    for l in self.lines:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   708
                        if l.endswith(b'\r\n'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   709
                            l = l[:-2] + b'\n'
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   710
                        nlines.append(l)
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   711
                    self.lines = nlines
22296
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
   712
        else:
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
   713
            if self.create:
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   714
                self.missing = False
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   715
            if self.mode is None:
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   716
                self.mode = (False, False)
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   717
        if self.missing:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   718
            self.ui.warn(_(b"unable to find '%s' for patching\n") % self.fname)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   719
            self.ui.warn(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   720
                _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   721
                    b"(use '--prefix' to apply patch relative to the "
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   722
                    b"current directory)\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   723
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   724
            )
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   725
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   726
        self.hash = {}
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   727
        self.dirty = 0
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   728
        self.offset = 0
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   729
        self.skew = 0
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   730
        self.rej = []
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   731
        self.fileprinted = False
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   732
        self.printfile(False)
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   733
        self.hunks = 0
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   734
14367
468d7d1744b4 patch: set desired mode when patching, not in updatedir()
Patrick Mezard <pmezard@gmail.com>
parents: 14366
diff changeset
   735
    def writelines(self, fname, lines, mode):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   736
        if self.eolmode == b'auto':
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   737
            eol = self.eol
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   738
        elif self.eolmode == b'crlf':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   739
            eol = b'\r\n'
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   740
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   741
            eol = b'\n'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   742
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   743
        if self.eolmode != b'strict' and eol and eol != b'\n':
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   744
            rawlines = []
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   745
            for l in lines:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   746
                if l and l.endswith(b'\n'):
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   747
                    l = l[:-1] + eol
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   748
                rawlines.append(l)
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   749
            lines = rawlines
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   750
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   751
        self.backend.setfile(fname, b''.join(lines), mode, self.copysource)
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   752
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   753
    def printfile(self, warn):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   754
        if self.fileprinted:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   755
            return
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   756
        if warn or self.ui.verbose:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   757
            self.fileprinted = True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   758
        s = _(b"patching file %s\n") % self.fname
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   759
        if warn:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   760
            self.ui.warn(s)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   761
        else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   762
            self.ui.note(s)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   763
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   764
    def findlines(self, l, linenum):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   765
        # looks through the hash and finds candidate lines.  The
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   766
        # result is a list of line numbers sorted based on distance
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   767
        # from linenum
5143
d4fa6bafc43a Remove trailing spaces, fix indentation
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5116
diff changeset
   768
9681
ac3a68cb16eb patch: simplify logic
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9642
diff changeset
   769
        cand = self.hash.get(l, [])
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   770
        if len(cand) > 1:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   771
            # resort our list of potentials forward then back.
9032
1fa80c5428b8 compat: use 'key' argument instead of 'cmp' when sorting a list
Alejandro Santos <alejolp@alejolp.com>
parents: 9031
diff changeset
   772
            cand.sort(key=lambda x: abs(x - linenum))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   773
        return cand
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   774
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   775
    def write_rej(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   776
        # our rejects are a little different from patch(1).  This always
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   777
        # creates rejects in the same form as the original patch.  A file
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   778
        # header is inserted so that you can run the reject through patch again
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   779
        # without having to type the filename.
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   780
        if not self.rej:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   781
            return
14349
776ae95b8835 patch: merge makerejlines() into write_rej()
Patrick Mezard <pmezard@gmail.com>
parents: 14348
diff changeset
   782
        base = os.path.basename(self.fname)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   783
        lines = [b"--- %s\n+++ %s\n" % (base, base)]
14349
776ae95b8835 patch: merge makerejlines() into write_rej()
Patrick Mezard <pmezard@gmail.com>
parents: 14348
diff changeset
   784
        for x in self.rej:
776ae95b8835 patch: merge makerejlines() into write_rej()
Patrick Mezard <pmezard@gmail.com>
parents: 14348
diff changeset
   785
            for l in x.hunk:
776ae95b8835 patch: merge makerejlines() into write_rej()
Patrick Mezard <pmezard@gmail.com>
parents: 14348
diff changeset
   786
                lines.append(l)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   787
                if l[-1:] != b'\n':
45154
10f48720ef95 diff: move no-eol text constant to a common location
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 45098
diff changeset
   788
                    lines.append(b'\n' + diffhelper.MISSING_NEWLINE_MARKER)
14349
776ae95b8835 patch: merge makerejlines() into write_rej()
Patrick Mezard <pmezard@gmail.com>
parents: 14348
diff changeset
   789
        self.backend.writerej(self.fname, len(self.rej), self.hunks, lines)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   790
9393
23c4e772c172 patch: remove the unused, broken reverse() function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9392
diff changeset
   791
    def apply(self, h):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   792
        if not h.complete():
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   793
            raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   794
                _(b"bad hunk #%d %s (%d %d %d %d)")
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   795
                % (h.number, h.desc, len(h.a), h.lena, len(h.b), h.lenb)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   796
            )
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   797
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   798
        self.hunks += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   799
5652
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
   800
        if self.missing:
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
   801
            self.rej.append(h)
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
   802
            return -1
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
   803
14451
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
   804
        if self.exists and self.create:
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   805
            if self.copysource:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   806
                self.ui.warn(
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43106
diff changeset
   807
                    _(b"cannot create %s: destination already exists\n")
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   808
                    % self.fname
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   809
                )
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
   810
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   811
                self.ui.warn(_(b"file %s already exists\n") % self.fname)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   812
            self.rej.append(h)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   813
            return -1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   814
9585
ea1935e2020a patch: handle symlinks without symlinkhunk
Patrick Mezard <pmezard@gmail.com>
parents: 9573
diff changeset
   815
        if isinstance(h, binhunk):
14451
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
   816
            if self.remove:
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   817
                self.backend.unlink(self.fname)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   818
            else:
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
   819
                l = h.new(self.lines)
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
   820
                self.lines[:] = l
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
   821
                self.offset += len(l)
14217
71d5287351e9 patchfile: use real Booleans instead of 0/1
Martin Geisler <mg@aragost.com>
parents: 14017
diff changeset
   822
                self.dirty = True
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   823
            return 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   824
10127
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
   825
        horig = h
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   826
        if (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   827
            self.eolmode in (b'crlf', b'lf')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   828
            or self.eolmode == b'auto'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   829
            and self.eol
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   830
        ):
10128
ea7c392f2b08 patch: drop eol normalization fast-path for 'lf' and 'crlf'
Patrick Mezard <pmezard@gmail.com>
parents: 10127
diff changeset
   831
            # If new eols are going to be normalized, then normalize
ea7c392f2b08 patch: drop eol normalization fast-path for 'lf' and 'crlf'
Patrick Mezard <pmezard@gmail.com>
parents: 10127
diff changeset
   832
            # hunk data before patching. Otherwise, preserve input
ea7c392f2b08 patch: drop eol normalization fast-path for 'lf' and 'crlf'
Patrick Mezard <pmezard@gmail.com>
parents: 10127
diff changeset
   833
            # line-endings.
10127
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
   834
            h = h.getnormalized()
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
   835
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   836
        # fast case first, no offsets, no fuzz
16122
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
   837
        old, oldstart, new, newstart = h.fuzzit(0, False)
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
   838
        oldstart += self.offset
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
   839
        orig_start = oldstart
10135
9a4034b630c4 patch: better handling of sequence of offset patch hunks (issue1941)
Greg Onufer <gonufer@jazzhaiku.com>
parents: 9725
diff changeset
   840
        # if there's skew we want to emit the "(offset %d lines)" even
9a4034b630c4 patch: better handling of sequence of offset patch hunks (issue1941)
Greg Onufer <gonufer@jazzhaiku.com>
parents: 9725
diff changeset
   841
        # when the hunk cleanly applies at start + skew, so skip the
9a4034b630c4 patch: better handling of sequence of offset patch hunks (issue1941)
Greg Onufer <gonufer@jazzhaiku.com>
parents: 9725
diff changeset
   842
        # fast case code
37803
72f6498c040b diffhelper: rename module to avoid conflicts with ancient C module (issue5846)
Yuya Nishihara <yuya@tcha.org>
parents: 37764
diff changeset
   843
        if self.skew == 0 and diffhelper.testhunk(old, self.lines, oldstart):
14451
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
   844
            if self.remove:
14348
c1c719103392 patch: extract fs access from patchfile into fsbackend
Patrick Mezard <pmezard@gmail.com>
parents: 14347
diff changeset
   845
                self.backend.unlink(self.fname)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   846
            else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   847
                self.lines[oldstart : oldstart + len(old)] = new
16122
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
   848
                self.offset += len(new) - len(old)
14217
71d5287351e9 patchfile: use real Booleans instead of 0/1
Martin Geisler <mg@aragost.com>
parents: 14017
diff changeset
   849
                self.dirty = True
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   850
            return 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   851
13700
63307feb59dd patch: inline patchfile.hashlines()
Patrick Mezard <pmezard@gmail.com>
parents: 13699
diff changeset
   852
        # ok, we couldn't match the hunk. Lets look for offsets and fuzz it
63307feb59dd patch: inline patchfile.hashlines()
Patrick Mezard <pmezard@gmail.com>
parents: 13699
diff changeset
   853
        self.hash = {}
63307feb59dd patch: inline patchfile.hashlines()
Patrick Mezard <pmezard@gmail.com>
parents: 13699
diff changeset
   854
        for x, s in enumerate(self.lines):
63307feb59dd patch: inline patchfile.hashlines()
Patrick Mezard <pmezard@gmail.com>
parents: 13699
diff changeset
   855
            self.hash.setdefault(s, []).append(x)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   856
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   857
        for fuzzlen in pycompat.xrange(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   858
            self.ui.configint(b"patch", b"fuzz") + 1
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   859
        ):
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   860
            for toponly in [True, False]:
16122
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
   861
                old, oldstart, new, newstart = h.fuzzit(fuzzlen, toponly)
16123
b0c7525f826d patch: fix fuzzing of hunks without previous lines (issue3264)
Patrick Mezard <patrick@mezard.eu>
parents: 16122
diff changeset
   862
                oldstart = oldstart + self.offset + self.skew
b0c7525f826d patch: fix fuzzing of hunks without previous lines (issue3264)
Patrick Mezard <patrick@mezard.eu>
parents: 16122
diff changeset
   863
                oldstart = min(oldstart, len(self.lines))
b0c7525f826d patch: fix fuzzing of hunks without previous lines (issue3264)
Patrick Mezard <patrick@mezard.eu>
parents: 16122
diff changeset
   864
                if old:
b0c7525f826d patch: fix fuzzing of hunks without previous lines (issue3264)
Patrick Mezard <patrick@mezard.eu>
parents: 16122
diff changeset
   865
                    cand = self.findlines(old[0][1:], oldstart)
b0c7525f826d patch: fix fuzzing of hunks without previous lines (issue3264)
Patrick Mezard <patrick@mezard.eu>
parents: 16122
diff changeset
   866
                else:
b0c7525f826d patch: fix fuzzing of hunks without previous lines (issue3264)
Patrick Mezard <patrick@mezard.eu>
parents: 16122
diff changeset
   867
                    # Only adding lines with no or fuzzed context, just
b0c7525f826d patch: fix fuzzing of hunks without previous lines (issue3264)
Patrick Mezard <patrick@mezard.eu>
parents: 16122
diff changeset
   868
                    # take the skew in account
b0c7525f826d patch: fix fuzzing of hunks without previous lines (issue3264)
Patrick Mezard <patrick@mezard.eu>
parents: 16122
diff changeset
   869
                    cand = [oldstart]
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   870
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   871
                for l in cand:
37803
72f6498c040b diffhelper: rename module to avoid conflicts with ancient C module (issue5846)
Yuya Nishihara <yuya@tcha.org>
parents: 37764
diff changeset
   872
                    if not old or diffhelper.testhunk(old, self.lines, l):
16121
ccba74472af2 patch: fuzz old and new lines at the same time
Patrick Mezard <patrick@mezard.eu>
parents: 16112
diff changeset
   873
                        self.lines[l : l + len(old)] = new
ccba74472af2 patch: fuzz old and new lines at the same time
Patrick Mezard <patrick@mezard.eu>
parents: 16112
diff changeset
   874
                        self.offset += len(new) - len(old)
10135
9a4034b630c4 patch: better handling of sequence of offset patch hunks (issue1941)
Greg Onufer <gonufer@jazzhaiku.com>
parents: 9725
diff changeset
   875
                        self.skew = l - orig_start
14217
71d5287351e9 patchfile: use real Booleans instead of 0/1
Martin Geisler <mg@aragost.com>
parents: 14017
diff changeset
   876
                        self.dirty = True
10518
5fe51d348daf patch, i18n: avoid parameterized messages
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 10501
diff changeset
   877
                        offset = l - orig_start - fuzzlen
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   878
                        if fuzzlen:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   879
                            msg = _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   880
                                b"Hunk #%d succeeded at %d "
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   881
                                b"with fuzz %d "
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   882
                                b"(offset %d lines).\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   883
                            )
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   884
                            self.printfile(True)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   885
                            self.ui.warn(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   886
                                msg % (h.number, l + 1, fuzzlen, offset)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   887
                            )
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   888
                        else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   889
                            msg = _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   890
                                b"Hunk #%d succeeded at %d "
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   891
                                b"(offset %d lines).\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   892
                            )
10518
5fe51d348daf patch, i18n: avoid parameterized messages
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 10501
diff changeset
   893
                            self.ui.note(msg % (h.number, l + 1, offset))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   894
                        return fuzzlen
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   895
        self.printfile(True)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   896
        self.ui.warn(_(b"Hunk #%d FAILED at %d\n") % (h.number, orig_start))
10127
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
   897
        self.rej.append(horig)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   898
        return -1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
   899
13701
bc38ff7cb919 patch: move closefile() into patchfile.close()
Patrick Mezard <pmezard@gmail.com>
parents: 13700
diff changeset
   900
    def close(self):
bc38ff7cb919 patch: move closefile() into patchfile.close()
Patrick Mezard <pmezard@gmail.com>
parents: 13700
diff changeset
   901
        if self.dirty:
14367
468d7d1744b4 patch: set desired mode when patching, not in updatedir()
Patrick Mezard <pmezard@gmail.com>
parents: 14366
diff changeset
   902
            self.writelines(self.fname, self.lines, self.mode)
13701
bc38ff7cb919 patch: move closefile() into patchfile.close()
Patrick Mezard <pmezard@gmail.com>
parents: 13700
diff changeset
   903
        self.write_rej()
bc38ff7cb919 patch: move closefile() into patchfile.close()
Patrick Mezard <pmezard@gmail.com>
parents: 13700
diff changeset
   904
        return len(self.rej)
bc38ff7cb919 patch: move closefile() into patchfile.close()
Patrick Mezard <pmezard@gmail.com>
parents: 13700
diff changeset
   905
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   906
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   907
class header(object):
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   908
    """patch header
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   909
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   910
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   911
    diffgit_re = re.compile(b'diff --git a/(.*) b/(.*)$')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   912
    diff_re = re.compile(b'diff -r .* (.*)$')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   913
    allhunks_re = re.compile(b'(?:index|deleted file) ')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   914
    pretty_re = re.compile(b'(?:new file|deleted file) ')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   915
    special_re = re.compile(b'(?:index|deleted|copy|rename|new mode) ')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   916
    newfile_re = re.compile(b'(?:new file|copy to|rename to)')
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   917
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   918
    def __init__(self, header):
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   919
        self.header = header
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   920
        self.hunks = []
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   921
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   922
    def binary(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   923
        return any(h.startswith(b'index ') for h in self.header)
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   924
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   925
    def pretty(self, fp):
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   926
        for h in self.header:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   927
            if h.startswith(b'index '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   928
                fp.write(_(b'this modifies a binary file (all or nothing)\n'))
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   929
                break
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   930
            if self.pretty_re.match(h):
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   931
                fp.write(h)
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   932
                if self.binary():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   933
                    fp.write(_(b'this is a binary file\n'))
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   934
                break
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   935
            if h.startswith(b'---'):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   936
                fp.write(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   937
                    _(b'%d hunks, %d lines changed\n')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   938
                    % (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   939
                        len(self.hunks),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   940
                        sum([max(h.added, h.removed) for h in self.hunks]),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   941
                    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   942
                )
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   943
                break
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   944
            fp.write(h)
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   945
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   946
    def write(self, fp):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   947
        fp.write(b''.join(self.header))
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   948
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   949
    def allhunks(self):
25149
3f0744eeaeaf cleanup: use __builtins__.any instead of util.any
Augie Fackler <augie@google.com>
parents: 25138
diff changeset
   950
        return any(self.allhunks_re.match(h) for h in self.header)
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   951
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   952
    def files(self):
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   953
        match = self.diffgit_re.match(self.header[0])
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   954
        if match:
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   955
            fromfile, tofile = match.groups()
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   956
            if fromfile == tofile:
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   957
                return [fromfile]
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   958
            return [fromfile, tofile]
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   959
        else:
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   960
            return self.diff_re.match(self.header[0]).groups()
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   961
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   962
    def filename(self):
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   963
        return self.files()[-1]
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   964
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   965
    def __repr__(self):
43943
0671f0a19d93 patch: fix header.__repr__() to not have `b''` prefixes in file names
Matt Harbison <matt_harbison@yahoo.com>
parents: 43906
diff changeset
   966
        return '<header %s>' % (
0671f0a19d93 patch: fix header.__repr__() to not have `b''` prefixes in file names
Matt Harbison <matt_harbison@yahoo.com>
parents: 43906
diff changeset
   967
            ' '.join(pycompat.rapply(pycompat.fsdecode, self.files()))
0671f0a19d93 patch: fix header.__repr__() to not have `b''` prefixes in file names
Matt Harbison <matt_harbison@yahoo.com>
parents: 43906
diff changeset
   968
        )
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   969
24845
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   970
    def isnewfile(self):
25149
3f0744eeaeaf cleanup: use __builtins__.any instead of util.any
Augie Fackler <augie@google.com>
parents: 25138
diff changeset
   971
        return any(self.newfile_re.match(h) for h in self.header)
24845
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   972
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   973
    def special(self):
24845
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   974
        # Special files are shown only at the header level and not at the hunk
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   975
        # level for example a file that has been deleted is a special file.
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   976
        # The user cannot change the content of the operation, in the case of
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   977
        # the deleted file he has to take the deletion or not take it, he
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   978
        # cannot take some of it.
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   979
        # Newly added files are special if they are empty, they are not special
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   980
        # if they have some content as we want to be able to change it
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   981
        nocontent = len(self.header) == 2
8133494accf1 record: edit patch of newly added files (issue4304)
Laurent Charignon <lcharignon@fb.com>
parents: 24837
diff changeset
   982
        emptynewfile = self.isnewfile() and nocontent
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   983
        return emptynewfile or any(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   984
            self.special_re.match(h) for h in self.header
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   985
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   986
24261
20aac24e2114 record: move header class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24260
diff changeset
   987
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
   988
class recordhunk(object):
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
   989
    """patch hunk
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
   990
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
   991
    XXX shouldn't we merge this with the other hunk class?
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
   992
    """
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
   993
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   994
    def __init__(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   995
        self,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   996
        header,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   997
        fromline,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   998
        toline,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
   999
        proc,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1000
        before,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1001
        hunk,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1002
        after,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1003
        maxcontext=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1004
    ):
33270
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1005
        def trimcontext(lines, reverse=False):
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1006
            if maxcontext is not None:
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1007
                delta = len(lines) - maxcontext
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1008
                if delta > 0:
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1009
                    if reverse:
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1010
                        return delta, lines[delta:]
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1011
                    else:
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1012
                        return delta, lines[:maxcontext]
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1013
            return 0, lines
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1014
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1015
        self.header = header
33270
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1016
        trimedbefore, self.before = trimcontext(before, True)
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1017
        self.fromline = fromline + trimedbefore
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1018
        self.toline = toline + trimedbefore
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1019
        _trimedafter, self.after = trimcontext(after, False)
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1020
        self.proc = proc
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1021
        self.hunk = hunk
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1022
        self.added, self.removed = self.countchanges(self.hunk)
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1023
24346
31edcea517c1 record: add comparison methods for recordhunk class
Laurent Charignon <lcharignon@fb.com>
parents: 24341
diff changeset
  1024
    def __eq__(self, v):
31edcea517c1 record: add comparison methods for recordhunk class
Laurent Charignon <lcharignon@fb.com>
parents: 24341
diff changeset
  1025
        if not isinstance(v, recordhunk):
31edcea517c1 record: add comparison methods for recordhunk class
Laurent Charignon <lcharignon@fb.com>
parents: 24341
diff changeset
  1026
            return False
31edcea517c1 record: add comparison methods for recordhunk class
Laurent Charignon <lcharignon@fb.com>
parents: 24341
diff changeset
  1027
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1028
        return (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1029
            (v.hunk == self.hunk)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1030
            and (v.proc == self.proc)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1031
            and (self.fromline == v.fromline)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1032
            and (self.header.files() == v.header.files())
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1033
        )
24346
31edcea517c1 record: add comparison methods for recordhunk class
Laurent Charignon <lcharignon@fb.com>
parents: 24341
diff changeset
  1034
31edcea517c1 record: add comparison methods for recordhunk class
Laurent Charignon <lcharignon@fb.com>
parents: 24341
diff changeset
  1035
    def __hash__(self):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1036
        return hash(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1037
            (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1038
                tuple(self.hunk),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1039
                tuple(self.header.files()),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1040
                self.fromline,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1041
                self.proc,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1042
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1043
        )
24346
31edcea517c1 record: add comparison methods for recordhunk class
Laurent Charignon <lcharignon@fb.com>
parents: 24341
diff changeset
  1044
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1045
    def countchanges(self, hunk):
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1046
        """hunk -> (n+,n-)"""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1047
        add = len([h for h in hunk if h.startswith(b'+')])
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1048
        rem = len([h for h in hunk if h.startswith(b'-')])
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1049
        return add, rem
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1050
32979
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1051
    def reversehunk(self):
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1052
        """return another recordhunk which is the reverse of the hunk
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1053
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1054
        If this hunk is diff(A, B), the returned hunk is diff(B, A). To do
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1055
        that, swap fromline/toline and +/- signs while keep other things
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1056
        unchanged.
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1057
        """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1058
        m = {b'+': b'-', b'-': b'+', b'\\': b'\\'}
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1059
        hunk = [b'%s%s' % (m[l[0:1]], l[1:]) for l in self.hunk]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1060
        return recordhunk(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1061
            self.header,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1062
            self.toline,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1063
            self.fromline,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1064
            self.proc,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1065
            self.before,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1066
            hunk,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1067
            self.after,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1068
        )
32979
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1069
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1070
    def write(self, fp):
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1071
        delta = len(self.before) + len(self.after)
45154
10f48720ef95 diff: move no-eol text constant to a common location
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 45098
diff changeset
  1072
        if self.after and self.after[-1] == diffhelper.MISSING_NEWLINE_MARKER:
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1073
            delta -= 1
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1074
        fromlen = delta + self.removed
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1075
        tolen = delta + self.added
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1076
        fp.write(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1077
            b'@@ -%d,%d +%d,%d @@%s\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1078
            % (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1079
                self.fromline,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1080
                fromlen,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1081
                self.toline,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1082
                tolen,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1083
                self.proc and (b' ' + self.proc),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1084
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1085
        )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1086
        fp.write(b''.join(self.before + self.hunk + self.after))
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1087
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1088
    pretty = write
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1089
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1090
    def filename(self):
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1091
        return self.header.filename()
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1092
44247
c443b9ba6f63 py3: __repr__ needs to return str, not bytes
Kyle Lippincott <spectral@google.com>
parents: 44060
diff changeset
  1093
    @encoding.strmethod
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1094
    def __repr__(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1095
        return b'<hunk %r@%d>' % (self.filename(), self.fromline)
24263
a45d1c51109e record: move hunk class from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24261
diff changeset
  1096
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1097
34566
60213a2eca81 patch: do not cache translated messages (API)
Jun Wu <quark@fb.com>
parents: 34561
diff changeset
  1098
def getmessages():
60213a2eca81 patch: do not cache translated messages (API)
Jun Wu <quark@fb.com>
parents: 34561
diff changeset
  1099
    return {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1100
        b'multiple': {
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1101
            b'apply': _(b"apply change %d/%d to '%s'?"),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1102
            b'discard': _(b"discard change %d/%d to '%s'?"),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1103
            b'keep': _(b"keep change %d/%d to '%s'?"),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1104
            b'record': _(b"record change %d/%d to '%s'?"),
34566
60213a2eca81 patch: do not cache translated messages (API)
Jun Wu <quark@fb.com>
parents: 34561
diff changeset
  1105
        },
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1106
        b'single': {
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1107
            b'apply': _(b"apply this change to '%s'?"),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1108
            b'discard': _(b"discard this change to '%s'?"),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1109
            b'keep': _(b"keep this change to '%s'?"),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1110
            b'record': _(b"record this change to '%s'?"),
34566
60213a2eca81 patch: do not cache translated messages (API)
Jun Wu <quark@fb.com>
parents: 34561
diff changeset
  1111
        },
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1112
        b'help': {
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1113
            b'apply': _(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1114
                b'[Ynesfdaq?]'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1115
                b'$$ &Yes, apply this change'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1116
                b'$$ &No, skip this change'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1117
                b'$$ &Edit this change manually'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1118
                b'$$ &Skip remaining changes to this file'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1119
                b'$$ Apply remaining changes to this &file'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1120
                b'$$ &Done, skip remaining changes and files'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1121
                b'$$ Apply &all changes to all remaining files'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1122
                b'$$ &Quit, applying no changes'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1123
                b'$$ &? (display help)'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1124
            ),
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1125
            b'discard': _(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1126
                b'[Ynesfdaq?]'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1127
                b'$$ &Yes, discard this change'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1128
                b'$$ &No, skip this change'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1129
                b'$$ &Edit this change manually'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1130
                b'$$ &Skip remaining changes to this file'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1131
                b'$$ Discard remaining changes to this &file'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1132
                b'$$ &Done, skip remaining changes and files'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1133
                b'$$ Discard &all changes to all remaining files'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1134
                b'$$ &Quit, discarding no changes'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1135
                b'$$ &? (display help)'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1136
            ),
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1137
            b'keep': _(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1138
                b'[Ynesfdaq?]'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1139
                b'$$ &Yes, keep this change'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1140
                b'$$ &No, skip this change'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1141
                b'$$ &Edit this change manually'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1142
                b'$$ &Skip remaining changes to this file'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1143
                b'$$ Keep remaining changes to this &file'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1144
                b'$$ &Done, skip remaining changes and files'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1145
                b'$$ Keep &all changes to all remaining files'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1146
                b'$$ &Quit, keeping all changes'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1147
                b'$$ &? (display help)'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1148
            ),
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1149
            b'record': _(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1150
                b'[Ynesfdaq?]'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1151
                b'$$ &Yes, record this change'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1152
                b'$$ &No, skip this change'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1153
                b'$$ &Edit this change manually'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1154
                b'$$ &Skip remaining changes to this file'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1155
                b'$$ Record remaining changes to this &file'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1156
                b'$$ &Done, skip remaining changes and files'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1157
                b'$$ Record &all changes to all remaining files'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1158
                b'$$ &Quit, recording no changes'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1159
                b'$$ &? (display help)'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1160
            ),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1161
        },
34042
c0170d88ed2b patch: take messages out of the function so that extensions can add entries
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34013
diff changeset
  1162
    }
c0170d88ed2b patch: take messages out of the function so that extensions can add entries
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34013
diff changeset
  1163
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1164
42071
db72f9f6580e interactive: do not prompt about files given in command line
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 41987
diff changeset
  1165
def filterpatch(ui, headers, match, operation=None):
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1166
    """Interactively filter patch chunks into applied-only chunks"""
34566
60213a2eca81 patch: do not cache translated messages (API)
Jun Wu <quark@fb.com>
parents: 34561
diff changeset
  1167
    messages = getmessages()
60213a2eca81 patch: do not cache translated messages (API)
Jun Wu <quark@fb.com>
parents: 34561
diff changeset
  1168
25359
724421cb4745 record: add default value for operation argument
Laurent Charignon <lcharignon@fb.com>
parents: 25310
diff changeset
  1169
    if operation is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1170
        operation = b'record'
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1171
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1172
    def prompt(skipfile, skipall, query, chunk):
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1173
        """prompt query, and process base inputs
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1174
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1175
        - y/n for the rest of file
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1176
        - y/n for the rest
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1177
        - ? (help)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1178
        - q (quit)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1179
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1180
        Return True/False and possibly updated skipfile and skipall.
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1181
        """
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1182
        newpatches = None
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1183
        if skipall is not None:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1184
            return skipall, skipfile, skipall, newpatches
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1185
        if skipfile is not None:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1186
            return skipfile, skipfile, skipall, newpatches
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1187
        while True:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1188
            resps = messages[b'help'][operation]
42566
f802a75da585 patch: use a short, fixed-size message for last line of prompt (issue6158)
Kyle Lippincott <spectral@google.com>
parents: 42071
diff changeset
  1189
            # IMPORTANT: keep the last line of this prompt short (<40 english
f802a75da585 patch: use a short, fixed-size message for last line of prompt (issue6158)
Kyle Lippincott <spectral@google.com>
parents: 42071
diff changeset
  1190
            # chars is a good target) because of issue6158.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1191
            r = ui.promptchoice(b"%s\n(enter ? for help) %s" % (query, resps))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1192
            ui.write(b"\n")
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1193
            if r == 8:  # ?
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1194
                for c, t in ui.extractchoices(resps)[1]:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1195
                    ui.write(b'%s - %s\n' % (c, encoding.lower(t)))
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1196
                continue
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1197
            elif r == 0:  # yes
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1198
                ret = True
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1199
            elif r == 1:  # no
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1200
                ret = False
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1201
            elif r == 2:  # Edit patch
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1202
                if chunk is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1203
                    ui.write(_(b'cannot edit patch for whole file'))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1204
                    ui.write(b"\n")
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1205
                    continue
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1206
                if chunk.header.binary():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1207
                    ui.write(_(b'cannot edit patch for binary file'))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1208
                    ui.write(b"\n")
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1209
                    continue
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1210
                # Patch comment based on the Git one (based on comment at end of
26421
4b0fc75f9403 urls: bulk-change primary website URLs
Matt Mackall <mpm@selenic.com>
parents: 25660
diff changeset
  1211
                # https://mercurial-scm.org/wiki/RecordExtension)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1212
                phelp = b'---' + _(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1213
                    """
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1214
To remove '-' lines, make them ' ' lines (context).
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1215
To remove '+' lines, delete them.
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1216
Lines starting with # will be removed from the patch.
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1217
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1218
If the patch applies cleanly, the edited hunk will immediately be
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1219
added to the record list. If it does not apply cleanly, a rejects
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1220
file will be generated: you can use that when you try again. If
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1221
all lines of the hunk are removed, then the edit is aborted and
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1222
the hunk is left unchanged.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1223
"""
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1224
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1225
                (patchfd, patchfn) = pycompat.mkstemp(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1226
                    prefix=b"hg-editor-", suffix=b".diff"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1227
                )
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1228
                ncpatchfp = None
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1229
                try:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1230
                    # Write the initial patch
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
  1231
                    f = util.nativeeolwriter(os.fdopen(patchfd, 'wb'))
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1232
                    chunk.header.write(f)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1233
                    chunk.write(f)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1234
                    f.write(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1235
                        b''.join(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1236
                            [b'# ' + i + b'\n' for i in phelp.splitlines()]
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1237
                        )
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1238
                    )
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1239
                    f.close()
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1240
                    # Start the editor and wait for it to complete
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1241
                    editor = ui.geteditor()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1242
                    ret = ui.system(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1243
                        b"%s \"%s\"" % (editor, patchfn),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1244
                        environ={b'HGUSER': ui.username()},
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1245
                        blockedtag=b'filterpatch',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1246
                    )
25483
fb04372d7b38 record: exiting editor with non-zero status should not stop recording session
Laurent Charignon <lcharignon@fb.com>
parents: 25424
diff changeset
  1247
                    if ret != 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1248
                        ui.warn(_(b"editor exited with exit code %d\n") % ret)
25483
fb04372d7b38 record: exiting editor with non-zero status should not stop recording session
Laurent Charignon <lcharignon@fb.com>
parents: 25424
diff changeset
  1249
                        continue
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1250
                    # Remove comment lines
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
  1251
                    patchfp = open(patchfn, 'rb')
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28341
diff changeset
  1252
                    ncpatchfp = stringio()
30397
564b33acc21f patch: migrate to util.iterfile
Jun Wu <quark@fb.com>
parents: 30078
diff changeset
  1253
                    for line in util.iterfile(patchfp):
36838
c268ba15deb3 py3: open patch file in binary mode and convert eol manually
Yuya Nishihara <yuya@tcha.org>
parents: 36837
diff changeset
  1254
                        line = util.fromnativeeol(line)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1255
                        if not line.startswith(b'#'):
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1256
                            ncpatchfp.write(line)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1257
                    patchfp.close()
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1258
                    ncpatchfp.seek(0)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1259
                    newpatches = parsepatch(ncpatchfp)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1260
                finally:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1261
                    os.unlink(patchfn)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1262
                    del ncpatchfp
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1263
                # Signal that the chunk shouldn't be applied as-is, but
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1264
                # provide the new patch to be used instead.
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1265
                ret = False
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1266
            elif r == 3:  # Skip
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1267
                ret = skipfile = False
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1268
            elif r == 4:  # file (Record remaining)
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1269
                ret = skipfile = True
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1270
            elif r == 5:  # done, skip remaining
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1271
                ret = skipall = False
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1272
            elif r == 6:  # all
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1273
                ret = skipall = True
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1274
            elif r == 7:  # quit
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1275
                raise error.Abort(_(b'user quit'))
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1276
            return ret, skipfile, skipall, newpatches
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1277
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1278
    seen = set()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1279
    applied = {}  # 'filename' -> [] of chunks
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1280
    skipfile, skipall = None, None
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1281
    pos, total = 1, sum(len(h.hunks) for h in headers)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1282
    for h in headers:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1283
        pos += len(h.hunks)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1284
        skipfile = None
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1285
        fixoffset = 0
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1286
        hdr = b''.join(h.header)
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1287
        if hdr in seen:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1288
            continue
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1289
        seen.add(hdr)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1290
        if skipall is None:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1291
            h.pretty(ui)
42071
db72f9f6580e interactive: do not prompt about files given in command line
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 41987
diff changeset
  1292
        files = h.files()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1293
        msg = _(b'examine changes to %s?') % _(b' and ').join(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1294
            b"'%s'" % f for f in files
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1295
        )
42071
db72f9f6580e interactive: do not prompt about files given in command line
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 41987
diff changeset
  1296
        if all(match.exact(f) for f in files):
db72f9f6580e interactive: do not prompt about files given in command line
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 41987
diff changeset
  1297
            r, skipall, np = True, None, None
db72f9f6580e interactive: do not prompt about files given in command line
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 41987
diff changeset
  1298
        else:
db72f9f6580e interactive: do not prompt about files given in command line
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 41987
diff changeset
  1299
            r, skipfile, skipall, np = prompt(skipfile, skipall, msg, None)
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1300
        if not r:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1301
            continue
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1302
        applied[h.filename()] = [h]
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1303
        if h.allhunks():
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1304
            applied[h.filename()] += h.hunks
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1305
            continue
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1306
        for i, chunk in enumerate(h.hunks):
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1307
            if skipfile is None and skipall is None:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1308
                chunk.pretty(ui)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1309
            if total == 1:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1310
                msg = messages[b'single'][operation] % chunk.filename()
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1311
            else:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1312
                idx = pos - len(h.hunks) + i
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1313
                msg = messages[b'multiple'][operation] % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1314
                    idx,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1315
                    total,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1316
                    chunk.filename(),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1317
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1318
            r, skipfile, skipall, newpatches = prompt(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1319
                skipfile, skipall, msg, chunk
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1320
            )
24269
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1321
            if r:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1322
                if fixoffset:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1323
                    chunk = copy.copy(chunk)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1324
                    chunk.toline += fixoffset
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1325
                applied[chunk.filename()].append(chunk)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1326
            elif newpatches is not None:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1327
                for newpatch in newpatches:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1328
                    for newhunk in newpatch.hunks:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1329
                        if fixoffset:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1330
                            newhunk.toline += fixoffset
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1331
                        applied[newhunk.filename()].append(newhunk)
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1332
            else:
9a745ced79a9 record: move filterpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24268
diff changeset
  1333
                fixoffset += chunk.removed - chunk.added
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1334
    return (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1335
        sum(
43104
74802979dd9d py3: define and use pycompat.itervalues()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43097
diff changeset
  1336
            [
74802979dd9d py3: define and use pycompat.itervalues()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43097
diff changeset
  1337
                h
74802979dd9d py3: define and use pycompat.itervalues()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43097
diff changeset
  1338
                for h in pycompat.itervalues(applied)
74802979dd9d py3: define and use pycompat.itervalues()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43097
diff changeset
  1339
                if h[0].special() or len(h) > 1
74802979dd9d py3: define and use pycompat.itervalues()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43097
diff changeset
  1340
            ],
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1341
            [],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1342
        ),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1343
        {},
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1344
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1345
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1346
8778
c5f36402daad use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8761
diff changeset
  1347
class hunk(object):
14451
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
  1348
    def __init__(self, desc, num, lr, context):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1349
        self.number = num
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1350
        self.desc = desc
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
  1351
        self.hunk = [desc]
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1352
        self.a = []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1353
        self.b = []
9682
bd70f645cfb0 patch: initialize all attributes of the hunk class
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9681
diff changeset
  1354
        self.starta = self.lena = None
bd70f645cfb0 patch: initialize all attributes of the hunk class
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9681
diff changeset
  1355
        self.startb = self.lenb = None
10127
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1356
        if lr is not None:
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1357
            if context:
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1358
                self.read_context_hunk(lr)
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1359
            else:
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1360
                self.read_unified_hunk(lr)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1361
10127
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1362
    def getnormalized(self):
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1363
        """Return a copy with line endings normalized to LF."""
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1364
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1365
        def normalize(lines):
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1366
            nlines = []
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1367
            for line in lines:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1368
                if line.endswith(b'\r\n'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1369
                    line = line[:-2] + b'\n'
10127
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1370
                nlines.append(line)
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1371
            return nlines
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1372
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1373
        # Dummy object, it is rebuilt manually
14451
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
  1374
        nh = hunk(self.desc, self.number, None, None)
10127
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1375
        nh.number = self.number
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1376
        nh.desc = self.desc
10524
3212afb33116 patch: fix patching with fuzz and eol normalization
Patrick Mezard <pmezard@gmail.com>
parents: 10518
diff changeset
  1377
        nh.hunk = self.hunk
10127
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1378
        nh.a = normalize(self.a)
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1379
        nh.b = normalize(self.b)
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1380
        nh.starta = self.starta
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1381
        nh.startb = self.startb
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1382
        nh.lena = self.lena
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1383
        nh.lenb = self.lenb
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1384
        return nh
d8214e944b84 patch: fix eolmode=auto with new files
Patrick Mezard <pmezard@gmail.com>
parents: 10102
diff changeset
  1385
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1386
    def read_unified_hunk(self, lr):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1387
        m = unidesc.match(self.desc)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1388
        if not m:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1389
            raise PatchError(_(b"bad hunk #%d") % self.number)
15510
5414b56cfad6 patch: simplify hunk extents parsing
Patrick Mezard <pmezard@gmail.com>
parents: 15462
diff changeset
  1390
        self.starta, self.lena, self.startb, self.lenb = m.groups()
8527
f9a80054dd3c use 'x is None' instead of 'x == None'
Martin Geisler <mg@lazybytes.net>
parents: 8526
diff changeset
  1391
        if self.lena is None:
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1392
            self.lena = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1393
        else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1394
            self.lena = int(self.lena)
8527
f9a80054dd3c use 'x is None' instead of 'x == None'
Martin Geisler <mg@lazybytes.net>
parents: 8526
diff changeset
  1395
        if self.lenb is None:
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1396
            self.lenb = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1397
        else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1398
            self.lenb = int(self.lenb)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1399
        self.starta = int(self.starta)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1400
        self.startb = int(self.startb)
37573
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37571
diff changeset
  1401
        try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1402
            diffhelper.addlines(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1403
                lr, self.hunk, self.lena, self.lenb, self.a, self.b
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1404
            )
37573
49b82cdb5983 patch: error out if reached to EOF while reading hunk
Yuya Nishihara <yuya@tcha.org>
parents: 37571
diff changeset
  1405
        except error.ParseError as e:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1406
            raise PatchError(_(b"bad hunk #%d: %s") % (self.number, e))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1407
        # if we hit eof before finishing out the hunk, the last line will
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1408
        # be zero length.  Lets try to fix it up.
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1409
        while len(self.hunk[-1]) == 0:
6948
359e93ceee3a fix double indentation and trailing whitespace
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
  1410
            del self.hunk[-1]
359e93ceee3a fix double indentation and trailing whitespace
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
  1411
            del self.a[-1]
359e93ceee3a fix double indentation and trailing whitespace
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
  1412
            del self.b[-1]
359e93ceee3a fix double indentation and trailing whitespace
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
  1413
            self.lena -= 1
359e93ceee3a fix double indentation and trailing whitespace
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
  1414
            self.lenb -= 1
13699
d3c0e0033f13 patch: fix hunk newlines when parsing hunks, not in iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 13395
diff changeset
  1415
        self._fixnewline(lr)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1416
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1417
    def read_context_hunk(self, lr):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1418
        self.desc = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1419
        m = contextdesc.match(self.desc)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1420
        if not m:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1421
            raise PatchError(_(b"bad hunk #%d") % self.number)
15510
5414b56cfad6 patch: simplify hunk extents parsing
Patrick Mezard <pmezard@gmail.com>
parents: 15462
diff changeset
  1422
        self.starta, aend = m.groups()
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1423
        self.starta = int(self.starta)
8527
f9a80054dd3c use 'x is None' instead of 'x == None'
Martin Geisler <mg@lazybytes.net>
parents: 8526
diff changeset
  1424
        if aend is None:
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1425
            aend = self.starta
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1426
        self.lena = int(aend) - self.starta
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1427
        if self.starta:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1428
            self.lena += 1
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38773
diff changeset
  1429
        for x in pycompat.xrange(self.lena):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1430
            l = lr.readline()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1431
            if l.startswith(b'---'):
12825
61f48581d8ef Test applying context diffs
Patrick Mezard <pmezard@gmail.com>
parents: 12728
diff changeset
  1432
                # lines addition, old block is empty
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1433
                lr.push(l)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1434
                break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1435
            s = l[2:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1436
            if l.startswith(b'- ') or l.startswith(b'! '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1437
                u = b'-' + s
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1438
            elif l.startswith(b'  '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1439
                u = b' ' + s
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1440
            else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1441
                raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1442
                    _(b"bad hunk #%d old text line %d") % (self.number, x)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1443
                )
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1444
            self.a.append(u)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1445
            self.hunk.append(u)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1446
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1447
        l = lr.readline()
41534
47c92f8ed128 patch: properly escape \ in string literals
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41532
diff changeset
  1448
        if l.startswith(br'\ '):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1449
            s = self.a[-1][:-1]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1450
            self.a[-1] = s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1451
            self.hunk[-1] = s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1452
            l = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1453
        m = contextdesc.match(l)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1454
        if not m:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1455
            raise PatchError(_(b"bad hunk #%d") % self.number)
15510
5414b56cfad6 patch: simplify hunk extents parsing
Patrick Mezard <pmezard@gmail.com>
parents: 15462
diff changeset
  1456
        self.startb, bend = m.groups()
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1457
        self.startb = int(self.startb)
8527
f9a80054dd3c use 'x is None' instead of 'x == None'
Martin Geisler <mg@lazybytes.net>
parents: 8526
diff changeset
  1458
        if bend is None:
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1459
            bend = self.startb
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1460
        self.lenb = int(bend) - self.startb
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1461
        if self.startb:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1462
            self.lenb += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1463
        hunki = 1
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38773
diff changeset
  1464
        for x in pycompat.xrange(self.lenb):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1465
            l = lr.readline()
41534
47c92f8ed128 patch: properly escape \ in string literals
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41532
diff changeset
  1466
            if l.startswith(br'\ '):
12825
61f48581d8ef Test applying context diffs
Patrick Mezard <pmezard@gmail.com>
parents: 12728
diff changeset
  1467
                # XXX: the only way to hit this is with an invalid line range.
61f48581d8ef Test applying context diffs
Patrick Mezard <pmezard@gmail.com>
parents: 12728
diff changeset
  1468
                # The no-eol marker is not counted in the line range, but I
61f48581d8ef Test applying context diffs
Patrick Mezard <pmezard@gmail.com>
parents: 12728
diff changeset
  1469
                # guess there are diff(1) out there which behave differently.
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1470
                s = self.b[-1][:-1]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1471
                self.b[-1] = s
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
  1472
                self.hunk[hunki - 1] = s
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1473
                continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1474
            if not l:
12825
61f48581d8ef Test applying context diffs
Patrick Mezard <pmezard@gmail.com>
parents: 12728
diff changeset
  1475
                # line deletions, new block is empty and we hit EOF
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1476
                lr.push(l)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1477
                break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1478
            s = l[2:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1479
            if l.startswith(b'+ ') or l.startswith(b'! '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1480
                u = b'+' + s
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1481
            elif l.startswith(b'  '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1482
                u = b' ' + s
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1483
            elif len(self.b) == 0:
12825
61f48581d8ef Test applying context diffs
Patrick Mezard <pmezard@gmail.com>
parents: 12728
diff changeset
  1484
                # line deletions, new block is empty
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1485
                lr.push(l)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1486
                break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1487
            else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1488
                raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1489
                    _(b"bad hunk #%d old text line %d") % (self.number, x)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1490
                )
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1491
            self.b.append(s)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1492
            while True:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1493
                if hunki >= len(self.hunk):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1494
                    h = b""
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1495
                else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1496
                    h = self.hunk[hunki]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1497
                hunki += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1498
                if h == u:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1499
                    break
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1500
                elif h.startswith(b'-'):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1501
                    continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1502
                else:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
  1503
                    self.hunk.insert(hunki - 1, u)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1504
                    break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1505
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1506
        if not self.a:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1507
            # this happens when lines were only added to the hunk
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1508
            for x in self.hunk:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1509
                if x.startswith(b'-') or x.startswith(b' '):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1510
                    self.a.append(x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1511
        if not self.b:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1512
            # this happens when lines were only deleted from the hunk
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1513
            for x in self.hunk:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1514
                if x.startswith(b'+') or x.startswith(b' '):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1515
                    self.b.append(x[1:])
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1516
        # @@ -start,len +start,len @@
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1517
        self.desc = b"@@ -%d,%d +%d,%d @@\n" % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1518
            self.starta,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1519
            self.lena,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1520
            self.startb,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1521
            self.lenb,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1522
        )
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1523
        self.hunk[0] = self.desc
13699
d3c0e0033f13 patch: fix hunk newlines when parsing hunks, not in iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 13395
diff changeset
  1524
        self._fixnewline(lr)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1525
13699
d3c0e0033f13 patch: fix hunk newlines when parsing hunks, not in iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 13395
diff changeset
  1526
    def _fixnewline(self, lr):
d3c0e0033f13 patch: fix hunk newlines when parsing hunks, not in iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 13395
diff changeset
  1527
        l = lr.readline()
41534
47c92f8ed128 patch: properly escape \ in string literals
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41532
diff changeset
  1528
        if l.startswith(br'\ '):
37803
72f6498c040b diffhelper: rename module to avoid conflicts with ancient C module (issue5846)
Yuya Nishihara <yuya@tcha.org>
parents: 37764
diff changeset
  1529
            diffhelper.fixnewline(self.hunk, self.a, self.b)
13699
d3c0e0033f13 patch: fix hunk newlines when parsing hunks, not in iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 13395
diff changeset
  1530
        else:
d3c0e0033f13 patch: fix hunk newlines when parsing hunks, not in iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 13395
diff changeset
  1531
            lr.push(l)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1532
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1533
    def complete(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1534
        return len(self.a) == self.lena and len(self.b) == self.lenb
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1535
16121
ccba74472af2 patch: fuzz old and new lines at the same time
Patrick Mezard <patrick@mezard.eu>
parents: 16112
diff changeset
  1536
    def _fuzzit(self, old, new, fuzz, toponly):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1537
        # this removes context lines from the top and bottom of list 'l'.  It
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1538
        # checks the hunk to make sure only context lines are removed, and then
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1539
        # returns a new shortened list of lines.
16124
0e0060bf2f44 patch: fuzz more aggressively to match patch(1) behaviour
Patrick Mezard <patrick@mezard.eu>
parents: 16123
diff changeset
  1540
        fuzz = min(fuzz, len(old))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1541
        if fuzz:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1542
            top = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1543
            bot = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1544
            hlen = len(self.hunk)
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38773
diff changeset
  1545
            for x in pycompat.xrange(hlen - 1):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1546
                # the hunk starts with the @@ line, so use x+1
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1547
                if self.hunk[x + 1].startswith(b' '):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1548
                    top += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1549
                else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1550
                    break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1551
            if not toponly:
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38773
diff changeset
  1552
                for x in pycompat.xrange(hlen - 1):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1553
                    if self.hunk[hlen - bot - 1].startswith(b' '):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1554
                        bot += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1555
                    else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1556
                        break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1557
16124
0e0060bf2f44 patch: fuzz more aggressively to match patch(1) behaviour
Patrick Mezard <patrick@mezard.eu>
parents: 16123
diff changeset
  1558
            bot = min(fuzz, bot)
0e0060bf2f44 patch: fuzz more aggressively to match patch(1) behaviour
Patrick Mezard <patrick@mezard.eu>
parents: 16123
diff changeset
  1559
            top = min(fuzz, top)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1560
            return old[top : len(old) - bot], new[top : len(new) - bot], top
16122
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
  1561
        return old, new, 0
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1562
16121
ccba74472af2 patch: fuzz old and new lines at the same time
Patrick Mezard <patrick@mezard.eu>
parents: 16112
diff changeset
  1563
    def fuzzit(self, fuzz, toponly):
16122
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
  1564
        old, new, top = self._fuzzit(self.a, self.b, fuzz, toponly)
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
  1565
        oldstart = self.starta + top
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
  1566
        newstart = self.startb + top
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
  1567
        # zero length hunk ranges already have their start decremented
16650
fcb97d9a26cd patch: fix segfault against unified diffs which start line is zero
Yuya Nishihara <yuya@tcha.org>
parents: 16524
diff changeset
  1568
        if self.lena and oldstart > 0:
16122
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
  1569
            oldstart -= 1
16650
fcb97d9a26cd patch: fix segfault against unified diffs which start line is zero
Yuya Nishihara <yuya@tcha.org>
parents: 16524
diff changeset
  1570
        if self.lenb and newstart > 0:
16122
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
  1571
            newstart -= 1
9ef3a4a2c6c0 patch: make hunk.fuzzit() compute the fuzzed start locations
Patrick Mezard <patrick@mezard.eu>
parents: 16121
diff changeset
  1572
        return old, oldstart, new, newstart
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1573
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1574
14764
a7d5816087a9 classes: fix class style problems found by b071cd58af50
Thomas Arendsen Hein <thomas@intevation.de>
parents: 14695
diff changeset
  1575
class binhunk(object):
43787
be8552f25cab cleanup: fix docstring formatting
Matt Harbison <matt_harbison@yahoo.com>
parents: 43735
diff changeset
  1576
    """A binary patch file."""
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1577
16523
727068417b95 patch: include file name in binary patch error messages
Patrick Mezard <patrick@mezard.eu>
parents: 16522
diff changeset
  1578
    def __init__(self, lr, fname):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1579
        self.text = None
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  1580
        self.delta = False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1581
        self.hunk = [b'GIT binary patch\n']
16523
727068417b95 patch: include file name in binary patch error messages
Patrick Mezard <patrick@mezard.eu>
parents: 16522
diff changeset
  1582
        self._fname = fname
14384
9d59c596eb9e patch: construct and parse binary hunks at the same time
Patrick Mezard <pmezard@gmail.com>
parents: 14383
diff changeset
  1583
        self._read(lr)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1584
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1585
    def complete(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1586
        return self.text is not None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1587
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  1588
    def new(self, lines):
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  1589
        if self.delta:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1590
            return [applybindelta(self.text, b''.join(lines))]
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1591
        return [self.text]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1592
14384
9d59c596eb9e patch: construct and parse binary hunks at the same time
Patrick Mezard <pmezard@gmail.com>
parents: 14383
diff changeset
  1593
    def _read(self, lr):
16524
ed6a74312176 patch: be more tolerant with EOLs in binary diffs (issue2870)
Patrick Mezard <patrick@mezard.eu>
parents: 16523
diff changeset
  1594
        def getline(lr, hunk):
ed6a74312176 patch: be more tolerant with EOLs in binary diffs (issue2870)
Patrick Mezard <patrick@mezard.eu>
parents: 16523
diff changeset
  1595
            l = lr.readline()
ed6a74312176 patch: be more tolerant with EOLs in binary diffs (issue2870)
Patrick Mezard <patrick@mezard.eu>
parents: 16523
diff changeset
  1596
            hunk.append(l)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1597
            return l.rstrip(b'\r\n')
16524
ed6a74312176 patch: be more tolerant with EOLs in binary diffs (issue2870)
Patrick Mezard <patrick@mezard.eu>
parents: 16523
diff changeset
  1598
16567
aef3d0d4631c patch: clarify binary hunk parsing loop
Patrick Mezard <patrick@mezard.eu>
parents: 16524
diff changeset
  1599
        while True:
16524
ed6a74312176 patch: be more tolerant with EOLs in binary diffs (issue2870)
Patrick Mezard <patrick@mezard.eu>
parents: 16523
diff changeset
  1600
            line = getline(lr, self.hunk)
16567
aef3d0d4631c patch: clarify binary hunk parsing loop
Patrick Mezard <patrick@mezard.eu>
parents: 16524
diff changeset
  1601
            if not line:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1602
                raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1603
                    _(b'could not extract "%s" binary data') % self._fname
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1604
                )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1605
            if line.startswith(b'literal '):
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  1606
                size = int(line[8:].rstrip())
16567
aef3d0d4631c patch: clarify binary hunk parsing loop
Patrick Mezard <patrick@mezard.eu>
parents: 16524
diff changeset
  1607
                break
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1608
            if line.startswith(b'delta '):
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  1609
                size = int(line[6:].rstrip())
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  1610
                self.delta = True
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  1611
                break
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3329
diff changeset
  1612
        dec = []
16524
ed6a74312176 patch: be more tolerant with EOLs in binary diffs (issue2870)
Patrick Mezard <patrick@mezard.eu>
parents: 16523
diff changeset
  1613
        line = getline(lr, self.hunk)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1614
        while len(line) > 1:
36192
eb91ffdaaece py3: slice over bytes to prevent getting ascii values
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36046
diff changeset
  1615
            l = line[0:1]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1616
            if l <= b'Z' and l >= b'A':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1617
                l = ord(l) - ord(b'A') + 1
3374
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
  1618
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1619
                l = ord(l) - ord(b'a') + 27
16522
a8065323c003 patch: display a nice error for invalid base85 data
Patrick Mezard <patrick@mezard.eu>
parents: 16506
diff changeset
  1620
            try:
32201
4462a981e8df base85: proxy through util module
Yuya Nishihara <yuya@tcha.org>
parents: 32191
diff changeset
  1621
                dec.append(util.b85decode(line[1:])[:l])
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25658
diff changeset
  1622
            except ValueError as e:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1623
                raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1624
                    _(b'could not decode "%s" binary patch: %s')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1625
                    % (self._fname, stringutil.forcebytestr(e))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1626
                )
16524
ed6a74312176 patch: be more tolerant with EOLs in binary diffs (issue2870)
Patrick Mezard <patrick@mezard.eu>
parents: 16523
diff changeset
  1627
            line = getline(lr, self.hunk)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1628
        text = zlib.decompress(b''.join(dec))
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3329
diff changeset
  1629
        if len(text) != size:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1630
            raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1631
                _(b'"%s" length is %d bytes, should be %d')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1632
                % (self._fname, len(text), size)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1633
            )
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1634
        self.text = text
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3329
diff changeset
  1635
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1636
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1637
def parsefilename(str):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1638
    # --- filename \t|space stuff
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1639
    s = str[4:].rstrip(b'\r\n')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1640
    i = s.find(b'\t')
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1641
    if i < 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1642
        i = s.find(b' ')
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1643
        if i < 0:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1644
            return s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1645
    return s[:i]
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
  1646
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1647
25424
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1648
def reversehunks(hunks):
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1649
    '''reverse the signs in the hunks given as argument
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1650
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1651
    This function operates on hunks coming out of patch.filterpatch, that is
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1652
    a list of the form: [header1, hunk1, hunk2, header2...]. Example usage:
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1653
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34067
diff changeset
  1654
    >>> rawpatch = b"""diff --git a/folder1/g b/folder1/g
25424
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1655
    ... --- a/folder1/g
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1656
    ... +++ b/folder1/g
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1657
    ... @@ -1,7 +1,7 @@
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1658
    ... +firstline
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1659
    ...  c
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1660
    ...  1
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1661
    ...  2
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1662
    ... + 3
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1663
    ... -4
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1664
    ...  5
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1665
    ...  d
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1666
    ... +lastline"""
34253
5ce32fe7df34 py3: fix doctests in patch.py to be compatible with Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34252
diff changeset
  1667
    >>> hunks = parsepatch([rawpatch])
25424
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1668
    >>> hunkscomingfromfilterpatch = []
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1669
    >>> for h in hunks:
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1670
    ...     hunkscomingfromfilterpatch.append(h)
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1671
    ...     hunkscomingfromfilterpatch.extend(h.hunks)
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1672
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1673
    >>> reversedhunks = reversehunks(hunkscomingfromfilterpatch)
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28341
diff changeset
  1674
    >>> from . import util
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28341
diff changeset
  1675
    >>> fp = util.stringio()
25424
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1676
    >>> for c in reversedhunks:
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1677
    ...      c.write(fp)
34253
5ce32fe7df34 py3: fix doctests in patch.py to be compatible with Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34252
diff changeset
  1678
    >>> fp.seek(0) or None
25424
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1679
    >>> reversedpatch = fp.read()
34137
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
  1680
    >>> print(pycompat.sysstr(reversedpatch))
25424
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1681
    diff --git a/folder1/g b/folder1/g
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1682
    --- a/folder1/g
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1683
    +++ b/folder1/g
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1684
    @@ -1,4 +1,3 @@
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1685
    -firstline
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1686
     c
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1687
     1
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1688
     2
32979
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1689
    @@ -2,6 +1,6 @@
25424
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1690
     c
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1691
     1
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1692
     2
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1693
    - 3
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1694
    +4
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1695
     5
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1696
     d
32979
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1697
    @@ -6,3 +5,2 @@
25424
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1698
     5
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1699
     d
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1700
    -lastline
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1701
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1702
    '''
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1703
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1704
    newhunks = []
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1705
    for c in hunks:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1706
        if util.safehasattr(c, b'reversehunk'):
32979
66117dae87f9 patch: rewrite reversehunks (issue5337)
Jun Wu <quark@fb.com>
parents: 32370
diff changeset
  1707
            c = c.reversehunk()
25424
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1708
        newhunks.append(c)
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1709
    return newhunks
69609f43c752 revert: add an experimental config to use inverted selection
Laurent Charignon <lcharignon@fb.com>
parents: 25359
diff changeset
  1710
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1711
33270
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1712
def parsepatch(originalchunks, maxcontext=None):
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1713
    """patch -> [] of headers -> [] of hunks
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1714
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1715
    If maxcontext is not None, trim context lines if necessary.
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1716
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34067
diff changeset
  1717
    >>> rawpatch = b'''diff --git a/folder1/g b/folder1/g
33270
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1718
    ... --- a/folder1/g
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1719
    ... +++ b/folder1/g
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1720
    ... @@ -1,8 +1,10 @@
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1721
    ...  1
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1722
    ...  2
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1723
    ... -3
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1724
    ...  4
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1725
    ...  5
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1726
    ...  6
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1727
    ... +6.1
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1728
    ... +6.2
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1729
    ...  7
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1730
    ...  8
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1731
    ... +9'''
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1732
    >>> out = util.stringio()
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1733
    >>> headers = parsepatch([rawpatch], maxcontext=1)
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1734
    >>> for header in headers:
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1735
    ...     header.write(out)
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1736
    ...     for hunk in header.hunks:
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1737
    ...         hunk.write(out)
34137
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
  1738
    >>> print(pycompat.sysstr(out.getvalue()))
33270
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1739
    diff --git a/folder1/g b/folder1/g
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1740
    --- a/folder1/g
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1741
    +++ b/folder1/g
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1742
    @@ -2,3 +2,2 @@
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1743
     2
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1744
    -3
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1745
     4
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1746
    @@ -6,2 +5,4 @@
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1747
     6
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1748
    +6.1
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1749
    +6.2
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1750
     7
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1751
    @@ -8,1 +9,2 @@
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1752
     8
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1753
    +9
f7b635716ef2 patch: make parsepatch optionally trim context lines
Jun Wu <quark@fb.com>
parents: 33229
diff changeset
  1754
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1755
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1756
    class parser(object):
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1757
        """patch parsing state machine"""
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1758
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1759
        def __init__(self):
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1760
            self.fromline = 0
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1761
            self.toline = 0
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1762
            self.proc = b''
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1763
            self.header = None
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1764
            self.context = []
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1765
            self.before = []
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1766
            self.hunk = []
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1767
            self.headers = []
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1768
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1769
        def addrange(self, limits):
41454
d1d3094b54f9 patch: handle 0 context lines (diff.unified=0) when parsing patches
Kyle Lippincott <spectral@google.com>
parents: 41401
diff changeset
  1770
            self.addcontext([])
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1771
            fromstart, fromend, tostart, toend, proc = limits
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1772
            self.fromline = int(fromstart)
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1773
            self.toline = int(tostart)
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1774
            self.proc = proc
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1775
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1776
        def addcontext(self, context):
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1777
            if self.hunk:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1778
                h = recordhunk(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1779
                    self.header,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1780
                    self.fromline,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1781
                    self.toline,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1782
                    self.proc,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1783
                    self.before,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1784
                    self.hunk,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1785
                    context,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1786
                    maxcontext,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1787
                )
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1788
                self.header.hunks.append(h)
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1789
                self.fromline += len(self.before) + h.removed
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1790
                self.toline += len(self.before) + h.added
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1791
                self.before = []
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1792
                self.hunk = []
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1793
            self.context = context
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1794
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1795
        def addhunk(self, hunk):
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1796
            if self.context:
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1797
                self.before = self.context
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1798
                self.context = []
41454
d1d3094b54f9 patch: handle 0 context lines (diff.unified=0) when parsing patches
Kyle Lippincott <spectral@google.com>
parents: 41401
diff changeset
  1799
            if self.hunk:
d1d3094b54f9 patch: handle 0 context lines (diff.unified=0) when parsing patches
Kyle Lippincott <spectral@google.com>
parents: 41401
diff changeset
  1800
                self.addcontext([])
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1801
            self.hunk = hunk
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1802
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1803
        def newfile(self, hdr):
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1804
            self.addcontext([])
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1805
            h = header(hdr)
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1806
            self.headers.append(h)
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1807
            self.header = h
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1808
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1809
        def addother(self, line):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1810
            pass  # 'other' lines are ignored
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1811
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1812
        def finished(self):
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1813
            self.addcontext([])
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1814
            return self.headers
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1815
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1816
        transitions = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1817
            b'file': {
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1818
                b'context': addcontext,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1819
                b'file': newfile,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1820
                b'hunk': addhunk,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1821
                b'range': addrange,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1822
            },
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1823
            b'context': {
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1824
                b'file': newfile,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1825
                b'hunk': addhunk,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1826
                b'range': addrange,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1827
                b'other': addother,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1828
            },
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1829
            b'hunk': {
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1830
                b'context': addcontext,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1831
                b'file': newfile,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1832
                b'range': addrange,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1833
            },
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1834
            b'range': {b'context': addcontext, b'hunk': addhunk},
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1835
            b'other': {b'other': addother},
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1836
        }
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1837
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1838
    p = parser()
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28341
diff changeset
  1839
    fp = stringio()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1840
    fp.write(b''.join(originalchunks))
24341
616c01b69898 record: change interface of the filtering function
Laurent Charignon <lcharignon@fb.com>
parents: 24306
diff changeset
  1841
    fp.seek(0)
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1842
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1843
    state = b'context'
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1844
    for newstate, data in scanpatch(fp):
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1845
        try:
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1846
            p.transitions[state][newstate](p, data)
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1847
        except KeyError:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1848
            raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1849
                b'unhandled transition: %s -> %s' % (state, newstate)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1850
            )
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1851
        state = newstate
24341
616c01b69898 record: change interface of the filtering function
Laurent Charignon <lcharignon@fb.com>
parents: 24306
diff changeset
  1852
    del fp
24265
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1853
    return p.finished()
dc655360bccb record: move parsepatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24264
diff changeset
  1854
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1855
24244
5918bb365c72 patch.pathtransform: add a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24243
diff changeset
  1856
def pathtransform(path, strip, prefix):
24243
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1857
    '''turn a path from a patch into a path suitable for the repository
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1858
24244
5918bb365c72 patch.pathtransform: add a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24243
diff changeset
  1859
    prefix, if not empty, is expected to be normalized with a / at the end.
5918bb365c72 patch.pathtransform: add a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24243
diff changeset
  1860
24243
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1861
    Returns (stripped components, path in repository).
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1862
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34067
diff changeset
  1863
    >>> pathtransform(b'a/b/c', 0, b'')
24243
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1864
    ('', 'a/b/c')
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34067
diff changeset
  1865
    >>> pathtransform(b'   a/b/c   ', 0, b'')
24243
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1866
    ('', '   a/b/c')
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34067
diff changeset
  1867
    >>> pathtransform(b'   a/b/c   ', 2, b'')
24243
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1868
    ('a/b/', 'c')
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34067
diff changeset
  1869
    >>> pathtransform(b'a/b/c', 0, b'd/e/')
24385
885a573fa619 patch.pathtransform: prepend prefix even if strip is 0
Siddharth Agarwal <sid0@fb.com>
parents: 24371
diff changeset
  1870
    ('', 'd/e/a/b/c')
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34067
diff changeset
  1871
    >>> pathtransform(b'   a//b/c   ', 2, b'd/e/')
24244
5918bb365c72 patch.pathtransform: add a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24243
diff changeset
  1872
    ('a//b/', 'd/e/c')
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34067
diff changeset
  1873
    >>> pathtransform(b'a/b/c', 3, b'')
24243
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1874
    Traceback (most recent call last):
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1875
    PatchError: unable to strip away 1 of 3 dirs from a/b/c
daee2039dd11 patch.pathtransform: add doctests
Siddharth Agarwal <sid0@fb.com>
parents: 24242
diff changeset
  1876
    '''
11022
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1877
    pathlen = len(path)
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1878
    i = 0
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1879
    if strip == 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1880
        return b'', prefix + path.rstrip()
11022
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1881
    count = strip
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1882
    while count > 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1883
        i = path.find(b'/', i)
11022
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1884
        if i == -1:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1885
            raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1886
                _(b"unable to strip away %d of %d dirs from %s")
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1887
                % (count, strip, path)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1888
            )
11022
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1889
        i += 1
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1890
        # consume '//' in the path
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1891
        while i < pathlen - 1 and path[i : i + 1] == b'/':
11022
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1892
            i += 1
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1893
        count -= 1
24244
5918bb365c72 patch.pathtransform: add a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24243
diff changeset
  1894
    return path[:i].lstrip(), prefix + path[i:].rstrip()
11022
0429d0d49f92 patch: strip paths in leaked git patchmeta objects
Mads Kiilerich <mads@kiilerich.com>
parents: 11021
diff changeset
  1895
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1896
24245
740a17f885a1 patch.makepatchmeta: accept a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24244
diff changeset
  1897
def makepatchmeta(backend, afile_orig, bfile_orig, hunk, strip, prefix):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1898
    nulla = afile_orig == b"/dev/null"
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1899
    nullb = bfile_orig == b"/dev/null"
14451
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
  1900
    create = nulla and hunk.starta == 0 and hunk.lena == 0
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
  1901
    remove = nullb and hunk.startb == 0 and hunk.lenb == 0
24245
740a17f885a1 patch.makepatchmeta: accept a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24244
diff changeset
  1902
    abase, afile = pathtransform(afile_orig, strip, prefix)
14351
d54f9bbcc640 patch: add lexists() to backends, use it in selectfile()
Patrick Mezard <pmezard@gmail.com>
parents: 14350
diff changeset
  1903
    gooda = not nulla and backend.exists(afile)
24245
740a17f885a1 patch.makepatchmeta: accept a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24244
diff changeset
  1904
    bbase, bfile = pathtransform(bfile_orig, strip, prefix)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1905
    if afile == bfile:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1906
        goodb = gooda
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1907
    else:
14351
d54f9bbcc640 patch: add lexists() to backends, use it in selectfile()
Patrick Mezard <pmezard@gmail.com>
parents: 14350
diff changeset
  1908
        goodb = not nullb and backend.exists(bfile)
14451
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
  1909
    missing = not goodb and not gooda and not create
9328
648d6a1a1cf2 patch: create file even if source is not /dev/null
Brendan Cully <brendan@kublai.com>
parents: 9248
diff changeset
  1910
11820
75de514a50f3 patch: fix typo in comment
Martin Geisler <mg@aragost.com>
parents: 11645
diff changeset
  1911
    # some diff programs apparently produce patches where the afile is
75de514a50f3 patch: fix typo in comment
Martin Geisler <mg@aragost.com>
parents: 11645
diff changeset
  1912
    # not /dev/null, but afile starts with bfile
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1913
    abasedir = afile[: afile.rfind(b'/') + 1]
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1914
    bbasedir = bfile[: bfile.rfind(b'/') + 1]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1915
    if (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1916
        missing
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1917
        and abasedir == bbasedir
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1918
        and afile.startswith(bfile)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1919
        and hunk.starta == 0
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1920
        and hunk.lena == 0
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1921
    ):
14451
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
  1922
        create = True
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
  1923
        missing = False
9328
648d6a1a1cf2 patch: create file even if source is not /dev/null
Brendan Cully <brendan@kublai.com>
parents: 9248
diff changeset
  1924
6295
bace1990ab12 patch: fix corner case with update + copy patch handling (issue 937)
Patrick Mezard <pmezard@gmail.com>
parents: 6280
diff changeset
  1925
    # If afile is "a/b/foo" and bfile is "a/b/foo.orig" we assume the
bace1990ab12 patch: fix corner case with update + copy patch handling (issue 937)
Patrick Mezard <pmezard@gmail.com>
parents: 6280
diff changeset
  1926
    # diff is between a file and its backup. In this case, the original
bace1990ab12 patch: fix corner case with update + copy patch handling (issue 937)
Patrick Mezard <pmezard@gmail.com>
parents: 6280
diff changeset
  1927
    # file should be patched (see original mpatch code).
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1928
    isbackup = abase == bbase and bfile.startswith(afile)
5652
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
  1929
    fname = None
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
  1930
    if not missing:
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
  1931
        if gooda and goodb:
24306
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  1932
            if isbackup:
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  1933
                fname = afile
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  1934
            else:
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  1935
                fname = bfile
5652
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
  1936
        elif gooda:
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1937
            fname = afile
5760
0145f9afb0e7 Removed tabs and trailing whitespace in python files
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5706
diff changeset
  1938
5652
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
  1939
    if not fname:
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
  1940
        if not nullb:
24306
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  1941
            if isbackup:
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  1942
                fname = afile
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  1943
            else:
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  1944
                fname = bfile
5652
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
  1945
        elif not nulla:
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1946
            fname = afile
5652
e90e72c6b4c7 patch: write rej files for missing targets (issue 853)
Patrick Mezard <pmezard@gmail.com>
parents: 5651
diff changeset
  1947
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1948
            raise PatchError(_(b"undefined source and destination files"))
5760
0145f9afb0e7 Removed tabs and trailing whitespace in python files
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5706
diff changeset
  1949
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  1950
    gp = patchmeta(fname)
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  1951
    if create:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1952
        gp.op = b'ADD'
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  1953
    elif remove:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1954
        gp.op = b'DELETE'
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  1955
    return gp
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  1956
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1957
24264
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1958
def scanpatch(fp):
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1959
    """like patch.iterhunks, but yield different events
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1960
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1961
    - ('file',    [header_lines + fromfile + tofile])
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1962
    - ('context', [context_lines])
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1963
    - ('hunk',    [hunk_lines])
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1964
    - ('range',   (-start,len, +start,len, proc))
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1965
    """
34066
871a58b5f428 py3: fix type of regex literals in patch.py
Yuya Nishihara <yuya@tcha.org>
parents: 34042
diff changeset
  1966
    lines_re = re.compile(br'@@ -(\d+),(\d+) \+(\d+),(\d+) @@\s*(.*)')
24264
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1967
    lr = linereader(fp)
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1968
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1969
    def scanwhile(first, p):
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1970
        """scan lr while predicate holds"""
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1971
        lines = [first]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1972
        for line in iter(lr.readline, b''):
24264
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1973
            if p(line):
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1974
                lines.append(line)
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1975
            else:
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1976
                lr.push(line)
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1977
                break
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1978
        return lines
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1979
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1980
    for line in iter(lr.readline, b''):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1981
        if line.startswith(b'diff --git a/') or line.startswith(b'diff -r '):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1982
24264
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1983
            def notheader(line):
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1984
                s = line.split(None, 1)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1985
                return not s or s[0] not in (b'---', b'diff')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  1986
24264
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1987
            header = scanwhile(line, notheader)
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1988
            fromfile = lr.readline()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1989
            if fromfile.startswith(b'---'):
24264
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1990
                tofile = lr.readline()
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1991
                header += [fromfile, tofile]
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1992
            else:
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  1993
                lr.push(fromfile)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1994
            yield b'file', header
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1995
        elif line.startswith(b' '):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1996
            cs = (b' ', b'\\')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1997
            yield b'context', scanwhile(line, lambda l: l.startswith(cs))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1998
        elif line.startswith((b'-', b'+')):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1999
            cs = (b'-', b'+', b'\\')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2000
            yield b'hunk', scanwhile(line, lambda l: l.startswith(cs))
24264
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  2001
        else:
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  2002
            m = lines_re.match(line)
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  2003
            if m:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2004
                yield b'range', m.groups()
24264
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  2005
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2006
                yield b'other', line
24264
c4205452f1b7 record: move scanpatch from record to patch
Laurent Charignon <lcharignon@fb.com>
parents: 24263
diff changeset
  2007
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2008
7152
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2009
def scangitpatch(lr, firstline):
7186
f77c8d8331ca clean up trailing spaces, leading spaces in C
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7153
diff changeset
  2010
    """
7152
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2011
    Git patches can emit:
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2012
    - rename a to b
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2013
    - change b
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2014
    - copy a to c
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2015
    - change c
7186
f77c8d8331ca clean up trailing spaces, leading spaces in C
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7153
diff changeset
  2016
7152
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2017
    We cannot apply this sequence as-is, the renamed 'a' could not be
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2018
    found for it would have been renamed already. And we cannot copy
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2019
    from 'b' instead because 'b' would have been changed already. So
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2020
    we scan the git patch for copy and rename commands so we can
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2021
    perform the copies ahead of time.
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2022
    """
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2023
    pos = 0
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2024
    try:
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2025
        pos = lr.fp.tell()
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2026
        fp = lr.fp
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2027
    except IOError:
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28341
diff changeset
  2028
        fp = stringio(lr.fp.read())
14418
0174d1f79280 patch: remove EOL support from linereader class
Patrick Mezard <pmezard@gmail.com>
parents: 14402
diff changeset
  2029
    gitlr = linereader(fp)
7152
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2030
    gitlr.push(firstline)
12669
b0fa39c68370 patch: remove unused flags from readgitpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 12645
diff changeset
  2031
    gitpatches = readgitpatch(gitlr)
7152
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2032
    fp.seek(pos)
12669
b0fa39c68370 patch: remove unused flags from readgitpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 12645
diff changeset
  2033
    return gitpatches
7152
f0055cec8446 patch: pass linereader to scangitpatch(), extract from iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 7151
diff changeset
  2034
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2035
14240
28762bb767dc patch: remove unused ui arg to iterhunks
Idan Kamara <idankk86@gmail.com>
parents: 14234
diff changeset
  2036
def iterhunks(fp):
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2037
    """Read a patch and yield the following events:
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2038
    - ("file", afile, bfile, firsthunk): select a new target file.
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2039
    - ("hunk", hunk): a new hunk is ready to be applied, follows a
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2040
    "file" event.
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2041
    - ("git", gitchanges): current diff is in git format, gitchanges
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2042
    maps filenames to gitpatch records. Unique event.
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2043
    """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2044
    afile = b""
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2045
    bfile = b""
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2046
    state = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2047
    hunknum = 0
14017
19a7b48446e3 patch: remove redundant variable in iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 13971
diff changeset
  2048
    emitfile = newfile = False
14388
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2049
    gitpatches = None
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
  2050
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2051
    # our states
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2052
    BFILE = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2053
    context = None
10128
ea7c392f2b08 patch: drop eol normalization fast-path for 'lf' and 'crlf'
Patrick Mezard <pmezard@gmail.com>
parents: 10127
diff changeset
  2054
    lr = linereader(fp)
2861
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
  2055
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2056
    for x in iter(lr.readline, b''):
14383
1bd52cb12a55 patch: refactor iterhunks() regular and binary files emission
Patrick Mezard <pmezard@gmail.com>
parents: 14382
diff changeset
  2057
        if state == BFILE and (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2058
            (not context and x.startswith(b'@'))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2059
            or (context is not False and x.startswith(b'***************'))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2060
            or x.startswith(b'GIT binary patch')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2061
        ):
14388
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2062
            gp = None
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2063
            if gitpatches and gitpatches[-1].ispatching(afile, bfile):
16506
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
  2064
                gp = gitpatches.pop()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2065
            if x.startswith(b'GIT binary patch'):
16523
727068417b95 patch: include file name in binary patch error messages
Patrick Mezard <patrick@mezard.eu>
parents: 16522
diff changeset
  2066
                h = binhunk(lr, gp.path)
14383
1bd52cb12a55 patch: refactor iterhunks() regular and binary files emission
Patrick Mezard <pmezard@gmail.com>
parents: 14382
diff changeset
  2067
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2068
                if context is None and x.startswith(b'***************'):
14383
1bd52cb12a55 patch: refactor iterhunks() regular and binary files emission
Patrick Mezard <pmezard@gmail.com>
parents: 14382
diff changeset
  2069
                    context = True
14451
c78d41db6f88 patch: refactor file creation/removal detection
Patrick Mezard <pmezard@gmail.com>
parents: 14437
diff changeset
  2070
                h = hunk(x, hunknum + 1, lr, context)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2071
            hunknum += 1
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2072
            if emitfile:
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2073
                emitfile = False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2074
                yield b'file', (afile, bfile, h, gp and gp.copy() or None)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2075
            yield b'hunk', h
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2076
        elif x.startswith(b'diff --git a/'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2077
            m = gitre.match(x.rstrip(b' \r\n'))
14387
e1b4a7a7263a patch: reindent code
Patrick Mezard <pmezard@gmail.com>
parents: 14386
diff changeset
  2078
            if not m:
e1b4a7a7263a patch: reindent code
Patrick Mezard <pmezard@gmail.com>
parents: 14386
diff changeset
  2079
                continue
16506
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
  2080
            if gitpatches is None:
14387
e1b4a7a7263a patch: reindent code
Patrick Mezard <pmezard@gmail.com>
parents: 14386
diff changeset
  2081
                # scan whole input for git metadata
16506
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
  2082
                gitpatches = scangitpatch(lr, x)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2083
                yield b'git', [
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2084
                    g.copy() for g in gitpatches if g.op in (b'COPY', b'RENAME')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2085
                ]
14388
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2086
                gitpatches.reverse()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2087
            afile = b'a/' + m.group(1)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2088
            bfile = b'b/' + m.group(2)
16506
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
  2089
            while gitpatches and not gitpatches[-1].ispatching(afile, bfile):
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
  2090
                gp = gitpatches.pop()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2091
                yield b'file', (
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2092
                    b'a/' + gp.path,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2093
                    b'b/' + gp.path,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2094
                    None,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2095
                    gp.copy(),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2096
                )
16506
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
  2097
            if not gitpatches:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2098
                raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2099
                    _(b'failed to synchronize metadata for "%s"') % afile[2:]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2100
                )
14387
e1b4a7a7263a patch: reindent code
Patrick Mezard <pmezard@gmail.com>
parents: 14386
diff changeset
  2101
            newfile = True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2102
        elif x.startswith(b'---'):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2103
            # check for a unified diff
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2104
            l2 = lr.readline()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2105
            if not l2.startswith(b'+++'):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2106
                lr.push(l2)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2107
                continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2108
            newfile = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2109
            context = False
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2110
            afile = parsefilename(x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2111
            bfile = parsefilename(l2)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2112
        elif x.startswith(b'***'):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2113
            # check for a context diff
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2114
            l2 = lr.readline()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2115
            if not l2.startswith(b'---'):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2116
                lr.push(l2)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2117
                continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2118
            l3 = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2119
            lr.push(l3)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2120
            if not l3.startswith(b"***************"):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2121
                lr.push(l2)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2122
                continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2123
            newfile = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2124
            context = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2125
            afile = parsefilename(x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2126
            bfile = parsefilename(l2)
3057
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3056
diff changeset
  2127
14017
19a7b48446e3 patch: remove redundant variable in iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 13971
diff changeset
  2128
        if newfile:
19a7b48446e3 patch: remove redundant variable in iterhunks()
Patrick Mezard <pmezard@gmail.com>
parents: 13971
diff changeset
  2129
            newfile = False
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2130
            emitfile = True
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2131
            state = BFILE
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2132
            hunknum = 0
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2133
14388
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2134
    while gitpatches:
16506
fc4e0fecf403 patch: fix patch hunk/metdata synchronization (issue3384)
Patrick Mezard <patrick@mezard.eu>
parents: 16475
diff changeset
  2135
        gp = gitpatches.pop()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2136
        yield b'file', (b'a/' + gp.path, b'b/' + gp.path, None, gp.copy())
14388
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2137
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2138
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2139
def applybindelta(binchunk, data):
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2140
    """Apply a binary delta hunk
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2141
    The algorithm used is the algorithm from git's patch-delta.c
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2142
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2143
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2144
    def deltahead(binchunk):
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2145
        i = 0
38085
e887381e2976 py3: bytestr() bytes to get bytechar while iterating on it
Pulkit Goyal <7895pulkit@gmail.com>
parents: 38084
diff changeset
  2146
        for c in pycompat.bytestr(binchunk):
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2147
            i += 1
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2148
            if not (ord(c) & 0x80):
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2149
                return i
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2150
        return i
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2151
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2152
    out = b""
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2153
    s = deltahead(binchunk)
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2154
    binchunk = binchunk[s:]
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2155
    s = deltahead(binchunk)
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2156
    binchunk = binchunk[s:]
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2157
    i = 0
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2158
    while i < len(binchunk):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2159
        cmd = ord(binchunk[i : i + 1])
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2160
        i += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2161
        if cmd & 0x80:
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2162
            offset = 0
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2163
            size = 0
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2164
            if cmd & 0x01:
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2165
                offset = ord(binchunk[i : i + 1])
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2166
                i += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2167
            if cmd & 0x02:
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2168
                offset |= ord(binchunk[i : i + 1]) << 8
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2169
                i += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2170
            if cmd & 0x04:
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2171
                offset |= ord(binchunk[i : i + 1]) << 16
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2172
                i += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2173
            if cmd & 0x08:
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2174
                offset |= ord(binchunk[i : i + 1]) << 24
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2175
                i += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2176
            if cmd & 0x10:
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2177
                size = ord(binchunk[i : i + 1])
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2178
                i += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2179
            if cmd & 0x20:
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2180
                size |= ord(binchunk[i : i + 1]) << 8
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2181
                i += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2182
            if cmd & 0x40:
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2183
                size |= ord(binchunk[i : i + 1]) << 16
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2184
                i += 1
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2185
            if size == 0:
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2186
                size = 0x10000
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2187
            offset_end = offset + size
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2188
            out += data[offset:offset_end]
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2189
        elif cmd != 0:
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2190
            offset_end = i + cmd
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2191
            out += binchunk[i:offset_end]
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2192
            i += cmd
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2193
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2194
            raise PatchError(_(b'unexpected delta opcode 0'))
20137
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2195
    return out
9f1d4323c749 patch: add support for git delta hunks
Nicolas Vigier <boklm@mars-attacks.org>
parents: 20035
diff changeset
  2196
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2197
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2198
def applydiff(ui, fp, backend, store, strip=1, prefix=b'', eolmode=b'strict'):
10966
91c58cf54eee patch: refactor applydiff to allow for mempatching
Augie Fackler <durin42@gmail.com>
parents: 10965
diff changeset
  2199
    """Reads a patch from fp and tries to apply it.
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2200
14565
3cacc232f27f patch: stop updating changed files set in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14564
diff changeset
  2201
    Returns 0 for a clean patch, -1 if any rejects were found and 1 if
3cacc232f27f patch: stop updating changed files set in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14564
diff changeset
  2202
    there was any fuzz.
8810
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2203
10101
155fe35534d3 patch: propagate eolmode down to patchfile
Martin Geisler <mg@lazybytes.net>
parents: 9725
diff changeset
  2204
    If 'eolmode' is 'strict', the patch content and patched file are
155fe35534d3 patch: propagate eolmode down to patchfile
Martin Geisler <mg@lazybytes.net>
parents: 9725
diff changeset
  2205
    read in binary mode. Otherwise, line endings are ignored when
155fe35534d3 patch: propagate eolmode down to patchfile
Martin Geisler <mg@lazybytes.net>
parents: 9725
diff changeset
  2206
    patching then normalized according to 'eolmode'.
8810
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2207
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2208
    return _applydiff(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2209
        ui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2210
        fp,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2211
        patchfile,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2212
        backend,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2213
        store,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2214
        strip=strip,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2215
        prefix=prefix,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2216
        eolmode=eolmode,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2217
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2218
10966
91c58cf54eee patch: refactor applydiff to allow for mempatching
Augie Fackler <durin42@gmail.com>
parents: 10965
diff changeset
  2219
35062
1706eae096e2 patch: accept prefix argument to changedfiles() helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 34968
diff changeset
  2220
def _canonprefix(repo, prefix):
1706eae096e2 patch: accept prefix argument to changedfiles() helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 34968
diff changeset
  2221
    if prefix:
1706eae096e2 patch: accept prefix argument to changedfiles() helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 34968
diff changeset
  2222
        prefix = pathutil.canonpath(repo.root, repo.getcwd(), prefix)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2223
        if prefix != b'':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2224
            prefix += b'/'
35062
1706eae096e2 patch: accept prefix argument to changedfiles() helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 34968
diff changeset
  2225
    return prefix
1706eae096e2 patch: accept prefix argument to changedfiles() helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 34968
diff changeset
  2226
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2227
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2228
def _applydiff(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2229
    ui, fp, patcher, backend, store, strip=1, prefix=b'', eolmode=b'strict'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2230
):
35062
1706eae096e2 patch: accept prefix argument to changedfiles() helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 34968
diff changeset
  2231
    prefix = _canonprefix(backend.repo, prefix)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2232
14389
909ac6b9636b patch: stop modifying gitpatch objects
Patrick Mezard <pmezard@gmail.com>
parents: 14388
diff changeset
  2233
    def pstrip(p):
24246
394a91cb3d4a patch._applydiff: accept a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24245
diff changeset
  2234
        return pathtransform(p, strip - 1, prefix)[1]
14389
909ac6b9636b patch: stop modifying gitpatch objects
Patrick Mezard <pmezard@gmail.com>
parents: 14388
diff changeset
  2235
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2236
    rejects = 0
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2237
    err = 0
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2238
    current_file = None
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2239
14240
28762bb767dc patch: remove unused ui arg to iterhunks
Idan Kamara <idankk86@gmail.com>
parents: 14234
diff changeset
  2240
    for state, values in iterhunks(fp):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2241
        if state == b'hunk':
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2242
            if not current_file:
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2243
                continue
11021
c47a1cfad572 patch: minor cleanup of _applydiff
Mads Kiilerich <mads@kiilerich.com>
parents: 11020
diff changeset
  2244
            ret = current_file.apply(values)
14565
3cacc232f27f patch: stop updating changed files set in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14564
diff changeset
  2245
            if ret > 0:
3cacc232f27f patch: stop updating changed files set in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14564
diff changeset
  2246
                err = 1
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2247
        elif state == b'file':
13701
bc38ff7cb919 patch: move closefile() into patchfile.close()
Patrick Mezard <pmezard@gmail.com>
parents: 13700
diff changeset
  2248
            if current_file:
bc38ff7cb919 patch: move closefile() into patchfile.close()
Patrick Mezard <pmezard@gmail.com>
parents: 13700
diff changeset
  2249
                rejects += current_file.close()
14388
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2250
                current_file = None
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2251
            afile, bfile, first_hunk, gp = values
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2252
            if gp:
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2253
                gp.path = pstrip(gp.path)
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
  2254
                if gp.oldpath:
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2255
                    gp.oldpath = pstrip(gp.oldpath)
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2256
            else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2257
                gp = makepatchmeta(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2258
                    backend, afile, bfile, first_hunk, strip, prefix
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2259
                )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2260
            if gp.op == b'RENAME':
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2261
                backend.unlink(gp.oldpath)
14388
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2262
            if not first_hunk:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2263
                if gp.op == b'DELETE':
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2264
                    backend.unlink(gp.path)
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2265
                    continue
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2266
                data, mode = None, None
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2267
                if gp.op in (b'RENAME', b'COPY'):
14609
f53dc0787424 patch: extend filtestore to store an optional copy source
Patrick Mezard <pmezard@gmail.com>
parents: 14566
diff changeset
  2268
                    data, mode = store.getfile(gp.oldpath)[:2]
30078
173bdb502503 import: abort instead of crashing when copy source does not exist (issue5375)
Ryan McElroy <rmcelroy@fb.com>
parents: 29948
diff changeset
  2269
                    if data is None:
173bdb502503 import: abort instead of crashing when copy source does not exist (issue5375)
Ryan McElroy <rmcelroy@fb.com>
parents: 29948
diff changeset
  2270
                        # This means that the old path does not exist
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2271
                        raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2272
                            _(b"source file '%s' does not exist") % gp.oldpath
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2273
                        )
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2274
                if gp.mode:
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2275
                    mode = gp.mode
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2276
                    if gp.op == b'ADD':
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2277
                        # Added files without content have no hunk and
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2278
                        # must be created
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2279
                        data = b''
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2280
                if data or mode:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2281
                    if gp.op in (b'ADD', b'RENAME', b'COPY') and backend.exists(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2282
                        gp.path
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2283
                    ):
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2284
                        raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2285
                            _(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2286
                                b"cannot create %s: destination "
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2287
                                b"already exists"
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2288
                            )
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2289
                            % gp.path
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2290
                        )
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2291
                    backend.setfile(gp.path, data, mode, gp.oldpath)
14388
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2292
                continue
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2293
            try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2294
                current_file = patcher(ui, gp, backend, store, eolmode=eolmode)
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25658
diff changeset
  2295
            except PatchError as inst:
43723
eab0b7383cd3 patch: fix a str + bytes issue in an exception handler
Matt Harbison <matt_harbison@yahoo.com>
parents: 43166
diff changeset
  2296
                ui.warn(stringutil.forcebytestr(inst) + b'\n')
11021
c47a1cfad572 patch: minor cleanup of _applydiff
Mads Kiilerich <mads@kiilerich.com>
parents: 11020
diff changeset
  2297
                current_file = None
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2298
                rejects += 1
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2299
                continue
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2300
        elif state == b'git':
11021
c47a1cfad572 patch: minor cleanup of _applydiff
Mads Kiilerich <mads@kiilerich.com>
parents: 11020
diff changeset
  2301
            for gp in values:
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
  2302
                path = pstrip(gp.oldpath)
22296
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
  2303
                data, mode = backend.getfile(path)
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
  2304
                if data is None:
16813
6d42c797ca6e patch: keep patching after missing copy source (issue3480)
Patrick Mezard <patrick@mezard.eu>
parents: 16650
diff changeset
  2305
                    # The error ignored here will trigger a getfile()
6d42c797ca6e patch: keep patching after missing copy source (issue3480)
Patrick Mezard <patrick@mezard.eu>
parents: 16650
diff changeset
  2306
                    # error in a place more appropriate for error
6d42c797ca6e patch: keep patching after missing copy source (issue3480)
Patrick Mezard <patrick@mezard.eu>
parents: 16650
diff changeset
  2307
                    # handling, and will not interrupt the patching
6d42c797ca6e patch: keep patching after missing copy source (issue3480)
Patrick Mezard <patrick@mezard.eu>
parents: 16650
diff changeset
  2308
                    # process.
22296
650b5b6e75ed convert: use None value for missing files instead of overloading IOError
Mads Kiilerich <madski@unity3d.com>
parents: 21833
diff changeset
  2309
                    pass
16813
6d42c797ca6e patch: keep patching after missing copy source (issue3480)
Patrick Mezard <patrick@mezard.eu>
parents: 16650
diff changeset
  2310
                else:
6d42c797ca6e patch: keep patching after missing copy source (issue3480)
Patrick Mezard <patrick@mezard.eu>
parents: 16650
diff changeset
  2311
                    store.setfile(path, data, mode)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2312
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2313
            raise error.Abort(_(b'unsupported parser state: %s') % state)
5649
a583117b536a patch: move NoHunk detection up with parsing code
Patrick Mezard <pmezard@gmail.com>
parents: 5581
diff changeset
  2314
13701
bc38ff7cb919 patch: move closefile() into patchfile.close()
Patrick Mezard <pmezard@gmail.com>
parents: 13700
diff changeset
  2315
    if current_file:
bc38ff7cb919 patch: move closefile() into patchfile.close()
Patrick Mezard <pmezard@gmail.com>
parents: 13700
diff changeset
  2316
        rejects += current_file.close()
5650
5d3e2f918d65 patch: move diff parsing in iterhunks generator
Patrick Mezard <pmezard@gmail.com>
parents: 5649
diff changeset
  2317
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2318
    if rejects:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2319
        return -1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4778
diff changeset
  2320
    return err
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2321
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2322
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2323
def _externalpatch(ui, repo, patcher, patchname, strip, files, similarity):
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2324
    """use <patcher> to apply <patchname> to the working directory.
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2325
    returns whether patch was applied with fuzz factor."""
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2326
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2327
    fuzz = False
12673
9ad16d1bce4b patch: simplify externalpatch() arguments
Patrick Mezard <pmezard@gmail.com>
parents: 12671
diff changeset
  2328
    args = []
14382
2d16f15da7bd patch: remove patch.patch() cwd argument
Patrick Mezard <pmezard@gmail.com>
parents: 14381
diff changeset
  2329
    cwd = repo.root
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2330
    if cwd:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2331
        args.append(b'-d %s' % procutil.shellquote(cwd))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2332
    cmd = b'%s %s -p%d < %s' % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2333
        patcher,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2334
        b' '.join(args),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2335
        strip,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2336
        procutil.shellquote(patchname),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2337
    )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2338
    ui.debug(b'Using external patch tool: %s\n' % cmd)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2339
    fp = procutil.popen(cmd, b'rb')
14381
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2340
    try:
30397
564b33acc21f patch: migrate to util.iterfile
Jun Wu <quark@fb.com>
parents: 30078
diff changeset
  2341
        for line in util.iterfile(fp):
14381
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2342
            line = line.rstrip()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2343
            ui.note(line + b'\n')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2344
            if line.startswith(b'patching file '):
14381
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2345
                pf = util.parsepatchoutput(line)
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2346
                printed_file = False
14564
65f4512e40e4 patch: turn patch() touched files dict into a set
Patrick Mezard <pmezard@gmail.com>
parents: 14535
diff changeset
  2347
                files.add(pf)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2348
            elif line.find(b'with fuzz') >= 0:
14381
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2349
                fuzz = True
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2350
                if not printed_file:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2351
                    ui.warn(pf + b'\n')
14381
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2352
                    printed_file = True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2353
                ui.warn(line + b'\n')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2354
            elif line.find(b'saving rejects to file') >= 0:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2355
                ui.warn(line + b'\n')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2356
            elif line.find(b'FAILED') >= 0:
14381
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2357
                if not printed_file:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2358
                    ui.warn(pf + b'\n')
14381
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2359
                    printed_file = True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2360
                ui.warn(line + b'\n')
14381
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2361
    finally:
d4192500586a patch: merge _updatedir() into externalpatch()
Patrick Mezard <pmezard@gmail.com>
parents: 14370
diff changeset
  2362
        if files:
19155
0b3689a08df5 patch: use scmutil.marktouched instead of scmutil.addremove
Siddharth Agarwal <sid0@fb.com>
parents: 18830
diff changeset
  2363
            scmutil.marktouched(repo, files, similarity)
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2364
    code = fp.close()
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2365
    if code:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2366
        raise PatchError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2367
            _(b"patch command failed: %s") % procutil.explainexit(code)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2368
        )
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2369
    return fuzz
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2370
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2371
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2372
def patchbackend(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2373
    ui, backend, patchobj, strip, prefix, files=None, eolmode=b'strict'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2374
):
9683
5c8651e2f5e0 patch: don't use mutable object as default argument
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9682
diff changeset
  2375
    if files is None:
14564
65f4512e40e4 patch: turn patch() touched files dict into a set
Patrick Mezard <pmezard@gmail.com>
parents: 14535
diff changeset
  2376
        files = set()
8810
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2377
    if eolmode is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2378
        eolmode = ui.config(b'patch', b'eol')
10101
155fe35534d3 patch: propagate eolmode down to patchfile
Martin Geisler <mg@lazybytes.net>
parents: 9725
diff changeset
  2379
    if eolmode.lower() not in eolmodes:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2380
        raise error.Abort(_(b'unsupported line endings type: %s') % eolmode)
10101
155fe35534d3 patch: propagate eolmode down to patchfile
Martin Geisler <mg@lazybytes.net>
parents: 9725
diff changeset
  2381
    eolmode = eolmode.lower()
8843
eb7b247a98ea kill trailing whitespace
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8817
diff changeset
  2382
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
  2383
    store = filestore()
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2384
    try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2385
        fp = open(patchobj, b'rb')
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2386
    except TypeError:
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2387
        fp = patchobj
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2388
    try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2389
        ret = applydiff(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2390
            ui, fp, backend, store, strip=strip, prefix=prefix, eolmode=eolmode
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2391
        )
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2392
    finally:
10203
6e26e3c2083f patch: explicitely close input patch files when leaving
Patrick Mezard <pmezard@gmail.com>
parents: 10135
diff changeset
  2393
        if fp != patchobj:
6e26e3c2083f patch: explicitely close input patch files when leaving
Patrick Mezard <pmezard@gmail.com>
parents: 10135
diff changeset
  2394
            fp.close()
14564
65f4512e40e4 patch: turn patch() touched files dict into a set
Patrick Mezard <pmezard@gmail.com>
parents: 14535
diff changeset
  2395
        files.update(backend.close())
14452
ee574cfd0c32 patch: use temporary files to handle intermediate copies
Patrick Mezard <pmezard@gmail.com>
parents: 14451
diff changeset
  2396
        store.close()
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2397
    if ret < 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2398
        raise PatchError(_(b'patch failed to apply'))
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2399
    return ret > 0
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2400
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2401
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2402
def internalpatch(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2403
    ui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2404
    repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2405
    patchobj,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2406
    strip,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2407
    prefix=b'',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2408
    files=None,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2409
    eolmode=b'strict',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2410
    similarity=0,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2411
):
14611
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
  2412
    """use builtin patch to apply <patchobj> to the working directory.
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
  2413
    returns whether patch was applied with fuzz factor."""
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
  2414
    backend = workingbackend(ui, repo, similarity)
24254
60c279ab7bd3 patch.internalpatch: accept a prefix parameter
Siddharth Agarwal <sid0@fb.com>
parents: 24253
diff changeset
  2415
    return patchbackend(ui, backend, patchobj, strip, prefix, files, eolmode)
14611
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
  2416
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2417
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2418
def patchrepo(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2419
    ui, repo, ctx, store, patchobj, strip, prefix, files=None, eolmode=b'strict'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2420
):
14611
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
  2421
    backend = repobackend(ui, repo, ctx, store)
24260
76225ab5a5da cmdutil.tryimportone: allow importing relative patches with --bypass
Siddharth Agarwal <sid0@fb.com>
parents: 24259
diff changeset
  2422
    return patchbackend(ui, backend, patchobj, strip, prefix, files, eolmode)
14611
adbf5e7df96d import: add --bypass option
Patrick Mezard <pmezard@gmail.com>
parents: 14609
diff changeset
  2423
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2424
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2425
def patch(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2426
    ui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2427
    repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2428
    patchname,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2429
    strip=1,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2430
    prefix=b'',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2431
    files=None,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2432
    eolmode=b'strict',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2433
    similarity=0,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2434
):
8810
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2435
    """Apply <patchname> to the working directory.
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2436
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2437
    'eolmode' specifies how end of lines should be handled. It can be:
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2438
    - 'strict': inputs are read in binary mode, EOLs are preserved
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2439
    - 'crlf': EOLs are ignored when patching and reset to CRLF
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2440
    - 'lf': EOLs are ignored when patching and reset to LF
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2441
    - None: get it from user settings, default to 'strict'
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2442
    'eolmode' is ignored when using an external patcher program.
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2443
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2444
    Returns whether patch was applied with fuzz factor.
ac92775b3b80 Add patch.eol to ignore EOLs when patching (issue1019)
Patrick Mezard <pmezard@gmail.com>
parents: 8778
diff changeset
  2445
    """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2446
    patcher = ui.config(b'ui', b'patch')
9683
5c8651e2f5e0 patch: don't use mutable object as default argument
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9682
diff changeset
  2447
    if files is None:
14564
65f4512e40e4 patch: turn patch() touched files dict into a set
Patrick Mezard <pmezard@gmail.com>
parents: 14535
diff changeset
  2448
        files = set()
21553
bee0e1cffdd3 import: add --partial flag to create a changeset despite failed hunks
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20972
diff changeset
  2449
    if patcher:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2450
        return _externalpatch(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2451
            ui, repo, patcher, patchname, strip, files, similarity
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2452
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2453
    return internalpatch(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2454
        ui, repo, patchname, strip, prefix, files, eolmode, similarity
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2455
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2456
7151
b5bc5293021c patch: change functions definition order for readability
Patrick Mezard <pmezard@gmail.com>
parents: 7150
diff changeset
  2457
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2458
def changedfiles(ui, repo, patchpath, strip=1, prefix=b''):
14351
d54f9bbcc640 patch: add lexists() to backends, use it in selectfile()
Patrick Mezard <pmezard@gmail.com>
parents: 14350
diff changeset
  2459
    backend = fsbackend(ui, repo.root)
35062
1706eae096e2 patch: accept prefix argument to changedfiles() helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 34968
diff changeset
  2460
    prefix = _canonprefix(repo, prefix)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2461
    with open(patchpath, b'rb') as fp:
14255
576256a81cb6 patch: introduce changedfiles
Idan Kamara <idankk86@gmail.com>
parents: 14240
diff changeset
  2462
        changed = set()
576256a81cb6 patch: introduce changedfiles
Idan Kamara <idankk86@gmail.com>
parents: 14240
diff changeset
  2463
        for state, values in iterhunks(fp):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2464
            if state == b'file':
14388
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2465
                afile, bfile, first_hunk, gp = values
37c997d21752 patch: stop handling hunkless git blocks out of stream
Patrick Mezard <pmezard@gmail.com>
parents: 14387
diff changeset
  2466
                if gp:
35062
1706eae096e2 patch: accept prefix argument to changedfiles() helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 34968
diff changeset
  2467
                    gp.path = pathtransform(gp.path, strip - 1, prefix)[1]
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2468
                    if gp.oldpath:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2469
                        gp.oldpath = pathtransform(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2470
                            gp.oldpath, strip - 1, prefix
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2471
                        )[1]
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2472
                else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2473
                    gp = makepatchmeta(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2474
                        backend, afile, bfile, first_hunk, strip, prefix
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2475
                    )
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2476
                changed.add(gp.path)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2477
                if gp.op == b'RENAME':
14566
d0c2cc11e611 patch: generalize the use of patchmeta in applydiff()
Patrick Mezard <pmezard@gmail.com>
parents: 14565
diff changeset
  2478
                    changed.add(gp.oldpath)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2479
            elif state not in (b'hunk', b'git'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2480
                raise error.Abort(_(b'unsupported parser state: %s') % state)
14255
576256a81cb6 patch: introduce changedfiles
Idan Kamara <idankk86@gmail.com>
parents: 14240
diff changeset
  2481
        return changed
576256a81cb6 patch: introduce changedfiles
Idan Kamara <idankk86@gmail.com>
parents: 14240
diff changeset
  2482
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2483
10189
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2484
class GitDiffRequired(Exception):
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2485
    pass
7198
df79ee9b6278 patch: extract local function addmodehdr
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7186
diff changeset
  2486
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2487
38587
b62000a28812 diffutil: remove diffopts() in favor of diffallopts()
Yuya Nishihara <yuya@tcha.org>
parents: 38562
diff changeset
  2488
diffopts = diffutil.diffallopts
38562
c88d2c9b00dd diffutil: extract diff options code into a dedicated util-module
Boris Feld <boris.feld@octobus.net>
parents: 38493
diff changeset
  2489
diffallopts = diffutil.diffallopts
c88d2c9b00dd diffutil: extract diff options code into a dedicated util-module
Boris Feld <boris.feld@octobus.net>
parents: 38493
diff changeset
  2490
difffeatureopts = diffutil.difffeatureopts
10615
3bb438ce4458 patch/diff: move diff related code next to each other
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10611
diff changeset
  2491
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2492
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2493
def diff(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2494
    repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2495
    node1=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2496
    node2=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2497
    match=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2498
    changes=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2499
    opts=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2500
    losedatafn=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2501
    pathfn=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2502
    copy=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2503
    copysourcematch=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2504
    hunksfilterfn=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2505
):
7308
b6f5490effbf patch: turn patch.diff() into a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7267
diff changeset
  2506
    '''yields diff of changes to files between two nodes, or node and
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2507
    working directory.
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2508
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2509
    if node1 is None, use first dirstate parent instead.
10189
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2510
    if node2 is None, compare node1 with working directory.
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2511
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2512
    losedatafn(**kwarg) is a callable run when opts.upgrade=True and
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2513
    every time some change cannot be represented with the current
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2514
    patch format. Return False to upgrade to git patch format, True to
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2515
    accept the loss or raise an exception to abort the diff. It is
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2516
    called with the name of current file being diffed as 'fn'. If set
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2517
    to None, patches will always be upgraded to git format when
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2518
    necessary.
12167
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12144
diff changeset
  2519
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12144
diff changeset
  2520
    prefix is a filename prefix that is prepended to all filenames on
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12144
diff changeset
  2521
    display (used for subrepos).
24417
f2e1e097cda1 patch.diff: add support for diffs relative to a subdirectory
Siddharth Agarwal <sid0@fb.com>
parents: 24416
diff changeset
  2522
f2e1e097cda1 patch.diff: add support for diffs relative to a subdirectory
Siddharth Agarwal <sid0@fb.com>
parents: 24416
diff changeset
  2523
    relroot, if not empty, must be normalized with a trailing /. Any match
29422
40d53d4b5925 patch: allow copy information to be passed in
Henrik Stuart <henriks@unity3d.com>
parents: 29341
diff changeset
  2524
    patterns that fall outside it will be ignored.
40d53d4b5925 patch: allow copy information to be passed in
Henrik Stuart <henriks@unity3d.com>
parents: 29341
diff changeset
  2525
40d53d4b5925 patch: allow copy information to be passed in
Henrik Stuart <henriks@unity3d.com>
parents: 29341
diff changeset
  2526
    copy, if not empty, should contain mappings {dst@y: src@x} of copy
34856
890afefa7296 diff: pass a diff hunks filter function from changeset_printer to patch.diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34855
diff changeset
  2527
    information.
890afefa7296 diff: pass a diff hunks filter function from changeset_printer to patch.diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34855
diff changeset
  2528
41620
74f53d3bd685 patch: accept second matcher that applies only to copy sources (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41619
diff changeset
  2529
    if copysourcematch is not None, then copy sources will be filtered by this
74f53d3bd685 patch: accept second matcher that applies only to copy sources (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41619
diff changeset
  2530
    matcher
74f53d3bd685 patch: accept second matcher that applies only to copy sources (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41619
diff changeset
  2531
34856
890afefa7296 diff: pass a diff hunks filter function from changeset_printer to patch.diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34855
diff changeset
  2532
    hunksfilterfn, if not None, should be a function taking a filectx and
890afefa7296 diff: pass a diff hunks filter function from changeset_printer to patch.diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34855
diff changeset
  2533
    hunks generator that may yield filtered hunks.
890afefa7296 diff: pass a diff hunks filter function from changeset_printer to patch.diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34855
diff changeset
  2534
    '''
41618
e834f6f6f221 patch: pass in context objects into diffhunks() (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41534
diff changeset
  2535
    if not node1 and not node2:
e834f6f6f221 patch: pass in context objects into diffhunks() (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41534
diff changeset
  2536
        node1 = repo.dirstate.p1()
e834f6f6f221 patch: pass in context objects into diffhunks() (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41534
diff changeset
  2537
e834f6f6f221 patch: pass in context objects into diffhunks() (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41534
diff changeset
  2538
    ctx1 = repo[node1]
e834f6f6f221 patch: pass in context objects into diffhunks() (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41534
diff changeset
  2539
    ctx2 = repo[node2]
e834f6f6f221 patch: pass in context objects into diffhunks() (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41534
diff changeset
  2540
34855
35c6a54ec1ff diff: also yield file context objects in patch.trydiff() (API)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34566
diff changeset
  2541
    for fctx1, fctx2, hdr, hunks in diffhunks(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2542
        repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2543
        ctx1=ctx1,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2544
        ctx2=ctx2,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2545
        match=match,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2546
        changes=changes,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2547
        opts=opts,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2548
        losedatafn=losedatafn,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2549
        pathfn=pathfn,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2550
        copy=copy,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2551
        copysourcematch=copysourcematch,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2552
    ):
34856
890afefa7296 diff: pass a diff hunks filter function from changeset_printer to patch.diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34855
diff changeset
  2553
        if hunksfilterfn is not None:
34908
907ff34e1460 log: add an assertion about fctx not being None in patch.diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34856
diff changeset
  2554
            # If the file has been removed, fctx2 is None; but this should
907ff34e1460 log: add an assertion about fctx not being None in patch.diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34856
diff changeset
  2555
            # not occur here since we catch removed files early in
35888
c8e2d6ed1f9e cmdutil: drop aliases for logcmdutil functions (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35850
diff changeset
  2556
            # logcmdutil.getlinerangerevs() for 'hg log -L'.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2557
            assert (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2558
                fctx2 is not None
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2559
            ), b'fctx2 unexpectly None in diff hunks filtering'
34856
890afefa7296 diff: pass a diff hunks filter function from changeset_printer to patch.diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34855
diff changeset
  2560
            hunks = hunksfilterfn(fctx2, hunks)
44759
e58422afbc74 diff: re-establish linear runtime performance
Elmar Bartel <elb_hg@leo.org>
parents: 44452
diff changeset
  2561
        text = b''.join(b''.join(hlines) for hrange, hlines in hunks)
34561
fe6125ebdf91 patch: rename "header" variable into "hdr" in diff()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 34521
diff changeset
  2562
        if hdr and (text or len(hdr) > 1):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2563
            yield b'\n'.join(hdr) + b'\n'
31274
a8023a64c40d patch: add a diffhunks function yielding (diffheaders, hunks)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 31273
diff changeset
  2564
        if text:
a8023a64c40d patch: add a diffhunks function yielding (diffheaders, hunks)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 31273
diff changeset
  2565
            yield text
a8023a64c40d patch: add a diffhunks function yielding (diffheaders, hunks)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 31273
diff changeset
  2566
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2567
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2568
def diffhunks(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2569
    repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2570
    ctx1,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2571
    ctx2,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2572
    match=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2573
    changes=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2574
    opts=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2575
    losedatafn=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2576
    pathfn=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2577
    copy=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2578
    copysourcematch=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2579
):
31274
a8023a64c40d patch: add a diffhunks function yielding (diffheaders, hunks)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 31273
diff changeset
  2580
    """Yield diff of changes to files in the form of (`header`, `hunks`) tuples
a8023a64c40d patch: add a diffhunks function yielding (diffheaders, hunks)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 31273
diff changeset
  2581
    where `header` is a list of diff headers and `hunks` is an iterable of
a8023a64c40d patch: add a diffhunks function yielding (diffheaders, hunks)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 31273
diff changeset
  2582
    (`hunkrange`, `hunklines`) tuples.
a8023a64c40d patch: add a diffhunks function yielding (diffheaders, hunks)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 31273
diff changeset
  2583
a8023a64c40d patch: add a diffhunks function yielding (diffheaders, hunks)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 31273
diff changeset
  2584
    See diff() for the meaning of parameters.
a8023a64c40d patch: add a diffhunks function yielding (diffheaders, hunks)
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 31273
diff changeset
  2585
    """
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2586
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2587
    if opts is None:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2588
        opts = mdiff.defaultopts
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2589
9123
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2590
    def lrugetfilectx():
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2591
        cache = {}
25113
0ca8410ea345 util: drop alias for collections.deque
Martin von Zweigbergk <martinvonz@google.com>
parents: 24845
diff changeset
  2592
        order = collections.deque()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2593
9123
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2594
        def getfilectx(f, ctx):
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2595
            fctx = ctx.filectx(f, filelog=cache.get(f))
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2596
            if f not in cache:
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2597
                if len(cache) > 20:
16803
107a3270a24a cleanup: use the deque type where appropriate
Bryan O'Sullivan <bryano@fb.com>
parents: 16705
diff changeset
  2598
                    del cache[order.popleft()]
9684
618af2034ca6 patch: use the public ctx API instead of the internals
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9683
diff changeset
  2599
                cache[f] = fctx.filelog()
9123
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2600
            else:
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2601
                order.remove(f)
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2602
            order.append(f)
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2603
            return fctx
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2604
9123
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2605
        return getfilectx
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2606
9123
360f61c2919f Make patch.diff filelog cache LRU of 20 files. Fixes issue1738.
Brendan Cully <brendan@kublai.com>
parents: 8891
diff changeset
  2607
    getfilectx = lrugetfilectx()
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
  2608
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2609
    if not changes:
38773
59af0c7d103f patch: use ctx1.status(ctx2) instead of repo.status(ctx1, ctx2)
Martin von Zweigbergk <martinvonz@google.com>
parents: 38630
diff changeset
  2610
        changes = ctx1.status(ctx2, match=match)
43649
d649de29f1ff patch: use field names instead of field numbers on scmutil.status
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
  2611
    if isinstance(changes, list):
d649de29f1ff patch: use field names instead of field numbers on scmutil.status
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
  2612
        modified, added, removed = changes[:3]
d649de29f1ff patch: use field names instead of field numbers on scmutil.status
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
  2613
    else:
d649de29f1ff patch: use field names instead of field numbers on scmutil.status
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
  2614
        modified, added, removed = (
d649de29f1ff patch: use field names instead of field numbers on scmutil.status
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
  2615
            changes.modified,
d649de29f1ff patch: use field names instead of field numbers on scmutil.status
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
  2616
            changes.added,
d649de29f1ff patch: use field names instead of field numbers on scmutil.status
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
  2617
            changes.removed,
d649de29f1ff patch: use field names instead of field numbers on scmutil.status
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
  2618
        )
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2619
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  2620
    if not modified and not added and not removed:
10189
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2621
        return []
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2622
24306
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  2623
    if repo.ui.debugflag:
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  2624
        hexfunc = hex
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  2625
    else:
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 24269
diff changeset
  2626
        hexfunc = short
21833
c1ceec0c8cb4 patch: use ctx.node() instead of bare node variable
Sean Farley <sean.michael.farley@gmail.com>
parents: 21790
diff changeset
  2627
    revs = [hexfunc(node) for node in [ctx1.node(), ctx2.node()] if node]
10189
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2628
29422
40d53d4b5925 patch: allow copy information to be passed in
Henrik Stuart <henriks@unity3d.com>
parents: 29341
diff changeset
  2629
    if copy is None:
40d53d4b5925 patch: allow copy information to be passed in
Henrik Stuart <henriks@unity3d.com>
parents: 29341
diff changeset
  2630
        copy = {}
40d53d4b5925 patch: allow copy information to be passed in
Henrik Stuart <henriks@unity3d.com>
parents: 29341
diff changeset
  2631
        if opts.git or opts.upgrade:
40d53d4b5925 patch: allow copy information to be passed in
Henrik Stuart <henriks@unity3d.com>
parents: 29341
diff changeset
  2632
            copy = copies.pathcopies(ctx1, ctx2, match=match)
10189
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2633
41620
74f53d3bd685 patch: accept second matcher that applies only to copy sources (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41619
diff changeset
  2634
    if copysourcematch:
74f53d3bd685 patch: accept second matcher that applies only to copy sources (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41619
diff changeset
  2635
        # filter out copies where source side isn't inside the matcher
41499
a5d8824483ba diff: drop duplicate filter of copies by destination
Martin von Zweigbergk <martinvonz@google.com>
parents: 41498
diff changeset
  2636
        # (copies.pathcopies() already filtered out the destination)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2637
        copy = {
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43104
diff changeset
  2638
            dst: src
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43104
diff changeset
  2639
            for dst, src in pycompat.iteritems(copy)
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43104
diff changeset
  2640
            if copysourcematch(src)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2641
        }
24417
f2e1e097cda1 patch.diff: add support for diffs relative to a subdirectory
Siddharth Agarwal <sid0@fb.com>
parents: 24416
diff changeset
  2642
27900
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2643
    modifiedset = set(modified)
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2644
    addedset = set(added)
27901
29c8e35d3283 diff: don't crash when merged-in addition was removed (issue4786)
Martin von Zweigbergk <martinvonz@google.com>
parents: 27900
diff changeset
  2645
    removedset = set(removed)
27900
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2646
    for f in modified:
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2647
        if f not in ctx1:
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2648
            # Fix up added, since merged-in additions appear as
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2649
            # modifications during merges
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2650
            modifiedset.remove(f)
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2651
            addedset.add(f)
27901
29c8e35d3283 diff: don't crash when merged-in addition was removed (issue4786)
Martin von Zweigbergk <martinvonz@google.com>
parents: 27900
diff changeset
  2652
    for f in removed:
29c8e35d3283 diff: don't crash when merged-in addition was removed (issue4786)
Martin von Zweigbergk <martinvonz@google.com>
parents: 27900
diff changeset
  2653
        if f not in ctx1:
29c8e35d3283 diff: don't crash when merged-in addition was removed (issue4786)
Martin von Zweigbergk <martinvonz@google.com>
parents: 27900
diff changeset
  2654
            # Merged-in additions that are then removed are reported as removed.
29c8e35d3283 diff: don't crash when merged-in addition was removed (issue4786)
Martin von Zweigbergk <martinvonz@google.com>
parents: 27900
diff changeset
  2655
            # They are not in ctx1, so We don't want to show them in the diff.
29c8e35d3283 diff: don't crash when merged-in addition was removed (issue4786)
Martin von Zweigbergk <martinvonz@google.com>
parents: 27900
diff changeset
  2656
            removedset.remove(f)
27900
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2657
    modified = sorted(modifiedset)
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2658
    added = sorted(addedset)
27901
29c8e35d3283 diff: don't crash when merged-in addition was removed (issue4786)
Martin von Zweigbergk <martinvonz@google.com>
parents: 27900
diff changeset
  2659
    removed = sorted(removedset)
35589
3328d53254d9 py3: use list() to get a list of items using dict.items()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35582
diff changeset
  2660
    for dst, src in list(copy.items()):
27902
51b6ce257e0a diff: don't crash when merged-in addition is copied
Martin von Zweigbergk <martinvonz@google.com>
parents: 27901
diff changeset
  2661
        if src not in ctx1:
51b6ce257e0a diff: don't crash when merged-in addition is copied
Martin von Zweigbergk <martinvonz@google.com>
parents: 27901
diff changeset
  2662
            # Files merged in during a merge and then copied/renamed are
51b6ce257e0a diff: don't crash when merged-in addition is copied
Martin von Zweigbergk <martinvonz@google.com>
parents: 27901
diff changeset
  2663
            # reported as copies. We want to show them in the diff as additions.
51b6ce257e0a diff: don't crash when merged-in addition is copied
Martin von Zweigbergk <martinvonz@google.com>
parents: 27901
diff changeset
  2664
            del copy[dst]
27900
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2665
37764
5e67c20915a7 diff: invoke the file prefetch hook
Matt Harbison <matt_harbison@yahoo.com>
parents: 37732
diff changeset
  2666
    prefetchmatch = scmutil.matchfiles(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2667
        repo, list(modifiedset | addedset | removedset)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2668
    )
45072
a56ba57c837d scmutil: allowing different files to be prefetched per revision
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 44759
diff changeset
  2669
    revmatches = [
a56ba57c837d scmutil: allowing different files to be prefetched per revision
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 44759
diff changeset
  2670
        (ctx1.rev(), prefetchmatch),
a56ba57c837d scmutil: allowing different files to be prefetched per revision
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 44759
diff changeset
  2671
        (ctx2.rev(), prefetchmatch),
a56ba57c837d scmutil: allowing different files to be prefetched per revision
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 44759
diff changeset
  2672
    ]
a56ba57c837d scmutil: allowing different files to be prefetched per revision
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 44759
diff changeset
  2673
    scmutil.prefetchfiles(repo, revmatches)
37764
5e67c20915a7 diff: invoke the file prefetch hook
Matt Harbison <matt_harbison@yahoo.com>
parents: 37732
diff changeset
  2674
17299
e51d4aedace9 check-code: indent 4 spaces in py files
Mads Kiilerich <mads@kiilerich.com>
parents: 16834
diff changeset
  2675
    def difffn(opts, losedata):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2676
        return trydiff(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2677
            repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2678
            revs,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2679
            ctx1,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2680
            ctx2,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2681
            modified,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2682
            added,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2683
            removed,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2684
            copy,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2685
            getfilectx,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2686
            opts,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2687
            losedata,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2688
            pathfn,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2689
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2690
10189
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2691
    if opts.upgrade and not opts.git:
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2692
        try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2693
10189
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2694
            def losedata(fn):
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2695
                if not losedatafn or not losedatafn(fn=fn):
16687
e34106fa0dc3 cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents: 16686
diff changeset
  2696
                    raise GitDiffRequired
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2697
10189
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2698
            # Buffer the whole output until we are sure it can be generated
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2699
            return list(difffn(opts.copy(git=False), losedata))
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2700
        except GitDiffRequired:
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2701
            return difffn(opts.copy(git=True), None)
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2702
    else:
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2703
        return difffn(opts, None)
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  2704
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2705
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2706
def diffsinglehunk(hunklines):
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2707
    """yield tokens for a list of lines in a single hunk"""
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2708
    for line in hunklines:
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2709
        # chomp
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2710
        chompline = line.rstrip(b'\r\n')
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2711
        # highlight tabs and trailing whitespace
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2712
        stripline = chompline.rstrip()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2713
        if line.startswith(b'-'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2714
            label = b'diff.deleted'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2715
        elif line.startswith(b'+'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2716
            label = b'diff.inserted'
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2717
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2718
            raise error.ProgrammingError(b'unexpected hunk line: %s' % line)
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2719
        for token in tabsplitter.findall(stripline):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2720
            if token.startswith(b'\t'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2721
                yield (token, b'diff.tab')
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2722
            else:
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2723
                yield (token, label)
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2724
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2725
        if chompline != stripline:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2726
            yield (chompline[len(stripline) :], b'diff.trailingwhitespace')
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2727
        if chompline != line:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2728
            yield (line[len(chompline) :], b'')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2729
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2730
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2731
def diffsinglehunkinline(hunklines):
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2732
    """yield tokens for a list of lines in a single hunk, with inline colors"""
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2733
    # prepare deleted, and inserted content
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2734
    a = b''
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2735
    b = b''
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2736
    for line in hunklines:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2737
        if line[0:1] == b'-':
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2738
            a += line[1:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2739
        elif line[0:1] == b'+':
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2740
            b += line[1:]
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2741
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2742
            raise error.ProgrammingError(b'unexpected hunk line: %s' % line)
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2743
    # fast path: if either side is empty, use diffsinglehunk
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2744
    if not a or not b:
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2745
        for t in diffsinglehunk(hunklines):
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2746
            yield t
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2747
        return
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2748
    # re-split the content into words
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2749
    al = wordsplitter.findall(a)
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2750
    bl = wordsplitter.findall(b)
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2751
    # re-arrange the words to lines since the diff algorithm is line-based
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2752
    aln = [s if s == b'\n' else s + b'\n' for s in al]
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2753
    bln = [s if s == b'\n' else s + b'\n' for s in bl]
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2754
    an = b''.join(aln)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2755
    bn = b''.join(bln)
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2756
    # run the diff algorithm, prepare atokens and btokens
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2757
    atokens = []
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2758
    btokens = []
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2759
    blocks = mdiff.allblocks(an, bn, lines1=aln, lines2=bln)
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2760
    for (a1, a2, b1, b2), btype in blocks:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2761
        changed = btype == b'!'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2762
        for token in mdiff.splitnewlines(b''.join(al[a1:a2])):
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2763
            atokens.append((changed, token))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2764
        for token in mdiff.splitnewlines(b''.join(bl[b1:b2])):
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2765
            btokens.append((changed, token))
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2766
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2767
    # yield deleted tokens, then inserted ones
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2768
    for prefix, label, tokens in [
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2769
        (b'-', b'diff.deleted', atokens),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2770
        (b'+', b'diff.inserted', btokens),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2771
    ]:
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2772
        nextisnewline = True
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2773
        for changed, token in tokens:
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2774
            if nextisnewline:
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2775
                yield (prefix, label)
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2776
                nextisnewline = False
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2777
            # special handling line end
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2778
            isendofline = token.endswith(b'\n')
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2779
            if isendofline:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2780
                chomp = token[:-1]  # chomp
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2781
                if chomp.endswith(b'\r'):
38630
e1987261dd05 patch: don't separate \r and \n when colorizing diff output
Sune Foldager <cryo@cyanite.org>
parents: 38588
diff changeset
  2782
                    chomp = chomp[:-1]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2783
                endofline = token[len(chomp) :]
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2784
                token = chomp.rstrip()  # detect spaces at the end
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2785
                endspaces = chomp[len(token) :]
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2786
            # scan tabs
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2787
            for maybetab in tabsplitter.findall(token):
40282
e4f82db071a4 py3: fix test-diff-color.t
Mark Thomas <mbthomas@fb.com>
parents: 39616
diff changeset
  2788
                if b'\t' == maybetab[0:1]:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2789
                    currentlabel = b'diff.tab'
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2790
                else:
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2791
                    if changed:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2792
                        currentlabel = label + b'.changed'
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2793
                    else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2794
                        currentlabel = label + b'.unchanged'
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2795
                yield (maybetab, currentlabel)
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2796
            if isendofline:
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2797
                if endspaces:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2798
                    yield (endspaces, b'diff.trailingwhitespace')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2799
                yield (endofline, b'')
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2800
                nextisnewline = True
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2801
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2802
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  2803
def difflabel(func, *args, **kw):
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  2804
    '''yields 2-tuples of (output, label) based on the output of func()'''
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
  2805
    if kw.get('opts') and kw['opts'].worddiff:
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2806
        dodiffhunk = diffsinglehunkinline
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2807
    else:
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2808
        dodiffhunk = diffsinglehunk
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2809
    headprefixes = [
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2810
        (b'diff', b'diff.diffline'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2811
        (b'copy', b'diff.extended'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2812
        (b'rename', b'diff.extended'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2813
        (b'old', b'diff.extended'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2814
        (b'new', b'diff.extended'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2815
        (b'deleted', b'diff.extended'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2816
        (b'index', b'diff.extended'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2817
        (b'similarity', b'diff.extended'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2818
        (b'---', b'diff.file_a'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2819
        (b'+++', b'diff.file_b'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2820
    ]
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2821
    textprefixes = [
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2822
        (b'@', b'diff.hunk'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2823
        # - and + are handled by diffsinglehunk
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2824
    ]
15201
2c4fdee4d1a8 diff: enhance highlighting with color (issue3034)
Kirill Elagin <kirelagin@gmail.com>
parents: 15159
diff changeset
  2825
    head = False
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2826
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2827
    # buffers a hunk, i.e. adjacent "-", "+" lines without other changes.
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2828
    hunkbuffer = []
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2829
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2830
    def consumehunkbuffer():
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2831
        if hunkbuffer:
37732
35632d392279 patch: implement a new worddiff algorithm
Jun Wu <quark@fb.com>
parents: 37731
diff changeset
  2832
            for token in dodiffhunk(hunkbuffer):
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2833
                yield token
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2834
            hunkbuffer[:] = []
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2835
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  2836
    for chunk in func(*args, **kw):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2837
        lines = chunk.split(b'\n')
37730
8d730f96e792 patch: move yielding "\n" to the end of loop
Jun Wu <quark@fb.com>
parents: 37621
diff changeset
  2838
        linecount = len(lines)
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  2839
        for i, line in enumerate(lines):
15201
2c4fdee4d1a8 diff: enhance highlighting with color (issue3034)
Kirill Elagin <kirelagin@gmail.com>
parents: 15159
diff changeset
  2840
            if head:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2841
                if line.startswith(b'@'):
15201
2c4fdee4d1a8 diff: enhance highlighting with color (issue3034)
Kirill Elagin <kirelagin@gmail.com>
parents: 15159
diff changeset
  2842
                    head = False
2c4fdee4d1a8 diff: enhance highlighting with color (issue3034)
Kirill Elagin <kirelagin@gmail.com>
parents: 15159
diff changeset
  2843
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2844
                if line and not line.startswith(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2845
                    (b' ', b'+', b'-', b'@', b'\\')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2846
                ):
15201
2c4fdee4d1a8 diff: enhance highlighting with color (issue3034)
Kirill Elagin <kirelagin@gmail.com>
parents: 15159
diff changeset
  2847
                    head = True
22460
c343557a8442 patch: enable diff.tab markup for the color extension
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22296
diff changeset
  2848
            diffline = False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2849
            if not head and line and line.startswith((b'+', b'-')):
22460
c343557a8442 patch: enable diff.tab markup for the color extension
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22296
diff changeset
  2850
                diffline = True
c343557a8442 patch: enable diff.tab markup for the color extension
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22296
diff changeset
  2851
15201
2c4fdee4d1a8 diff: enhance highlighting with color (issue3034)
Kirill Elagin <kirelagin@gmail.com>
parents: 15159
diff changeset
  2852
            prefixes = textprefixes
2c4fdee4d1a8 diff: enhance highlighting with color (issue3034)
Kirill Elagin <kirelagin@gmail.com>
parents: 15159
diff changeset
  2853
            if head:
2c4fdee4d1a8 diff: enhance highlighting with color (issue3034)
Kirill Elagin <kirelagin@gmail.com>
parents: 15159
diff changeset
  2854
                prefixes = headprefixes
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2855
            if diffline:
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2856
                # buffered
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2857
                bufferedline = line
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2858
                if i + 1 < linecount:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2859
                    bufferedline += b"\n"
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2860
                hunkbuffer.append(bufferedline)
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  2861
            else:
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2862
                # unbuffered
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2863
                for token in consumehunkbuffer():
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2864
                    yield token
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2865
                stripline = line.rstrip()
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2866
                for prefix, label in prefixes:
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2867
                    if stripline.startswith(prefix):
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2868
                        yield (stripline, label)
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2869
                        if line != stripline:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2870
                            yield (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2871
                                line[len(stripline) :],
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2872
                                b'diff.trailingwhitespace',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2873
                            )
35277
6ba79cf34f5e patch: add within-line color diff capacity
Matthieu Laneuville <matthieu.laneuville@octobus.net>
parents: 35191
diff changeset
  2874
                        break
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2875
                else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2876
                    yield (line, b'')
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2877
                if i + 1 < linecount:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2878
                    yield (b'\n', b'')
37731
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2879
        for token in consumehunkbuffer():
5471348921c1 patch: buffer lines for a same hunk
Jun Wu <quark@fb.com>
parents: 37730
diff changeset
  2880
            yield token
35277
6ba79cf34f5e patch: add within-line color diff capacity
Matthieu Laneuville <matthieu.laneuville@octobus.net>
parents: 35191
diff changeset
  2881
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2882
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  2883
def diffui(*args, **kw):
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  2884
    '''like diff(), but yields 2-tuples of (output, label) for ui.write()'''
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  2885
    return difflabel(diff, *args, **kw)
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  2886
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2887
27900
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2888
def _filepairs(modified, added, removed, copy, opts):
24106
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2889
    '''generates tuples (f1, f2, copyop), where f1 is the name of the file
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2890
    before and f2 is the the name after. For added files, f1 will be None,
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2891
    and for removed files, f2 will be None. copyop may be set to None, 'copy'
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2892
    or 'rename' (the latter two only if opts.git is set).'''
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2893
    gone = set()
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2894
44452
9d2b2df2c2ba cleanup: run pyupgrade on our source tree to clean up varying things
Augie Fackler <augie@google.com>
parents: 44247
diff changeset
  2895
    copyto = {v: k for k, v in copy.items()}
24106
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2896
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2897
    addedset, removedset = set(added), set(removed)
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2898
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2899
    for f in sorted(modified + added + removed):
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2900
        copyop = None
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2901
        f1, f2 = f, f
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2902
        if f in addedset:
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2903
            f1 = None
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2904
            if f in copy:
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2905
                if opts.git:
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2906
                    f1 = copy[f]
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2907
                    if f1 in removedset and f1 not in gone:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2908
                        copyop = b'rename'
24106
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2909
                        gone.add(f1)
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2910
                    else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2911
                        copyop = b'copy'
24106
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2912
        elif f in removedset:
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2913
            f2 = None
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2914
            if opts.git:
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2915
                # have we already reported a copy above?
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2916
                if (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2917
                    f in copyto
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2918
                    and copyto[f] in addedset
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2919
                    and copy[copyto[f]] == f
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2920
                ):
24106
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2921
                    continue
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2922
        yield f1, f2, copyop
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  2923
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2924
45098
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2925
def _gitindex(text):
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2926
    if not text:
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2927
        text = b""
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2928
    l = len(text)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2929
    s = hashutil.sha1(b'blob %d\0' % l)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2930
    s.update(text)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2931
    return hex(s.digest())
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2932
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2933
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2934
_gitmode = {b'l': b'120000', b'x': b'100755', b'': b'100644'}
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2935
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  2936
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2937
def trydiff(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2938
    repo,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2939
    revs,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2940
    ctx1,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2941
    ctx2,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2942
    modified,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2943
    added,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2944
    removed,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2945
    copy,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2946
    getfilectx,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2947
    opts,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2948
    losedatafn,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2949
    pathfn,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  2950
):
24371
8a997bd73448 patch.trydiff: add a docstring
Siddharth Agarwal <sid0@fb.com>
parents: 24346
diff changeset
  2951
    '''given input data, generate a diff and yield it in blocks
8a997bd73448 patch.trydiff: add a docstring
Siddharth Agarwal <sid0@fb.com>
parents: 24346
diff changeset
  2952
8a997bd73448 patch.trydiff: add a docstring
Siddharth Agarwal <sid0@fb.com>
parents: 24346
diff changeset
  2953
    If generating a diff would lose data like flags or binary data and
8a997bd73448 patch.trydiff: add a docstring
Siddharth Agarwal <sid0@fb.com>
parents: 24346
diff changeset
  2954
    losedatafn is not None, it will be called.
8a997bd73448 patch.trydiff: add a docstring
Siddharth Agarwal <sid0@fb.com>
parents: 24346
diff changeset
  2955
41646
d4c9eebdd72d patch: replace "prefix" and "relroot" arguments by "pathfn" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41624
diff changeset
  2956
    pathfn is applied to every path in the diff output.
d4c9eebdd72d patch: replace "prefix" and "relroot" arguments by "pathfn" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41624
diff changeset
  2957
    '''
12167
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12144
diff changeset
  2958
23300
f8b5c3e77d4b patch.trydiff: add support for noprefix
Siddharth Agarwal <sid0@fb.com>
parents: 23297
diff changeset
  2959
    if opts.noprefix:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2960
        aprefix = bprefix = b''
23300
f8b5c3e77d4b patch.trydiff: add support for noprefix
Siddharth Agarwal <sid0@fb.com>
parents: 23297
diff changeset
  2961
    else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2962
        aprefix = b'a/'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2963
        bprefix = b'b/'
23300
f8b5c3e77d4b patch.trydiff: add support for noprefix
Siddharth Agarwal <sid0@fb.com>
parents: 23297
diff changeset
  2964
24021
f51a822dcf3b trydiff: remove unused argument to diffline()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24020
diff changeset
  2965
    def diffline(f, revs):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2966
        revinfo = b' '.join([b"-r %s" % rev for rev in revs])
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  2967
        return b'diff %s %s' % (revinfo, f)
17941
9a6e4d5d7ea8 diff: move diffline to patch module
Guillermo Pérez <bisho@fb.com>
parents: 17940
diff changeset
  2968
32188
776127b29a5c diff: use fctx.size() to test empty
Jun Wu <quark@fb.com>
parents: 32187
diff changeset
  2969
    def isempty(fctx):
776127b29a5c diff: use fctx.size() to test empty
Jun Wu <quark@fb.com>
parents: 32187
diff changeset
  2970
        return fctx is None or fctx.size() == 0
776127b29a5c diff: use fctx.size() to test empty
Jun Wu <quark@fb.com>
parents: 32187
diff changeset
  2971
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36447
diff changeset
  2972
    date1 = dateutil.datestr(ctx1.date())
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36447
diff changeset
  2973
    date2 = dateutil.datestr(ctx2.date())
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
  2974
41646
d4c9eebdd72d patch: replace "prefix" and "relroot" arguments by "pathfn" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41624
diff changeset
  2975
    if not pathfn:
d4c9eebdd72d patch: replace "prefix" and "relroot" arguments by "pathfn" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41624
diff changeset
  2976
        pathfn = lambda f: f
24416
f07047a506d1 patch.trydiff: add support for stripping a relative root
Siddharth Agarwal <sid0@fb.com>
parents: 24390
diff changeset
  2977
27900
27572a5cc409 diff: move status fixup earlier, out of _filepairs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27796
diff changeset
  2978
    for f1, f2, copyop in _filepairs(modified, added, removed, copy, opts):
24105
0f8baebcdbea trydiff: read file data in only one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24104
diff changeset
  2979
        content1 = None
0f8baebcdbea trydiff: read file data in only one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24104
diff changeset
  2980
        content2 = None
32187
e62cf13e0858 diff: use fctx.isbinary() to test binary
Jun Wu <quark@fb.com>
parents: 32068
diff changeset
  2981
        fctx1 = None
e62cf13e0858 diff: use fctx.isbinary() to test binary
Jun Wu <quark@fb.com>
parents: 32068
diff changeset
  2982
        fctx2 = None
24103
c666c85f71ba trydiff: read flags in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24102
diff changeset
  2983
        flag1 = None
c666c85f71ba trydiff: read flags in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24102
diff changeset
  2984
        flag2 = None
24107
32e8d94b9473 trydiff: transpose 'if opts.git or losedatafn' with 'if f[12]'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24106
diff changeset
  2985
        if f1:
32187
e62cf13e0858 diff: use fctx.isbinary() to test binary
Jun Wu <quark@fb.com>
parents: 32068
diff changeset
  2986
            fctx1 = getfilectx(f1, ctx1)
24107
32e8d94b9473 trydiff: transpose 'if opts.git or losedatafn' with 'if f[12]'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24106
diff changeset
  2987
            if opts.git or losedatafn:
32e8d94b9473 trydiff: transpose 'if opts.git or losedatafn' with 'if f[12]'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24106
diff changeset
  2988
                flag1 = ctx1.flags(f1)
32e8d94b9473 trydiff: transpose 'if opts.git or losedatafn' with 'if f[12]'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24106
diff changeset
  2989
        if f2:
32187
e62cf13e0858 diff: use fctx.isbinary() to test binary
Jun Wu <quark@fb.com>
parents: 32068
diff changeset
  2990
            fctx2 = getfilectx(f2, ctx2)
24107
32e8d94b9473 trydiff: transpose 'if opts.git or losedatafn' with 'if f[12]'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24106
diff changeset
  2991
            if opts.git or losedatafn:
32e8d94b9473 trydiff: transpose 'if opts.git or losedatafn' with 'if f[12]'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24106
diff changeset
  2992
                flag2 = ctx2.flags(f2)
32190
0c67ab3d77d5 diff: correct binary testing logic
Jun Wu <quark@fb.com>
parents: 32189
diff changeset
  2993
        # if binary is True, output "summary" or "base85", but not "text diff"
35850
079b27b5a869 patch: avoid repeated binary checks if all files in a patch are text
Joerg Sonnenberger <joerg@bec.de>
parents: 35633
diff changeset
  2994
        if opts.text:
079b27b5a869 patch: avoid repeated binary checks if all files in a patch are text
Joerg Sonnenberger <joerg@bec.de>
parents: 35633
diff changeset
  2995
            binary = False
079b27b5a869 patch: avoid repeated binary checks if all files in a patch are text
Joerg Sonnenberger <joerg@bec.de>
parents: 35633
diff changeset
  2996
        else:
35951
8b6dd3922f70 patch: unify check_binary and binary flags
Yuya Nishihara <yuya@tcha.org>
parents: 35888
diff changeset
  2997
            binary = any(f.isbinary() for f in [fctx1, fctx2] if f is not None)
24057
696d0fd77d94 trydiff: collect all lossiness checks in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24056
diff changeset
  2998
696d0fd77d94 trydiff: collect all lossiness checks in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24056
diff changeset
  2999
        if losedatafn and not opts.git:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3000
            if (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3001
                binary
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3002
                or
24057
696d0fd77d94 trydiff: collect all lossiness checks in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24056
diff changeset
  3003
                # copy/rename
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3004
                f2 in copy
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3005
                or
24057
696d0fd77d94 trydiff: collect all lossiness checks in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24056
diff changeset
  3006
                # empty file creation
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3007
                (not f1 and isempty(fctx2))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3008
                or
24057
696d0fd77d94 trydiff: collect all lossiness checks in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24056
diff changeset
  3009
                # empty file deletion
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3010
                (isempty(fctx1) and not f2)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3011
                or
24057
696d0fd77d94 trydiff: collect all lossiness checks in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24056
diff changeset
  3012
                # create with flags
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3013
                (not f1 and flag2)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3014
                or
24057
696d0fd77d94 trydiff: collect all lossiness checks in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 24056
diff changeset
  3015
                # change flags
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3016
                (f1 and f2 and flag1 != flag2)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3017
            ):
24106
9cf9432a505b trydiff: extract function that generates filename pairs
Martin von Zweigbergk <martinvonz@google.com>
parents: 24105
diff changeset
  3018
                losedatafn(f2 or f1)
10189
e451e599fbcf patch: support diff data loss detection and upgrade
Patrick Mezard <pmezard@gmail.com>
parents: 10151
diff changeset
  3019
41646
d4c9eebdd72d patch: replace "prefix" and "relroot" arguments by "pathfn" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41624
diff changeset
  3020
        path1 = pathfn(f1 or f2)
d4c9eebdd72d patch: replace "prefix" and "relroot" arguments by "pathfn" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41624
diff changeset
  3021
        path2 = pathfn(f2 or f1)
23998
b65637247c69 trydiff: collect header-writing in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 23997
diff changeset
  3022
        header = []
24022
da63f557d0dc trydiff: make 'revs' ignored if opts.git is set
Martin von Zweigbergk <martinvonz@google.com>
parents: 24021
diff changeset
  3023
        if opts.git:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3024
            header.append(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3025
                b'diff --git %s%s %s%s' % (aprefix, path1, bprefix, path2)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3026
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3027
            if not f1:  # added
45098
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3028
                header.append(b'new file mode %s' % _gitmode[flag2])
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3029
            elif not f2:  # removed
45098
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3030
                header.append(b'deleted file mode %s' % _gitmode[flag1])
23998
b65637247c69 trydiff: collect header-writing in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 23997
diff changeset
  3031
            else:  # modified/copied/renamed
45098
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3032
                mode1, mode2 = _gitmode[flag1], _gitmode[flag2]
24000
82e3324c4df9 trydiff: inline sole addmodehdr() call
Martin von Zweigbergk <martinvonz@google.com>
parents: 23999
diff changeset
  3033
                if mode1 != mode2:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3034
                    header.append(b'old mode %s' % mode1)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3035
                    header.append(b'new mode %s' % mode2)
24055
7f4e6b5fce03 trydiff: rename 'op' to make it more specific
Martin von Zweigbergk <martinvonz@google.com>
parents: 24025
diff changeset
  3036
                if copyop is not None:
30807
6381a6dbc325 patch: use opt.showsimilarity to calculate and show the similarity
Sean Farley <sean@farley.io>
parents: 30806
diff changeset
  3037
                    if opts.showsimilarity:
6381a6dbc325 patch: use opt.showsimilarity to calculate and show the similarity
Sean Farley <sean@farley.io>
parents: 30806
diff changeset
  3038
                        sim = similar.score(ctx1[path1], ctx2[path2]) * 100
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3039
                        header.append(b'similarity index %d%%' % sim)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3040
                    header.append(b'%s from %s' % (copyop, path1))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3041
                    header.append(b'%s to %s' % (copyop, path2))
41784
251332dbf33d diff: make sure we output stat even when --git is not passed (issue4037) (BC)
Pulkit Goyal <pulkit@yandex-team.ru>
parents: 41759
diff changeset
  3042
        elif revs:
24022
da63f557d0dc trydiff: make 'revs' ignored if opts.git is set
Martin von Zweigbergk <martinvonz@google.com>
parents: 24021
diff changeset
  3043
            header.append(diffline(path1, revs))
23998
b65637247c69 trydiff: collect header-writing in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 23997
diff changeset
  3044
32189
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3045
        #  fctx.is  | diffopts                | what to   | is fctx.data()
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3046
        #  binary() | text nobinary git index | output?   | outputted?
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3047
        # ------------------------------------|----------------------------
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3048
        #  yes      | no   no       no  *     | summary   | no
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3049
        #  yes      | no   no       yes *     | base85    | yes
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3050
        #  yes      | no   yes      no  *     | summary   | no
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3051
        #  yes      | no   yes      yes 0     | summary   | no
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3052
        #  yes      | no   yes      yes >0    | summary   | semi [1]
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3053
        #  yes      | yes  *        *   *     | text diff | yes
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3054
        #  no       | *    *        *   *     | text diff | yes
15f10ee778f8 diff: draw a table about binary diff behaviors
Jun Wu <quark@fb.com>
parents: 32188
diff changeset
  3055
        # [1]: hash(fctx.data()) is outputted. so fctx.data() cannot be faked
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3056
        if binary and (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3057
            not opts.git or (opts.git and opts.nobinary and not opts.index)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3058
        ):
32191
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3059
            # fast path: no binary content will be displayed, content1 and
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3060
            # content2 are only used for equivalent test. cmp() could have a
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3061
            # fast path.
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3062
            if fctx1 is not None:
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3063
                content1 = b'\0'
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3064
            if fctx2 is not None:
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3065
                if fctx1 is not None and not fctx1.cmp(fctx2):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3066
                    content2 = b'\0'  # not different
32191
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3067
                else:
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3068
                    content2 = b'\0\0'
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3069
        else:
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3070
            # normal path: load contents
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3071
            if fctx1 is not None:
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3072
                content1 = fctx1.data()
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3073
            if fctx2 is not None:
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3074
                content2 = fctx2.data()
31f42e683321 diff: add a fast path to avoid loading binary contents
Jun Wu <quark@fb.com>
parents: 32190
diff changeset
  3075
45098
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3076
        data1 = (ctx1, fctx1, path1, flag1, content1, date1)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3077
        data2 = (ctx2, fctx2, path2, flag2, content2, date2)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3078
        yield diffcontent(data1, data2, header, binary, opts)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3079
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3080
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3081
def diffcontent(data1, data2, header, binary, opts):
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3082
    """ diffs two versions of a file.
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3083
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3084
    data1 and data2 are tuples containg:
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3085
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3086
        * ctx: changeset for the file
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3087
        * fctx: file context for that file
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3088
        * path1: name of the file
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3089
        * flag: flags of the file
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3090
        * content: full content of the file (can be null in case of binary)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3091
        * date: date of the changeset
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3092
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3093
    header: the patch header
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3094
    binary: whether the any of the version of file is binary or not
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3095
    opts:   user passed options
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3096
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3097
    It exists as a separate function so that extensions like extdiff can wrap
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3098
    it and use the file content directly.
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3099
    """
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3100
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3101
    ctx1, fctx1, path1, flag1, content1, date1 = data1
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3102
    ctx2, fctx2, path2, flag2, content2, date2 = data2
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3103
    if binary and opts.git and not opts.nobinary:
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3104
        text = mdiff.b85diff(content1, content2)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3105
        if text:
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3106
            header.append(
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3107
                b'index %s..%s' % (_gitindex(content1), _gitindex(content2))
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3108
            )
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3109
        hunks = ((None, [text]),)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3110
    else:
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3111
        if opts.git and opts.index > 0:
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3112
            flag = flag1
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3113
            if flag is None:
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3114
                flag = flag2
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3115
            header.append(
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3116
                b'index %s..%s %s'
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3117
                % (
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3118
                    _gitindex(content1)[0 : opts.index],
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3119
                    _gitindex(content2)[0 : opts.index],
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3120
                    _gitmode[flag],
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3121
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3122
            )
45098
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3123
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3124
        uheaders, hunks = mdiff.unidiff(
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3125
            content1,
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3126
            date1,
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3127
            content2,
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3128
            date2,
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3129
            path1,
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3130
            path2,
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3131
            binary=binary,
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3132
            opts=opts,
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3133
        )
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3134
        header.extend(uheaders)
20a65e397943 patch: refactor content diffing part in separate fn so extensions can wrap
Pulkit Goyal <7895pulkit@gmail.com>
parents: 45072
diff changeset
  3135
    return fctx1, fctx2, header, hunks
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2868
diff changeset
  3136
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3137
14401
7bb7be1c1385 patch: add diffstatsum helper
Matt Mackall <mpm@selenic.com>
parents: 14400
diff changeset
  3138
def diffstatsum(stats):
14437
cbe13e6bdc34 patch: restore the previous output of 'diff --stat'
Steven Brown <StevenGBrown@gmail.com>
parents: 14435
diff changeset
  3139
    maxfile, maxtotal, addtotal, removetotal, binary = 0, 0, 0, 0, False
14401
7bb7be1c1385 patch: add diffstatsum helper
Matt Mackall <mpm@selenic.com>
parents: 14400
diff changeset
  3140
    for f, a, r, b in stats:
7bb7be1c1385 patch: add diffstatsum helper
Matt Mackall <mpm@selenic.com>
parents: 14400
diff changeset
  3141
        maxfile = max(maxfile, encoding.colwidth(f))
14437
cbe13e6bdc34 patch: restore the previous output of 'diff --stat'
Steven Brown <StevenGBrown@gmail.com>
parents: 14435
diff changeset
  3142
        maxtotal = max(maxtotal, a + r)
14401
7bb7be1c1385 patch: add diffstatsum helper
Matt Mackall <mpm@selenic.com>
parents: 14400
diff changeset
  3143
        addtotal += a
7bb7be1c1385 patch: add diffstatsum helper
Matt Mackall <mpm@selenic.com>
parents: 14400
diff changeset
  3144
        removetotal += r
7bb7be1c1385 patch: add diffstatsum helper
Matt Mackall <mpm@selenic.com>
parents: 14400
diff changeset
  3145
        binary = binary or b
7bb7be1c1385 patch: add diffstatsum helper
Matt Mackall <mpm@selenic.com>
parents: 14400
diff changeset
  3146
14437
cbe13e6bdc34 patch: restore the previous output of 'diff --stat'
Steven Brown <StevenGBrown@gmail.com>
parents: 14435
diff changeset
  3147
    return maxfile, maxtotal, addtotal, removetotal, binary
14401
7bb7be1c1385 patch: add diffstatsum helper
Matt Mackall <mpm@selenic.com>
parents: 14400
diff changeset
  3148
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3149
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3150
def diffstatdata(lines):
41532
bd3f03d8cc9f global: use raw strings for regular expressions with escapes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41499
diff changeset
  3151
    diffre = re.compile(br'^diff .*-r [a-z0-9]+\s(.*)$')
13395
104c9ed93fc5 diffstat: fix parsing of filenames with spaces
Gastón Kleiman <gaston.kleiman@gmail.com>
parents: 13112
diff changeset
  3152
14400
cd1ca2556cac diffstatdata: no longer a generator
Matt Mackall <mpm@selenic.com>
parents: 14392
diff changeset
  3153
    results = []
15363
628a4a9e411d diffstat: be more picky when marking file as 'binary' (issue2816)
Patrick Mezard <pmezard@gmail.com>
parents: 15201
diff changeset
  3154
    filename, adds, removes, isbinary = None, 0, 0, False
14400
cd1ca2556cac diffstatdata: no longer a generator
Matt Mackall <mpm@selenic.com>
parents: 14392
diff changeset
  3155
cd1ca2556cac diffstatdata: no longer a generator
Matt Mackall <mpm@selenic.com>
parents: 14392
diff changeset
  3156
    def addresult():
cd1ca2556cac diffstatdata: no longer a generator
Matt Mackall <mpm@selenic.com>
parents: 14392
diff changeset
  3157
        if filename:
cd1ca2556cac diffstatdata: no longer a generator
Matt Mackall <mpm@selenic.com>
parents: 14392
diff changeset
  3158
            results.append((filename, adds, removes, isbinary))
cd1ca2556cac diffstatdata: no longer a generator
Matt Mackall <mpm@selenic.com>
parents: 14392
diff changeset
  3159
32320
0e29ce16ec38 diffstat: properly count lines starting in '--' or '++' (issue5479)
Andrew Zwicky <andrew.zwicky@gmail.com>
parents: 32201
diff changeset
  3160
    # inheader is used to track if a line is in the
0e29ce16ec38 diffstat: properly count lines starting in '--' or '++' (issue5479)
Andrew Zwicky <andrew.zwicky@gmail.com>
parents: 32201
diff changeset
  3161
    # header portion of the diff.  This helps properly account
0e29ce16ec38 diffstat: properly count lines starting in '--' or '++' (issue5479)
Andrew Zwicky <andrew.zwicky@gmail.com>
parents: 32201
diff changeset
  3162
    # for lines that start with '--' or '++'
0e29ce16ec38 diffstat: properly count lines starting in '--' or '++' (issue5479)
Andrew Zwicky <andrew.zwicky@gmail.com>
parents: 32201
diff changeset
  3163
    inheader = False
0e29ce16ec38 diffstat: properly count lines starting in '--' or '++' (issue5479)
Andrew Zwicky <andrew.zwicky@gmail.com>
parents: 32201
diff changeset
  3164
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3165
    for line in lines:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3166
        if line.startswith(b'diff'):
14400
cd1ca2556cac diffstatdata: no longer a generator
Matt Mackall <mpm@selenic.com>
parents: 14392
diff changeset
  3167
            addresult()
32320
0e29ce16ec38 diffstat: properly count lines starting in '--' or '++' (issue5479)
Andrew Zwicky <andrew.zwicky@gmail.com>
parents: 32201
diff changeset
  3168
            # starting a new file diff
0e29ce16ec38 diffstat: properly count lines starting in '--' or '++' (issue5479)
Andrew Zwicky <andrew.zwicky@gmail.com>
parents: 32201
diff changeset
  3169
            # set numbers to 0 and reset inheader
0e29ce16ec38 diffstat: properly count lines starting in '--' or '++' (issue5479)
Andrew Zwicky <andrew.zwicky@gmail.com>
parents: 32201
diff changeset
  3170
            inheader = True
15363
628a4a9e411d diffstat: be more picky when marking file as 'binary' (issue2816)
Patrick Mezard <pmezard@gmail.com>
parents: 15201
diff changeset
  3171
            adds, removes, isbinary = 0, 0, False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3172
            if line.startswith(b'diff --git a/'):
20972
4e2fb0ad00a9 diff: use second filename for --stat reporting on git patches (issue4221)
Matt Mackall <mpm@selenic.com>
parents: 20869
diff changeset
  3173
                filename = gitre.search(line).group(2)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3174
            elif line.startswith(b'diff -r'):
8761
0289f384e1e5 Generally replace "file name" with "filename" in help and comments.
timeless <timeless@gmail.com>
parents: 8632
diff changeset
  3175
                # format: "diff -r ... -r ... filename"
13395
104c9ed93fc5 diffstat: fix parsing of filenames with spaces
Gastón Kleiman <gaston.kleiman@gmail.com>
parents: 13112
diff changeset
  3176
                filename = diffre.search(line).group(1)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3177
        elif line.startswith(b'@@'):
32320
0e29ce16ec38 diffstat: properly count lines starting in '--' or '++' (issue5479)
Andrew Zwicky <andrew.zwicky@gmail.com>
parents: 32201
diff changeset
  3178
            inheader = False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3179
        elif line.startswith(b'+') and not inheader:
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3180
            adds += 1
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3181
        elif line.startswith(b'-') and not inheader:
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3182
            removes += 1
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3183
        elif line.startswith(b'GIT binary patch') or line.startswith(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3184
            b'Binary file'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3185
        ):
15363
628a4a9e411d diffstat: be more picky when marking file as 'binary' (issue2816)
Patrick Mezard <pmezard@gmail.com>
parents: 15201
diff changeset
  3186
            isbinary = True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3187
        elif line.startswith(b'rename from'):
41401
4a33a6bf2b52 diffstat: support filenames with whitespaces on renames
Navaneeth Suresh <navaneeths1998@gmail.com>
parents: 41375
diff changeset
  3188
            filename = line[12:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3189
        elif line.startswith(b'rename to'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3190
            filename += b' => %s' % line[10:]
14400
cd1ca2556cac diffstatdata: no longer a generator
Matt Mackall <mpm@selenic.com>
parents: 14392
diff changeset
  3191
    addresult()
cd1ca2556cac diffstatdata: no longer a generator
Matt Mackall <mpm@selenic.com>
parents: 14392
diff changeset
  3192
    return results
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3193
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3194
30407
e1677cc29da6 patch: remove unused git parameter from patch.diffstat()
Henning Schild <henning@hennsch.de>
parents: 30397
diff changeset
  3195
def diffstat(lines, width=80):
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3196
    output = []
14402
f03f08240c32 patch: use diffstatsum in diffstat
Matt Mackall <mpm@selenic.com>
parents: 14401
diff changeset
  3197
    stats = diffstatdata(lines)
14437
cbe13e6bdc34 patch: restore the previous output of 'diff --stat'
Steven Brown <StevenGBrown@gmail.com>
parents: 14435
diff changeset
  3198
    maxname, maxtotal, totaladds, totalremoves, hasbinary = diffstatsum(stats)
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3199
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3200
    countwidth = len(str(maxtotal))
9642
7d17794f08a9 diffstat: with --git, mark binary files with Bin
Brodie Rao <me+hg@dackz.net>
parents: 9639
diff changeset
  3201
    if hasbinary and countwidth < 3:
7d17794f08a9 diffstat: with --git, mark binary files with Bin
Brodie Rao <me+hg@dackz.net>
parents: 9639
diff changeset
  3202
        countwidth = 3
9330
be2a13153372 diffstat: scale adds/removes proportionally to graph width
Brodie Rao <me+hg@dackz.net>
parents: 9328
diff changeset
  3203
    graphwidth = width - countwidth - maxname - 6
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3204
    if graphwidth < 10:
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3205
        graphwidth = 10
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3206
9330
be2a13153372 diffstat: scale adds/removes proportionally to graph width
Brodie Rao <me+hg@dackz.net>
parents: 9328
diff changeset
  3207
    def scale(i):
be2a13153372 diffstat: scale adds/removes proportionally to graph width
Brodie Rao <me+hg@dackz.net>
parents: 9328
diff changeset
  3208
        if maxtotal <= graphwidth:
be2a13153372 diffstat: scale adds/removes proportionally to graph width
Brodie Rao <me+hg@dackz.net>
parents: 9328
diff changeset
  3209
            return i
be2a13153372 diffstat: scale adds/removes proportionally to graph width
Brodie Rao <me+hg@dackz.net>
parents: 9328
diff changeset
  3210
        # If diffstat runs out of room it doesn't print anything,
be2a13153372 diffstat: scale adds/removes proportionally to graph width
Brodie Rao <me+hg@dackz.net>
parents: 9328
diff changeset
  3211
        # which isn't very useful, so always print at least one + or -
be2a13153372 diffstat: scale adds/removes proportionally to graph width
Brodie Rao <me+hg@dackz.net>
parents: 9328
diff changeset
  3212
        # if there were at least some changes.
be2a13153372 diffstat: scale adds/removes proportionally to graph width
Brodie Rao <me+hg@dackz.net>
parents: 9328
diff changeset
  3213
        return max(i * graphwidth // maxtotal, int(bool(i)))
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3214
14402
f03f08240c32 patch: use diffstatsum in diffstat
Matt Mackall <mpm@selenic.com>
parents: 14401
diff changeset
  3215
    for filename, adds, removes, isbinary in stats:
15363
628a4a9e411d diffstat: be more picky when marking file as 'binary' (issue2816)
Patrick Mezard <pmezard@gmail.com>
parents: 15201
diff changeset
  3216
        if isbinary:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3217
            count = b'Bin'
9642
7d17794f08a9 diffstat: with --git, mark binary files with Bin
Brodie Rao <me+hg@dackz.net>
parents: 9639
diff changeset
  3218
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3219
            count = b'%d' % (adds + removes)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3220
        pluses = b'+' * scale(adds)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3221
        minuses = b'-' * scale(removes)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3222
        output.append(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3223
            b' %s%s |  %*s %s%s\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3224
            % (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3225
                filename,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3226
                b' ' * (maxname - encoding.colwidth(filename)),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3227
                countwidth,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3228
                count,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3229
                pluses,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3230
                minuses,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3231
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3232
        )
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3233
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3234
    if stats:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3235
        output.append(
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43106
diff changeset
  3236
            _(b' %d files changed, %d insertions(+), %d deletions(-)\n')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3237
            % (len(stats), totaladds, totalremoves)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3238
        )
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7521
diff changeset
  3239
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3240
    return b''.join(output)
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3241
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43066
diff changeset
  3242
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3243
def diffstatui(*args, **kw):
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3244
    '''like diffstat(), but yields 2-tuples of (output, label) for
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3245
    ui.write()
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3246
    '''
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3247
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3248
    for line in diffstat(*args, **kw).splitlines():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3249
        if line and line[-1] in b'+-':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3250
            name, graph = line.rsplit(b' ', 1)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3251
            yield (name + b' ', b'')
33096
d9962854a4a2 py3: add b'' to make the regex pattern bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32990
diff changeset
  3252
            m = re.search(br'\++', graph)
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3253
            if m:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3254
                yield (m.group(0), b'diffstat.inserted')
33096
d9962854a4a2 py3: add b'' to make the regex pattern bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32990
diff changeset
  3255
            m = re.search(br'-+', graph)
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3256
            if m:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3257
                yield (m.group(0), b'diffstat.deleted')
10818
d14d45fae927 diff: make use of output labeling
Brodie Rao <brodie@bitheap.org>
parents: 10751
diff changeset
  3258
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3259
            yield (line, b'')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  3260
        yield (b'\n', b'')