[PATCH] import: --obsolete flag for automatic obsolescence marker

pierre-yves.david at logilab.fr pierre-yves.david at logilab.fr
Thu Mar 28 13:43:10 CDT 2013


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at ens-lyon.org>
# 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)


More information about the Mercurial-devel mailing list