Patchwork [3,of,7,shelve-ext,v5] shelve: add obs-based shelve functionality

login
register
mail settings
Submitter Kostia Balytskyi
Date March 29, 2017, 1:18 p.m.
Message ID <fc1144e5993a5c85060b.1490793526@devvm1416.lla2.facebook.com>
Download mbox | patch
Permalink /patch/19813/
State Changes Requested
Headers show

Comments

Kostia Balytskyi - March 29, 2017, 1:18 p.m.
# HG changeset patch
# User Kostia Balytskyi <ikostia@fb.com>
# Date 1490790691 25200
#      Wed Mar 29 05:31:31 2017 -0700
# Node ID fc1144e5993a5c85060b913e2d92cd4b1b61772e
# Parent  0aa864184c9d78c11d18980cf0faa10828445ff5
shelve: add obs-based shelve functionality

Obsolescense-based shelve works in a following way:
1. In order to shelve some changes, it creates a commit, records its
node into a .oshelve file and prunes created commit.
2. In order to finish a shelve operation, transaction is just
closed and not aborted.
Ryan McElroy - March 30, 2017, 9:15 a.m.
On 3/29/17 2:18 PM, Kostia Balytskyi wrote:
> # HG changeset patch
> # User Kostia Balytskyi <ikostia@fb.com>
> # Date 1490790691 25200
> #      Wed Mar 29 05:31:31 2017 -0700
> # Node ID fc1144e5993a5c85060b913e2d92cd4b1b61772e
> # Parent  0aa864184c9d78c11d18980cf0faa10828445ff5
> shelve: add obs-based shelve functionality
>
> Obsolescense-based shelve works in a following way:

s/ a/ the

> 1. In order to shelve some changes, it creates a commit, records its
> node into a .oshelve file and prunes created commit.
> 2. In order to finish a shelve operation, transaction is just
> closed and not aborted.

s/transaction/the transaction

