[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