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

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Tue May 5 12:19:51 CDT 2015


At Sun, 3 May 2015 19:16:39 +0900,
Yuya Nishihara wrote:
> 
> On Sun, 03 May 2015 00:59:36 +0900, FUJIWARA Katsunori wrote:
> > # HG changeset patch
> > # User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
> > # Date 1430582197 -32400
> > #      Sun May 03 00:56:37 2015 +0900
> > # Node ID fac0b879377d014c4081940040d092469635447a
> > # Parent  e9edd53770fb77a9787a3e6592a3bf0a29c1bd80
> > cmdutil: add the class to restore dirstate at unexpected failure easily
> > 
> > Before this patch, after "dirstate.write()" execution, there is no way
> > to restore dirstate to the original status before "dirstate.write()".
> > 
> > In some code paths, "dirstate.invalidate()" is used as a kind of
> > "restore .hg/dirstate to the original status". But it just avoids
> > writing changes in memory out, and doesn't actually restore
> > ".hg/dirstate" file. "dirstate.write()" prevents it from working as
> > expected.
> > 
> > To fix the issue that recent (in memory) dirstate isn't visible to
> > external process (e.g. "precommit" hooks), "dirstate.write()" should
> > be invoked before invocation of external process. But at the same
> > time, ".hg/dirstate" should be restored to the status before
> > "dirstate.write()" at unexpected failure in some cases.
> > 
> > This patch adds the class "dirstateguard" to easily restore
> > ".hg/dirstate" at unexpected failure. Typical usecase of it is:
> > 
> >     # (1) build dirstate up
> >     ....
> > 
> >     # (2) write dirstate out, and backup ".hg/dirstate"
> >     dsguard = dirstateguard(repo, 'scopename')
> >     try:
> >         # (3) execute somethig to do:
> >         #     this may imply making some additional changes on dirstate
> >         ....
> > 
> >         # (4) unlink backup-ed dirstate file at the end of dsguard scope
> >         dsguard.close()
> >     finally:
> >         # (5) if execution is aborted before "dsguard.close()",
> >         #     ".hg/dirstate" is restored from the backup
> >         dsguard.release()
> [...]
> > +    def _abort(self):
> > +        # this "invalidate()" prevents "wlock.release()" from writing
> > +        # changes of dirstate out after restoring to original status
> > +        self.repo.dirstate.invalidate()
> > +
> > +        self.repo.vfs.write('dirstate', self.repo.vfs.read(self.name))
> > +        self.repo.vfs.unlink(self.name)
> > +        self.active = False
> 
> Do you avoid atomic rename for some reason?
> Another process could read 'dirstate' in the middle of vfs.write() even if
> wlock was taken.
> 

I just forgot that normal "vfs.write()" doesn't use "atomictemp=True".

I'll write dirstate out via fp opened with "atomictemp=True()" in
revised series.

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


More information about the Mercurial-devel mailing list