From patchwork Thu Mar 28 18:43:10 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: import: --obsolete flag for automatic obsolescence marker From: Pierre-Yves David X-Patchwork-Id: 1207 Message-Id: <89f8f7ad21e55e444247.1364496190@crater1.logilab.fr> To: mercurial-devel@selenic.com Date: Thu, 28 Mar 2013 19:43:10 +0100 # HG changeset patch # User Pierre-Yves David # Date 1364495597 -3600 # Thu Mar 28 19:33:17 2013 +0100 # Node ID 89f8f7ad21e55e4442478909c9a3d269e418e6d6 # Parent fc5388b69f50c5c504736151898a4da0471811f8 import: --obsolete flag for automatic obsolescence marker A new `--obsolete` flag is added to import. When present, the new node will be marked as a successors of the one specified in the `Node` field of the imported patch. No marker are created is created revision have the same node. This improve email based work flow where implicit rebase are likely to happen. This new behavior requires a flags, otherwise the `hg export x | hg import -` idiot would change, turning the source obsolete. (Changing from `hg graft x` to `hg rebase --dest . --rev x`) diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -3485,11 +3485,14 @@ def identify(ui, repo, source=None, rev= ('', 'bypass', None, _("apply patch without touching the working directory")), ('', 'exact', None, _('apply patch to the nodes from which it was generated')), ('', 'import-branch', None, - _('use any branch information in patch (implied by --exact)'))] + + _('use any branch information in patch (implied by --exact)')), + ('', 'obsolete', False, + _('mark the old node as obsoleted by the created commit ' + '(require obsolescence feature to be enabled)'))] + commitopts + commitopts2 + similarityopts, _('[OPTION]... PATCH...')) def import_(ui, repo, patch1=None, *patches, **opts): """import an ordered set of patches @@ -3588,11 +3591,11 @@ def import_(ui, repo, patch1=None, *patc def checkexact(repo, n, nodeid): if opts.get('exact') and hex(n) != nodeid: raise util.Abort(_('patch is damaged or loses information')) - def tryone(ui, hunk, parents): + def tryone(ui, hunk, parents, tr): tmpname, message, user, date, branch, nodeid, p1, p2 = \ patch.extract(ui, hunk) if not tmpname: return (None, None) @@ -3660,10 +3663,18 @@ def import_(ui, repo, patch1=None, *patc m = scmutil.matchfiles(repo, files or []) n = repo.commit(message, opts.get('user') or user, opts.get('date') or date, match=m, editor=editor) checkexact(repo, n, nodeid) + if opts['obsolete']: + if not obsolete._enabled: + raise util.Abort(_('--obsolete require obsolescence' + ' feature to be enabled')) + if tr is not None and n != nodeid: + metadata = {'user': ui.username()} + repo.obsstore.create(tr, bin(nodeid), (n,), + metadata=metadata) else: if opts.get('exact') or opts.get('import_branch'): branch = branch or 'default' else: branch = p1.branch() @@ -3681,10 +3692,19 @@ def import_(ui, repo, patch1=None, *patc opts.get('date') or date, branch, files, store, editor=cmdutil.commiteditor) repo.savecommitmessage(memctx.description()) n = memctx.commit() + if opts['obsolete']: + if not obsolete._enabled: + raise util.Abort(_('--obsolete require obsolescence' + ' feature to be enabled')) + if tr is not None and n != nodeid: + metadata = {'user': ui.username()} + repo.obsstore.create(tr, bin(nodeid), (n,), + metadata=metadata) + checkexact(repo, n, nodeid) finally: store.close() if n: # i18n: refers to a short changeset id @@ -3710,11 +3730,11 @@ def import_(ui, repo, patch1=None, *patc ui.status(_('applying %s\n') % patchurl) patchfile = hg.openpath(ui, patchurl) haspatch = False for hunk in patch.split(patchfile): - (msg, node) = tryone(ui, hunk, parents) + (msg, node) = tryone(ui, hunk, parents, tr) if msg: haspatch = True ui.note(msg + '\n') if update or opts.get('exact'): parents = repo.parents() diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -259,11 +259,11 @@ Show all commands + options graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude heads: rev, topo, active, closed, style, template help: extension, command, keyword identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure - import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity + import: strip, base, edit, force, no-commit, bypass, exact, import-branch, obsolete, message, logfile, date, user, similarity incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos locate: rev, print0, fullpath, include, exclude manifest: rev, all outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos parents: rev, style, template diff --git a/tests/test-import.t b/tests/test-import.t --- a/tests/test-import.t +++ b/tests/test-import.t @@ -1155,5 +1155,72 @@ Test corner case involving fuzz and skew 3 4 line $ cd .. + + +Test creation of obsolescence marker by path import + + $ cat > ./obs.py << EOF + > import mercurial.obsolete + > mercurial.obsolete._enabled = True + > EOF + $ hg init auto-obsolete + $ cd auto-obsolete + $ echo '[extensions]' >> .hg/hgrc + $ echo "obs=${TESTTMP}/obs.py" >> .hg/hgrc + $ echo A > a + $ hg commit -Am A + adding a + $ echo B > b + $ hg commit -Am B + adding b + $ hg up '.^' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo C > c + $ hg commit -Am C + adding c + created new head + $ hg log -G + @ changeset: 2:eb8dd0f31b51 + | tag: tip + | parent: 0:f2bbf19cf96d + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C + | + | o changeset: 1:95b760afef3c + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B + | + o changeset: 0:f2bbf19cf96d + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: A + + +(actual test) + + $ hg export 'desc(B)' | hg import - --obsolete + applying patch from stdin + $ hg log -G + @ changeset: 3:00c49133f17e + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B + | + o changeset: 2:eb8dd0f31b51 + | parent: 0:f2bbf19cf96d + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C + | + o changeset: 0:f2bbf19cf96d + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: A + + $ hg debugobsolete + 95b760afef3c234ffb3f9fd391edcb36e60921a4 00c49133f17e5e5a52b6ef1b6d516c0e90b56d8a 0 {'date': '* *', 'user': 'test'} (glob)