annotate mercurial/patch.py @ 5053:47a8ea1eb2c3

del transaction before lock before wlock This way rollbacks happen while the repo is still locked. Deleting lock before wlock is not strictly necessary, but is more consistent with the locking order.
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Thu, 02 Aug 2007 01:56:08 -0300
parents a675f6d5d069
children 35d47b06d4e3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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>
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
4 # Copyright 2007 Chris Mason <chris.mason@oracle.com>
2864
71e78f2ca5ae merge git patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2862
diff changeset
5 #
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
6 # 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
7 # 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
8
3893
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3886
diff changeset
9 from i18n import _
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
10 from node import *
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
11 import base85, cmdutil, mdiff, util, context, revlog, diffhelpers
3963
ba45041827a2 remove various unused import
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3902
diff changeset
12 import cStringIO, email.Parser, os, popen2, re, sha
3886
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents: 3717
diff changeset
13 import sys, tempfile, zlib
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
14
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
15 class PatchError(Exception):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
16 pass
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
17
4900
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
18 class NoHunks(PatchError):
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
19 pass
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
20
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
21 # helper functions
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
22
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
23 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
24 if not basedir:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
25 basedir = os.getcwd()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
26
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
27 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
28 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
29 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
30 dst)
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
31
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
32 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
33 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
34 os.makedirs(targetdir)
3632
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3588
diff changeset
35
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3588
diff changeset
36 util.copyfile(abssrc, absdst)
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
37
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
38 # public functions
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
39
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
40 def extract(ui, fileobj):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
41 '''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
42
4258
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
43 patch can be a normal patch or contained in an email message.
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
44
4258
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
45 return tuple (filename, message, user, date, node, p1, p2).
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
46 Any item in the returned tuple can be None. If filename is None,
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
47 fileobj did not contain a patch. Caller must unlink filename when done.'''
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
48
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
49 # 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
50 # (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
51 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
52 '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
53 '(---|\*\*\*)[ \t])', re.MULTILINE)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
54
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
55 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
56 tmpfp = os.fdopen(fd, 'w')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
57 try:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
58 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
59
4770
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
60 subject = msg['Subject']
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
61 user = msg['From']
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
62 # 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
63 date = None
4258
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
64 nodeid = None
4440
eff2eefdb65a Add ability to parse branch information to hg import
Eric Hopper <hopper@omnifarious.org>
parents: 4436
diff changeset
65 branch = None
4258
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
66 parents = []
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
67
4770
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
68 if subject:
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
69 if subject.startswith('[PATCH'):
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
70 pend = subject.find(']')
4203
bd9b84b9a84b Make [PATCH] removal slightly more robust
Brendan Cully <brendan@kublai.com>
parents: 4196
diff changeset
71 if pend >= 0:
4770
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
72 subject = subject[pend+1:].lstrip()
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
73 subject = subject.replace('\n\t', ' ')
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
74 ui.debug('Subject: %s\n' % subject)
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
75 if user:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
76 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
77 diffs_seen = 0
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
78 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
4900
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
79 message = ''
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
80 for part in msg.walk():
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
81 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
82 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
83 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
84 continue
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
85 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
86 m = diffre.search(payload)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
87 if m:
4211
1253703853a8 git-send-email compatibility: stop reading changelog after ^---$
Brendan Cully <brendan@kublai.com>
parents: 4203
diff changeset
88 hgpatch = False
1253703853a8 git-send-email compatibility: stop reading changelog after ^---$
Brendan Cully <brendan@kublai.com>
parents: 4203
diff changeset
89 ignoretext = False
1253703853a8 git-send-email compatibility: stop reading changelog after ^---$
Brendan Cully <brendan@kublai.com>
parents: 4203
diff changeset
90
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
91 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
92 diffs_seen += 1
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
93 cfp = cStringIO.StringIO()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
94 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
95 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
96 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
97 hgpatch = True
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
98 # drop earlier commit message content
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
99 cfp.seek(0)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
100 cfp.truncate()
4771
e321f16f4eac patch.extract: fix test-import breakage introduced in the previous changeset
Brendan Cully <brendan@kublai.com>
parents: 4770
diff changeset
101 subject = None
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
102 elif hgpatch:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
103 if line.startswith('# User '):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
104 user = line[7:]
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
105 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
106 elif line.startswith("# Date "):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
107 date = line[7:]
4440
eff2eefdb65a Add ability to parse branch information to hg import
Eric Hopper <hopper@omnifarious.org>
parents: 4436
diff changeset
108 elif line.startswith("# Branch "):
eff2eefdb65a Add ability to parse branch information to hg import
Eric Hopper <hopper@omnifarious.org>
parents: 4436
diff changeset
109 branch = line[9:]
4258
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
110 elif line.startswith("# Node ID "):
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
111 nodeid = line[10:]
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
112 elif line.startswith("# Parent "):
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
113 parents.append(line[10:])
4211
1253703853a8 git-send-email compatibility: stop reading changelog after ^---$
Brendan Cully <brendan@kublai.com>
parents: 4203
diff changeset
114 elif line == '---' and 'git-send-email' in msg['X-Mailer']:
1253703853a8 git-send-email compatibility: stop reading changelog after ^---$
Brendan Cully <brendan@kublai.com>
parents: 4203
diff changeset
115 ignoretext = True
1253703853a8 git-send-email compatibility: stop reading changelog after ^---$
Brendan Cully <brendan@kublai.com>
parents: 4203
diff changeset
116 if not line.startswith('# ') and not ignoretext:
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
117 cfp.write(line)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
118 cfp.write('\n')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
119 message = cfp.getvalue()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
120 if tmpfp:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
121 tmpfp.write(payload)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
122 if not payload.endswith('\n'):
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
123 tmpfp.write('\n')
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
124 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
125 message += '\n' + payload
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
126 except:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
127 tmpfp.close()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
128 os.unlink(tmpname)
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
129 raise
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
130
4770
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
131 if subject and not message.startswith(subject):
5ee5cbfceff3 patch.extract: do not prepend subject if the description already starts with it
Brendan Cully <brendan@kublai.com>
parents: 4659
diff changeset
132 message = '%s\n%s' % (subject, message)
2865
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
133 tmpfp.close()
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
134 if not diffs_seen:
2893e51407a4 commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2864
diff changeset
135 os.unlink(tmpname)
4440
eff2eefdb65a Add ability to parse branch information to hg import
Eric Hopper <hopper@omnifarious.org>
parents: 4436
diff changeset
136 return None, message, user, date, branch, None, None, None
4258
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
137 p1 = parents and parents.pop(0) or None
47ba52121433 Add import --exact.
Brendan Cully <brendan@kublai.com>
parents: 4232
diff changeset
138 p2 = parents and parents.pop(0) or None
4440
eff2eefdb65a Add ability to parse branch information to hg import
Eric Hopper <hopper@omnifarious.org>
parents: 4436
diff changeset
139 return tmpname, message, user, date, branch, nodeid, p1, p2
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
140
3716
ab5600428b08 handle files with both git binary patches and copy/rename ops
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3702
diff changeset
141 GP_PATCH = 1 << 0 # we have to run patch
ab5600428b08 handle files with both git binary patches and copy/rename ops
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3702
diff changeset
142 GP_FILTER = 1 << 1 # there's some copy/rename operation
ab5600428b08 handle files with both git binary patches and copy/rename ops
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3702
diff changeset
143 GP_BINARY = 1 << 2 # there's a binary patch
ab5600428b08 handle files with both git binary patches and copy/rename ops
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3702
diff changeset
144
5035
a675f6d5d069 patch: make internal code a bit friendlier to use
Bryan O'Sullivan <bos@serpentine.com>
parents: 5033
diff changeset
145 def readgitpatch(fp, firstline=None):
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
146 """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
147 class gitpatch:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
148 "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
149 def __init__(self, path):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
150 self.path = path
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
151 self.oldpath = None
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
152 self.mode = None
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
153 self.op = 'MODIFY'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
154 self.copymod = False
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
155 self.lineno = 0
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
156 self.binary = False
3215
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3192
diff changeset
157
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
158 def reader(fp, firstline):
5035
a675f6d5d069 patch: make internal code a bit friendlier to use
Bryan O'Sullivan <bos@serpentine.com>
parents: 5033
diff changeset
159 if firstline is not None:
a675f6d5d069 patch: make internal code a bit friendlier to use
Bryan O'Sullivan <bos@serpentine.com>
parents: 5033
diff changeset
160 yield firstline
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
161 for line in fp:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
162 yield line
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
163
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
164 # Filter patch for git information
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
165 gitre = re.compile('diff --git a/(.*) b/(.*)')
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
166 gp = None
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
167 gitpatches = []
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
168 # Can have a git patch with only metadata, causing patch to complain
3716
ab5600428b08 handle files with both git binary patches and copy/rename ops
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3702
diff changeset
169 dopatch = 0
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
170
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
171 lineno = 0
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
172 for line in reader(fp, firstline):
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
173 lineno += 1
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
174 if line.startswith('diff --git'):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
175 m = gitre.match(line)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
176 if m:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
177 if gp:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
178 gitpatches.append(gp)
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3632
diff changeset
179 src, dst = m.group(1, 2)
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
180 gp = gitpatch(dst)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
181 gp.lineno = lineno
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
182 elif gp:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
183 if line.startswith('--- '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
184 if gp.op in ('COPY', 'RENAME'):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
185 gp.copymod = True
3716
ab5600428b08 handle files with both git binary patches and copy/rename ops
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3702
diff changeset
186 dopatch |= GP_FILTER
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
187 gitpatches.append(gp)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
188 gp = None
3716
ab5600428b08 handle files with both git binary patches and copy/rename ops
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3702
diff changeset
189 dopatch |= GP_PATCH
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
190 continue
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
191 if line.startswith('rename from '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
192 gp.op = 'RENAME'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
193 gp.oldpath = line[12:].rstrip()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
194 elif line.startswith('rename to '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
195 gp.path = line[10:].rstrip()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
196 elif line.startswith('copy from '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
197 gp.op = 'COPY'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
198 gp.oldpath = line[10:].rstrip()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
199 elif line.startswith('copy to '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
200 gp.path = line[8:].rstrip()
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
201 elif line.startswith('deleted file'):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
202 gp.op = 'DELETE'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
203 elif line.startswith('new file mode '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
204 gp.op = 'ADD'
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
205 gp.mode = int(line.rstrip()[-3:], 8)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
206 elif line.startswith('new mode '):
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
207 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
208 elif line.startswith('GIT binary patch'):
3716
ab5600428b08 handle files with both git binary patches and copy/rename ops
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3702
diff changeset
209 dopatch |= GP_BINARY
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
210 gp.binary = True
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
211 if gp:
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
212 gitpatches.append(gp)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
213
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
214 if not gitpatches:
3716
ab5600428b08 handle files with both git binary patches and copy/rename ops
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3702
diff changeset
215 dopatch = GP_PATCH
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
216
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
217 return (dopatch, gitpatches)
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
218
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
219 def patch(patchname, ui, strip=1, cwd=None, files={}):
4900
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
220 """apply <patchname> to the working directory.
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
221 returns whether patch was applied with fuzz factor."""
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
222 patcher = ui.config('ui', 'patch')
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
223 args = []
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
224 try:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
225 if patcher:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
226 return externalpatch(patcher, args, patchname, ui, strip, cwd,
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
227 files)
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
228 else:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
229 try:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
230 return internalpatch(patchname, ui, strip, cwd, files)
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
231 except NoHunks:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
232 patcher = util.find_exe('gpatch') or util.find_exe('patch')
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
233 ui.debug('no valid hunks found; trying with %r instead\n' %
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
234 patcher)
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
235 if util.needbinarypatch():
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
236 args.append('--binary')
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
237 return externalpatch(patcher, args, patchname, ui, strip, cwd,
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
238 files)
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
239 except PatchError, err:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
240 s = str(err)
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
241 if s:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
242 raise util.Abort(s)
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
243 else:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
244 raise util.Abort(_('patch failed to apply'))
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
245
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
246 def externalpatch(patcher, args, patchname, ui, strip, cwd, files):
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
247 """use <patcher> to apply <patchname> to the working directory.
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
248 returns whether patch was applied with fuzz factor."""
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
249
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
250 fuzz = False
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
251 if cwd:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
252 args.append('-d %s' % util.shellquote(cwd))
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
253 fp = os.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip,
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
254 util.shellquote(patchname)))
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
255
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
256 for line in fp:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
257 line = line.rstrip()
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
258 ui.note(line + '\n')
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
259 if line.startswith('patching file '):
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
260 pf = util.parse_patch_output(line)
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
261 printed_file = False
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
262 files.setdefault(pf, (None, None))
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
263 elif line.find('with fuzz') >= 0:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
264 fuzz = True
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
265 if not printed_file:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
266 ui.warn(pf + '\n')
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
267 printed_file = True
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
268 ui.warn(line + '\n')
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
269 elif line.find('saving rejects to file') >= 0:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
270 ui.warn(line + '\n')
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
271 elif line.find('FAILED') >= 0:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
272 if not printed_file:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
273 ui.warn(pf + '\n')
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
274 printed_file = True
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
275 ui.warn(line + '\n')
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
276 code = fp.close()
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
277 if code:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
278 raise PatchError(_("patch command failed: %s") %
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
279 util.explain_exit(code)[0])
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
280 return fuzz
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
281
5035
a675f6d5d069 patch: make internal code a bit friendlier to use
Bryan O'Sullivan <bos@serpentine.com>
parents: 5033
diff changeset
282 def internalpatch(patchobj, ui, strip, cwd, files={}):
a675f6d5d069 patch: make internal code a bit friendlier to use
Bryan O'Sullivan <bos@serpentine.com>
parents: 5033
diff changeset
283 """use builtin patch to apply <patchobj> to the working directory.
4900
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
284 returns whether patch was applied with fuzz factor."""
5035
a675f6d5d069 patch: make internal code a bit friendlier to use
Bryan O'Sullivan <bos@serpentine.com>
parents: 5033
diff changeset
285 try:
a675f6d5d069 patch: make internal code a bit friendlier to use
Bryan O'Sullivan <bos@serpentine.com>
parents: 5033
diff changeset
286 fp = file(patchobj, 'rb')
a675f6d5d069 patch: make internal code a bit friendlier to use
Bryan O'Sullivan <bos@serpentine.com>
parents: 5033
diff changeset
287 except TypeError:
a675f6d5d069 patch: make internal code a bit friendlier to use
Bryan O'Sullivan <bos@serpentine.com>
parents: 5033
diff changeset
288 fp = patchobj
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
289 if cwd:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
290 curdir = os.getcwd()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
291 os.chdir(cwd)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
292 try:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
293 ret = applydiff(ui, fp, files, strip=strip)
4900
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
294 finally:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
295 if cwd:
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
296 os.chdir(curdir)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
297 if ret < 0:
4900
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
298 raise PatchError
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
299 return ret > 0
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
300
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
301 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
302 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
303 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
304
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
305 class patchfile:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
306 def __init__(self, ui, fname):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
307 self.fname = fname
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
308 self.ui = ui
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
309 try:
4904
59b8ff35c4ed patch: patches should be read and written in binary mode when possible.
Patrick Mezard <pmezard@gmail.com>
parents: 4903
diff changeset
310 fp = file(fname, 'rb')
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
311 self.lines = fp.readlines()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
312 self.exists = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
313 except IOError:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
314 dirname = os.path.dirname(fname)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
315 if dirname and not os.path.isdir(dirname):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
316 dirs = dirname.split(os.path.sep)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
317 d = ""
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
318 for x in dirs:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
319 d = os.path.join(d, x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
320 if not os.path.isdir(d):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
321 os.mkdir(d)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
322 self.lines = []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
323 self.exists = False
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
324
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
325 self.hash = {}
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
326 self.dirty = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
327 self.offset = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
328 self.rej = []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
329 self.fileprinted = False
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
330 self.printfile(False)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
331 self.hunks = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
332
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
333 def printfile(self, warn):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
334 if self.fileprinted:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
335 return
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
336 if warn or self.ui.verbose:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
337 self.fileprinted = True
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
338 s = _("patching file %s\n") % self.fname
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
339 if warn:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
340 self.ui.warn(s)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
341 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
342 self.ui.note(s)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
343
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
344
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
345 def findlines(self, l, linenum):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
346 # looks through the hash and finds candidate lines. The
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
347 # result is a list of line numbers sorted based on distance
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
348 # from linenum
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
349 def sorter(a, b):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
350 vala = abs(a - linenum)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
351 valb = abs(b - linenum)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
352 return cmp(vala, valb)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
353
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
354 try:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
355 cand = self.hash[l]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
356 except:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
357 return []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
358
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
359 if len(cand) > 1:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
360 # resort our list of potentials forward then back.
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
361 cand.sort(cmp=sorter)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
362 return cand
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
363
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
364 def hashlines(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
365 self.hash = {}
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
366 for x in xrange(len(self.lines)):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
367 s = self.lines[x]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
368 self.hash.setdefault(s, []).append(x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
369
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
370 def write_rej(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
371 # our rejects are a little different from patch(1). This always
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
372 # creates rejects in the same form as the original patch. A file
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
373 # header is inserted so that you can run the reject through patch again
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
374 # without having to type the filename.
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
375
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
376 if not self.rej:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
377 return
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
378 if self.hunks != 1:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
379 hunkstr = "s"
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
380 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
381 hunkstr = ""
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
382
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
383 fname = self.fname + ".rej"
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
384 self.ui.warn(
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
385 _("%d out of %d hunk%s FAILED -- saving rejects to file %s\n") %
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
386 (len(self.rej), self.hunks, hunkstr, fname))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
387 try: os.unlink(fname)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
388 except:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
389 pass
4904
59b8ff35c4ed patch: patches should be read and written in binary mode when possible.
Patrick Mezard <pmezard@gmail.com>
parents: 4903
diff changeset
390 fp = file(fname, 'wb')
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
391 base = os.path.basename(self.fname)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
392 fp.write("--- %s\n+++ %s\n" % (base, base))
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
393 for x in self.rej:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
394 for l in x.hunk:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
395 fp.write(l)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
396 if l[-1] != '\n':
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
397 fp.write("\n\ No newline at end of file\n")
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
398
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
399 def write(self, dest=None):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
400 if self.dirty:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
401 if not dest:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
402 dest = self.fname
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
403 st = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
404 try:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
405 st = os.lstat(dest)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
406 if st.st_nlink > 1:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
407 os.unlink(dest)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
408 except: pass
4904
59b8ff35c4ed patch: patches should be read and written in binary mode when possible.
Patrick Mezard <pmezard@gmail.com>
parents: 4903
diff changeset
409 fp = file(dest, 'wb')
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
410 if st:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
411 os.chmod(dest, st.st_mode)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
412 fp.writelines(self.lines)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
413 fp.close()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
414
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
415 def close(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
416 self.write()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
417 self.write_rej()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
418
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
419 def apply(self, h, reverse):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
420 if not h.complete():
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
421 raise PatchError(_("bad hunk #%d %s (%d %d %d %d)") %
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
422 (h.number, h.desc, len(h.a), h.lena, len(h.b),
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
423 h.lenb))
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
424
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
425 self.hunks += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
426 if reverse:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
427 h.reverse()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
428
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
429 if self.exists and h.createfile():
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
430 self.ui.warn(_("file %s already exists\n") % self.fname)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
431 self.rej.append(h)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
432 return -1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
433
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
434 if isinstance(h, binhunk):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
435 if h.rmfile():
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
436 os.unlink(self.fname)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
437 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
438 self.lines[:] = h.new()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
439 self.offset += len(h.new())
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
440 self.dirty = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
441 return 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
442
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
443 # fast case first, no offsets, no fuzz
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
444 old = h.old()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
445 # patch starts counting at 1 unless we are adding the file
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
446 if h.starta == 0:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
447 start = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
448 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
449 start = h.starta + self.offset - 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
450 orig_start = start
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
451 if diffhelpers.testhunk(old, self.lines, start) == 0:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
452 if h.rmfile():
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
453 os.unlink(self.fname)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
454 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
455 self.lines[start : start + h.lena] = h.new()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
456 self.offset += h.lenb - h.lena
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
457 self.dirty = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
458 return 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
459
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
460 # ok, we couldn't match the hunk. Lets look for offsets and fuzz it
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
461 self.hashlines()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
462 if h.hunk[-1][0] != ' ':
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
463 # if the hunk tried to put something at the bottom of the file
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
464 # override the start line and use eof here
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
465 search_start = len(self.lines)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
466 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
467 search_start = orig_start
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
468
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
469 for fuzzlen in xrange(3):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
470 for toponly in [ True, False ]:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
471 old = h.old(fuzzlen, toponly)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
472
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
473 cand = self.findlines(old[0][1:], search_start)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
474 for l in cand:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
475 if diffhelpers.testhunk(old, self.lines, l) == 0:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
476 newlines = h.new(fuzzlen, toponly)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
477 self.lines[l : l + len(old)] = newlines
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
478 self.offset += len(newlines) - len(old)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
479 self.dirty = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
480 if fuzzlen:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
481 fuzzstr = "with fuzz %d " % fuzzlen
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
482 f = self.ui.warn
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
483 self.printfile(True)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
484 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
485 fuzzstr = ""
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
486 f = self.ui.note
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
487 offset = l - orig_start - fuzzlen
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
488 if offset == 1:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
489 linestr = "line"
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
490 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
491 linestr = "lines"
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
492 f(_("Hunk #%d succeeded at %d %s(offset %d %s).\n") %
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
493 (h.number, l+1, fuzzstr, offset, linestr))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
494 return fuzzlen
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
495 self.printfile(True)
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
496 self.ui.warn(_("Hunk #%d FAILED at %d\n") % (h.number, orig_start))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
497 self.rej.append(h)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
498 return -1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
499
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
500 class hunk:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
501 def __init__(self, desc, num, lr, context):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
502 self.number = num
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
503 self.desc = desc
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
504 self.hunk = [ desc ]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
505 self.a = []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
506 self.b = []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
507 if context:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
508 self.read_context_hunk(lr)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
509 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
510 self.read_unified_hunk(lr)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
511
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
512 def read_unified_hunk(self, lr):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
513 m = unidesc.match(self.desc)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
514 if not m:
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
515 raise PatchError(_("bad hunk #%d") % self.number)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
516 self.starta, foo, self.lena, self.startb, foo2, self.lenb = m.groups()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
517 if self.lena == None:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
518 self.lena = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
519 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
520 self.lena = int(self.lena)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
521 if self.lenb == None:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
522 self.lenb = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
523 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
524 self.lenb = int(self.lenb)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
525 self.starta = int(self.starta)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
526 self.startb = int(self.startb)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
527 diffhelpers.addlines(lr.fp, self.hunk, self.lena, self.lenb, self.a, self.b)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
528 # if we hit eof before finishing out the hunk, the last line will
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
529 # be zero length. Lets try to fix it up.
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
530 while len(self.hunk[-1]) == 0:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
531 del self.hunk[-1]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
532 del self.a[-1]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
533 del self.b[-1]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
534 self.lena -= 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
535 self.lenb -= 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
536
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
537 def read_context_hunk(self, lr):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
538 self.desc = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
539 m = contextdesc.match(self.desc)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
540 if not m:
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
541 raise PatchError(_("bad hunk #%d") % self.number)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
542 foo, self.starta, foo2, aend, foo3 = m.groups()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
543 self.starta = int(self.starta)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
544 if aend == None:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
545 aend = self.starta
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
546 self.lena = int(aend) - self.starta
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
547 if self.starta:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
548 self.lena += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
549 for x in xrange(self.lena):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
550 l = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
551 if l.startswith('---'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
552 lr.push(l)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
553 break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
554 s = l[2:]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
555 if l.startswith('- ') or l.startswith('! '):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
556 u = '-' + s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
557 elif l.startswith(' '):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
558 u = ' ' + s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
559 else:
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
560 raise PatchError(_("bad hunk #%d old text line %d") %
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
561 (self.number, x))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
562 self.a.append(u)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
563 self.hunk.append(u)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
564
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
565 l = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
566 if l.startswith('\ '):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
567 s = self.a[-1][:-1]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
568 self.a[-1] = s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
569 self.hunk[-1] = s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
570 l = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
571 m = contextdesc.match(l)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
572 if not m:
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
573 raise PatchError(_("bad hunk #%d") % self.number)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
574 foo, self.startb, foo2, bend, foo3 = m.groups()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
575 self.startb = int(self.startb)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
576 if bend == None:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
577 bend = self.startb
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
578 self.lenb = int(bend) - self.startb
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
579 if self.startb:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
580 self.lenb += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
581 hunki = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
582 for x in xrange(self.lenb):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
583 l = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
584 if l.startswith('\ '):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
585 s = self.b[-1][:-1]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
586 self.b[-1] = s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
587 self.hunk[hunki-1] = s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
588 continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
589 if not l:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
590 lr.push(l)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
591 break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
592 s = l[2:]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
593 if l.startswith('+ ') or l.startswith('! '):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
594 u = '+' + s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
595 elif l.startswith(' '):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
596 u = ' ' + s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
597 elif len(self.b) == 0:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
598 # this can happen when the hunk does not add any lines
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
599 lr.push(l)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
600 break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
601 else:
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
602 raise PatchError(_("bad hunk #%d old text line %d") %
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
603 (self.number, x))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
604 self.b.append(s)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
605 while True:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
606 if hunki >= len(self.hunk):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
607 h = ""
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
608 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
609 h = self.hunk[hunki]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
610 hunki += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
611 if h == u:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
612 break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
613 elif h.startswith('-'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
614 continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
615 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
616 self.hunk.insert(hunki-1, u)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
617 break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
618
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
619 if not self.a:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
620 # this happens when lines were only added to the hunk
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
621 for x in self.hunk:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
622 if x.startswith('-') or x.startswith(' '):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
623 self.a.append(x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
624 if not self.b:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
625 # this happens when lines were only deleted from the hunk
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
626 for x in self.hunk:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
627 if x.startswith('+') or x.startswith(' '):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
628 self.b.append(x[1:])
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
629 # @@ -start,len +start,len @@
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
630 self.desc = "@@ -%d,%d +%d,%d @@\n" % (self.starta, self.lena,
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
631 self.startb, self.lenb)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
632 self.hunk[0] = self.desc
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
633
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
634 def reverse(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
635 origlena = self.lena
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
636 origstarta = self.starta
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
637 self.lena = self.lenb
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
638 self.starta = self.startb
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
639 self.lenb = origlena
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
640 self.startb = origstarta
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
641 self.a = []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
642 self.b = []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
643 # self.hunk[0] is the @@ description
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
644 for x in xrange(1, len(self.hunk)):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
645 o = self.hunk[x]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
646 if o.startswith('-'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
647 n = '+' + o[1:]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
648 self.b.append(o[1:])
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
649 elif o.startswith('+'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
650 n = '-' + o[1:]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
651 self.a.append(n)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
652 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
653 n = o
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
654 self.b.append(o[1:])
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
655 self.a.append(o)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
656 self.hunk[x] = o
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
657
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
658 def fix_newline(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
659 diffhelpers.fix_newline(self.hunk, self.a, self.b)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
660
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
661 def complete(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
662 return len(self.a) == self.lena and len(self.b) == self.lenb
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
663
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
664 def createfile(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
665 return self.starta == 0 and self.lena == 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
666
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
667 def rmfile(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
668 return self.startb == 0 and self.lenb == 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
669
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
670 def fuzzit(self, l, fuzz, toponly):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
671 # this removes context lines from the top and bottom of list 'l'. It
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
672 # checks the hunk to make sure only context lines are removed, and then
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
673 # returns a new shortened list of lines.
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
674 fuzz = min(fuzz, len(l)-1)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
675 if fuzz:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
676 top = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
677 bot = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
678 hlen = len(self.hunk)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
679 for x in xrange(hlen-1):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
680 # the hunk starts with the @@ line, so use x+1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
681 if self.hunk[x+1][0] == ' ':
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
682 top += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
683 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
684 break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
685 if not toponly:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
686 for x in xrange(hlen-1):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
687 if self.hunk[hlen-bot-1][0] == ' ':
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
688 bot += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
689 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
690 break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
691
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
692 # top and bot now count context in the hunk
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
693 # adjust them if either one is short
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
694 context = max(top, bot, 3)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
695 if bot < context:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
696 bot = max(0, fuzz - (context - bot))
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
697 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
698 bot = min(fuzz, bot)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
699 if top < context:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
700 top = max(0, fuzz - (context - top))
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
701 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
702 top = min(fuzz, top)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
703
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
704 return l[top:len(l)-bot]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
705 return l
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
706
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
707 def old(self, fuzz=0, toponly=False):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
708 return self.fuzzit(self.a, fuzz, toponly)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
709
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
710 def newctrl(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
711 res = []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
712 for x in self.hunk:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
713 c = x[0]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
714 if c == ' ' or c == '+':
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
715 res.append(x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
716 return res
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
717
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
718 def new(self, fuzz=0, toponly=False):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
719 return self.fuzzit(self.b, fuzz, toponly)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
720
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
721 class binhunk:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
722 'A binary patch file. Only understands literals so far.'
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
723 def __init__(self, gitpatch):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
724 self.gitpatch = gitpatch
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
725 self.text = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
726 self.hunk = ['GIT binary patch\n']
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
727
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
728 def createfile(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
729 return self.gitpatch.op in ('ADD', 'RENAME', 'COPY')
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
730
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
731 def rmfile(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
732 return self.gitpatch.op == 'DELETE'
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
733
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
734 def complete(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
735 return self.text is not None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
736
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
737 def new(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
738 return [self.text]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
739
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
740 def extract(self, fp):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
741 line = fp.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
742 self.hunk.append(line)
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
743 while line and not line.startswith('literal '):
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
744 line = fp.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
745 self.hunk.append(line)
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
746 if not line:
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
747 raise PatchError(_('could not extract binary patch'))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
748 size = int(line[8:].rstrip())
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
749 dec = []
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
750 line = fp.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
751 self.hunk.append(line)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
752 while len(line) > 1:
3372
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
753 l = line[0]
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
754 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
755 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
756 else:
fd43ff3b4442 Use line length field when extracting git binary patches
Brendan Cully <brendan@kublai.com>
parents: 3367
diff changeset
757 l = ord(l) - ord('a') + 27
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
758 dec.append(base85.b85decode(line[1:-1])[:l])
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
759 line = fp.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
760 self.hunk.append(line)
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
761 text = zlib.decompress(''.join(dec))
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
762 if len(text) != size:
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
763 raise PatchError(_('binary patch is %d bytes, not %d') %
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
764 len(text), size)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
765 self.text = text
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
766
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
767 def parsefilename(str):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
768 # --- filename \t|space stuff
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
769 s = str[4:]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
770 i = s.find('\t')
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
771 if i < 0:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
772 i = s.find(' ')
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
773 if i < 0:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
774 return s
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
775 return s[:i]
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
776
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
777 def selectfile(afile_orig, bfile_orig, hunk, strip, reverse):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
778 def pathstrip(path, count=1):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
779 pathlen = len(path)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
780 i = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
781 if count == 0:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
782 return path.rstrip()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
783 while count > 0:
4903
020ee9c781cf patch: fix normalized paths separators.
Patrick Mezard <pmezard@gmail.com>
parents: 4900
diff changeset
784 i = path.find('/', i)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
785 if i == -1:
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
786 raise PatchError(_("unable to strip away %d dirs from %s") %
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
787 (count, path))
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
788 i += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
789 # consume '//' in the path
4903
020ee9c781cf patch: fix normalized paths separators.
Patrick Mezard <pmezard@gmail.com>
parents: 4900
diff changeset
790 while i < pathlen - 1 and path[i] == '/':
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
791 i += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
792 count -= 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
793 return path[i:].rstrip()
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
794
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
795 nulla = afile_orig == "/dev/null"
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
796 nullb = bfile_orig == "/dev/null"
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
797 afile = pathstrip(afile_orig, strip)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
798 gooda = os.path.exists(afile) and not nulla
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
799 bfile = pathstrip(bfile_orig, strip)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
800 if afile == bfile:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
801 goodb = gooda
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
802 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
803 goodb = os.path.exists(bfile) and not nullb
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
804 createfunc = hunk.createfile
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
805 if reverse:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
806 createfunc = hunk.rmfile
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
807 if not goodb and not gooda and not createfunc():
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
808 raise PatchError(_("unable to find %s or %s for patching") %
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
809 (afile, bfile))
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
810 if gooda and goodb:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
811 fname = bfile
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
812 if afile in bfile:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
813 fname = afile
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
814 elif gooda:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
815 fname = afile
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
816 elif not nullb:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
817 fname = bfile
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
818 if afile in bfile:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
819 fname = afile
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
820 elif not nulla:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
821 fname = afile
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
822 return fname
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
823
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
824 class linereader:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
825 # simple class to allow pushing lines back into the input stream
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
826 def __init__(self, fp):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
827 self.fp = fp
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
828 self.buf = []
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
829
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
830 def push(self, line):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
831 self.buf.append(line)
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
832
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
833 def readline(self):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
834 if self.buf:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
835 l = self.buf[0]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
836 del self.buf[0]
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
837 return l
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
838 return self.fp.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
839
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
840 def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False,
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
841 rejmerge=None, updatedir=None):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
842 """reads a patch from fp and tries to apply it. The dict 'changed' is
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
843 filled in with all of the filenames changed by the patch. Returns 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
844 for a clean patch, -1 if any rejects were found and 1 if there was
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
845 any fuzz."""
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
846
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
847 def scangitpatch(fp, firstline, cwd=None):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
848 '''git patches can modify a file, then copy that file to
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
849 a new file, but expect the source to be the unmodified form.
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
850 So we scan the patch looking for that case so we can do
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
851 the copies ahead of time.'''
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
852
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
853 pos = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
854 try:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
855 pos = fp.tell()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
856 except IOError:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
857 fp = cStringIO.StringIO(fp.read())
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
858
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
859 (dopatch, gitpatches) = readgitpatch(fp, firstline)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
860 for gp in gitpatches:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
861 if gp.copymod:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
862 copyfile(gp.oldpath, gp.path, basedir=cwd)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
863
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
864 fp.seek(pos)
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
865
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
866 return fp, dopatch, gitpatches
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
867
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
868 current_hunk = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
869 current_file = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
870 afile = ""
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
871 bfile = ""
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
872 state = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
873 hunknum = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
874 rejects = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
875
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
876 git = False
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
877 gitre = re.compile('diff --git (a/.*) (b/.*)')
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
878
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
879 # our states
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
880 BFILE = 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
881 err = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
882 context = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
883 lr = linereader(fp)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
884 dopatch = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
885 gitworkdone = False
2860
0f08f2c042ec Move patch-related code into its own module.
Brendan Cully <brendan@kublai.com>
parents:
diff changeset
886
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
887 while True:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
888 newfile = False
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
889 x = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
890 if not x:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
891 break
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
892 if current_hunk:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
893 if x.startswith('\ '):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
894 current_hunk.fix_newline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
895 ret = current_file.apply(current_hunk, reverse)
4899
1b7bbc4349e7 patch.py: don't mark files as changed unless they have actually been changed
Bryan O'Sullivan <bos@serpentine.com>
parents: 4898
diff changeset
896 if ret >= 0:
1b7bbc4349e7 patch.py: don't mark files as changed unless they have actually been changed
Bryan O'Sullivan <bos@serpentine.com>
parents: 4898
diff changeset
897 changed.setdefault(current_file.fname, (None, None))
1b7bbc4349e7 patch.py: don't mark files as changed unless they have actually been changed
Bryan O'Sullivan <bos@serpentine.com>
parents: 4898
diff changeset
898 if ret > 0:
1b7bbc4349e7 patch.py: don't mark files as changed unless they have actually been changed
Bryan O'Sullivan <bos@serpentine.com>
parents: 4898
diff changeset
899 err = 1
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
900 current_hunk = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
901 gitworkdone = False
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
902 if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
903 ((context or context == None) and x.startswith('***************')))):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
904 try:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
905 if context == None and x.startswith('***************'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
906 context = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
907 current_hunk = hunk(x, hunknum + 1, lr, context)
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
908 except PatchError, err:
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
909 ui.debug(err)
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
910 current_hunk = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
911 continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
912 hunknum += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
913 if not current_file:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
914 if sourcefile:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
915 current_file = patchfile(ui, sourcefile)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
916 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
917 current_file = selectfile(afile, bfile, current_hunk,
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
918 strip, reverse)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
919 current_file = patchfile(ui, current_file)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
920 elif state == BFILE and x.startswith('GIT binary patch'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
921 current_hunk = binhunk(changed[bfile[2:]][1])
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
922 if not current_file:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
923 if sourcefile:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
924 current_file = patchfile(ui, sourcefile)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
925 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
926 current_file = selectfile(afile, bfile, current_hunk,
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
927 strip, reverse)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
928 current_file = patchfile(ui, current_file)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
929 hunknum += 1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
930 current_hunk.extract(fp)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
931 elif x.startswith('diff --git'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
932 # check for git diff, scanning the whole patch file if needed
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
933 m = gitre.match(x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
934 if m:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
935 afile, bfile = m.group(1, 2)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
936 if not git:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
937 git = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
938 fp, dopatch, gitpatches = scangitpatch(fp, x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
939 for gp in gitpatches:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
940 changed[gp.path] = (gp.op, gp)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
941 # else error?
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
942 # copy/rename + modify should modify target, not source
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
943 if changed.get(bfile[2:], (None, None))[0] in ('COPY',
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
944 'RENAME'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
945 afile = bfile
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
946 gitworkdone = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
947 newfile = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
948 elif x.startswith('---'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
949 # check for a unified diff
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
950 l2 = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
951 if not l2.startswith('+++'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
952 lr.push(l2)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
953 continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
954 newfile = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
955 context = False
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
956 afile = parsefilename(x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
957 bfile = parsefilename(l2)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
958 elif x.startswith('***'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
959 # check for a context diff
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
960 l2 = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
961 if not l2.startswith('---'):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
962 lr.push(l2)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
963 continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
964 l3 = lr.readline()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
965 lr.push(l3)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
966 if not l3.startswith("***************"):
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
967 lr.push(l2)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
968 continue
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
969 newfile = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
970 context = True
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
971 afile = parsefilename(x)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
972 bfile = parsefilename(l2)
3054
d16b93f4a6ca unlink temporary patch files even when an exception is raised
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3053
diff changeset
973
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
974 if newfile:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
975 if current_file:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
976 current_file.close()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
977 if rejmerge:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
978 rejmerge(current_file)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
979 rejects += len(current_file.rej)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
980 state = BFILE
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
981 current_file = None
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
982 hunknum = 0
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
983 if current_hunk:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
984 if current_hunk.complete():
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
985 ret = current_file.apply(current_hunk, reverse)
4899
1b7bbc4349e7 patch.py: don't mark files as changed unless they have actually been changed
Bryan O'Sullivan <bos@serpentine.com>
parents: 4898
diff changeset
986 if ret >= 0:
1b7bbc4349e7 patch.py: don't mark files as changed unless they have actually been changed
Bryan O'Sullivan <bos@serpentine.com>
parents: 4898
diff changeset
987 changed.setdefault(current_file.fname, (None, None))
1b7bbc4349e7 patch.py: don't mark files as changed unless they have actually been changed
Bryan O'Sullivan <bos@serpentine.com>
parents: 4898
diff changeset
988 if ret > 0:
1b7bbc4349e7 patch.py: don't mark files as changed unless they have actually been changed
Bryan O'Sullivan <bos@serpentine.com>
parents: 4898
diff changeset
989 err = 1
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
990 else:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
991 fname = current_file and current_file.fname or None
4898
bc905a6c0e76 patch.py: fix some incorrect uses of _() for i18n
Bryan O'Sullivan <bos@serpentine.com>
parents: 4897
diff changeset
992 raise PatchError(_("malformed patch %s %s") % (fname,
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
993 current_hunk.desc))
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
994 if current_file:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
995 current_file.close()
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
996 if rejmerge:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
997 rejmerge(current_file)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
998 rejects += len(current_file.rej)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
999 if updatedir and git:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
1000 updatedir(gitpatches)
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
1001 if rejects:
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
1002 return -1
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
1003 if hunknum == 0 and dopatch and not gitworkdone:
4900
e56c7e05c7e6 patch.py: re-add the ability to use an external patch program
Bryan O'Sullivan <bos@serpentine.com>
parents: 4899
diff changeset
1004 raise NoHunks
4897
4574925db5c0 Add Chris Mason's mpatch library.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4771
diff changeset
1005 return err
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1006
3540
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1007 def diffopts(ui, opts={}, untrusted=False):
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1008 def get(key, name=None):
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1009 return (opts.get(key) or
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1010 ui.configbool('diff', name or key, None, untrusted=untrusted))
2908
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
1011 return mdiff.diffopts(
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
1012 text=opts.get('text'),
3540
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1013 git=get('git'),
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1014 nodates=get('nodates'),
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1015 showfunc=get('show_function', 'showfunc'),
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1016 ignorews=get('ignore_all_space', 'ignorews'),
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1017 ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
da3ee7ca620f add untrusted argument to patch.diffopts
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3468
diff changeset
1018 ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'))
2908
3848488244fc Move ui.diffopts to patch.diffopts where it belongs
Matt Mackall <mpm@selenic.com>
parents: 2880
diff changeset
1019
4961
126f527b3ba3 Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents: 4900
diff changeset
1020 def updatedir(ui, repo, patches):
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1021 '''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
1022 if not patches:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1023 return
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1024 copies = []
3701
05c8704a3743 handle git patches that rename a file to more than one destination
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3696
diff changeset
1025 removes = {}
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1026 cfiles = patches.keys()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1027 cwd = repo.getcwd()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1028 if cwd:
4229
24c22a3f2ef8 pass repo.root to util.pathto() in preparation for the next patch
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4105
diff changeset
1029 cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()]
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1030 for f in patches:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1031 ctype, gp = patches[f]
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1032 if ctype == 'RENAME':
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1033 copies.append((gp.oldpath, gp.path, gp.copymod))
3701
05c8704a3743 handle git patches that rename a file to more than one destination
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3696
diff changeset
1034 removes[gp.oldpath] = 1
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1035 elif ctype == 'COPY':
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1036 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
1037 elif ctype == 'DELETE':
3701
05c8704a3743 handle git patches that rename a file to more than one destination
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3696
diff changeset
1038 removes[gp.path] = 1
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1039 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
1040 if not after:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1041 copyfile(src, dst, repo.root)
4961
126f527b3ba3 Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents: 4900
diff changeset
1042 repo.copy(src, dst)
3701
05c8704a3743 handle git patches that rename a file to more than one destination
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3696
diff changeset
1043 removes = removes.keys()
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1044 if removes:
3701
05c8704a3743 handle git patches that rename a file to more than one destination
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3696
diff changeset
1045 removes.sort()
4961
126f527b3ba3 Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents: 4900
diff changeset
1046 repo.remove(removes, True)
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1047 for f in patches:
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1048 ctype, gp = patches[f]
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1049 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
1050 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
1051 dst = os.path.join(repo.root, gp.path)
3588
45574a225632 git patch: create empty added files
Brendan Cully <brendan@kublai.com>
parents: 3540
diff changeset
1052 # patch won't create empty files
45574a225632 git patch: create empty added files
Brendan Cully <brendan@kublai.com>
parents: 3540
diff changeset
1053 if ctype == 'ADD' and not os.path.exists(dst):
4006
67982d3ee76c symlinks: add flags param to wwrite
Matt Mackall <mpm@selenic.com>
parents: 3996
diff changeset
1054 repo.wwrite(gp.path, '', x and 'x' or '')
67982d3ee76c symlinks: add flags param to wwrite
Matt Mackall <mpm@selenic.com>
parents: 3996
diff changeset
1055 else:
67982d3ee76c symlinks: add flags param to wwrite
Matt Mackall <mpm@selenic.com>
parents: 3996
diff changeset
1056 util.set_exec(dst, x)
4961
126f527b3ba3 Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents: 4900
diff changeset
1057 cmdutil.addremove(repo, cfiles)
2933
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1058 files = patches.keys()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1059 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
1060 files.sort()
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1061
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1062 return files
439fd013360d Move import's working dir update code into patch.updatedir
Brendan Cully <brendan@kublai.com>
parents: 2922
diff changeset
1063
5033
1b07668b8cc3 patch: remove unused parameter from b85diff
Bryan O'Sullivan <bos@serpentine.com>
parents: 4965
diff changeset
1064 def b85diff(to, tn):
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1065 '''print base85-encoded binary diff'''
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1066 def gitindex(text):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1067 if not text:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1068 return '0' * 40
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1069 l = len(text)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1070 s = sha.new('blob %d\0' % l)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1071 s.update(text)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1072 return s.hexdigest()
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1073
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1074 def fmtline(line):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1075 l = len(line)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1076 if l <= 26:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1077 l = chr(ord('A') + l - 1)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1078 else:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1079 l = chr(l - 26 + ord('a') - 1)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1080 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
1081
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1082 def chunk(text, csize=52):
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1083 l = len(text)
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1084 i = 0
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1085 while i < l:
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1086 yield text[i:i+csize]
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1087 i += csize
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1088
4104
ed46895aa38c git binary patches: use hashes to detect identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4092
diff changeset
1089 tohash = gitindex(to)
ed46895aa38c git binary patches: use hashes to detect identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4092
diff changeset
1090 tnhash = gitindex(tn)
ed46895aa38c git binary patches: use hashes to detect identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4092
diff changeset
1091 if tohash == tnhash:
4105
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1092 return ""
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1093
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1094 # TODO: deltas
4105
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1095 ret = ['index %s..%s\nGIT binary patch\nliteral %s\n' %
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1096 (tohash, tnhash, len(tn))]
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1097 for l in chunk(zlib.compress(tn)):
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1098 ret.append(fmtline(l))
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1099 ret.append('\n')
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1100 return ''.join(ret)
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1101
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1102 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
1103 fp=None, changes=None, opts=None):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1104 '''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
1105 working directory.
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1106
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1107 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
1108 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
1109
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1110 if opts is None:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1111 opts = mdiff.defaultopts
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1112 if fp is None:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1113 fp = repo.ui
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1114
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1115 if not node1:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1116 node1 = repo.dirstate.parents()[0]
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
1117
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1118 ccache = {}
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1119 def getctx(r):
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1120 if r not in ccache:
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1121 ccache[r] = context.changectx(repo, r)
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1122 return ccache[r]
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1123
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1124 flcache = {}
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1125 def getfilectx(f, ctx):
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1126 flctx = ctx.filectx(f, filelog=flcache.get(f))
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1127 if f not in flcache:
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1128 flcache[f] = flctx._filelog
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1129 return flctx
2934
2f190e998eb3 Teach mq about git patches
Brendan Cully <brendan@kublai.com>
parents: 2933
diff changeset
1130
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1131 # 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
1132 # with repo.status and the revlog cache.
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1133 ctx1 = context.changectx(repo, node1)
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1134 # force manifest reading
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1135 man1 = ctx1.manifest()
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1136 date1 = util.datestr(ctx1.date())
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1137
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1138 if not changes:
2874
3d6efcbbd1c9 remove localrepository.changes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2873
diff changeset
1139 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
1140 modified, added, removed, deleted, unknown = changes
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1141
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1142 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
1143 return
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1144
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1145 if node2:
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1146 ctx2 = context.changectx(repo, node2)
4492
b79cdb7f0597 patch.diff: avoid calling workingctx().manifest()
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4484
diff changeset
1147 execf2 = ctx2.manifest().execf
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1148 else:
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1149 ctx2 = context.workingctx(repo)
4492
b79cdb7f0597 patch.diff: avoid calling workingctx().manifest()
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4484
diff changeset
1150 execf2 = util.execfunc(repo.root, None)
b79cdb7f0597 patch.diff: avoid calling workingctx().manifest()
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4484
diff changeset
1151 if execf2 is None:
b79cdb7f0597 patch.diff: avoid calling workingctx().manifest()
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4484
diff changeset
1152 execf2 = ctx2.parents()[0].manifest().copy().execf
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1153
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1154 # returns False if there was no rename between ctx1 and ctx2
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1155 # returns None if the file was created between ctx1 and ctx2
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1156 # returns the (file, node) present in ctx1 that was renamed to f in ctx2
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1157 def renamed(f):
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1158 startrev = ctx1.rev()
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1159 c = ctx2
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1160 crev = c.rev()
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1161 if crev is None:
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1162 crev = repo.changelog.count()
3694
c0b1a0c72c7d renamedbetween: only return (file, node) pairs that exist in the original rev
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3693
diff changeset
1163 orig = f
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1164 while crev > startrev:
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1165 if f in c.files():
3693
454b3a8cdf28 diff: improve detection of renames when diffing across many revisions
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
1166 try:
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1167 src = getfilectx(f, c).renamed()
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1168 except revlog.LookupError:
3693
454b3a8cdf28 diff: improve detection of renames when diffing across many revisions
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
1169 return None
454b3a8cdf28 diff: improve detection of renames when diffing across many revisions
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
1170 if src:
454b3a8cdf28 diff: improve detection of renames when diffing across many revisions
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
1171 f = src[0]
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1172 crev = c.parents()[0].rev()
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1173 # try to reuse
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1174 c = getctx(crev)
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1175 if f not in man1:
3694
c0b1a0c72c7d renamedbetween: only return (file, node) pairs that exist in the original rev
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3693
diff changeset
1176 return None
3696
562a65635bcb diff: better detection of renames when comparing with the working dir.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3695
diff changeset
1177 if f == orig:
562a65635bcb diff: better detection of renames when comparing with the working dir.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3695
diff changeset
1178 return False
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1179 return f
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1180
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1181 if repo.ui.quiet:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1182 r = None
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1183 else:
3386
2065789f6a3e use short hashes with diff -v
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3376
diff changeset
1184 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
1185 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
1186
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1187 if opts.git:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1188 copied = {}
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1189 for f in added:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1190 src = renamed(f)
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1191 if src:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1192 copied[f] = src
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1193 srcs = [x[1] for x in copied.items()]
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1194
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1195 all = modified + added + removed
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1196 all.sort()
3702
70c3ee224c08 Don't generate git patches that rename a file to multiple destinations
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3701
diff changeset
1197 gone = {}
3996
c190df14338c exec: add execfunc to simplify exec flag support on non-exec filesystems
Matt Mackall <mpm@selenic.com>
parents: 3970
diff changeset
1198
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1199 for f in all:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1200 to = None
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1201 tn = None
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1202 dodiff = True
3327
319358e6bd96 Don't generate git diff header for empty diffs
Brendan Cully <brendan@kublai.com>
parents: 3223
diff changeset
1203 header = []
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1204 if f in man1:
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1205 to = getfilectx(f, ctx1).data()
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1206 if f not in removed:
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1207 tn = getfilectx(f, ctx2).data()
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1208 if opts.git:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1209 def gitmode(x):
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1210 return x and '100755' or '100644'
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1211 def addmodehdr(header, omode, nmode):
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1212 if omode != nmode:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1213 header.append('old mode %s\n' % omode)
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1214 header.append('new mode %s\n' % nmode)
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1215
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1216 a, b = f, f
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1217 if f in added:
4492
b79cdb7f0597 patch.diff: avoid calling workingctx().manifest()
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4484
diff changeset
1218 mode = gitmode(execf2(f))
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1219 if f in copied:
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1220 a = copied[f]
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1221 omode = gitmode(man1.execf(a))
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1222 addmodehdr(header, omode, mode)
3702
70c3ee224c08 Don't generate git patches that rename a file to multiple destinations
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3701
diff changeset
1223 if a in removed and a not in gone:
70c3ee224c08 Don't generate git patches that rename a file to multiple destinations
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3701
diff changeset
1224 op = 'rename'
70c3ee224c08 Don't generate git patches that rename a file to multiple destinations
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3701
diff changeset
1225 gone[a] = 1
70c3ee224c08 Don't generate git patches that rename a file to multiple destinations
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3701
diff changeset
1226 else:
70c3ee224c08 Don't generate git patches that rename a file to multiple destinations
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3701
diff changeset
1227 op = 'copy'
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1228 header.append('%s from %s\n' % (op, a))
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1229 header.append('%s to %s\n' % (op, f))
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1230 to = getfilectx(a, ctx1).data()
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1231 else:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1232 header.append('new file mode %s\n' % mode)
4092
4ced663bebf0 git patches: handle renames of binary files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3900
diff changeset
1233 if util.binary(tn):
4ced663bebf0 git patches: handle renames of binary files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3900
diff changeset
1234 dodiff = 'binary'
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1235 elif f in removed:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1236 if f in srcs:
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1237 dodiff = False
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1238 else:
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1239 mode = gitmode(man1.execf(f))
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1240 header.append('deleted file mode %s\n' % mode)
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1241 else:
3967
dccb83241dd0 patch: use contexts for diff
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3963
diff changeset
1242 omode = gitmode(man1.execf(f))
4492
b79cdb7f0597 patch.diff: avoid calling workingctx().manifest()
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4484
diff changeset
1243 nmode = gitmode(execf2(f))
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1244 addmodehdr(header, omode, nmode)
3367
7f486971d263 Add git-1.4 binary patch support
Brendan Cully <brendan@kublai.com>
parents: 3327
diff changeset
1245 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
1246 dodiff = 'binary'
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1247 r = None
3327
319358e6bd96 Don't generate git diff header for empty diffs
Brendan Cully <brendan@kublai.com>
parents: 3223
diff changeset
1248 header.insert(0, 'diff --git a/%s b/%s\n' % (a, b))
4105
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1249 if dodiff:
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1250 if dodiff == 'binary':
5033
1b07668b8cc3 patch: remove unused parameter from b85diff
Bryan O'Sullivan <bos@serpentine.com>
parents: 4965
diff changeset
1251 text = b85diff(to, tn)
4105
797dbdd4d7e1 git binary patches: don't print the header for identical files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4104
diff changeset
1252 else:
4107
226df1808f16 merge with crew-stable
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4096 4105
diff changeset
1253 text = mdiff.unidiff(to, date1,
226df1808f16 merge with crew-stable
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4096 4105
diff changeset
1254 # ctx2 date may be dynamic
226df1808f16 merge with crew-stable
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4096 4105
diff changeset
1255 tn, util.datestr(ctx2.date()),
226df1808f16 merge with crew-stable
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4096 4105
diff changeset
1256 f, r, opts=opts)
3327
319358e6bd96 Don't generate git diff header for empty diffs
Brendan Cully <brendan@kublai.com>
parents: 3223
diff changeset
1257 if text or len(header) > 1:
2892
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2880
diff changeset
1258 fp.write(''.join(header))
3327
319358e6bd96 Don't generate git diff header for empty diffs
Brendan Cully <brendan@kublai.com>
parents: 3223
diff changeset
1259 fp.write(text)
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1260
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1261 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
1262 opts=None):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1263 '''export changesets as hg patches.'''
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1264
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1265 total = len(revs)
3900
2b3175acb653 Don't use node length for calculating revision number length.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3899
diff changeset
1266 revwidth = max([len(str(rev)) for rev in revs])
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1267
3970
fff8a5345eb0 commands.py: use contexts in export
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3967
diff changeset
1268 def single(rev, seqno, fp):
fff8a5345eb0 commands.py: use contexts in export
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3967
diff changeset
1269 ctx = repo.changectx(rev)
fff8a5345eb0 commands.py: use contexts in export
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3967
diff changeset
1270 node = ctx.node()
fff8a5345eb0 commands.py: use contexts in export
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3967
diff changeset
1271 parents = [p.node() for p in ctx.parents() if p]
4436
a764edb6fc95 Add branch information to hg export.
Eric Hopper <hopper@omnifarious.org>
parents: 4435
diff changeset
1272 branch = ctx.branch()
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1273 if switch_parent:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1274 parents.reverse()
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1275 prev = (parents and parents[0]) or nullid
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1276
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1277 if not fp:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1278 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
1279 seqno=seqno, revwidth=revwidth)
4125
ef7c39ae5d4c Suppress <stdout> before hg export -v (regression from previous patch).
Brendan Cully <brendan@kublai.com>
parents: 4124
diff changeset
1280 if fp != sys.stdout and hasattr(fp, 'name'):
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1281 repo.ui.note("%s\n" % fp.name)
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1282
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1283 fp.write("# HG changeset patch\n")
3970
fff8a5345eb0 commands.py: use contexts in export
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3967
diff changeset
1284 fp.write("# User %s\n" % ctx.user())
fff8a5345eb0 commands.py: use contexts in export
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3967
diff changeset
1285 fp.write("# Date %d %d\n" % ctx.date())
4436
a764edb6fc95 Add branch information to hg export.
Eric Hopper <hopper@omnifarious.org>
parents: 4435
diff changeset
1286 if branch and (branch != 'default'):
a764edb6fc95 Add branch information to hg export.
Eric Hopper <hopper@omnifarious.org>
parents: 4435
diff changeset
1287 fp.write("# Branch %s\n" % branch)
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1288 fp.write("# Node ID %s\n" % hex(node))
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1289 fp.write("# Parent %s\n" % hex(prev))
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1290 if len(parents) > 1:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1291 fp.write("# Parent %s\n" % hex(parents[1]))
3970
fff8a5345eb0 commands.py: use contexts in export
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3967
diff changeset
1292 fp.write(ctx.description().rstrip())
2873
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1293 fp.write("\n\n")
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1294
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1295 diff(repo, prev, node, fp=fp, opts=opts)
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1296 if fp not in (sys.stdout, repo.ui):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1297 fp.close()
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2867
diff changeset
1298
3900
2b3175acb653 Don't use node length for calculating revision number length.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3899
diff changeset
1299 for seqno, rev in enumerate(revs):
3970
fff8a5345eb0 commands.py: use contexts in export
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3967
diff changeset
1300 single(rev, seqno+1, fp)
3093
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1301
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1302 def diffstat(patchlines):
4482
62019c4427e3 Introduce find_exe. Use instead of find_in_path for programs.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4436
diff changeset
1303 if not util.find_exe('diffstat'):
4316
6e4334be0aaa Try to find diffstat in PATH before calling it
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4229
diff changeset
1304 return
3093
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1305 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
1306 try:
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1307 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
1308 try:
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1309 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
1310 p.tochild.close()
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1311 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
1312 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
1313 stat = []
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1314 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
1315 last = stat.pop()
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1316 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
1317 stat = ''.join(stat)
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1318 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
1319 return stat
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1320 except: raise
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1321 finally:
f422c8265ae5 Add support for diffstat in commit emails, and move diffstat from
Matt Doar <matt@xensource.com>
parents: 3063
diff changeset
1322 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
1323 except: pass