[PATCH 1 of 9 V3] cmdutil: add the class to restore dirstate at unexpected failure easily

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Tue May 12 07:54:23 CDT 2015


At Mon, 11 May 2015 17:49:43 -0700,
Pierre-Yves David wrote:
> 
> On 05/11/2015 08:49 AM, FUJIWARA Katsunori wrote:
> >
> > At Fri, 08 May 2015 19:00:02 -0700,
> > Pierre-Yves David wrote:
> >>
> >> On 05/06/2015 08:15 PM, FUJIWARA Katsunori wrote:
> >>> # HG changeset patch
> >>> # User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
> >>> # Date 1430968030 -32400
> >>> #      Thu May 07 12:07:10 2015 +0900
> >>> # Node ID 449a46109f0c96bb8d82d4edf2c8855341558c2f
> >>> # Parent  8174d27576a3fff28fb6f952a4c89d5c0b900214
> >>> cmdutil: add the class to restore dirstate at unexpected failure easily

[snip]

> >>> For this kind of issue, "extending transaction" approach (in
> >>> https://titanpad.com/mercurial32-sprint) seems not to be suitable,
> >>> because:
> >>>
> >>>     - transaction nesting occurs in some cases (e.g. "shelve => rebase"), and
> >>>
> >>>     - "dirstate" may be already modified since the beginning of OUTER
> >>>       transaction scope, then
> >>>
> >>>     - dirstate should be backed up into the file other than
> >>>       "dirstate.journal" at the beginning of INNER transaction scope, but
> >>>
> >>>     - such alternative backup files are useless for transaction itself,
> >>>       and increases complication of its implementation
> >>
> >> Some part about the transaction confuses me.
> >>
> >>    - Yes, you are right, the dirstate changes may have a wider life spawn
> >> than the transaction.
> >>
> >>    - Therefor doing backup there is not suitable (and is maybe never
> >> useful) (your are still right there)
> >>
> >>    - However, for any changes started inside a transaction, we should
> >> never write data in .hg/dirstate until the transaction is actually
> >> committed (because it likely refers to unwritten data in the
> >> transaction). This means that hooks/editors/etc would need to access a
> >> .hg/distate.pending in that case.
> >>
> >>    - The transaction API allow for both "wait until transaction is closed
> >> to flush that file" logic and "please write pending data for hooks"
> >> logic. It looks like the dirstate handling should collaborate with the
> >> transaction if one exist when dirstate manipulation are done. I'm not
> >> sure how much it happen.
> >
> > Committing via "repo.commit()" may cause invoking editor process out
> > of transaction scope, but flushing dirstate is still needed: for
> > example, "hg commit -A" changes status of each unknown files before
> > "repo.commit()".
> >
> > `.pending` mechanism of transaction itself can't be used directly in
> > such cases.
> >
> > But on the other hand, editor process may be invoked in transaction
> > scope, and (maybe) pending changelog and so on should become visible
> > for external process: for example, "hg import -e" with multiple
> > patches should cause such situation (BTW, rebasing multiple revisions
> > creates a transaction for each revisions to be rebased).
> >
> > So, I'll try to follow the style of `.pending` mechanism of
> > transaction for dirstate.
> 
> The way transaction works for that (roughly) is:
> 
> - write all files with a '.pending' suffix,
> - set an environment variable HG_PENDING=<repo-root>
> - Mercurial process during hooks detect the HG_PENDING vars and read the 
> .pending file if they exists.
> 
> As you point out, there is case where the dirstate writing is not done 
> during a transaction (eg: update). And in this case, we should -not- 
> collaborate with the transaction and we should -not- use 
> dirstate.pending file.
> 
> However, if we are in the middle of a transaction, the new dirstate will 
> likely point to content of the transaction and we should rely on the 
> transaction to generate a '.pending' file when needed (also meaning, we 
> should teach dirstate to read them) and to flush data to disk when the 
> the transaction is committed (see the file generator API, taking care of 
> both).
> 
> (you can use `localrepo.currenttransaction()` to check if a transaction 
> is open and if we jump onboard).
> 
> All that said, current dirstate implementation is not collaborating with 
> transaction either. So your changes are an improvement. I'll take your 
> series as is (with a couple of typo, and name fixed) and will hope for 
> more follow up on this topic.

Thank you for pushing to clowncopter with in-flight fixing.

After working with '.pending' mechanism, I realize that writing
dirstate out should be done in "cmdutil.commitforceeditor()" instead
of in "repo.commit()" for '.pending' awareness.

Could you drop only #9 of this series from clowncopter ?

I'll soon post follow up series, which also takes care of ".pending"
mechanism (regardless of dropping #9).


> >> This re-entrance business transition perfectly to my last question: It
> >> seems like this superseed the beginparentchange/endparentchange system
> >> previously in place. However, there is still multiple call to this
> >> system. Could we, in theory replace them will with the new system? If
> >> not, why?
> >
> > begin/end-parentchange system seems handy for small (a few lines)
> > scope changes, because it doesn't need writing current dirstate out
> > and backing it up.
> >
> > For example, current "heavy" dirstateguard doesn't seem suitable for
> > "committablectx.markcommitted()".
> >
> >      def markcommitted(self, node):
> >          self._repo.dirstate.beginparentchange()
> >          for f in self.modified() + self.added():
> >              self._repo.dirstate.normal(f)
> >          for f in self.removed():
> >              self._repo.dirstate.drop(f)
> >          self._repo.dirstate.setparents(node)
> >          self._repo.dirstate.endparentchange()
> >
> > For such lightweight use, we may have to add the flag to
> > enable/disable "writing current dirstate out and backing it up" to
> > dirstateguard: when backup is disabled, "dirstate.write()" may have to
> > be blocked for safety.
> >
> > On the other hand, begin/end-parentchange system doesn't seem suitable
> > for non-small scope or complicated changes, because it is difficult to
> > ensure that "dirstate.write()" isn't implied in such case (like ones
> > in mq, commands.import and cmdutil.tryimportone replaced by this
> > series).
> >
> > begin/end-parentchange in this condition should be replaced by
> > dirstateguard or so, as soon as possible.
> 
> I think we should have a single mechanism of people will use it wrong. 
> We should also makes it mandatory (or at least issue devel-warning) to 
> get people to use it.
> 
> Can we flag the old system for deletion and hunt down all it's current user?

I'll try.

> >> Also, this old system was living on the dirstate object directly. would
> >> it make sense to move the guardian business there?
> >
> > IMHO, yes, even though some more preparations may be needed to
> > complete moving.
> 
> Could be done in a follow up.

----------------------------------------------------------------------
[FUJIWARA Katsunori]                             foozy at lares.dti.ne.jp


More information about the Mercurial-devel mailing list