views:

726

answers:

1

I'm trying to set up my Mercurial repository system to work with multiple subrepos. I've basically followed these instructions to set up the client repo with Mercurial client v1.5 and I'm using HgWebDir to host my multiple projects.

I have an HgWebDir with the following structure:

http://myserver/hg
|-- fooproj
|-- mylib

where mylib is some collection of common template library to be consumed by fooproj. The structure of fooproj looks like this:

 fooproj
 |-- doc/
 |   `-- readme
 |-- src/
 |   `-- main.cpp
 |-- .hgignore
 |-- .hgsub
 `-- .hgsubstate

And .hgsub looks like:

src/mylib = http://myserver/hg/mylib

This should work, per my interpretation of the documentation:

The first 'nested' is the path in our working dir, and the second is a URL or path to pull from.

Also, the mylib project directory structure looks like this:

mylib
|-- .hg
|   |-- 00changelog.i
|   |-- dirstate
|   |-- requires
|   |-- store
|   |   |-- 00changelog.i
|   |   |-- 00manifest.i
|   |   |   |-- data
|   |   |   |   ` magic.h.i
|   |   |-- fncache
|   |   `-- undo
|   |-- undo.branch
|   `-- undo.dirstate
`-- magic.h

So, let's say I pull down fooproj to my home folder with:

~$ hg clone http://myserver/hg/fooproj foo

Which pulls down the directory structure properly and adds the folder ~/foo/src/mylib which is a local Mercurial repository. This is where the problems begin: the mylib folder is empty aside from the items in .hg. The messages from Mercurial are:

requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 5 changes to 5 files
updating working directory
5 files updated, 0 files merged, 0 files removed, 0 files unresolved

With 2 seconds of investigation, one can see the src/mylib/.hg/hgrc is:

[paths]
default = http://myserver/hg/fooproj/src/mylib

which is completely wrong (attempting a pull of that repo will give a 404 because, well, that URL doesn't make any sense).

foo
|-- .hg
|   |-- 00changelog.i
|   |-- branch
|   |-- branchheads.cache
|   |-- dirstate
|   |-- hgrc
|   |-- requires
|   |-- store
|   |   |-- 00changelog.i
|   |   |-- 00manifest.i
|   |   |-- data
|   |   |   |-- .hgignore.i
|   |   |   |-- .hgsub.i
|   |   |   |-- .hgsubstate.i
|   |   |   |-- doc
|   |   |   |   `-- readme.i
|   |   |   `-- src
|   |   |       `-- main.cpp.i
|   |   |-- fncache
|   |   `-- undo
|   |-- tags.cache
|   |-- undo.branch
|   `-- undo.dirstate
|-- .hgignore
|-- .hgsub
|-- .hgsubstate
|-- doc
|   `-- readme
`-- src
    |-- main.cpp
    `-- mylib
        `-- .hg
            |-- 00changelog.i
            |-- branch
            |-- dirstate
            |-- hgrc
            |-- requires
            `-- store

Logically, the default value should be what I specified in .hgsub or it would get the files from the repository in some way. Of course, changing src/mylib/.hg/hgrc to:

[paths]
default = http://myserver/hg/mylib

and running hg pull && hg update works perfectly. Of course, this is basically the same thing as not using subrepos in the first place.

None of the Mercurial commands return error codes (aside from a pull from within src/mylib), so it clearly believes that it is behaving properly (and just might be), although this does not seem logical at all.

What am I doing wrong?

The ultimate problem might be that .hgsubstate will always look like:

0000000000000000000000000000000000000000 src/mylib

But I have no idea how to fix that...

+1  A: 

The left-hand-side path in your .hgsub file is relative to its location in your tree. It's already down in src, so src doesn't need to be in the path. I think if you make the .hgsub file look like:

mylib = http://myserver/hg/mylib

and leave it where it is you'll get what you want. Alternately, you could move the location of .hgsub up a directory (outside of src, in your root) and then it would be correct as it is now.

I've just confirmed this interpretation with a setup like this:

.
|-- .hg
|   |-- 00changelog.i
|   |-- branch
|   |-- branchheads.cache
|   |-- dirstate
|   |-- last-message.txt
|   |-- requires
|   |-- store
|   |   |-- 00changelog.i
|   |   |-- 00manifest.i
|   |   |-- data
|   |   |   |-- .hgsub.i
|   |   |   `-- .hgsubstate.i
|   |   |-- fncache
|   |   `-- undo
|   |-- undo.branch
|   `-- undo.dirstate
|-- .hgsub
|-- .hgsubstate
`-- src
    `-- mylib
        |-- .hg
        |   |-- 00changelog.i
        |   |-- branch
        |   |-- branchheads.cache
        |   |-- dirstate
        |   |-- hgrc
        |   |-- last-message.txt
        |   |-- requires
        |   |-- store
        |   |   |-- 00changelog.i
        |   |   |-- 00manifest.i
        |   |   |-- data
        |   |   |   |-- .hgignore.i
        |   |   |   |-- _p_k_g-_i_n_f_o.i
        |   |   |   |-- _r_e_a_d_m_e.i
        |   |   |   |-- hgext
        |   |   |   |   `-- chart.py.i
        |   |   |   `-- setup.py.i
        |   |   |-- fncache
        |   |   `-- undo
        |   |-- tags.cache
        |   |-- undo.branch
        |   `-- undo.dirstate
        |-- .hgignore
        |-- PKG-INFO
        |-- README
        |-- hgext
        |   `-- chart.py
        `-- setup.py

Where that top level .hgsub file contains:

$ cat .hgsub
src/mylib = https://[email protected]/Ry4an/hg-chart-extension/

and a cone done of the parent shows it cloning the child too:

$ hg clone parent parent-clone
updating to branch default
pulling subrepo src/mylib
requesting all changes
adding changesets
adding manifests
adding file changes
added 8 changesets with 14 changes to 5 files
Ry4an
My `.hgsub` is in the top level directory as well (I guess that wasn't clear)...the problem is that when I clone...it just doesn't pull the subrepo properly. It works fine if it is in the top-level directory (`mylib = http://myserver/hg/mylib`), but I need to have it check out to `src/mylib`.
Travis Gockel
You're right I just misread your tree output. Can you try running my script from my answer to this question: http://stackoverflow.com/questions/2570289/making-mercurial-subrepositories-behave-like-subversion-externalsI initially set them up as sibling repositories and then link the one as the parent to the other. When doing that commit the hgsubstate gets updated.Subsequently, I can clone the parent and get the kid as a subrepo w/o additional clones.
Ry4an
Call me stupid, but I don't see a script in your answer. But I did find that if I alter the `.hgsubstate` file manually it works perfectly fine - other users will automatically pull the subrepos when they pull and update. It's great, I'm just editing it manually. *Almost there*
Travis Gockel
Ah, it was all thelines starting with a plus, which is the output of sh -x. The .hgsubstate is supposed to get updated whenever you commmit in the parent repo or update in the child repo. It gets its initial value (tip of the subrepo) when the initial clone of lib happens in my example.
Ry4an
Wow, I just had to clone the subrepo manually to get it off of the `00000000000000000000000000000000000000` substate. I didn't realize that was a step.
Travis Gockel