comparison mercurial/cmdutil.py @ 21553:bee0e1cffdd3

import: add --partial flag to create a changeset despite failed hunks The `hg import` command gains a `--partial` flag. When specified, a commit will always be created from a patch import. Any hunk that fails to apply will create .rej file, same as what `hg qimport` would do. This change is mainly aimed at preserving changeset metadata when applying a patch, something very important for reviewers. In case of failure with `--partial`, `hg import` returns 1 and the following message is displayed: patch applied partially (fix the .rej files and run `hg commit --amend`) When multiple patches are imported, we stop at the first one with failed hunks. In the future, someone may feel brave enough to tackle a --continue flag to import.
author Pierre-Yves David <pierre-yves.david@fb.com>
date Thu, 08 May 2014 17:08:17 -0700
parents 272785489ed3
children 404ff404db79
comparison
equal deleted inserted replaced
21552:61151f429a5f 21553:bee0e1cffdd3
589 editor = getcommiteditor(**opts) 589 editor = getcommiteditor(**opts)
590 update = not opts.get('bypass') 590 update = not opts.get('bypass')
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
597 rejects = False
596 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:
600 # pickup the cmdline msg 602 # pickup the cmdline msg
637 repo.setparents(p1.node(), p2.node()) 639 repo.setparents(p1.node(), p2.node())
638 640
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:
648 msgs.append(message) 658 msgs.append(message)
649 else: 659 else:
654 m = None 664 m = None
655 else: 665 else:
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'
663 else: 673 else:
664 branch = p1.branch() 674 branch = p1.branch()
682 if opts.get('exact') and hex(n) != nodeid: 692 if opts.get('exact') and hex(n) != nodeid:
683 raise util.Abort(_('patch is damaged or loses information')) 693 raise util.Abort(_('patch is damaged or loses information'))
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
691 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False, 701 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
692 opts=None): 702 opts=None):