diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -741,7 +741,15 @@ def applyupdates(repo, actions, wctx, mc numupdates = sum(len(l) for m, l in actions.items() if m != 'k') + def dirtysubstate(): + # mark '.hgsubstate' as possibly dirty forcibly, because + # modified '.hgsubstate' is misunderstood as clean, + # when both st_size/st_mtime of '.hgsubstate' aren't changed, + # even if "submerge" fails and '.hgsubstate' is inconsistent + repo.dirstate.normallookup('.hgsubstate') + if [a for a in actions['r'] if a[0] == '.hgsubstate']: + dirtysubstate() subrepo.submerge(repo, wctx, mctx, wctx, overwrite) # remove in parallel (must come first) @@ -760,6 +768,7 @@ def applyupdates(repo, actions, wctx, mc updated = len(actions['g']) if [a for a in actions['g'] if a[0] == '.hgsubstate']: + dirtysubstate() subrepo.submerge(repo, wctx, mctx, wctx, overwrite) # forget (manifest only, just log it) (must come first) @@ -785,6 +794,7 @@ def applyupdates(repo, actions, wctx, mc z += 1 progress(_updating, z, item=f, total=numupdates, unit=_files) if f == '.hgsubstate': # subrepo states need updating + dirtysubstate() subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite) continue diff --git a/tests/test-subrepo.t b/tests/test-subrepo.t --- a/tests/test-subrepo.t +++ b/tests/test-subrepo.t @@ -758,6 +758,8 @@ test if untracked file is not overwritte $ echo issue3276_ok > repo/s/b $ hg -R repo2 push -f -q + $ touch -t 200001010000 repo/.hgsubstate + $ hg -R repo status --config debug.dirstate.delaywrite=2 repo/.hgsubstate $ hg -R repo update b: untracked file differs abort: untracked files in working directory differ from files in requested revision (in subrepo s) @@ -766,6 +768,7 @@ test if untracked file is not overwritte $ cat repo/s/b issue3276_ok $ rm repo/s/b + $ touch -t 200001010000 repo/.hgsubstate $ hg -R repo revert --all reverting repo/.hgsubstate (glob) reverting subrepo s