Issue1771

Title update fails hard if subrepo rev is missing
Priority urgent Status chatting
Superseder Nosy List bos, marcusl, mg, mpm
Assigned To mpm Topics subrepositories

Created on 2009-07-28.22:26:17 by bos, last changed 2010-01-06.09:23:04 by marcusl.

Messages
msg10250 (view) Author: mpm Date: 2009-07-29.22:26:53
>>> I think that a minimal improvement would be a clearer error message,
indicating *what* failed and *why*. For instance, Mercurial should print the
name of the subrepo it was trying to update at the time.

Well it already reported 'why' to the best of its abilities. But I suppose
it could be clearer about which subrepo was affected.

>>> The other troubling part of this is that the problem really isn't
fixable without resorting to the debug* commands, so it requires some
wizardry to expunge it.

You should have been able to fix it in the repo of origin without any
special machinations as it should be unaware of any difficulty. Elsewhere,
unless we add an 'hg co --ignore-all-errors', I'm not sure what else we'd
do. Whatever we do, it's not going to be default update behavior for safety
reasons so it's going to be just as obscure as a debug command.

>>> One possibility would be to check the .hgsubstate and the subrepos for
consistency prior to a commit.  If .hgsubstate refers to a nonexistent rev
in a subrepo, it could barf.

But this didn't happen in the case described. What instead happened was that
subrepo listed in .hgsubs didn't correspond with what was present locally.
And that is in fact a perfectly valid and usual state of things (local
changes not present on server) at least up until push happens. And as a
disconnected system, we have no way of knowing whether we're out of sync
until we're asked to push or pull.

And when push happens, we push a subrepo to its default-push destination.
Otherwise we'd be unable to work with anything but canonical sources for
subrepositories. This is probably what actually bit you here. If the
subrepo's default path had been updated, pushing in the parent would have
pushed any outstanding changes to the subrepo.

Again, we can't do much about this if we allow manual editing of .hgsubs OR
subrepo/.hg/hgrc. Changing either independently can get us into this situation.
msg10249 (view) Author: bos Date: 2009-07-29.21:50:49
I think that a minimal improvement would be a clearer error message,
indicating *what* failed and *why*. For instance, Mercurial should print the
name of the subrepo it was trying to update at the time.

The other troubling part of this is that the problem really isn't fixable
without resorting to the debug* commands, so it requires some wizardry to
expunge it.

One possibility would be to check the .hgsubstate and the subrepos for
consistency prior to a commit.  If .hgsubstate refers to a nonexistent rev
in a subrepo, it could barf. I've also found that under some circumstances
(not yet solidly identified), .hgsubstate can end up with the null revision
in it, which such a check could also disallow.  This check should be free in
the common case, since most people won't be using subrepos.

I could add these checks to a pretxncommit hook on a server, but that only
solves the symptom of the inconsistency problem for me. Without adding the
checks and improved reporting to core Mercurial, other people would still
lack the tools to prevent, understand, or fix the issue.
msg10247 (view) Author: mpm Date: 2009-07-29.20:43:34
Correcting title.

>> It seems to be quite easy for a user to commit a change to a subrepo that
they then fail to push.

That doesn't match your description of how this happened and doesn't seem to
be true: Mercurial pushes subrepos before repos.

>> In this case, a developer updated the .hgsub file to point one subrepo at
a new URL, but he didn't know that he also needed to update the contained
subrepo to be a clone of that URL

Hadn't anticipated that. But it's not clear what should be done. Checking
out an incomplete state is a good way to later check in, build, or otherwise
silently perpetuate a highly broken state and Mercurial generally refuses to
do it whether subrepos are involved or not. We fail similarly for things
like case collisions and unwritable directories.

Also, it doesn't seem like we can detect this case on the commit side. The
committer may or may not have manually retargeted the subrepo properly and
we won't even know if the new target subrepo exists until we try to push. If
we have nothing to push in the subrepo, we won't even try that much.

We could prevent some errors by making a command to manipulate subrepos,
probably with subcommands like add and remove. But would we have a retarget
command? Or would we simply insist on doing remove (which removes the local
sub) followed by add (which repulls it)?
msg10238 (view) Author: bos Date: 2009-07-28.22:40:33
Actually, the problem is messier than I thought. Under some circumstances,
the missing rev in .hgsubstate makes it completely impossible to run "hg
update" or "hg update -C", so I have to manually whack things in this manner:

hg debugsetparents tip
hg debugrebuildstate
hg cat -rtip .hgsubstate > .hgsubstate
vi .hgsubstate
hg ci -m "Barf-o-rama" .hgsubstate

That's really nasty.
msg10237 (view) Author: bos Date: 2009-07-28.22:26:17
I've been repeatedly bitten by a kind of UI problem with the new subrepo
support.

It seems to be quite easy for a user to commit a change to a subrepo that
they then fail to push. This will result in a .hgsubstate file containing a
rev that nobody else has, which will cause "hg pull -u" to fail with a
mysterious and scary error message:

$ hg pull -u
pulling from ssh://hg.example.com/api
searching for changes
adding changesets
adding manifests
adding file changes
added 11 changesets with 27 changes to 19 files
pulling subrepo api
real URL is http://hg.example.org/frob
searching for changes
adding changesets
adding manifests
adding file changes
added 4 changesets with 5 changes to 4 files
abort: unknown revision '8bc7d7869066c9feda4dd8503a4b437e4bb82f7d'!

To a user who doesn't understand the implementation of subrepos, this error
message is confusing. There is no indication of why it occurs or what to do
about it, and people flounder until a local expert comes along to clean up.

In this case, a developer updated the .hgsub file to point one subrepo at a
new URL, but he didn't know that he also needed to update the contained
subrepo to be a clone of that URL, and that he needed to update the
.hgsubstate file to refer to a valid changeset in that repo. It's rather too
easy to make these mistakes :-(
History
Date User Action Args
2010-01-06 09:23:04marcuslsetnosy: + marcusl
2009-10-30 11:41:31tonfasettopic: + subrepositories
nosy: mpm, bos, mg
2009-07-29 22:26:53mpmsetnosy: mpm, bos, mg
messages: + msg10250
2009-07-29 21:50:49bossetnosy: mpm, bos, mg
messages: + msg10249
2009-07-29 20:43:34mpmsetnosy: mpm, bos, mg
messages: + msg10247
title: pull fails hard if subrepo rev is missing -> update fails hard if subrepo rev is missing
2009-07-29 09:07:30mgsetnosy: + mg
2009-07-28 22:40:33bossetstatus: unread -> chatting
messages: + msg10238
2009-07-28 22:26:17boscreate