>
> diff --git a/hgext/shelve.py b/hgext/shelve.py
> --- a/hgext/shelve.py
> +++ b/hgext/shelve.py
> @@ -380,10 +380,15 @@ def _nothingtoshelvemessaging(ui, repo,
>       else:
>           ui.status(_("nothing changed\n"))
>   
> -def _shelvecreatedcommit(repo, node, name):
> -    bases = list(mutableancestors(repo[node]))
> -    shelvedfile(repo, name, 'hg').writebundle(bases, node)
> -    cmdutil.export(repo, [node],
> +def _shelvecreatedcommit(ui, repo, node, name, tr):
> +    if isobsshelve(repo, ui):
> +        shelvedfile(repo, name, 'oshelve').writeobsshelveinfo({
> +            'node': nodemod.hex(node)
> +        })
> +    else:
> +        bases = list(mutableancestors(repo[node]))
> +        shelvedfile(repo, name, 'hg').writebundle(bases, node)
> +    cmdutil.export(repo.unfiltered(), [node],
>                      fp=shelvedfile(repo, name, patchextension).opener('wb'),
>                      opts=mdiff.diffopts(git=True))

I'm a latecomer to paying attention to this series, so please push back 
on me if this has already been discussed, but I think it would be 
"cleaner" to not mix old shelve and logic, and instead have just have 
the main function _shelvecreatedcommit() call out to 
_obsshelvecreatedcommit() or _abortshelvecreatedcommit() (or whatever we 
call the traditional version).

Again, feel free to push back if this has already been discussed or 
discarded as a direction, or if there are other reasons to not do it.

>   
> @@ -394,8 +399,13 @@ def _includeunknownfiles(repo, pats, opt
>           extra['shelve_unknown'] = '\0'.join(s.unknown)
>           repo[None].add(s.unknown)
>   
> -def _finishshelve(repo):
> -    _aborttransaction(repo)
> +def _finishshelve(ui, repo, tr, node):
> +    if isobsshelve(repo, ui):
> +        obsolete.createmarkers(repo, [(repo.unfiltered()[node], ())])
> +        tr.close()
> +        tr.release()
> +    else:
> +        _aborttransaction(repo)
>   
>   def _docreatecmd(ui, repo, pats, opts):
>       wctx = repo[None]
> @@ -417,9 +427,12 @@ def _docreatecmd(ui, repo, pats, opts):
>       try:
>           lock = repo.lock()
>   
> -        # use an uncommitted transaction to generate the bundle to avoid
> -        # pull races. ensure we don't print the abort message to stderr.
> -        tr = repo.transaction('commit', report=lambda x: None)
> +        # depending on whether shelve is traditional or
> +        # obsolescense-based, we either abort or commit this
> +        # transaction in the end. If we abort it, we don't
> +        # want to print anything to stderr
> +        report = None if isobsshelve(repo, ui) else (lambda x: None)
> +        tr = repo.transaction('commit', report=report)
>   
>           interactive = opts.get('interactive', False)
>           includeunknown = (opts.get('unknown', False) and
> @@ -447,16 +460,19 @@ def _docreatecmd(ui, repo, pats, opts):
>               _nothingtoshelvemessaging(ui, repo, pats, opts)
>               return 1
>   
> -        _shelvecreatedcommit(repo, node, name)
> +        _shelvecreatedcommit(ui, repo, node, name, tr)
>   
>           if ui.formatted():
>               desc = util.ellipsis(desc, ui.termwidth())
>           ui.status(_('shelved as %s\n') % name)
> -        hg.update(repo, parent.node())
> +        # current wc parent may be already obsolete becuase
> +        # it might have been created previously and shelve just
> +        # reuses it
> +        hg.update(repo.unfiltered(), parent.node())
>           if origbranch != repo['.'].branch() and not _isbareshelve(pats, opts):
>               repo.dirstate.setbranch(origbranch)
>   
> -        _finishshelve(repo)
> +        _finishshelve(ui, repo, tr, node)
>       finally:
>           _restoreactivebookmark(repo, activebookmark)
>           lockmod.release(tr, lock)
>
Kostia Balytskyi - March 30, 2017, 10:11 a.m.
On 30/03/2017 10:15, Ryan McElroy wrote:
>

>

> On 3/29/17 2:18 PM, Kostia Balytskyi wrote:

>> # HG changeset patch

>> # User Kostia Balytskyi <ikostia@fb.com>

>> # Date 1490790691 25200

>> #      Wed Mar 29 05:31:31 2017 -0700

>> # Node ID fc1144e5993a5c85060b913e2d92cd4b1b61772e

>> # Parent  0aa864184c9d78c11d18980cf0faa10828445ff5

>> shelve: add obs-based shelve functionality

>>

>> Obsolescense-based shelve works in a following way:

>

> s/ a/ the

sigh :/ Will fix.
>

>> 1. In order to shelve some changes, it creates a commit, records its

>> node into a .oshelve file and prunes created commit.

>> 2. In order to finish a shelve operation, transaction is just

>> closed and not aborted.

>

> s/transaction/the transaction

>

>>

>> diff --git a/hgext/shelve.py b/hgext/shelve.py

>> --- a/hgext/shelve.py

>> +++ b/hgext/shelve.py

>> @@ -380,10 +380,15 @@ def _nothingtoshelvemessaging(ui, repo,

>>       else:

>>           ui.status(_("nothing changed\n"))

>>   -def _shelvecreatedcommit(repo, node, name):

>> -    bases = list(mutableancestors(repo[node]))

>> -    shelvedfile(repo, name, 'hg').writebundle(bases, node)

>> -    cmdutil.export(repo, [node],

>> +def _shelvecreatedcommit(ui, repo, node, name, tr):

>> +    if isobsshelve(repo, ui):

>> +        shelvedfile(repo, name, 'oshelve').writeobsshelveinfo({

>> +            'node': nodemod.hex(node)

>> +        })

>> +    else:

>> +        bases = list(mutableancestors(repo[node]))

>> +        shelvedfile(repo, name, 'hg').writebundle(bases, node)

>> +    cmdutil.export(repo.unfiltered(), [node],

>>                      fp=shelvedfile(repo, name, 

>> patchextension).opener('wb'),

>>                      opts=mdiff.diffopts(git=True))

>

> I'm a latecomer to paying attention to this series, so please push 

> back on me if this has already been discussed, but I think it would be 

> "cleaner" to not mix old shelve and logic, and instead have just have 

> the main function _shelvecreatedcommit() call out to 

> _obsshelvecreatedcommit() or _abortshelvecreatedcommit() (or whatever 

> we call the traditional version).

>

> Again, feel free to push back if this has already been discussed or 

> discarded as a direction, or if there are other reasons to not do it.

I agree that this can be made better. Sean Farley (if I'm not mistaken) 
suggested that this should be a class. I do not mind refactrong it 
later, but I want to get it in first as a functionality. Also, 
currently, if I understand you correctly, you want to split an 11 line 
function into two. I don't think it's worth it at the moment.
>

>>   @@ -394,8 +399,13 @@ def _includeunknownfiles(repo, pats, opt

>>           extra['shelve_unknown'] = '\0'.join(s.unknown)

>>           repo[None].add(s.unknown)

>>   -def _finishshelve(repo):

>> -    _aborttransaction(repo)

>> +def _finishshelve(ui, repo, tr, node):

>> +    if isobsshelve(repo, ui):

>> +        obsolete.createmarkers(repo, [(repo.unfiltered()[node], ())])

>> +        tr.close()

>> +        tr.release()

>> +    else:

>> +        _aborttransaction(repo)

>>     def _docreatecmd(ui, repo, pats, opts):

>>       wctx = repo[None]

>> @@ -417,9 +427,12 @@ def _docreatecmd(ui, repo, pats, opts):

>>       try:

>>           lock = repo.lock()

>>   -        # use an uncommitted transaction to generate the bundle to 

>> avoid

>> -        # pull races. ensure we don't print the abort message to 

>> stderr.

>> -        tr = repo.transaction('commit', report=lambda x: None)

>> +        # depending on whether shelve is traditional or

>> +        # obsolescense-based, we either abort or commit this

>> +        # transaction in the end. If we abort it, we don't

>> +        # want to print anything to stderr

>> +        report = None if isobsshelve(repo, ui) else (lambda x: None)

>> +        tr = repo.transaction('commit', report=report)

>>             interactive = opts.get('interactive', False)

>>           includeunknown = (opts.get('unknown', False) and

>> @@ -447,16 +460,19 @@ def _docreatecmd(ui, repo, pats, opts):

>>               _nothingtoshelvemessaging(ui, repo, pats, opts)

>>               return 1

>>   -        _shelvecreatedcommit(repo, node, name)

>> +        _shelvecreatedcommit(ui, repo, node, name, tr)

>>             if ui.formatted():

>>               desc = util.ellipsis(desc, ui.termwidth())

>>           ui.status(_('shelved as %s\n') % name)

>> -        hg.update(repo, parent.node())

>> +        # current wc parent may be already obsolete becuase

>> +        # it might have been created previously and shelve just

>> +        # reuses it

>> +        hg.update(repo.unfiltered(), parent.node())

>>           if origbranch != repo['.'].branch() and not 

>> _isbareshelve(pats, opts):

>>               repo.dirstate.setbranch(origbranch)

>>   -        _finishshelve(repo)

>> +        _finishshelve(ui, repo, tr, node)

>>       finally:

>>           _restoreactivebookmark(repo, activebookmark)

>>           lockmod.release(tr, lock)

>>

>

> _______________________________________________

> Mercurial-devel mailing list

> Mercurial-devel@mercurial-scm.org

> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Jun Wu - March 30, 2017, 6:03 p.m.
As long as evolve does not have a way to unhide a commit. I think we do need
to use strip on repos that with obsstore enabled. So I'd say the patch
probably needs to be deferred until we can unhide a commit.

Excerpts from Kostia Balytskyi's message of 2017-03-30 10:11:55 +0000:
> 
> On 30/03/2017 10:15, Ryan McElroy wrote:
> >
> >
> > On 3/29/17 2:18 PM, Kostia Balytskyi wrote:
> >> # HG changeset patch
> >> # User Kostia Balytskyi <ikostia@fb.com>
> >> # Date 1490790691 25200
> >> #      Wed Mar 29 05:31:31 2017 -0700
> >> # Node ID fc1144e5993a5c85060b913e2d92cd4b1b61772e
> >> # Parent  0aa864184c9d78c11d18980cf0faa10828445ff5
> >> shelve: add obs-based shelve functionality
> >>
> >> Obsolescense-based shelve works in a following way:
> >
> > s/ a/ the
> sigh :/ Will fix.
> >
> >> 1. In order to shelve some changes, it creates a commit, records its
> >> node into a .oshelve file and prunes created commit.
> >> 2. In order to finish a shelve operation, transaction is just
> >> closed and not aborted.
> >
> > s/transaction/the transaction
> >
> >>
> >> diff --git a/hgext/shelve.py b/hgext/shelve.py
> >> --- a/hgext/shelve.py
> >> +++ b/hgext/shelve.py
> >> @@ -380,10 +380,15 @@ def _nothingtoshelvemessaging(ui, repo,
> >>       else:
> >>           ui.status(_("nothing changed\n"))
> >>   -def _shelvecreatedcommit(repo, node, name):
> >> -    bases = list(mutableancestors(repo[node]))
> >> -    shelvedfile(repo, name, 'hg').writebundle(bases, node)
> >> -    cmdutil.export(repo, [node],
> >> +def _shelvecreatedcommit(ui, repo, node, name, tr):
> >> +    if isobsshelve(repo, ui):
> >> +        shelvedfile(repo, name, 'oshelve').writeobsshelveinfo({
> >> +            'node': nodemod.hex(node)
> >> +        })
> >> +    else:
> >> +        bases = list(mutableancestors(repo[node]))
> >> +        shelvedfile(repo, name, 'hg').writebundle(bases, node)
> >> +    cmdutil.export(repo.unfiltered(), [node],
> >>                      fp=shelvedfile(repo, name, 
> >> patchextension).opener('wb'),
> >>                      opts=mdiff.diffopts(git=True))
> >
> > I'm a latecomer to paying attention to this series, so please push 
> > back on me if this has already been discussed, but I think it would be 
> > "cleaner" to not mix old shelve and logic, and instead have just have 
> > the main function _shelvecreatedcommit() call out to 
> > _obsshelvecreatedcommit() or _abortshelvecreatedcommit() (or whatever 
> > we call the traditional version).
> >
> > Again, feel free to push back if this has already been discussed or 
> > discarded as a direction, or if there are other reasons to not do it.
> I agree that this can be made better. Sean Farley (if I'm not mistaken) 
> suggested that this should be a class. I do not mind refactrong it 
> later, but I want to get it in first as a functionality. Also, 
> currently, if I understand you correctly, you want to split an 11 line 
> function into two. I don't think it's worth it at the moment.
> >
> >>   @@ -394,8 +399,13 @@ def _includeunknownfiles(repo, pats, opt
> >>           extra['shelve_unknown'] = '\0'.join(s.unknown)
> >>           repo[None].add(s.unknown)
> >>   -def _finishshelve(repo):
> >> -    _aborttransaction(repo)
> >> +def _finishshelve(ui, repo, tr, node):
> >> +    if isobsshelve(repo, ui):
> >> +        obsolete.createmarkers(repo, [(repo.unfiltered()[node], ())])
> >> +        tr.close()
> >> +        tr.release()
> >> +    else:
> >> +        _aborttransaction(repo)
> >>     def _docreatecmd(ui, repo, pats, opts):
> >>       wctx = repo[None]
> >> @@ -417,9 +427,12 @@ def _docreatecmd(ui, repo, pats, opts):
> >>       try:
> >>           lock = repo.lock()
> >>   -        # use an uncommitted transaction to generate the bundle to 
> >> avoid
> >> -        # pull races. ensure we don't print the abort message to 
> >> stderr.
> >> -        tr = repo.transaction('commit', report=lambda x: None)
> >> +        # depending on whether shelve is traditional or
> >> +        # obsolescense-based, we either abort or commit this
> >> +        # transaction in the end. If we abort it, we don't
> >> +        # want to print anything to stderr
> >> +        report = None if isobsshelve(repo, ui) else (lambda x: None)
> >> +        tr = repo.transaction('commit', report=report)
> >>             interactive = opts.get('interactive', False)
> >>           includeunknown = (opts.get('unknown', False) and
> >> @@ -447,16 +460,19 @@ def _docreatecmd(ui, repo, pats, opts):
> >>               _nothingtoshelvemessaging(ui, repo, pats, opts)
> >>               return 1
> >>   -        _shelvecreatedcommit(repo, node, name)
> >> +        _shelvecreatedcommit(ui, repo, node, name, tr)
> >>             if ui.formatted():
> >>               desc = util.ellipsis(desc, ui.termwidth())
> >>           ui.status(_('shelved as %s\n') % name)
> >> -        hg.update(repo, parent.node())
> >> +        # current wc parent may be already obsolete becuase
> >> +        # it might have been created previously and shelve just
> >> +        # reuses it
> >> +        hg.update(repo.unfiltered(), parent.node())
> >>           if origbranch != repo['.'].branch() and not 
> >> _isbareshelve(pats, opts):
> >>               repo.dirstate.setbranch(origbranch)
> >>   -        _finishshelve(repo)
> >> +        _finishshelve(ui, repo, tr, node)
> >>       finally:
> >>           _restoreactivebookmark(repo, activebookmark)
> >>           lockmod.release(tr, lock)
> >>
> >
> > _______________________________________________
> > Mercurial-devel mailing list
> > Mercurial-devel@mercurial-scm.org
> > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel 
>
Kostia Balytskyi - March 31, 2017, 1:54 p.m.
Thunderbird lets me down, so I will reply one more time from Outlook. I do not understand why we need to unhide a commit. Can you explain?

-----Original Message-----
From: Mercurial-devel [mailto:mercurial-devel-bounces@mercurial-scm.org] On Behalf Of Jun Wu

Sent: Thursday, 30 March, 2017 19:03
To: Kostia Balytskyi <kobalyts@outlook.com>
Cc: mercurial-devel@mercurial-scm.org
Subject: Re: [PATCH 3 of 7 shelve-ext v5] shelve: add obs-based shelve functionality

As long as evolve does not have a way to unhide a commit. I think we do need to use strip on repos that with obsstore enabled. So I'd say the patch probably needs to be deferred until we can unhide a commit.

Excerpts from Kostia Balytskyi's message of 2017-03-30 10:11:55 +0000:
> 

> On 30/03/2017 10:15, Ryan McElroy wrote:

> >

> >

> > On 3/29/17 2:18 PM, Kostia Balytskyi wrote:

> >> # HG changeset patch

> >> # User Kostia Balytskyi <ikostia@fb.com> # Date 1490790691 25200

> >> #      Wed Mar 29 05:31:31 2017 -0700

> >> # Node ID fc1144e5993a5c85060b913e2d92cd4b1b61772e

> >> # Parent  0aa864184c9d78c11d18980cf0faa10828445ff5

> >> shelve: add obs-based shelve functionality

> >>

> >> Obsolescense-based shelve works in a following way:

> >

> > s/ a/ the

> sigh :/ Will fix.

> >

> >> 1. In order to shelve some changes, it creates a commit, records 

> >> its node into a .oshelve file and prunes created commit.

> >> 2. In order to finish a shelve operation, transaction is just 

> >> closed and not aborted.

> >

> > s/transaction/the transaction

> >

> >>

> >> diff --git a/hgext/shelve.py b/hgext/shelve.py

> >> --- a/hgext/shelve.py

> >> +++ b/hgext/shelve.py

> >> @@ -380,10 +380,15 @@ def _nothingtoshelvemessaging(ui, repo,

> >>       else:

> >>           ui.status(_("nothing changed\n"))

> >>   -def _shelvecreatedcommit(repo, node, name):

> >> -    bases = list(mutableancestors(repo[node]))

> >> -    shelvedfile(repo, name, 'hg').writebundle(bases, node)

> >> -    cmdutil.export(repo, [node],

> >> +def _shelvecreatedcommit(ui, repo, node, name, tr):

> >> +    if isobsshelve(repo, ui):

> >> +        shelvedfile(repo, name, 'oshelve').writeobsshelveinfo({

> >> +            'node': nodemod.hex(node)

> >> +        })

> >> +    else:

> >> +        bases = list(mutableancestors(repo[node]))

> >> +        shelvedfile(repo, name, 'hg').writebundle(bases, node)

> >> +    cmdutil.export(repo.unfiltered(), [node],

> >>                      fp=shelvedfile(repo, name, 

> >> patchextension).opener('wb'),

> >>                      opts=mdiff.diffopts(git=True))

> >

> > I'm a latecomer to paying attention to this series, so please push 

> > back on me if this has already been discussed, but I think it would 

> > be "cleaner" to not mix old shelve and logic, and instead have just 

> > have the main function _shelvecreatedcommit() call out to

> > _obsshelvecreatedcommit() or _abortshelvecreatedcommit() (or 

> > whatever we call the traditional version).

> >

> > Again, feel free to push back if this has already been discussed or 

> > discarded as a direction, or if there are other reasons to not do it.

> I agree that this can be made better. Sean Farley (if I'm not 

> mistaken) suggested that this should be a class. I do not mind 

> refactrong it later, but I want to get it in first as a functionality. 

> Also, currently, if I understand you correctly, you want to split an 

> 11 line function into two. I don't think it's worth it at the moment.

> >

> >>   @@ -394,8 +399,13 @@ def _includeunknownfiles(repo, pats, opt

> >>           extra['shelve_unknown'] = '\0'.join(s.unknown)

> >>           repo[None].add(s.unknown)

> >>   -def _finishshelve(repo):

> >> -    _aborttransaction(repo)

> >> +def _finishshelve(ui, repo, tr, node):

> >> +    if isobsshelve(repo, ui):

> >> +        obsolete.createmarkers(repo, [(repo.unfiltered()[node], ())])

> >> +        tr.close()

> >> +        tr.release()

> >> +    else:

> >> +        _aborttransaction(repo)

> >>     def _docreatecmd(ui, repo, pats, opts):

> >>       wctx = repo[None]

> >> @@ -417,9 +427,12 @@ def _docreatecmd(ui, repo, pats, opts):

> >>       try:

> >>           lock = repo.lock()

> >>   -        # use an uncommitted transaction to generate the bundle to 

> >> avoid

> >> -        # pull races. ensure we don't print the abort message to 

> >> stderr.

> >> -        tr = repo.transaction('commit', report=lambda x: None)

> >> +        # depending on whether shelve is traditional or

> >> +        # obsolescense-based, we either abort or commit this

> >> +        # transaction in the end. If we abort it, we don't

> >> +        # want to print anything to stderr

> >> +        report = None if isobsshelve(repo, ui) else (lambda x: None)

> >> +        tr = repo.transaction('commit', report=report)

> >>             interactive = opts.get('interactive', False)

> >>           includeunknown = (opts.get('unknown', False) and @@ 

> >> -447,16 +460,19 @@ def _docreatecmd(ui, repo, pats, opts):

> >>               _nothingtoshelvemessaging(ui, repo, pats, opts)

> >>               return 1

> >>   -        _shelvecreatedcommit(repo, node, name)

> >> +        _shelvecreatedcommit(ui, repo, node, name, tr)

> >>             if ui.formatted():

> >>               desc = util.ellipsis(desc, ui.termwidth())

> >>           ui.status(_('shelved as %s\n') % name)

> >> -        hg.update(repo, parent.node())

> >> +        # current wc parent may be already obsolete becuase

> >> +        # it might have been created previously and shelve just

> >> +        # reuses it

> >> +        hg.update(repo.unfiltered(), parent.node())

> >>           if origbranch != repo['.'].branch() and not 

> >> _isbareshelve(pats, opts):

> >>               repo.dirstate.setbranch(origbranch)

> >>   -        _finishshelve(repo)

> >> +        _finishshelve(ui, repo, tr, node)

> >>       finally:

> >>           _restoreactivebookmark(repo, activebookmark)

> >>           lockmod.release(tr, lock)

> >>

> >

> > _______________________________________________

> > Mercurial-devel mailing list

> > Mercurial-devel@mercurial-scm.org

> > https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2

> > Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=DwIGaQ&c=5VD0RTtNlTh3y

> > cd41b3MUw&r=Pp-gQYFgs4tKlSFPF5kfCw&m=qAVx3CWvQmul5_yACH3VOILLHV82o-y

> > XY7HRz2iV5fE&s=Y_5Tnx37Hf8mrMgepf8a0dVgWgR4iU5-QAu-zxax_oo&e=

> 

_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Pp-gQYFgs4tKlSFPF5kfCw&m=qAVx3CWvQmul5_yACH3VOILLHV82o-yXY7HRz2iV5fE&s=Y_5Tnx37Hf8mrMgepf8a0dVgWgR4iU5-QAu-zxax_oo&e=

Patch

diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -380,10 +380,15 @@  def _nothingtoshelvemessaging(ui, repo, 
     else:
         ui.status(_("nothing changed\n"))
 
-def _shelvecreatedcommit(repo, node, name):
-    bases = list(mutableancestors(repo[node]))
-    shelvedfile(repo, name, 'hg').writebundle(bases, node)
-    cmdutil.export(repo, [node],
+def _shelvecreatedcommit(ui, repo, node, name, tr):
+    if isobsshelve(repo, ui):
+        shelvedfile(repo, name, 'oshelve').writeobsshelveinfo({
+            'node': nodemod.hex(node)
+        })
+    else:
+        bases = list(mutableancestors(repo[node]))
+        shelvedfile(repo, name, 'hg').writebundle(bases, node)
+    cmdutil.export(repo.unfiltered(), [node],
                    fp=shelvedfile(repo, name, patchextension).opener('wb'),
                    opts=mdiff.diffopts(git=True))
 
@@ -394,8 +399,13 @@  def _includeunknownfiles(repo, pats, opt
         extra['shelve_unknown'] = '\0'.join(s.unknown)
         repo[None].add(s.unknown)
 
-def _finishshelve(repo):
-    _aborttransaction(repo)
+def _finishshelve(ui, repo, tr, node):
+    if isobsshelve(repo, ui):
+        obsolete.createmarkers(repo, [(repo.unfiltered()[node], ())])
+        tr.close()
+        tr.release()
+    else:
+        _aborttransaction(repo)
 
 def _docreatecmd(ui, repo, pats, opts):
     wctx = repo[None]
@@ -417,9 +427,12 @@  def _docreatecmd(ui, repo, pats, opts):
     try:
         lock = repo.lock()
 
-        # use an uncommitted transaction to generate the bundle to avoid
-        # pull races. ensure we don't print the abort message to stderr.
-        tr = repo.transaction('commit', report=lambda x: None)
+        # depending on whether shelve is traditional or
+        # obsolescense-based, we either abort or commit this
+        # transaction in the end. If we abort it, we don't
+        # want to print anything to stderr
+        report = None if isobsshelve(repo, ui) else (lambda x: None)
+        tr = repo.transaction('commit', report=report)
 
         interactive = opts.get('interactive', False)
         includeunknown = (opts.get('unknown', False) and
@@ -447,16 +460,19 @@  def _docreatecmd(ui, repo, pats, opts):
             _nothingtoshelvemessaging(ui, repo, pats, opts)
             return 1
 
-        _shelvecreatedcommit(repo, node, name)
+        _shelvecreatedcommit(ui, repo, node, name, tr)
 
         if ui.formatted():
             desc = util.ellipsis(desc, ui.termwidth())
         ui.status(_('shelved as %s\n') % name)
-        hg.update(repo, parent.node())
+        # current wc parent may be already obsolete becuase
+        # it might have been created previously and shelve just
+        # reuses it
+        hg.update(repo.unfiltered(), parent.node())
         if origbranch != repo['.'].branch() and not _isbareshelve(pats, opts):
             repo.dirstate.setbranch(origbranch)
 
-        _finishshelve(repo)
+        _finishshelve(ui, repo, tr, node)
     finally:
         _restoreactivebookmark(repo, activebookmark)
         lockmod.release(tr, lock)