##// END OF EJS Templates
commands.import: refactor patch parsing into patch.extract.
Vadim Gelfer -
r2866:2893e514 default
parent child Browse files
Show More
@@ -12,7 +12,7 b' demandload(globals(), "os re sys signal '
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
13 demandload(globals(), "fnmatch mdiff patch random signal tempfile time")
13 demandload(globals(), "fnmatch mdiff patch random signal tempfile time")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
15 demandload(globals(), "archival cStringIO changegroup email.Parser")
15 demandload(globals(), "archival cStringIO changegroup")
16 demandload(globals(), "hgweb.server sshserver")
16 demandload(globals(), "hgweb.server sshserver")
17
17
18 class UnknownCommand(Exception):
18 class UnknownCommand(Exception):
@@ -1814,84 +1814,23 b' def import_(ui, repo, patch1, *patches, '
1814 d = opts["base"]
1814 d = opts["base"]
1815 strip = opts["strip"]
1815 strip = opts["strip"]
1816
1816
1817 mailre = re.compile(r'(?:From |[\w-]+:)')
1818
1819 # attempt to detect the start of a patch
1820 # (this heuristic is borrowed from quilt)
1821 diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1822 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1823 '(---|\*\*\*)[ \t])', re.MULTILINE)
1824
1825 wlock = repo.wlock()
1817 wlock = repo.wlock()
1826 lock = repo.lock()
1818 lock = repo.lock()
1827
1819
1828 for p in patches:
1820 for p in patches:
1829 pf = os.path.join(d, p)
1821 pf = os.path.join(d, p)
1830
1822
1831 message = None
1832 user = None
1833 date = None
1834 hgpatch = False
1835
1836 parser = email.Parser.Parser()
1837 if pf == '-':
1823 if pf == '-':
1838 msg = parser.parse(sys.stdin)
1839 ui.status(_("applying patch from stdin\n"))
1824 ui.status(_("applying patch from stdin\n"))
1825 tmpname, message, user, date = patch.extract(ui, sys.stdin)
1840 else:
1826 else:
1841 msg = parser.parse(file(pf))
1842 ui.status(_("applying %s\n") % p)
1827 ui.status(_("applying %s\n") % p)
1843
1828 tmpname, message, user, date = patch.extract(ui, file(pf))
1844 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
1829
1845 tmpfp = os.fdopen(fd, 'w')
1830 if tmpname is None:
1831 raise util.Abort(_('no diffs found'))
1832
1846 try:
1833 try:
1847 message = msg['Subject']
1848 if message:
1849 message = message.replace('\n\t', ' ')
1850 ui.debug('Subject: %s\n' % message)
1851 user = msg['From']
1852 if user:
1853 ui.debug('From: %s\n' % user)
1854 diffs_seen = 0
1855 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
1856 for part in msg.walk():
1857 content_type = part.get_content_type()
1858 ui.debug('Content-Type: %s\n' % content_type)
1859 if content_type not in ok_types:
1860 continue
1861 payload = part.get_payload(decode=True)
1862 m = diffre.search(payload)
1863 if m:
1864 ui.debug(_('found patch at byte %d\n') % m.start(0))
1865 diffs_seen += 1
1866 hgpatch = False
1867 fp = cStringIO.StringIO()
1868 if message:
1869 fp.write(message)
1870 fp.write('\n')
1871 for line in payload[:m.start(0)].splitlines():
1872 if line.startswith('# HG changeset patch'):
1873 ui.debug(_('patch generated by hg export\n'))
1874 hgpatch = True
1875 # drop earlier commit message content
1876 fp.seek(0)
1877 fp.truncate()
1878 elif hgpatch:
1879 if line.startswith('# User '):
1880 user = line[7:]
1881 ui.debug('From: %s\n' % user)
1882 elif line.startswith("# Date "):
1883 date = line[7:]
1884 if not line.startswith('# '):
1885 fp.write(line)
1886 fp.write('\n')
1887 message = fp.getvalue()
1888 if tmpfp:
1889 tmpfp.write(payload)
1890 if not payload.endswith('\n'):
1891 tmpfp.write('\n')
1892 elif not diffs_seen and message and content_type == 'text/plain':
1893 message += '\n' + payload
1894
1895 if opts['message']:
1834 if opts['message']:
1896 # pickup the cmdline msg
1835 # pickup the cmdline msg
1897 message = opts['message']
1836 message = opts['message']
@@ -1903,10 +1842,6 b' def import_(ui, repo, patch1, *patches, '
1903 message = None
1842 message = None
1904 ui.debug(_('message:\n%s\n') % message)
1843 ui.debug(_('message:\n%s\n') % message)
1905
1844
1906 tmpfp.close()
1907 if not diffs_seen:
1908 raise util.Abort(_('no diffs found'))
1909
1910 files = patch.patch(strip, tmpname, ui, cwd=repo.root)
1845 files = patch.patch(strip, tmpname, ui, cwd=repo.root)
1911 removes = []
1846 removes = []
1912 if len(files) > 0:
1847 if len(files) > 0:
@@ -6,8 +6,92 b''
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>"""
General Comments 0
You need to be logged in to leave comments. Login now