Patchwork import: --obsolete flag for automatic obsolescence marker

login
register
mail settings
Submitter Pierre-Yves David
Date March 28, 2013, 6:43 p.m.
Message ID <89f8f7ad21e55e444247.1364496190@crater1.logilab.fr>
Download mbox | patch
Permalink /patch/1207/
State Rejected, archived
Headers show

Comments

Pierre-Yves David - March 28, 2013, 6:43 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@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`)
Sean Farley - March 28, 2013, 10:08 p.m.
Kevin Bullock writes:

> On 28 Mar 2013, at 1:43 PM, pierre-yves.david@logilab.fr wrote:
>
>> # HG changeset patch
>> # User Pierre-Yves David <pierre-yves.david@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`)
>
> I'd rather we do it without a flag (if obsolescence is enabled). For starters, we have a built-in graft command, making the old idiom obsolete and unnecessary. But if people want to do this sort of "manual graft", _and_ have obsolete enabled, they can use --config to disable it for the import invocation.
>
> If we add a flag, no one will use it and we won't get our lovely obsolescence markers added.

+1 on Kevin's reasoning here
Pierre-Yves David - March 29, 2013, 6:10 p.m.
On Thu, Mar 28, 2013 at 05:08:44PM -0500, Sean Farley wrote:
> 
> Kevin Bullock writes:
> 
> > On 28 Mar 2013, at 1:43 PM, pierre-yves.david@logilab.fr wrote:
> >
> >> # HG changeset patch
> >> # User Pierre-Yves David <pierre-yves.david@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`)
> >
> > I'd rather we do it without a flag (if obsolescence is enabled). For starters, we have a built-in graft command, making the old idiom obsolete and unnecessary. But if people want to do this sort of "manual graft", _and_ have obsolete enabled, they can use --config to disable it for the import invocation.
> >
> > If we add a flag, no one will use it and we won't get our lovely obsolescence markers added.
> 
> +1 on Kevin's reasoning here

still -1 on doing it on an automatic basis. hg import never had
"deleting commit" in it semantic and I do not think it is a good idea to
changes that.

We could hide the auto obsolesting under a richer flag like

    "hg import --rebase"

Whose semantic would be:

    1) apply the patch using pvec were it apply the best
    2) rebase it on the current working directory parent
    3) create obsolescence marker from <patch->#Node> to >result>
Matt Mackall - April 1, 2013, 9:08 p.m.
On Thu, 2013-03-28 at 14:36 -0500, Kevin Bullock wrote:
> On 28 Mar 2013, at 1:43 PM, pierre-yves.david@logilab.fr wrote:
> 
> > # HG changeset patch
> > # User Pierre-Yves David <pierre-yves.david@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`)
> 
> I'd rather we do it without a flag (if obsolescence is enabled). For
> starters, we have a built-in graft command, making the old idiom
> obsolete and unnecessary.

Obsolete != candidate for breakage.

I've been recommending people learn and understand export + import
before trying to use transplant for years. So consider this an
officially sanctioned way of doing transplants. I don't think everyone
will be on the graft bandwagon for a while.

Patch

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)