Mercurial > public > mercurial-scm > hg
diff mercurial/commands.py @ 14611:adbf5e7df96d
import: add --bypass option
This feature is more a way to test patching without a working directory than
something people asked about. Adding a --rev option to specify the parent patch
revision would make it a little more useful.
What this change introduces is patch.repobackend class which let patches be
applied against repository revisions. The caller must supply a filestore object
to receive patched content, which can be turned into a memctx with
patch.makememctx() helper.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Tue, 14 Jun 2011 23:26:35 +0200 |
parents | 5d6244930559 |
children | 234b9795d74e |
line wrap: on
line diff
--- a/mercurial/commands.py Tue Jun 14 23:24:40 2011 +0200 +++ b/mercurial/commands.py Tue Jun 14 23:26:35 2011 +0200 @@ -3002,6 +3002,8 @@ ('f', 'force', None, _('skip check for outstanding uncommitted changes')), ('', 'no-commit', None, _("don't commit, just update the working directory")), + ('', 'bypass', None, + _("apply patch without touching the working directory")), ('', 'exact', None, _('apply patch to the nodes from which it was generated')), ('', 'import-branch', None, @@ -3035,6 +3037,11 @@ the patch. This may happen due to character set problems or other deficiencies in the text patch format. + Use --bypass to apply and commit patches directly to the + repository, not touching the working directory. Without --exact, + patches will be applied on top of the working directory parent + revision. + With -s/--similarity, hg will attempt to discover renames and copies in the patch in the same way as 'addremove'. @@ -3050,14 +3057,19 @@ if date: opts['date'] = util.parsedate(date) + update = not opts.get('bypass') + if not update and opts.get('no_commit'): + raise util.Abort(_('cannot use --no-commit with --bypass')) try: sim = float(opts.get('similarity') or 0) except ValueError: raise util.Abort(_('similarity must be a number')) if sim < 0 or sim > 100: raise util.Abort(_('similarity must be between 0 and 100')) - - if opts.get('exact') or not opts.get('force'): + if sim and not update: + raise util.Abort(_('cannot use --similarity with --bypass')) + + if (opts.get('exact') or not opts.get('force')) and update: cmdutil.bailifchanged(repo) d = opts["base"] @@ -3065,7 +3077,12 @@ wlock = lock = None msgs = [] - def tryone(ui, hunk): + def checkexact(repo, n, nodeid): + if opts.get('exact') and hex(n) != nodeid: + repo.rollback() + raise util.Abort(_('patch is damaged or loses information')) + + def tryone(ui, hunk, parents): tmpname, message, user, date, branch, nodeid, p1, p2 = \ patch.extract(ui, hunk) @@ -3086,9 +3103,8 @@ message = None ui.debug('message:\n%s\n' % message) - wp = repo.parents() - if len(wp) == 1: - wp.append(repo[nullid]) + if len(parents) == 1: + parents.append(repo[nullid]) if opts.get('exact'): if not nodeid or not p1: raise util.Abort(_('not a Mercurial patch')) @@ -3099,44 +3115,65 @@ p1 = repo[p1] p2 = repo[p2] except error.RepoError: - p1, p2 = wp + p1, p2 = parents else: - p1, p2 = wp - - if opts.get('exact') and p1 != wp[0]: - hg.clean(repo, p1.node()) - if p1 != wp[0] and p2 != wp[1]: - repo.dirstate.setparents(p1.node(), p2.node()) - - if opts.get('exact') or opts.get('import_branch'): - repo.dirstate.setbranch(branch or 'default') - - files = set() - patch.patch(ui, repo, tmpname, strip=strip, files=files, - eolmode=None, similarity=sim / 100.0) - files = list(files) - if opts.get('no_commit'): - if message: - msgs.append(message) + p1, p2 = parents + + n = None + if update: + if opts.get('exact') and p1 != parents[0]: + hg.clean(repo, p1.node()) + if p1 != parents[0] and p2 != parents[1]: + repo.dirstate.setparents(p1.node(), p2.node()) + + if opts.get('exact') or opts.get('import_branch'): + repo.dirstate.setbranch(branch or 'default') + + files = set() + patch.patch(ui, repo, tmpname, strip=strip, files=files, + eolmode=None, similarity=sim / 100.0) + files = list(files) + if opts.get('no_commit'): + if message: + msgs.append(message) + else: + if opts.get('exact'): + m = None + else: + m = scmutil.matchfiles(repo, files or []) + n = repo.commit(message, opts.get('user') or user, + opts.get('date') or date, match=m, + editor=cmdutil.commiteditor) + checkexact(repo, n, nodeid) + # Force a dirstate write so that the next transaction + # backups an up-to-date file. + repo.dirstate.write() else: - if opts.get('exact'): - m = None + if opts.get('exact') or opts.get('import_branch'): + branch = branch or 'default' else: - m = scmutil.matchfiles(repo, files or []) - n = repo.commit(message, opts.get('user') or user, - opts.get('date') or date, match=m, - editor=cmdutil.commiteditor) - if opts.get('exact'): - if hex(n) != nodeid: - repo.rollback() - raise util.Abort(_('patch is damaged' - ' or loses information')) - # Force a dirstate write so that the next transaction - # backups an up-do-date file. - repo.dirstate.write() - if n: - commitid = short(n) - + branch = p1.branch() + store = patch.filestore() + try: + files = set() + try: + patch.patchrepo(ui, repo, p1, store, tmpname, strip, + files, eolmode=None) + except patch.PatchError, e: + raise util.Abort(str(e)) + memctx = patch.makememctx(repo, (p1.node(), p2.node()), + message, + opts.get('user') or user, + opts.get('date') or date, + branch, files, store, + editor=cmdutil.commiteditor) + repo.savecommitmessage(memctx.description()) + n = memctx.commit() + checkexact(repo, n, nodeid) + finally: + store.close() + if n: + commitid = short(n) return commitid finally: os.unlink(tmpname) @@ -3144,6 +3181,7 @@ try: wlock = repo.wlock() lock = repo.lock() + parents = repo.parents() lastcommit = None for p in patches: pf = os.path.join(d, p) @@ -3157,12 +3195,16 @@ haspatch = False for hunk in patch.split(pf): - commitid = tryone(ui, hunk) + commitid = tryone(ui, hunk, parents) if commitid: haspatch = True if lastcommit: ui.status(_('applied %s\n') % lastcommit) lastcommit = commitid + if update or opts.get('exact'): + parents = repo.parents() + else: + parents = [repo[commitid]] if not haspatch: raise util.Abort(_('no diffs found'))