mercurial/patch.py
author Thomas Arendsen Hein <thomas@intevation.de>
Mon, 16 Oct 2006 09:53:31 +0200
changeset 3409 1ae738bacf74
parent 3386 2065789f6a3e
child 3460 2d35a8d2b32d
permissions -rw-r--r--
Fixed page overlap for file revision links in hgweb. This is another step to fix issue189, but currently the file revision numbers are read as changeset revision numbers, so the link will point to the wrong revision.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2860
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
#
2864
71e78f2ca5ae merge git patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2862
diff changeset
     3
# Copyright 2006 Brendan Cully <brendan@kublai.com>
71e78f2ca5ae merge git patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2862
diff changeset
     4
#
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     7
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
     8
from demandload import demandload
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
     9
from i18n import gettext as _
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
    10
from node import *
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
    11
demandload(globals(), "base85 cmdutil mdiff util")
3376
1106e00e6847 Add popen2 demandload to patch.py, required by diffstat
Brendan Cully <brendan@kublai.com>
parents: 3372
diff changeset
    12
demandload(globals(), "cStringIO email.Parser errno os popen2 re shutil sha")
1106e00e6847 Add popen2 demandload to patch.py, required by diffstat
Brendan Cully <brendan@kublai.com>
parents: 3372
diff changeset
    13
demandload(globals(), "sys tempfile zlib")
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    14
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    15
# helper functions
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    16
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    17
def copyfile(src, dst, basedir=None):
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    18
    if not basedir:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    19
        basedir = os.getcwd()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    20
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    21
    abssrc, absdst = [os.path.join(basedir, n) for n in (src, dst)]
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    22
    if os.path.exists(absdst):
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    23
        raise util.Abort(_("cannot create %s: destination already exists") %
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    24
                         dst)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    25
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    26
    targetdir = os.path.dirname(absdst)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    27
    if not os.path.isdir(targetdir):
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    28
        os.makedirs(targetdir)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    29
    try:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    30
        shutil.copyfile(abssrc, absdst)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    31
        shutil.copymode(abssrc, absdst)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    32
    except shutil.Error, inst:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    33
        raise util.Abort(str(inst))
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    34
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    35
# public functions
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
    36
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    37
def extract(ui, fileobj):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    38
    '''extract patch from data read from fileobj.
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    39
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    40
    patch can be normal patch or contained in email message.
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    41
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    42
    return tuple (filename, message, user, date). any item in returned
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    43
    tuple can be None.  if filename is None, fileobj did not contain
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    44
    patch. caller must unlink filename when done.'''
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    45
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    46
    # attempt to detect the start of a patch
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    47
    # (this heuristic is borrowed from quilt)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    48
    diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' +
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    49
                        'retrieving revision [0-9]+(\.[0-9]+)*$|' +
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    50
                        '(---|\*\*\*)[ \t])', re.MULTILINE)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    51
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    52
    fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    53
    tmpfp = os.fdopen(fd, 'w')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    54
    try:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    55
        hgpatch = False
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    56
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    57
        msg = email.Parser.Parser().parse(fileobj)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    58
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    59
        message = msg['Subject']
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    60
        user = msg['From']
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    61
        # should try to parse msg['Date']
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    62
        date = None
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    63
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    64
        if message:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    65
            message = message.replace('\n\t', ' ')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    66
            ui.debug('Subject: %s\n' % message)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    67
        if user:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    68
            ui.debug('From: %s\n' % user)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    69
        diffs_seen = 0
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    70
        ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    71
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    72
        for part in msg.walk():
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    73
            content_type = part.get_content_type()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    74
            ui.debug('Content-Type: %s\n' % content_type)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    75
            if content_type not in ok_types:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    76
                continue
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    77
            payload = part.get_payload(decode=True)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    78
            m = diffre.search(payload)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    79
            if m:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    80
                ui.debug(_('found patch at byte %d\n') % m.start(0))
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    81
                diffs_seen += 1
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    82
                cfp = cStringIO.StringIO()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    83
                if message:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    84
                    cfp.write(message)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    85
                    cfp.write('\n')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    86
                for line in payload[:m.start(0)].splitlines():
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    87
                    if line.startswith('# HG changeset patch'):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    88
                        ui.debug(_('patch generated by hg export\n'))
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    89
                        hgpatch = True
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    90
                        # drop earlier commit message content
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    91
                        cfp.seek(0)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    92
                        cfp.truncate()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    93
                    elif hgpatch:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    94
                        if line.startswith('# User '):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    95
                            user = line[7:]
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    96
                            ui.debug('From: %s\n' % user)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    97
                        elif line.startswith("# Date "):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    98
                            date = line[7:]
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
    99
                    if not line.startswith('# '):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   100
                        cfp.write(line)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   101
                        cfp.write('\n')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   102
                message = cfp.getvalue()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   103
                if tmpfp:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   104
                    tmpfp.write(payload)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   105
                    if not payload.endswith('\n'):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   106
                        tmpfp.write('\n')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   107
            elif not diffs_seen and message and content_type == 'text/plain':
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   108
                message += '\n' + payload
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   109
    except:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   110
        tmpfp.close()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   111
        os.unlink(tmpname)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   112
        raise
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   113
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   114
    tmpfp.close()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   115
    if not diffs_seen:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   116
        os.unlink(tmpname)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   117
        return None, message, user, date
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
   118
    return tmpname, message, user, date
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   119
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   120
def readgitpatch(patchname):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   121
    """extract git-style metadata about patches from <patchname>"""
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   122
    class gitpatch:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   123
        "op is one of ADD, DELETE, RENAME, MODIFY or COPY"
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   124
        def __init__(self, path):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   125
            self.path = path
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   126
            self.oldpath = None
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   127
            self.mode = None
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   128
            self.op = 'MODIFY'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   129
            self.copymod = False
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   130
            self.lineno = 0
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   131
            self.binary = False
