##// END OF EJS Templates
import: add --partial flag to create a changeset despite failed hunks...
Pierre-Yves David -
r21553:bee0e1cf default
parent child Browse files
Show More
@@ -591,9 +591,11 b' def tryimportone(ui, repo, hunk, parents'
591 strip = opts["strip"]
591 strip = opts["strip"]
592 sim = float(opts.get('similarity') or 0)
592 sim = float(opts.get('similarity') or 0)
593 if not tmpname:
593 if not tmpname:
594 return (None, None)
594 return (None, None, False)
595 msg = _('applied to working directory')
595 msg = _('applied to working directory')
596
596
597 rejects = False
598
597 try:
599 try:
598 cmdline_message = logmessage(ui, opts)
600 cmdline_message = logmessage(ui, opts)
599 if cmdline_message:
601 if cmdline_message:
@@ -639,9 +641,17 b' def tryimportone(ui, repo, hunk, parents'
639 if opts.get('exact') or opts.get('import_branch'):
641 if opts.get('exact') or opts.get('import_branch'):
640 repo.dirstate.setbranch(branch or 'default')
642 repo.dirstate.setbranch(branch or 'default')
641
643
644 partial = opts.get('partial', False)
642 files = set()
645 files = set()
643 patch.patch(ui, repo, tmpname, strip=strip, files=files,
646 try:
644 eolmode=None, similarity=sim / 100.0)
647 patch.patch(ui, repo, tmpname, strip=strip, files=files,
648 eolmode=None, similarity=sim / 100.0)
649 except patch.PatchError, e:
650 if not partial:
651 raise util.Abort(str(e))
652 if partial:
653 rejects = True
654
645 files = list(files)
655 files = list(files)
646 if opts.get('no_commit'):
656 if opts.get('no_commit'):
647 if message:
657 if message:
@@ -656,7 +666,7 b' def tryimportone(ui, repo, hunk, parents'
656 m = scmutil.matchfiles(repo, files or [])
666 m = scmutil.matchfiles(repo, files or [])
657 n = repo.commit(message, opts.get('user') or user,
667 n = repo.commit(message, opts.get('user') or user,
658 opts.get('date') or date, match=m,
668 opts.get('date') or date, match=m,
659 editor=editor)
669 editor=editor, force=partial)
660 else:
670 else:
661 if opts.get('exact') or opts.get('import_branch'):
671 if opts.get('exact') or opts.get('import_branch'):
662 branch = branch or 'default'
672 branch = branch or 'default'
@@ -684,7 +694,7 b' def tryimportone(ui, repo, hunk, parents'
684 if n:
694 if n:
685 # i18n: refers to a short changeset id
695 # i18n: refers to a short changeset id
686 msg = _('created %s') % short(n)
696 msg = _('created %s') % short(n)
687 return (msg, n)
697 return (msg, n, rejects)
688 finally:
698 finally:
689 os.unlink(tmpname)
699 os.unlink(tmpname)
690
700
@@ -3685,6 +3685,8 b' def identify(ui, repo, source=None, rev='
3685 _("don't commit, just update the working directory")),
3685 _("don't commit, just update the working directory")),
3686 ('', 'bypass', None,
3686 ('', 'bypass', None,
3687 _("apply patch without touching the working directory")),
3687 _("apply patch without touching the working directory")),
3688 ('', 'partial', None,
3689 _('commit even if some hunks fail')),
3688 ('', 'exact', None,
3690 ('', 'exact', None,
3689 _('apply patch to the nodes from which it was generated')),
3691 _('apply patch to the nodes from which it was generated')),
3690 ('', 'import-branch', None,
3692 ('', 'import-branch', None,
@@ -3726,6 +3728,16 b' def import_(ui, repo, patch1=None, *patc'
3726 With -s/--similarity, hg will attempt to discover renames and
3728 With -s/--similarity, hg will attempt to discover renames and
3727 copies in the patch in the same way as :hg:`addremove`.
3729 copies in the patch in the same way as :hg:`addremove`.
3728
3730
3731 Use --partial to ensure a changeset will be created from the patch
3732 even if some hunks fail to apply. Hunks that fail to apply will be
3733 written to a <target-file>.rej file. Conflicts can then be resolved
3734 by hand before :hg:`commit --amend` is run to update the created
3735 changeset. This flag exists to let people import patches that
3736 partially apply without losing the associated metadata (author,
3737 date, description, ...), Note that when none of the hunk applies
3738 cleanly, :hg:`import --partial` will create an empty changeset,
3739 importing only the patch metadata.
3740
3729 To read a patch from standard input, use "-" as the patch name. If
3741 To read a patch from standard input, use "-" as the patch name. If
3730 a URL is specified, the patch will be downloaded from it.
3742 a URL is specified, the patch will be downloaded from it.
3731 See :hg:`help dates` for a list of formats valid for -d/--date.
3743 See :hg:`help dates` for a list of formats valid for -d/--date.
@@ -3751,7 +3763,7 b' def import_(ui, repo, patch1=None, *patc'
3751
3763
3752 hg import --exact proposed-fix.patch
3764 hg import --exact proposed-fix.patch
3753
3765
3754 Returns 0 on success.
3766 Returns 0 on success, 1 on partial success (see --partial).
3755 """
3767 """
3756
3768
3757 if not patch1:
3769 if not patch1:
@@ -3783,6 +3795,7 b' def import_(ui, repo, patch1=None, *patc'
3783 base = opts["base"]
3795 base = opts["base"]
3784 wlock = lock = tr = None
3796 wlock = lock = tr = None
3785 msgs = []
3797 msgs = []
3798 ret = 0
3786
3799
3787
3800
3788 try:
3801 try:
@@ -3804,8 +3817,9 b' def import_(ui, repo, patch1=None, *patc'
3804
3817
3805 haspatch = False
3818 haspatch = False
3806 for hunk in patch.split(patchfile):
3819 for hunk in patch.split(patchfile):
3807 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3820 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3808 opts, msgs, hg.clean)
3821 parents, opts,
3822 msgs, hg.clean)
3809 if msg:
3823 if msg:
3810 haspatch = True
3824 haspatch = True
3811 ui.note(msg + '\n')
3825 ui.note(msg + '\n')
@@ -3813,6 +3827,12 b' def import_(ui, repo, patch1=None, *patc'
3813 parents = repo.parents()
3827 parents = repo.parents()
3814 else:
3828 else:
3815 parents = [repo[node]]
3829 parents = [repo[node]]
3830 if rej:
3831 ui.write_err(_("patch applied partially\n"))
3832 ui.write_err(("(fix the .rej files and run "
3833 "`hg commit --amend`)\n"))
3834 ret = 1
3835 break
3816
3836
3817 if not haspatch:
3837 if not haspatch:
3818 raise util.Abort(_('%s: no diffs found') % patchurl)
3838 raise util.Abort(_('%s: no diffs found') % patchurl)
@@ -3821,6 +3841,7 b' def import_(ui, repo, patch1=None, *patc'
3821 tr.close()
3841 tr.close()
3822 if msgs:
3842 if msgs:
3823 repo.savecommitmessage('\n* * *\n'.join(msgs))
3843 repo.savecommitmessage('\n* * *\n'.join(msgs))
3844 return ret
3824 except: # re-raises
3845 except: # re-raises
3825 # wlock.release() indirectly calls dirstate.write(): since
3846 # wlock.release() indirectly calls dirstate.write(): since
3826 # we're crashing, we do not want to change the working dir
3847 # we're crashing, we do not want to change the working dir
@@ -1521,14 +1521,11 b' def patch(ui, repo, patchname, strip=1, '
1521 patcher = ui.config('ui', 'patch')
1521 patcher = ui.config('ui', 'patch')
1522 if files is None:
1522 if files is None:
1523 files = set()
1523 files = set()
1524 try:
1524 if patcher:
1525 if patcher:
1525 return _externalpatch(ui, repo, patcher, patchname, strip,
1526 return _externalpatch(ui, repo, patcher, patchname, strip,
1526 files, similarity)
1527 files, similarity)
1527 return internalpatch(ui, repo, patchname, strip, files, eolmode,
1528 return internalpatch(ui, repo, patchname, strip, files, eolmode,
1528 similarity)
1529 similarity)
1530 except PatchError, err:
1531 raise util.Abort(str(err))
1532
1529
1533 def changedfiles(ui, repo, patchpath, strip=1):
1530 def changedfiles(ui, repo, patchpath, strip=1):
1534 backend = fsbackend(ui, repo.root)
1531 backend = fsbackend(ui, repo.root)
@@ -262,7 +262,7 b' Show all commands + options'
262 heads: rev, topo, active, closed, style, template
262 heads: rev, topo, active, closed, style, template
263 help: extension, command, keyword
263 help: extension, command, keyword
264 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
264 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
265 import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
265 import: strip, base, edit, force, no-commit, bypass, partial, exact, import-branch, message, logfile, date, user, similarity
266 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
266 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
267 locate: rev, print0, fullpath, include, exclude
267 locate: rev, print0, fullpath, include, exclude
268 manifest: rev, all
268 manifest: rev, all
@@ -1181,5 +1181,272 b' Test corner case involving fuzz and skew'
1181 3
1181 3
1182 4
1182 4
1183 line
1183 line
1184 $ cd ..
1184
1185
1185 $ cd ..
1186 Test partial application
1187 ------------------------
1188
1189 prepare a stack of patches depending on each other
1190
1191 $ hg init partial
1192 $ cd partial
1193 $ cat << EOF > a
1194 > one
1195 > two
1196 > three
1197 > four
1198 > five
1199 > six
1200 > seven
1201 > EOF
1202 $ hg add a
1203 $ echo 'b' > b
1204 $ hg add b
1205 $ hg commit -m 'initial' -u Babar
1206 $ cat << EOF > a
1207 > one
1208 > two
1209 > 3
1210 > four
1211 > five
1212 > six
1213 > seven
1214 > EOF
1215 $ hg commit -m 'three' -u Celeste
1216 $ cat << EOF > a
1217 > one
1218 > two
1219 > 3
1220 > 4
1221 > five
1222 > six
1223 > seven
1224 > EOF
1225 $ hg commit -m 'four' -u Rataxes
1226 $ cat << EOF > a
1227 > one
1228 > two
1229 > 3
1230 > 4
1231 > 5
1232 > six
1233 > seven
1234 > EOF
1235 $ echo bb >> b
1236 $ hg commit -m 'five' -u Arthur
1237 $ echo 'Babar' > jungle
1238 $ hg add jungle
1239 $ hg ci -m 'jungle' -u Zephir
1240 $ echo 'Celeste' >> jungle
1241 $ hg ci -m 'extended jungle' -u Cornelius
1242 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1243 @ extended jungle [Cornelius] 1: +1/-0
1244 |
1245 o jungle [Zephir] 1: +1/-0
1246 |
1247 o five [Arthur] 2: +2/-1
1248 |
1249 o four [Rataxes] 1: +1/-1
1250 |
1251 o three [Celeste] 1: +1/-1
1252 |
1253 o initial [Babar] 2: +8/-0
1254
1255
1256 Importing with some success and some errors:
1257
1258 $ hg update --rev 'desc(initial)'
1259 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1260 $ hg export --rev 'desc(five)' | hg import --partial -
1261 applying patch from stdin
1262 patching file a
1263 Hunk #1 FAILED at 1
1264 1 out of 1 hunks FAILED -- saving rejects to file a.rej
1265 patch applied partially
1266 (fix the .rej files and run `hg commit --amend`)
1267 [1]
1268
1269 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1270 @ five [Arthur] 1: +1/-0
1271 |
1272 | o extended jungle [Cornelius] 1: +1/-0
1273 | |
1274 | o jungle [Zephir] 1: +1/-0
1275 | |
1276 | o five [Arthur] 2: +2/-1
1277 | |
1278 | o four [Rataxes] 1: +1/-1
1279 | |
1280 | o three [Celeste] 1: +1/-1
1281 |/
1282 o initial [Babar] 2: +8/-0
1283
1284 $ hg export
1285 # HG changeset patch
1286 # User Arthur
1287 # Date 0 0
1288 # Thu Jan 01 00:00:00 1970 +0000
1289 # Node ID 26e6446bb2526e2be1037935f5fca2b2706f1509
1290 # Parent 8e4f0351909eae6b9cf68c2c076cb54c42b54b2e
1291 five
1292
1293 diff -r 8e4f0351909e -r 26e6446bb252 b
1294 --- a/b Thu Jan 01 00:00:00 1970 +0000
1295 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1296 @@ -1,1 +1,2 @@
1297 b
1298 +bb
1299 $ hg status -c .
1300 C a
1301 C b
1302 $ ls
1303 a
1304 a.rej
1305 b
1306
1307 Importing with zero success:
1308
1309 $ hg update --rev 'desc(initial)'
1310 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1311 $ hg export --rev 'desc(four)' | hg import --partial -
1312 applying patch from stdin
1313 patching file a
1314 Hunk #1 FAILED at 0
1315 1 out of 1 hunks FAILED -- saving rejects to file a.rej
1316 patch applied partially
1317 (fix the .rej files and run `hg commit --amend`)
1318 [1]
1319
1320 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1321 @ four [Rataxes] 0: +0/-0
1322 |
1323 | o five [Arthur] 1: +1/-0
1324 |/
1325 | o extended jungle [Cornelius] 1: +1/-0
1326 | |
1327 | o jungle [Zephir] 1: +1/-0
1328 | |
1329 | o five [Arthur] 2: +2/-1
1330 | |
1331 | o four [Rataxes] 1: +1/-1
1332 | |
1333 | o three [Celeste] 1: +1/-1
1334 |/
1335 o initial [Babar] 2: +8/-0
1336
1337 $ hg export
1338 # HG changeset patch
1339 # User Rataxes
1340 # Date 0 0
1341 # Thu Jan 01 00:00:00 1970 +0000
1342 # Node ID cb9b1847a74d9ad52e93becaf14b98dbcc274e1e
1343 # Parent 8e4f0351909eae6b9cf68c2c076cb54c42b54b2e
1344 four
1345
1346 $ hg status -c .
1347 C a
1348 C b
1349 $ ls
1350 a
1351 a.rej
1352 b
1353
1354 Importing with unknown file:
1355
1356 $ hg update --rev 'desc(initial)'
1357 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1358 $ hg export --rev 'desc("extended jungle")' | hg import --partial -
1359 applying patch from stdin
1360 unable to find 'jungle' for patching
1361 1 out of 1 hunks FAILED -- saving rejects to file jungle.rej
1362 patch applied partially
1363 (fix the .rej files and run `hg commit --amend`)
1364 [1]
1365
1366 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1367 @ extended jungle [Cornelius] 0: +0/-0
1368 |
1369 | o four [Rataxes] 0: +0/-0
1370 |/
1371 | o five [Arthur] 1: +1/-0
1372 |/
1373 | o extended jungle [Cornelius] 1: +1/-0
1374 | |
1375 | o jungle [Zephir] 1: +1/-0
1376 | |
1377 | o five [Arthur] 2: +2/-1
1378 | |
1379 | o four [Rataxes] 1: +1/-1
1380 | |
1381 | o three [Celeste] 1: +1/-1
1382 |/
1383 o initial [Babar] 2: +8/-0
1384
1385 $ hg export
1386 # HG changeset patch
1387 # User Cornelius
1388 # Date 0 0
1389 # Thu Jan 01 00:00:00 1970 +0000
1390 # Node ID 1fb1f86bef43c5a75918178f8d23c29fb0a7398d
1391 # Parent 8e4f0351909eae6b9cf68c2c076cb54c42b54b2e
1392 extended jungle
1393
1394 $ hg status -c .
1395 C a
1396 C b
1397 $ ls
1398 a
1399 a.rej
1400 b
1401 jungle.rej
1402
1403 Importing multiple failing patches:
1404
1405 $ hg update --rev 'desc(initial)'
1406 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1407 $ echo 'B' > b # just to make another commit
1408 $ hg commit -m "a new base"
1409 created new head
1410 $ hg export --rev 'desc("extended jungle") + desc("four")' | hg import --partial -
1411 applying patch from stdin
1412 patching file a
1413 Hunk #1 FAILED at 0
1414 1 out of 1 hunks FAILED -- saving rejects to file a.rej
1415 patch applied partially
1416 (fix the .rej files and run `hg commit --amend`)
1417 [1]
1418 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1419 @ four [Rataxes] 0: +0/-0
1420 |
1421 o a new base [test] 1: +1/-1
1422 |
1423 | o extended jungle [Cornelius] 0: +0/-0
1424 |/
1425 | o four [Rataxes] 0: +0/-0
1426 |/
1427 | o five [Arthur] 1: +1/-0
1428 |/
1429 | o extended jungle [Cornelius] 1: +1/-0
1430 | |
1431 | o jungle [Zephir] 1: +1/-0
1432 | |
1433 | o five [Arthur] 2: +2/-1
1434 | |
1435 | o four [Rataxes] 1: +1/-1
1436 | |
1437 | o three [Celeste] 1: +1/-1
1438 |/
1439 o initial [Babar] 2: +8/-0
1440
1441 $ hg export
1442 # HG changeset patch
1443 # User Rataxes
1444 # Date 0 0
1445 # Thu Jan 01 00:00:00 1970 +0000
1446 # Node ID a9d7b6d0ffbb4eb12b7d5939250fcd42e8930a1d
1447 # Parent f59f8d2e95a8ca5b1b4ca64320140da85f3b44fd
1448 four
1449
1450 $ hg status -c .
1451 C a
1452 C b
General Comments 0
You need to be logged in to leave comments. Login now