[PATCH 1 of 9 V2] cmdutil: add the class to restore dirstate at unexpected failure easily
Yuya Nishihara
yuya at tcha.org
Sun May 3 05:16:39 CDT 2015
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.
More information about the Mercurial-devel
mailing list