##// END OF EJS Templates
Add import --exact....
Brendan Cully -
r4263:47ba5212 default
parent child Browse files
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'))] + commitopts,
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). any item in returned
38 return tuple (filename, message, user, date, node, p1, p2).
39 tuple can be None. if filename is None, fileobj did not contain
39 Any item in the returned tuple can be None. If filename is None,
40 patch. caller must unlink filename when done.'''
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