[PATCH 2 of 6 V2] localrepo: restore dirstate to one before rollbacking if not parent-gone

Pierre-Yves David pierre-yves.david at ens-lyon.org
Tue Oct 13 14:28:56 CDT 2015



On 10/13/2015 10:54 AM, FUJIWARA Katsunori wrote:
> # HG changeset patch
> # User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
> # Date 1444758556 -32400
> #      Wed Oct 14 02:49:16 2015 +0900
> # Node ID 04f94f9be97fcff64587440aa1e1ec3afb4f7639
> # Parent  b441136da58f3542910d71e9ad3353340ce8fb90
> localrepo: restore dirstate to one before rollbacking if not parent-gone
>
> 'localrepository.rollback()' explicilty restores dirstate, only if at
> least one of current parents of the working directory is removed at
> rollbacking (a.k.a "parent-gone").
>
> After DirstateTransactionPlan, 'dirstate.write()' will cause marking
> '.hg/dirstate' as a file to be restored at rollbacking.
>
>      https://mercurial.selenic.com/wiki/DirstateTransactionPlan
>
> Then, 'transaction.rollback()' restores '.hg/dirstate' regardless of
> parents of the working directory at that time, and this causes
> unexpected dirstate changes if not "parent-gone" (e.g.  "hg update" to
> another branch after "hg commit" or so, then "hg rollback").
>
> To avoid such situation, this patch restores dirstate to one before
> rollbacking if not "parent-gone".
>
>    before:
>      b1. restore dirstate explicitly, if "parent-gone"
>
>    after:
>      a1. save dirstate before actual rollbacking via dirstateguard
>      a2. restore dirstate via 'transaction.rollback()'
>      a3. if "parent-gone"
>          - discard backup (a1)
>          - restore dirstate from 'undo.dirstate'
>      a4. otherwise, restore dirstate from backup (a1)
>
> Even though restoring dirstate at (a3) after (a2) seems redundant,
> this patch keeps this existing code path, because:
>
>    - it isn't ensured that 'dirstate.write()' was invoked at least once
>      while transaction running
>
>      If not, '.hg/dirstate' isn't restored at (a2).
>
>      In addition to it, rude 3rd party extension invoking
>      'dirstate.write()' without 'repo' while transaction running (see
>      subsequent patches for detail) may break consistency of a file
>      backup-ed by transaction.
>
>    - this patch mainly focuses on changes for DirstateTransactionPlan
>
>      Restoring dirstate at (a3) itself should be cheaper enough than
>      rollbacking itself. Redundancy will be removed in next step.
>
> Newly added test is almost meaningless at this point. It will be used
> to detect regression while implementing delayed dirstate write out.
>
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -1084,20 +1084,24 @@
>               lock.release()
>
>       def rollback(self, dryrun=False, force=False):
> -        wlock = lock = None
> +        wlock = lock = dsguard = None
>           try:
>               wlock = self.wlock()
>               lock = self.lock()
>               if self.svfs.exists("undo"):
> -                return self._rollback(dryrun, force)
> +                # delay importing avoids cyclic dependency
> +                from cmdutil import dirstateguard

I'm not sure why you need this. I've dropped it and everything seems fine.

-- 
Pierre-Yves David


More information about the Mercurial-devel mailing list