commands.import: refactor patch parsing into patch.extract.
--- a/mercurial/commands.py Sat Aug 12 12:47:18 2006 -0700
+++ b/mercurial/commands.py Sat Aug 12 13:16:48 2006 -0700
@@ -12,7 +12,7 @@
demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
demandload(globals(), "fnmatch mdiff patch random signal tempfile time")
demandload(globals(), "traceback errno socket version struct atexit sets bz2")
-demandload(globals(), "archival cStringIO changegroup email.Parser")
+demandload(globals(), "archival cStringIO changegroup")
demandload(globals(), "hgweb.server sshserver")
class UnknownCommand(Exception):
@@ -1814,84 +1814,23 @@
d = opts["base"]
strip = opts["strip"]
- mailre = re.compile(r'(?:From |[\w-]+:)')
-
- # attempt to detect the start of a patch
- # (this heuristic is borrowed from quilt)
- diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' +
- 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
- '(---|\*\*\*)[ \t])', re.MULTILINE)
-
wlock = repo.wlock()
lock = repo.lock()
for p in patches:
pf = os.path.join(d, p)
- message = None
- user = None
- date = None
- hgpatch = False
-
- parser = email.Parser.Parser()
if pf == '-':
- msg = parser.parse(sys.stdin)
ui.status(_("applying patch from stdin\n"))
+ tmpname, message, user, date = patch.extract(ui, sys.stdin)
else:
- msg = parser.parse(file(pf))
ui.status(_("applying %s\n") % p)
-
- fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
- tmpfp = os.fdopen(fd, 'w')
+ tmpname, message, user, date = patch.extract(ui, file(pf))
+
+ if tmpname is None:
+ raise util.Abort(_('no diffs found'))
+
try:
- message = msg['Subject']
- if message:
- message = message.replace('\n\t', ' ')
- ui.debug('Subject: %s\n' % message)
- user = msg['From']
- if user:
- ui.debug('From: %s\n' % user)
- diffs_seen = 0
- ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
- for part in msg.walk():
- content_type = part.get_content_type()
- ui.debug('Content-Type: %s\n' % content_type)
- if content_type not in ok_types:
- continue
- payload = part.get_payload(decode=True)
- m = diffre.search(payload)
- if m:
- ui.debug(_('found patch at byte %d\n') % m.start(0))
- diffs_seen += 1
- hgpatch = False
- fp = cStringIO.StringIO()
- if message:
- fp.write(message)
- fp.write('\n')
- for line in payload[:m.start(0)].splitlines():
- if line.startswith('# HG changeset patch'):
- ui.debug(_('patch generated by hg export\n'))
- hgpatch = True
- # drop earlier commit message content
- fp.seek(0)
- fp.truncate()
- elif hgpatch:
- if line.startswith('# User '):
- user = line[7:]
- ui.debug('From: %s\n' % user)
- elif line.startswith("# Date "):
- date = line[7:]
- if not line.startswith('# '):
- fp.write(line)
- fp.write('\n')
- message = fp.getvalue()
- if tmpfp:
- tmpfp.write(payload)
- if not payload.endswith('\n'):
- tmpfp.write('\n')
- elif not diffs_seen and message and content_type == 'text/plain':
- message += '\n' + payload
-
if opts['message']:
# pickup the cmdline msg
message = opts['message']
@@ -1903,10 +1842,6 @@
message = None
ui.debug(_('message:\n%s\n') % message)
- tmpfp.close()
- if not diffs_seen:
- raise util.Abort(_('no diffs found'))
-
files = patch.patch(strip, tmpname, ui, cwd=repo.root)
removes = []
if len(files) > 0:
--- a/mercurial/patch.py Sat Aug 12 12:47:18 2006 -0700
+++ b/mercurial/patch.py Sat Aug 12 13:16:48 2006 -0700
@@ -6,8 +6,92 @@
# of the GNU General Public License, incorporated herein by reference.
from demandload import demandload
+from i18n import gettext as _
demandload(globals(), "util")
-demandload(globals(), "os re shutil tempfile")
+demandload(globals(), "cStringIO email.Parser os re shutil tempfile")
+
+def extract(ui, fileobj):
+ '''extract patch from data read from fileobj.
+
+ patch can be normal patch or contained in email message.
+
+ return tuple (filename, message, user, date). any item in returned
+ tuple can be None. if filename is None, fileobj did not contain
+ patch. caller must unlink filename when done.'''
+
+ # attempt to detect the start of a patch
+ # (this heuristic is borrowed from quilt)
+ diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' +
+ 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
+ '(---|\*\*\*)[ \t])', re.MULTILINE)
+
+ fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
+ tmpfp = os.fdopen(fd, 'w')
+ try:
+ hgpatch = False
+
+ msg = email.Parser.Parser().parse(fileobj)
+
+ message = msg['Subject']
+ user = msg['From']
+ # should try to parse msg['Date']
+ date = None
+
+ if message:
+ message = message.replace('\n\t', ' ')
+ ui.debug('Subject: %s\n' % message)
+ if user:
+ ui.debug('From: %s\n' % user)
+ diffs_seen = 0
+ ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
+
+ for part in msg.walk():
+ content_type = part.get_content_type()
+ ui.debug('Content-Type: %s\n' % content_type)
+ if content_type not in ok_types:
+ continue
+ payload = part.get_payload(decode=True)
+ m = diffre.search(payload)
+ if m:
+ ui.debug(_('found patch at byte %d\n') % m.start(0))
+ diffs_seen += 1
+ cfp = cStringIO.StringIO()
+ if message:
+ cfp.write(message)
+ cfp.write('\n')
+ for line in payload[:m.start(0)].splitlines():
+ if line.startswith('# HG changeset patch'):
+ ui.debug(_('patch generated by hg export\n'))
+ hgpatch = True
+ # drop earlier commit message content
+ cfp.seek(0)
+ cfp.truncate()
+ elif hgpatch:
+ if line.startswith('# User '):
+ user = line[7:]
+ ui.debug('From: %s\n' % user)
+ elif line.startswith("# Date "):
+ date = line[7:]
+ if not line.startswith('# '):
+ cfp.write(line)
+ cfp.write('\n')
+ message = cfp.getvalue()
+ if tmpfp:
+ tmpfp.write(payload)
+ if not payload.endswith('\n'):
+ tmpfp.write('\n')
+ elif not diffs_seen and message and content_type == 'text/plain':
+ message += '\n' + payload
+ except:
+ tmpfp.close()
+ os.unlink(tmpname)
+ raise
+
+ tmpfp.close()
+ if not diffs_seen:
+ os.unlink(tmpname)
+ return None, message, user, date
+ return tmpname, message, user, date
def readgitpatch(patchname):
"""extract git-style metadata about patches from <patchname>"""