[PATCH 2 of 5] localrepo: invoke dirstate.unsureifambig in wwrite for safety

Martin von Zweigbergk martinvonz at google.com
Thu Jun 25 10:35:40 CDT 2015


On Thu, Jun 25, 2015 at 2:54 AM FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
wrote:

> At Mon, 22 Jun 2015 18:23:29 +0000,
> Martin von Zweigbergk wrote:
> >
> > On Mon, Jun 22, 2015 at 9:19 AM FUJIWARA Katsunori <
> foozy at lares.dti.ne.jp>
> > wrote:
>
> (snip)
>
> > > I summarized about "dirstate changes at failure" as a basis for
> > > discussion. Please comment !
> > >
> > > BTW, it is assumed that `dirstate.normallookup` is invoked at
> > > `repo.wwrite` or so, because, without these changes, problems like
> > > issue4583 ("changed files are treated as clean") appear occasionally,
> > > even if processing terminates successfully (e.g, at `hg revert`, `hg
> > > import` and so on):
> > >
> >
> > As I wrote before, I think the general problem is "that dirstate gets
> > updated but not written to disk before working copy files get written to
> > disk". I hope that is a correct assessment. I'm not convinced that
> calling
> > dirstate.normallookup() is the right solution (but I'm also not convinced
> > it's not). It seems like an alternative would be to not write working
> copy
> > files while the dirstate is dirty. Hopefully someone else can have an
> > opinion on this. It took me a long time to understand the issue even just
> > somewhat well, so I understand that it's a lot to ask, but I think we
> need
> > more than just two people thinking about this.
> >
> > I haven't yet read the remainder of the email.
>
> The timetable below shows steps in typical case:
>
>   ---- ----------------------------------- ----------------
>                                            timestamp of "f"
>                                            ----------------
>                                            dirstate    file
>   time          action                     mem  file   system
>   ---- ----------------------------------- ---- ----- -----
>   N                                              -1    ***
>        - change file "f"                                N
>
>        - execute `hg foobar`
>          - get wlock
>          - instanciate dirstate             -1   -1
>          - `dirstate.normal("f")`           N    -1
>            (e.g. via dirty check)
>
>          (*1)
>
>          - overwrite "f", but keep size                 N
>   N+1
>          - release wlock
>            - `dirstate.write()`             N    N
>
>        - `hg status` shows "f" as "clean"   N    N      N
>   ---- ----------------------------------- ---- ----- -----
>
> Your solution is "dirstate should be written out at (*1) above", isn't
> it ?
>

Yes, exactly. Thanks for the very detailed explanation. Before I comment on
the details below, let's make sure we agree on what would happen during the
write operation at (*1): Since the timestamp in the dirstate (N) is the
same as the current time, the dirstate timestamp, in memory and on file,
would be replaced by -1. Agree?

This is no different from running "hg status" right before "hg foobar"
(i.e. still within time N), right?


>
> Once I thought that it can resolve this kind of issue, too. But I
> noticed that it requires one of conditions below:
>
>   1. dirstate is never written out after (*1)
>
>      In other words, "none of entries in dirstate is updated after (*1)".
>
>      Updating ones for other files marks dirstate as "dirty" and
>      causes writing timestamp N of "f" again at subsequent
>      `dirstate.write`.
>
>   2. dirstate entry of "f" is certainly updated by `normallookup`
>
>      This drops timestamp N from in-memory dirstate changes, and
>      subsequent `dirstate.write` doesn't cause issue.
>
>
> In `merge.update` case, it works as expected:
>
>   - at failure, (1) should be satisfied, because dirstate is updated
>     only in `merge.recordupdates`
>
>   - otherwise, (2) should be satisfied, because all dirstate entries
>     of updated files are updated in `merge.recordsupdates`
>
>
> On the other hand, in `hg revert --rev REV` case, it doesn't work as
> expected, because:
>
>   - #2 and/or #4 break condition (1), and
>   - #3 breaks condition (2)
>
>     ================
>     commands.revert():
>       cmdutil.revert():
>         with repo.wlock() as wlock:
>           repo.status('to get current status') #1
>
>           dirstate.write("as (*1) in timetable above")
>
>           repo.wwrite('files to be reverted')
>           dirstate.remove('reverting to un-added') #2
>           dirstate.normal('reverting to un-changed) if not opts['rev'] #3
>           dirstate.add('reverting to un-removed ') #4
>     ================
>
> `hg import` using `patch.patch` also causes similar situation, because
> it updates dirstate entries only for files to be added or removed.
>
>
> Then, we should always apply `dirstate.normallookup` on files being
> changed (= removing `if not opts['rev']` at #3), for "`dirstate.write`
> before working copy files get written to disk".
>
> But this decreases performance of subsequent `hg status` or so,
> because dropping timestamp/size forces examination of file content.
>
>
> ----------------------------------------------------------------------
> [FUJIWARA Katsunori]                             foozy at lares.dti.ne.jp
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20150625/f9086993/attachment.html>


More information about the Mercurial-devel mailing list