3215
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3192
diff changeset
   132
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   133
    # Filter patch for git information
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   134
    gitre = re.compile('diff --git a/(.*) b/(.*)')
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   135
    pf = file(patchname)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   136
    gp = None
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   137
    gitpatches = []
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   138
    # Can have a git patch with only metadata, causing patch to complain
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   139
    dopatch = False
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   140
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   141
    lineno = 0
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   142
    for line in pf:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   143
        lineno += 1
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   144
        if line.startswith('diff --git'):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   145
            m = gitre.match(line)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   146
            if m:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   147
                if gp:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   148
                    gitpatches.append(gp)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   149
                src, dst = m.group(1,2)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   150
                gp = gitpatch(dst)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   151
                gp.lineno = lineno
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   152
        elif gp:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   153
            if line.startswith('--- '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   154
                if gp.op in ('COPY', 'RENAME'):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   155
                    gp.copymod = True
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   156
                    dopatch = 'filter'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   157
                gitpatches.append(gp)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   158
                gp = None
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   159
                if not dopatch:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   160
                    dopatch = True
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   161
                continue
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   162
            if line.startswith('rename from '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   163
                gp.op = 'RENAME'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   164
                gp.oldpath = line[12:].rstrip()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   165
            elif line.startswith('rename to '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   166
                gp.path = line[10:].rstrip()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   167
            elif line.startswith('copy from '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   168
                gp.op = 'COPY'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   169
                gp.oldpath = line[10:].rstrip()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   170
            elif line.startswith('copy to '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   171
                gp.path = line[8:].rstrip()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   172
            elif line.startswith('deleted file'):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   173
                gp.op = 'DELETE'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   174
            elif line.startswith('new file mode '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   175
                gp.op = 'ADD'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   176
                gp.mode = int(line.rstrip()[-3:], 8)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   177
            elif line.startswith('new mode '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   178
                gp.mode = int(line.rstrip()[-3:], 8)
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   179
            elif line.startswith('GIT binary patch'):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   180
                if not dopatch:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   181
                    dopatch = 'binary'
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   182
                gp.binary = True
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   183
    if gp:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   184
        gitpatches.append(gp)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   185
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   186
    if not gitpatches:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   187
        dopatch = True
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   188
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   189
    return (dopatch, gitpatches)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   190
3052
efd26ceedafb Fix git patch application when cwd != repo.root
Brendan Cully <brendan@kublai.com>
parents: 2952
diff changeset
   191
def dogitpatch(patchname, gitpatches, cwd=None):
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   192
    """Preprocess git patch so that vanilla patch can handle it"""
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   193
    def extractbin(fp):
3372
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   194
        line = fp.readline().rstrip()
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   195
        while line and not line.startswith('literal '):
3372
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   196
            line = fp.readline().rstrip()
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   197
        if not line:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   198
            return
3372
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   199
        size = int(line[8:])
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   200
        dec = []
3372
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   201
        line = fp.readline().rstrip()
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   202
        while line:
3372
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   203
            l = line[0]
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   204
            if l <= 'Z' and l >= 'A':
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   205
                l = ord(l) - ord('A') + 1
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   206
            else:
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   207
                l = ord(l) - ord('a') + 27
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   208
            dec.append(base85.b85decode(line[1:])[:l])
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
   209
            line = fp.readline().rstrip()
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   210
        text = zlib.decompress(''.join(dec))
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   211
        if len(text) != size:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   212
            raise util.Abort(_('binary patch is %d bytes, not %d') %
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   213
                             (len(text), size))
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   214
        return text
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   215
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   216
    pf = file(patchname)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   217
    pfline = 1
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   218
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   219
    fd, patchname = tempfile.mkstemp(prefix='hg-patch-')
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   220
    tmpfp = os.fdopen(fd, 'w')
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   221
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   222
    try:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   223
        for i in range(len(gitpatches)):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   224
            p = gitpatches[i]
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   225
            if not p.copymod and not p.binary:
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   226
                continue
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   227
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   228
            # rewrite patch hunk
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   229
            while pfline < p.lineno:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   230
                tmpfp.write(pf.readline())
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   231
                pfline += 1
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   232
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   233
            if p.binary:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   234
                text = extractbin(pf)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   235
                if not text:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   236
                    raise util.Abort(_('binary patch extraction failed'))
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   237
                if not cwd:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   238
                    cwd = os.getcwd()
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   239
                absdst = os.path.join(cwd, p.path)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   240
                basedir = os.path.dirname(absdst)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   241
                if not os.path.isdir(basedir):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   242
                    os.makedirs(basedir)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   243
                out = file(absdst, 'wb')
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   244
                out.write(text)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   245
                out.close()
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   246
            elif p.copymod:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   247
                copyfile(p.oldpath, p.path, basedir=cwd)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   248
                tmpfp.write('diff --git a/%s b/%s\n' % (p.path, p.path))
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   249
                line = pf.readline()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   250
                pfline += 1
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   251
                while not line.startswith('--- a/'):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   252
                    tmpfp.write(line)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   253
                    line = pf.readline()
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   254
                    pfline += 1
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   255
                tmpfp.write('--- a/%s\n' % p.path)
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   256
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   257
        line = pf.readline()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   258
        while line:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   259
            tmpfp.write(line)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   260
            line = pf.readline()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   261
    except:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   262
        tmpfp.close()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   263
        os.unlink(patchname)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   264
        raise
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   265
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   266
    tmpfp.close()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   267
    return patchname
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   268
2907
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   269
def patch(patchname, ui, strip=1, cwd=None):
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   270
    """apply the patch <patchname> to the working directory.
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   271
    a list of patched files is returned"""
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   272
3054
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   273
    # helper function
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   274
    def __patch(patchname):
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   275
        """patch and updates the files and fuzz variables"""
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   276
        files = {}
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   277
        fuzz = False
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   278
3054
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   279
        patcher = util.find_in_path('gpatch', os.environ.get('PATH', ''),
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   280
                                    'patch')
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   281
        args = []
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   282
        if cwd:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   283
            args.append('-d %s' % util.shellquote(cwd))
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   284
        fp = os.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip,
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   285
                                           util.shellquote(patchname)))
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   286
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   287
        for line in fp:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   288
            line = line.rstrip()
2907
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   289
            ui.note(line + '\n')
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   290
            if line.startswith('patching file '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   291
                pf = util.parse_patch_output(line)
2907
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   292
                printed_file = False
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   293
                files.setdefault(pf, (None, None))
2907
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   294
            elif line.find('with fuzz') >= 0:
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   295
                fuzz = True
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   296
                if not printed_file:
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   297
                    ui.warn(pf + '\n')
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   298
                    printed_file = True
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   299
                ui.warn(line + '\n')
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   300
            elif line.find('saving rejects to file') >= 0:
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   301
                ui.warn(line + '\n')
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   302
            elif line.find('FAILED') >= 0:
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   303
                if not printed_file:
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   304
                    ui.warn(pf + '\n')
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   305
                    printed_file = True
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   306
                ui.warn(line + '\n')
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   307
        code = fp.close()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   308
        if code:
2867
9a2a481ec3ea util: qualify name properly.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   309
            raise util.Abort(_("patch command failed: %s") %
9a2a481ec3ea util: qualify name properly.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2865
diff changeset
   310
                             util.explain_exit(code)[0])
3054
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   311
        return files, fuzz
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   312
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   313
    (dopatch, gitpatches) = readgitpatch(patchname)
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   314
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   315
    files, fuzz = {}, False
3054
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   316
    if dopatch:
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   317
        if dopatch in ('filter', 'binary'):
3054
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   318
            patchname = dogitpatch(patchname, gitpatches, cwd=cwd)
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   319
        try:
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   320
            if dopatch != 'binary':
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   321
                files, fuzz = __patch(patchname)
3054
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   322
        finally:
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   323
            if dopatch == 'filter':
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
   324
                os.unlink(patchname)
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   325
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   326
    for gp in gitpatches:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   327
        files[gp.path] = (gp.op, gp)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
   328
2907
b70740aefa4d Unify mq and hg patch invocation.
Brendan Cully <brendan@kublai.com>
parents: 2892
diff changeset
   329
    return (files, fuzz)
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   330
2908
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   331
def diffopts(ui, opts={}):
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   332
    return mdiff.diffopts(
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   333
        text=opts.get('text'),
2921
addb58e3b41c redo merge with mpm.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2907 2908
diff changeset
   334
        git=(opts.get('git') or
addb58e3b41c redo merge with mpm.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2907 2908
diff changeset
   335
                  ui.configbool('diff', 'git', None)),
3192
096f1c73cdc3 Add -D/--nodates options to hg diff/export that removes dates from diff headers
Stephen Darnell <stephen@darnell.plus.com>
parents: 3159
diff changeset
   336
        nodates=(opts.get('nodates') or
096f1c73cdc3 Add -D/--nodates options to hg diff/export that removes dates from diff headers
Stephen Darnell <stephen@darnell.plus.com>
parents: 3159
diff changeset
   337
                  ui.configbool('diff', 'nodates', None)),
2908
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   338
        showfunc=(opts.get('show_function') or
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   339
                  ui.configbool('diff', 'showfunc', None)),
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   340
        ignorews=(opts.get('ignore_all_space') or
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   341
                  ui.configbool('diff', 'ignorews', None)),
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   342
        ignorewsamount=(opts.get('ignore_space_change') or
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   343
                        ui.configbool('diff', 'ignorewsamount', None)),
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   344
        ignoreblanklines=(opts.get('ignore_blank_lines') or
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   345
                          ui.configbool('diff', 'ignoreblanklines', None)))
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
   346
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   347
def updatedir(ui, repo, patches, wlock=None):
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   348
    '''Update dirstate after patch application according to metadata'''
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   349
    if not patches:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   350
        return
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   351
    copies = []
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   352
    removes = []
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   353
    cfiles = patches.keys()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   354
    cwd = repo.getcwd()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   355
    if cwd:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   356
        cfiles = [util.pathto(cwd, f) for f in patches.keys()]
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   357
    for f in patches:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   358
        ctype, gp = patches[f]
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   359
        if ctype == 'RENAME':
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   360
            copies.append((gp.oldpath, gp.path, gp.copymod))
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   361
            removes.append(gp.oldpath)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   362
        elif ctype == 'COPY':
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   363
            copies.append((gp.oldpath, gp.path, gp.copymod))
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   364
        elif ctype == 'DELETE':
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   365
            removes.append(gp.path)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   366
    for src, dst, after in copies:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   367
        if not after:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   368
            copyfile(src, dst, repo.root)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   369
        repo.copy(src, dst, wlock=wlock)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   370
    if removes:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   371
        repo.remove(removes, True, wlock=wlock)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   372
    for f in patches:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   373
        ctype, gp = patches[f]
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   374
        if gp and gp.mode:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   375
            x = gp.mode & 0100 != 0
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   376
            dst = os.path.join(repo.root, gp.path)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   377
            util.set_exec(dst, x)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   378
    cmdutil.addremove(repo, cfiles, wlock=wlock)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   379
    files = patches.keys()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   380
    files.extend([r for r in removes if r not in files])
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   381
    files.sort()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   382
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   383
    return files
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
   384
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   385
def b85diff(fp, to, tn):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   386
    '''print base85-encoded binary diff'''
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   387
    def gitindex(text):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   388
        if not text:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   389
            return '0' * 40
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   390
        l = len(text)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   391
        s = sha.new('blob %d\0' % l)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   392
        s.update(text)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   393
        return s.hexdigest()
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   394
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   395
    def fmtline(line):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   396
        l = len(line)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   397
        if l <= 26:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   398
            l = chr(ord('A') + l - 1)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   399
        else:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   400
            l = chr(l - 26 + ord('a') - 1)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   401
        return '%c%s\n' % (l, base85.b85encode(line, True))
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   402
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   403
    def chunk(text, csize=52):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   404
        l = len(text)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   405
        i = 0
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   406
        while i < l:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   407
            yield text[i:i+csize]
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   408
            i += csize
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   409
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   410
    # TODO: deltas
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   411
    l = len(tn)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   412
    fp.write('index %s..%s\nGIT binary patch\nliteral %s\n' %
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   413
             (gitindex(to), gitindex(tn), len(tn)))
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   414
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   415
    tn = ''.join([fmtline(l) for l in chunk(zlib.compress(tn))])
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   416
    fp.write(tn)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   417
    fp.write('\n')
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   418
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   419
def diff(repo, node1=None, node2=None, files=None, match=util.always,
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   420
         fp=None, changes=None, opts=None):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   421
    '''print diff of changes to files between two nodes, or node and
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   422
    working directory.
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   423
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   424
    if node1 is None, use first dirstate parent instead.
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   425
    if node2 is None, compare node1 with working directory.'''
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   426
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   427
    if opts is None:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   428
        opts = mdiff.defaultopts
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   429
    if fp is None:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   430
        fp = repo.ui
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   431
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   432
    if not node1:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   433
        node1 = repo.dirstate.parents()[0]
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   434
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   435
    clcache = {}
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   436
    def getchangelog(n):
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   437
        if n not in clcache:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   438
            clcache[n] = repo.changelog.read(n)
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   439
        return clcache[n]
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   440
    mcache = {}
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   441
    def getmanifest(n):
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   442
        if n not in mcache:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   443
            mcache[n] = repo.manifest.read(n)
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   444
        return mcache[n]
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   445
    fcache = {}
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   446
    def getfile(f):
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   447
        if f not in fcache:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   448
            fcache[f] = repo.file(f)
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   449
        return fcache[f]
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   450
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   451
    # reading the data for node1 early allows it to play nicely
2874
3d6efcbbd1c9 remove localrepository.changes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2873
diff changeset
   452
    # with repo.status and the revlog cache.
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   453
    change = getchangelog(node1)
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   454
    mmap = getmanifest(change[0])
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   455
    date1 = util.datestr(change[2])
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   456
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   457
    if not changes:
2874
3d6efcbbd1c9 remove localrepository.changes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2873
diff changeset
   458
        changes = repo.status(node1, node2, files, match=match)[:5]
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   459
    modified, added, removed, deleted, unknown = changes
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   460
    if files:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   461
        def filterfiles(filters):
2880
eab07a7b7491 fix patch.patch.filterfiles.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2874
diff changeset
   462
            l = [x for x in filters if x in files]
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   463
2880
eab07a7b7491 fix patch.patch.filterfiles.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2874
diff changeset
   464
            for t in files:
eab07a7b7491 fix patch.patch.filterfiles.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2874
diff changeset
   465
                if not t.endswith("/"):
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   466
                    t += "/"
2880
eab07a7b7491 fix patch.patch.filterfiles.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2874
diff changeset
   467
                l += [x for x in filters if x.startswith(t)]
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   468
            return l
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   469
2880
eab07a7b7491 fix patch.patch.filterfiles.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2874
diff changeset
   470
        modified, added, removed = map(filterfiles, (modified, added, removed))
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   471
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   472
    if not modified and not added and not removed:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   473
        return
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   474
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   475
    def renamedbetween(f, n1, n2):
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   476
        r1, r2 = map(repo.changelog.rev, (n1, n2))
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   477
        src = None
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   478
        while r2 > r1:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   479
            cl = getchangelog(n2)[0]
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   480
            m = getmanifest(cl)
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   481
            try:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   482
                src = getfile(f).renamed(m[f])
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   483
            except KeyError:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   484
                return None
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   485
            if src:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   486
                f = src[0]
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   487
            n2 = repo.changelog.parents(n2)[0]
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   488
            r2 = repo.changelog.rev(n2)
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   489
        return src
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   490
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   491
    if node2:
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   492
        change = getchangelog(node2)
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   493
        mmap2 = getmanifest(change[0])
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   494
        _date2 = util.datestr(change[2])
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   495
        def date2(f):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   496
            return _date2
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   497
        def read(f):
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   498
            return getfile(f).read(mmap2[f])
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   499
        def renamed(f):
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   500
            return renamedbetween(f, node1, node2)
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   501
    else:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   502
        tz = util.makedate()[1]
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   503
        _date2 = util.datestr()
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   504
        def date2(f):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   505
            try:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   506
                return util.datestr((os.lstat(repo.wjoin(f)).st_mtime, tz))
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   507
            except OSError, err:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   508
                if err.errno != errno.ENOENT: raise
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   509
                return _date2
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   510
        def read(f):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   511
            return repo.wread(f)
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   512
        def renamed(f):
3159
e43fd1623fe1 fix users of dirstate.copies broken by b1f10d3223c1
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3093
diff changeset
   513
            src = repo.dirstate.copied(f)
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   514
            parent = repo.dirstate.parents()[0]
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   515
            if src:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   516
                f = src[0]
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   517
            of = renamedbetween(f, node1, parent)
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   518
            if of:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   519
                return of
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   520
            elif src:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   521
                cl = getchangelog(parent)[0]
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   522
                return (src, getmanifest(cl)[src])
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   523
            else:
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   524
                return None
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   525
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   526
    if repo.ui.quiet:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   527
        r = None
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   528
    else:
3386
2065789f6a3e use short hashes with diff -v
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3376
diff changeset
   529
        hexfunc = repo.ui.debugflag and hex or short
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   530
        r = [hexfunc(node) for node in [node1, node2] if node]
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   531
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   532
    if opts.git:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   533
        copied = {}
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   534
        for f in added:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   535
            src = renamed(f)
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   536
            if src:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   537
                copied[f] = src
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   538
        srcs = [x[1][0] for x in copied.items()]
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   539
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   540
    all = modified + added + removed
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   541
    all.sort()
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   542
    for f in all:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   543
        to = None
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   544
        tn = None
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   545
        dodiff = True
3327
319358e6bd96 Don't generate git diff header for empty diffs
Brendan Cully <brendan@kublai.com>
parents: 3223
diff changeset
   546
        header = []
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   547
        if f in mmap:
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   548
            to = getfile(f).read(mmap[f])
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   549
        if f not in removed:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   550
            tn = read(f)
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   551
        if opts.git:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   552
            def gitmode(x):
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   553
                return x and '100755' or '100644'
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   554
            def addmodehdr(header, omode, nmode):
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   555
                if omode != nmode:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   556
                    header.append('old mode %s\n' % omode)
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   557
                    header.append('new mode %s\n' % nmode)
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   558
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   559
            a, b = f, f
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   560
            if f in added:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   561
                if node2:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   562
                    mode = gitmode(mmap2.execf(f))
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   563
                else:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   564
                    mode = gitmode(util.is_exec(repo.wjoin(f), None))
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   565
                if f in copied:
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   566
                    a, arev = copied[f]
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   567
                    omode = gitmode(mmap.execf(a))
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   568
                    addmodehdr(header, omode, mode)
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   569
                    op = a in removed and 'rename' or 'copy'
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   570
                    header.append('%s from %s\n' % (op, a))
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   571
                    header.append('%s to %s\n' % (op, f))
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
   572
                    to = getfile(a).read(arev)
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   573
                else:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   574
                    header.append('new file mode %s\n' % mode)
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   575
                    if util.binary(tn):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   576
                        dodiff = 'binary'
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   577
            elif f in removed:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   578
                if f in srcs:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   579
                    dodiff = False
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   580
                else:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   581
                    mode = gitmode(mmap.execf(f))
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   582
                    header.append('deleted file mode %s\n' % mode)
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   583
            else:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   584
                omode = gitmode(mmap.execf(f))
3063
035fd2029575 git --diff: fix traceback when getting mode change
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3054
diff changeset
   585
                if node2:
035fd2029575 git --diff: fix traceback when getting mode change
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3054
diff changeset
   586
                    nmode = gitmode(mmap2.execf(f))
035fd2029575 git --diff: fix traceback when getting mode change
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3054
diff changeset
   587
                else:
035fd2029575 git --diff: fix traceback when getting mode change
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3054
diff changeset
   588
                    nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f)))
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   589
                addmodehdr(header, omode, nmode)
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   590
                if util.binary(to) or util.binary(tn):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   591
                    dodiff = 'binary'
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   592
            r = None
3327
319358e6bd96 Don't generate git diff header for empty diffs
Brendan Cully <brendan@kublai.com>
parents: 3223
diff changeset
   593
            header.insert(0, 'diff --git a/%s b/%s\n' % (a, b))
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   594
        if dodiff == 'binary':
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   595
            fp.write(''.join(header))
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   596
            b85diff(fp, to, tn)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
   597
        elif dodiff:
3327
319358e6bd96 Don't generate git diff header for empty diffs
Brendan Cully <brendan@kublai.com>
parents: 3223
diff changeset
   598
            text = mdiff.unidiff(to, date1, tn, date2(f), f, r, opts=opts)
319358e6bd96 Don't generate git diff header for empty diffs
Brendan Cully <brendan@kublai.com>
parents: 3223
diff changeset
   599
            if text or len(header) > 1:
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
   600
                fp.write(''.join(header))
3327
319358e6bd96 Don't generate git diff header for empty diffs
Brendan Cully <brendan@kublai.com>
parents: 3223
diff changeset
   601
            fp.write(text)
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   602
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   603
def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   604
           opts=None):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   605
    '''export changesets as hg patches.'''
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   606
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   607
    total = len(revs)
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   608
    revwidth = max(map(len, revs))
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   609
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   610
    def single(node, seqno, fp):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   611
        parents = [p for p in repo.changelog.parents(node) if p != nullid]
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   612
        if switch_parent:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   613
            parents.reverse()
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   614
        prev = (parents and parents[0]) or nullid
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   615
        change = repo.changelog.read(node)
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   616
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   617
        if not fp:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   618
            fp = cmdutil.make_file(repo, template, node, total=total,
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   619
                                   seqno=seqno, revwidth=revwidth)
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   620
        if fp not in (sys.stdout, repo.ui):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   621
            repo.ui.note("%s\n" % fp.name)
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   622
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   623
        fp.write("# HG changeset patch\n")
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   624
        fp.write("# User %s\n" % change[1])
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   625
        fp.write("# Date %d %d\n" % change[2])
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   626
        fp.write("# Node ID %s\n" % hex(node))
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   627
        fp.write("# Parent  %s\n" % hex(prev))
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   628
        if len(parents) > 1:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   629
            fp.write("# Parent  %s\n" % hex(parents[1]))
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   630
        fp.write(change[4].rstrip())
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   631
        fp.write("\n\n")
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   632
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   633
        diff(repo, prev, node, fp=fp, opts=opts)
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   634
        if fp not in (sys.stdout, repo.ui):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   635
            fp.close()
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   636
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   637
    for seqno, cset in enumerate(revs):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
   638
        single(cset, seqno, fp)
3093
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   639
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   640
def diffstat(patchlines):
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   641
    fd, name = tempfile.mkstemp(prefix="hg-patchbomb-", suffix=".txt")
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   642
    try:
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   643
        p = popen2.Popen3('diffstat -p1 -w79 2>/dev/null > ' + name)
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   644
        try:
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   645
            for line in patchlines: print >> p.tochild, line
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   646
            p.tochild.close()
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   647
            if p.wait(): return
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   648
            fp = os.fdopen(fd, 'r')
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   649
            stat = []
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   650
            for line in fp: stat.append(line.lstrip())
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   651
            last = stat.pop()
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   652
            stat.insert(0, last)
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   653
            stat = ''.join(stat)
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   654
            if stat.startswith('0 files'): raise ValueError
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   655
            return stat
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   656
        except: raise
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   657
    finally:
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   658
        try: os.unlink(name)
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
   659
        except: pass