Show More
@@ -1477,15 +1477,21 b' def import_(ui, repo, patch1, *patches, ' | |||||
1477 | text/plain body parts before first diff are added to commit |
|
1477 | text/plain body parts before first diff are added to commit | |
1478 | message. |
|
1478 | message. | |
1479 |
|
1479 | |||
1480 | If imported patch was generated by hg export, user and description |
|
1480 | If the imported patch was generated by hg export, user and description | |
1481 | from patch override values from message headers and body. Values |
|
1481 | from patch override values from message headers and body. Values | |
1482 | given on command line with -m and -u override these. |
|
1482 | given on command line with -m and -u override these. | |
1483 |
|
1483 | |||
|
1484 | If --exact is specified, import will set the working directory | |||
|
1485 | to the parent of each patch before applying it, and will abort | |||
|
1486 | if the resulting changeset has a different ID than the one | |||
|
1487 | recorded in the patch. This may happen due to character set | |||
|
1488 | problems or other deficiencies in the text patch format. | |||
|
1489 | ||||
1484 | To read a patch from standard input, use patch name "-". |
|
1490 | To read a patch from standard input, use patch name "-". | |
1485 | """ |
|
1491 | """ | |
1486 | patches = (patch1,) + patches |
|
1492 | patches = (patch1,) + patches | |
1487 |
|
1493 | |||
1488 | if not opts['force']: |
|
1494 | if opts.get('exact') or not opts['force']: | |
1489 | bail_if_changed(repo) |
|
1495 | bail_if_changed(repo) | |
1490 |
|
1496 | |||
1491 | d = opts["base"] |
|
1497 | d = opts["base"] | |
@@ -1499,10 +1505,10 b' def import_(ui, repo, patch1, *patches, ' | |||||
1499 |
|
1505 | |||
1500 | if pf == '-': |
|
1506 | if pf == '-': | |
1501 | ui.status(_("applying patch from stdin\n")) |
|
1507 | ui.status(_("applying patch from stdin\n")) | |
1502 | tmpname, message, user, date = patch.extract(ui, sys.stdin) |
|
1508 | tmpname, message, user, date, nodeid, p1, p2 = patch.extract(ui, sys.stdin) | |
1503 | else: |
|
1509 | else: | |
1504 | ui.status(_("applying %s\n") % p) |
|
1510 | ui.status(_("applying %s\n") % p) | |
1505 | tmpname, message, user, date = patch.extract(ui, file(pf)) |
|
1511 | tmpname, message, user, date, nodeid, p1, p2 = patch.extract(ui, file(pf)) | |
1506 |
|
1512 | |||
1507 | if tmpname is None: |
|
1513 | if tmpname is None: | |
1508 | raise util.Abort(_('no diffs found')) |
|
1514 | raise util.Abort(_('no diffs found')) | |
@@ -1521,12 +1527,27 b' def import_(ui, repo, patch1, *patches, ' | |||||
1521 | ui.debug(_('message:\n%s\n') % message) |
|
1527 | ui.debug(_('message:\n%s\n') % message) | |
1522 |
|
1528 | |||
1523 | files = {} |
|
1529 | files = {} | |
|
1530 | if opts.get('exact'): | |||
|
1531 | if not nodeid or not p1: | |||
|
1532 | raise util.Abort(_('not a mercurial patch')) | |||
|
1533 | p1 = repo.lookup(p1) | |||
|
1534 | p2 = repo.lookup(p2 or hex(nullid)) | |||
|
1535 | ||||
|
1536 | wctx = repo.workingctx() | |||
|
1537 | wp = repo.workingctx().parents() | |||
|
1538 | if p1 != wp[0].node(): | |||
|
1539 | hg.clean(repo, p1, wlock=wlock) | |||
|
1540 | repo.dirstate.setparents(p1, p2) | |||
1524 | try: |
|
1541 | try: | |
1525 | fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root, |
|
1542 | fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root, | |
1526 | files=files) |
|
1543 | files=files) | |
1527 | finally: |
|
1544 | finally: | |
1528 | files = patch.updatedir(ui, repo, files, wlock=wlock) |
|
1545 | files = patch.updatedir(ui, repo, files, wlock=wlock) | |
1529 | repo.commit(files, message, user, date, wlock=wlock, lock=lock) |
|
1546 | n = repo.commit(files, message, user, date, wlock=wlock, lock=lock) | |
|
1547 | if opts.get('exact'): | |||
|
1548 | if hex(n) != nodeid: | |||
|
1549 | repo.rollback() | |||
|
1550 | raise util.Abort(_('patch is damaged or loses information')) | |||
1530 | finally: |
|
1551 | finally: | |
1531 | os.unlink(tmpname) |
|
1552 | os.unlink(tmpname) | |
1532 |
|
1553 | |||
@@ -2772,7 +2793,9 b' table = {' | |||||
2772 | 'meaning as the corresponding patch option')), |
|
2793 | 'meaning as the corresponding patch option')), | |
2773 | ('b', 'base', '', _('base path')), |
|
2794 | ('b', 'base', '', _('base path')), | |
2774 | ('f', 'force', None, |
|
2795 | ('f', 'force', None, | |
2775 |
_('skip check for outstanding uncommitted changes')) |
|
2796 | _('skip check for outstanding uncommitted changes')), | |
|
2797 | ('', 'exact', None, | |||
|
2798 | _('apply patch to the nodes from which it was generated'))] + commitopts, | |||
2776 | _('hg import [-p NUM] [-m MESSAGE] [-f] PATCH...')), |
|
2799 | _('hg import [-p NUM] [-m MESSAGE] [-f] PATCH...')), | |
2777 | "incoming|in": (incoming, |
|
2800 | "incoming|in": (incoming, | |
2778 | [('M', 'no-merges', None, _('do not show merges')), |
|
2801 | [('M', 'no-merges', None, _('do not show merges')), |
@@ -33,11 +33,11 b' def copyfile(src, dst, basedir=None):' | |||||
33 | def extract(ui, fileobj): |
|
33 | def extract(ui, fileobj): | |
34 | '''extract patch from data read from fileobj. |
|
34 | '''extract patch from data read from fileobj. | |
35 |
|
35 | |||
36 | patch can be normal patch or contained in email message. |
|
36 | patch can be a normal patch or contained in an email message. | |
37 |
|
37 | |||
38 |
return tuple (filename, message, user, date |
|
38 | return tuple (filename, message, user, date, node, p1, p2). | |
39 |
tuple can be None. |
|
39 | Any item in the returned tuple can be None. If filename is None, | |
40 |
patch. |
|
40 | fileobj did not contain a patch. Caller must unlink filename when done.''' | |
41 |
|
41 | |||
42 | # attempt to detect the start of a patch |
|
42 | # attempt to detect the start of a patch | |
43 | # (this heuristic is borrowed from quilt) |
|
43 | # (this heuristic is borrowed from quilt) | |
@@ -54,6 +54,8 b' def extract(ui, fileobj):' | |||||
54 | user = msg['From'] |
|
54 | user = msg['From'] | |
55 | # should try to parse msg['Date'] |
|
55 | # should try to parse msg['Date'] | |
56 | date = None |
|
56 | date = None | |
|
57 | nodeid = None | |||
|
58 | parents = [] | |||
57 |
|
59 | |||
58 | if message: |
|
60 | if message: | |
59 | if message.startswith('[PATCH'): |
|
61 | if message.startswith('[PATCH'): | |
@@ -97,6 +99,10 b' def extract(ui, fileobj):' | |||||
97 | ui.debug('From: %s\n' % user) |
|
99 | ui.debug('From: %s\n' % user) | |
98 | elif line.startswith("# Date "): |
|
100 | elif line.startswith("# Date "): | |
99 | date = line[7:] |
|
101 | date = line[7:] | |
|
102 | elif line.startswith("# Node ID "): | |||
|
103 | nodeid = line[10:] | |||
|
104 | elif line.startswith("# Parent "): | |||
|
105 | parents.append(line[10:]) | |||
100 | elif line == '---' and 'git-send-email' in msg['X-Mailer']: |
|
106 | elif line == '---' and 'git-send-email' in msg['X-Mailer']: | |
101 | ignoretext = True |
|
107 | ignoretext = True | |
102 | if not line.startswith('# ') and not ignoretext: |
|
108 | if not line.startswith('# ') and not ignoretext: | |
@@ -117,8 +123,10 b' def extract(ui, fileobj):' | |||||
117 | tmpfp.close() |
|
123 | tmpfp.close() | |
118 | if not diffs_seen: |
|
124 | if not diffs_seen: | |
119 | os.unlink(tmpname) |
|
125 | os.unlink(tmpname) | |
120 | return None, message, user, date |
|
126 | return None, message, user, date, None, None, None | |
121 | return tmpname, message, user, date |
|
127 | p1 = parents and parents.pop(0) or None | |
|
128 | p2 = parents and parents.pop(0) or None | |||
|
129 | return tmpname, message, user, date, nodeid, p1, p2 | |||
122 |
|
130 | |||
123 | GP_PATCH = 1 << 0 # we have to run patch |
|
131 | GP_PATCH = 1 << 0 # we have to run patch | |
124 | GP_FILTER = 1 << 1 # there's some copy/rename operation |
|
132 | GP_FILTER = 1 << 1 # there's some copy/rename operation |
General Comments 0
You need to be logged in to leave comments.
Login now