Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/commands.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 | 61151f429a5f |
children | 652e07debf10 |
comparison
equal
deleted
inserted
replaced
21552:61151f429a5f | 21553:bee0e1cffdd3 |
---|---|
3683 _('skip check for outstanding uncommitted changes (DEPRECATED)')), | 3683 _('skip check for outstanding uncommitted changes (DEPRECATED)')), |
3684 ('', 'no-commit', None, | 3684 ('', 'no-commit', None, |
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, |
3691 _('use any branch information in patch (implied by --exact)'))] + | 3693 _('use any branch information in patch (implied by --exact)'))] + |
3692 commitopts + commitopts2 + similarityopts, | 3694 commitopts + commitopts2 + similarityopts, |
3724 revision. | 3726 revision. |
3725 | 3727 |
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. |
3732 | 3744 |
3733 .. container:: verbose | 3745 .. container:: verbose |
3749 - attempt to exactly restore an exported changeset (not always | 3761 - attempt to exactly restore an exported changeset (not always |
3750 possible):: | 3762 possible):: |
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: |
3758 raise util.Abort(_('need at least one patch to import')) | 3770 raise util.Abort(_('need at least one patch to import')) |
3759 | 3771 |
3781 cmdutil.bailifchanged(repo) | 3793 cmdutil.bailifchanged(repo) |
3782 | 3794 |
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: |
3789 try: | 3802 try: |
3790 wlock = repo.wlock() | 3803 wlock = repo.wlock() |
3802 ui.status(_('applying %s\n') % patchurl) | 3815 ui.status(_('applying %s\n') % patchurl) |
3803 patchfile = hg.openpath(ui, patchurl) | 3816 patchfile = hg.openpath(ui, patchurl) |
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') |
3812 if update or opts.get('exact'): | 3826 if update or opts.get('exact'): |
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) |
3819 | 3839 |
3820 if tr: | 3840 if tr: |
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 |
3827 # parent after all, so make sure it writes nothing | 3848 # parent after all, so make sure it writes nothing |
3828 repo.dirstate.invalidate() | 3849 repo.dirstate.invalidate() |