Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/patch.py @ 2866:2893e51407a4
commands.import: refactor patch parsing into patch.extract.
author | Vadim Gelfer <vadim.gelfer@gmail.com> |
---|---|
date | Sat, 12 Aug 2006 13:16:48 -0700 |
parents | 71e78f2ca5ae |
children | 9a2a481ec3ea |
comparison
equal
deleted
inserted
replaced
2865:71e78f2ca5ae | 2866:2893e51407a4 |
---|---|
4 # | 4 # |
5 # This software may be used and distributed according to the terms | 5 # This software may be used and distributed according to the terms |
6 # of the GNU General Public License, incorporated herein by reference. | 6 # of the GNU General Public License, incorporated herein by reference. |
7 | 7 |
8 from demandload import demandload | 8 from demandload import demandload |
9 from i18n import gettext as _ | |
9 demandload(globals(), "util") | 10 demandload(globals(), "util") |
10 demandload(globals(), "os re shutil tempfile") | 11 demandload(globals(), "cStringIO email.Parser os re shutil tempfile") |
12 | |
13 def extract(ui, fileobj): | |
14 '''extract patch from data read from fileobj. | |
15 | |
16 patch can be normal patch or contained in email message. | |
17 | |
18 return tuple (filename, message, user, date). any item in returned | |
19 tuple can be None. if filename is None, fileobj did not contain | |
20 patch. caller must unlink filename when done.''' | |
21 | |
22 # attempt to detect the start of a patch | |
23 # (this heuristic is borrowed from quilt) | |
24 diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' + | |
25 'retrieving revision [0-9]+(\.[0-9]+)*$|' + | |
26 '(---|\*\*\*)[ \t])', re.MULTILINE) | |
27 | |
28 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-') | |
29 tmpfp = os.fdopen(fd, 'w') | |
30 try: | |
31 hgpatch = False | |
32 | |
33 msg = email.Parser.Parser().parse(fileobj) | |
34 | |
35 message = msg['Subject'] | |
36 user = msg['From'] | |
37 # should try to parse msg['Date'] | |
38 date = None | |
39 | |
40 if message: | |
41 message = message.replace('\n\t', ' ') | |
42 ui.debug('Subject: %s\n' % message) | |
43 if user: | |
44 ui.debug('From: %s\n' % user) | |
45 diffs_seen = 0 | |
46 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch') | |
47 | |
48 for part in msg.walk(): | |
49 content_type = part.get_content_type() | |
50 ui.debug('Content-Type: %s\n' % content_type) | |
51 if content_type not in ok_types: | |
52 continue | |
53 payload = part.get_payload(decode=True) | |
54 m = diffre.search(payload) | |
55 if m: | |
56 ui.debug(_('found patch at byte %d\n') % m.start(0)) | |
57 diffs_seen += 1 | |
58 cfp = cStringIO.StringIO() | |
59 if message: | |
60 cfp.write(message) | |
61 cfp.write('\n') | |
62 for line in payload[:m.start(0)].splitlines(): | |
63 if line.startswith('# HG changeset patch'): | |
64 ui.debug(_('patch generated by hg export\n')) | |
65 hgpatch = True | |
66 # drop earlier commit message content | |
67 cfp.seek(0) | |
68 cfp.truncate() | |
69 elif hgpatch: | |
70 if line.startswith('# User '): | |
71 user = line[7:] | |
72 ui.debug('From: %s\n' % user) | |
73 elif line.startswith("# Date "): | |
74 date = line[7:] | |
75 if not line.startswith('# '): | |
76 cfp.write(line) | |
77 cfp.write('\n') | |
78 message = cfp.getvalue() | |
79 if tmpfp: | |
80 tmpfp.write(payload) | |
81 if not payload.endswith('\n'): | |
82 tmpfp.write('\n') | |
83 elif not diffs_seen and message and content_type == 'text/plain': | |
84 message += '\n' + payload | |
85 except: | |
86 tmpfp.close() | |
87 os.unlink(tmpname) | |
88 raise | |
89 | |
90 tmpfp.close() | |
91 if not diffs_seen: | |
92 os.unlink(tmpname) | |
93 return None, message, user, date | |
94 return tmpname, message, user, date | |
11 | 95 |
12 def readgitpatch(patchname): | 96 def readgitpatch(patchname): |
13 """extract git-style metadata about patches from <patchname>""" | 97 """extract git-style metadata about patches from <patchname>""" |
14 class gitpatch: | 98 class gitpatch: |
15 "op is one of ADD, DELETE, RENAME, MODIFY or COPY" | 99 "op is one of ADD, DELETE, RENAME, MODIFY or COPY" |