TortoiseHG, fork with subrepos - force commit&push .hgsubstate only - mercurial

There is public repo on mercurial (not mine). It contains two subrepos. I've made a fork for both main repo nad two subrepos. I want to create pull requests from time to time, but I can't make subrepos work properly.
When I clone my forked repo, it will be downloaded, but two subrepos will remain original, not my forked one. If I'll replace them with forked, I won't be able to make a pull request cos I don't want to switch original repo to my subrepos. But I want to change both repo and subrepo.
Once I've found a solution. I've modified hgrc file in .hg folder of subrepo.
It was:
[paths]
default = ssh://hg#bitbucket.org/originator/subrepo
It become:
[paths]
Me = ssh://hg#bitbucket.org/Me/subrepo
Original = ssh://hg#bitbucket.org/originator/subrepo
It was working exactly as it should. I've changed code, pushed to my subrepo, created pull request for subrepo. Then I've pushed changes in my main repo and it simply worked. .hgsubstate is now reffering to commit that exist on forked repo, but not on original one. When orignator will megre both pull requests, everything would work.
Is I said, it worked before, but not now. For some weird reason I can't just push .hgsubstate that point to new subrepo revision that exists on forked subrepo. I simply can't include it in commit. I click "commit", but in result commit it's not included. And I don't know how to force is being included - HG too "smart" about it. Also TortoiseHG marks my subrepo as dirty. But if I'll try to add both .hgsubstate and my dirty repo, it for some reason tries to push changes to originator's repo. It seems like my HG just can't commit .hgsubstate without pushing changes to subrepo on itself.
Any way to solve this? Everything I want is to commit and push .hgsubstate without doing anything else.

Did you adjust your .hgsub accordingly so that it works for both, your local paths as well as the remote paths to which you push to the server?
It's advisable to add to your .hgsub sections which describe the paths in an absolute sense. I used to struggle with that when I had the subrepos as the same level in the dir structure on the server but wanted them as sub-dirs on my own computer. It helped me to add to .hgsub a subpaths section:
[subpaths]
ssh://user#host.org/path/subrepo1 = ssh://user#host.org/subrepo1
ssh://user#host.org/path/subrepo2 = ssh://user#host.org/subrepo2
/home/user/project/subrepo1 = /home/user/subrepo1
/home/user/project/subrepo2 = /home/user/subrepo2
project/subrepo1 = subrepo1
project/subrepo2 = subrepo2

Related

Mercurial - Pull changes after Clone

Say I cloned a remote repository and called it "A"
Then I cloned another remote repository and called it "B"
"B" has the .hg folder and src folder , and "A" only has the .hg folder.
If I pull changes from "B" to "A", should now "A" also contain the src folder? Because that's exactly what I did and it did not
You mix the concepts of 'repository' with the working directory, the actually checked-out changeset, which indicates the state of the repository at a particular revision.
If the two repositories A and B are pulled into one repository, all changesets are present there, but they are present in different changesets. If you want to bring them together, you have to merge two changesets; most likely you want to merge the two heads you have, the one from repository A and the one from repository B. For example:
# check heads:
hg heads --template="{rev}:{node|short} {desc}\n"
2332:d69c8aaf6db6 Doc: Changelog as it should have been
2128:6f38df710194 Added tag 0.2.5 for changeset 6d89bb9ad3f6
Update to one head and then merge the other. Make sure to use the actual revisions:
hg up -r2332
hg merge -r2128
Whether or not that works without any conflicts depends on how A and B look like.
Does src contain any files? You cannot add an empty directory to a mercurial repo. If you tried hg add src and src was empty, you won't get an error but nothing happens. If that's really what you want, there are ways, but it sounds like you're just experimenting.
More specifically: You can only add files, and the directories that contain them are added implicitly. After you create a file in src, add the file to the repo and commit the change (along with anything else you may want to bring along). Now you have a changeset you can push or pull to repository "B".
Once the changeset has become part of "B"'s history (check with hg log), you need to update to it (hg update); or, if you've ended up with a branch, merge it to your current branch.

"Side-Pull" a mercurial repo into main project

I have a repo in my VCS called CodingStandards. In it is a checkstyle.xml file along with findbugs.xml and it will no doubt grow in the future.
What I want to do is in my project FunkyApp is pull CodingStandards into the project and maintain the link to CodingStandards so that if I change it, I can pull & update in my FunkyApp.
Subrepositories are what you are looking for.
However they forces you to have these files in a subdirectory of your project. There's no way to add juste one file to a repository from another.
First of all setup the CodingStandards repo in .hg/hgrc to make life easier
[paths]
default = https://url/FunkyApp
standards = https://url/CodingStandards
Then you can force pull into your repository
hg pull -f standards
This will create two heads in your repo that need to be merged with hg merge and then committed into your main repo.
To be clear CodingStandards will be unchanged. FunkyApp will have all the files from CodingStandards imported in it. Anyone else who clones FunkyApp will get the files without knowing about CodingStandards.

Mercurial workflow with subrepositories and offline clones?

I'm offline a lot.
So normally, I use one local clone as a "hub" for features, bugs, etc.
hg clone local-hub bug-123
Works offline. Cool.
Can I use a similar workflow if that project contains remote subrepositories?
Because, if .hgsub says
sub/shared = http://server/hg/shared
hg clone says
abort: error: getaddrinfo failed
Note that once the clone is created (while connected), push and pull will use the path in the subrepo's hgrc (instead of the location in .hgsub). So I can point this to a local clone and everything is cool.
But clone looks at .hgsub (as it's supposed to). So if the "blessed" subrepo is on a server, I can't create new clones offline, even though the files I need are right there.
This is a problem, right?
Ideally whomever set up the project uses relative URLs in their .hgsub file like this:
sub/shared = ../shared
and then, of course, actually makes shared a sibling of the main repo. Then as long as you have cloned down the main repo and the subs (as siblings) then everything will work out.
If they've used absolute URLs in their .hgsub file you can work around it using the subpaths section in your .hgrc like this:
[subpaths]
http://server/hg/shared = ../shared
which provides a translation layer in your client.
The canonical way to use subrepositories is to have X = X paths in the .hgsub file:
sub/shared = sub/shared
That way a clone will structurally look just like the original -- and so you can use the clone to make further (local!) clones.
However, this is not always possible, for example, Bitbucket wont let you create the nested repositories on their server. In that case, the ../X style paths in the .hgsub file is better, and you can use the subpaths configuration section to translate these paths into paths you can use locally.

Mercurial subrepo and relative path

I have a project, which I have a bitbucket repository for, and it is dependent on another project that I incorporate as a subrepo. Now, I don't have push access to the subrepository, nor do I want or need to--it's a pull-only relationship.
I realize that when you push the main repository, it will try to push the subrepositories, as well. Since I cannot do that, I pulled a local copy of the dependent project, at the same level as the main repository's directory. In essence, I have the following layout:
Main/ ; pushes to https://mine.org/Main
.hg/
.hgsub
Lib/
SubRepo/ ; clone of Main/../SubRepo/
.hg/
SubRepo/ ; local copy of https://forbidden.org/SubRepo
.hg/
The content of .hgsub is something like,
Lib/SubRepo = ../SubRepo
Then I cloned,
~/path/to/Main $ hg clone ../SubRepo/ Lib/SubRepo
So far, so good. The problem is, after I set this all up and committed the changes, when I try to push Main Mercurial will try to push SubRepo to https://mine.org/SubRepo, which does not exist, thereby failing the whole push operation.
Is there something I'm missing?
Why not just create a https://mine.org/SubRepo -- if you don't want to advertise it you can always turn on hide for it in the [web] section in its .hg/hgrc file. This is the pattern I'm used to, where you clone down the main repo and all the subrepos in the same layout at each place you'll use them: both your development box and your web-facing hgweb install.
Alternately, you could use a [subpaths] section in Main/.hg/hgrc with something like this in it:
[subpaths]
https://mine.org/SubRepo = https://forbidden.org/SubRepo
which should let you intercept the derrived target for the push and point it at a place that which it won't let you push, will let you see nothing has changed so push can continue.
It seems like what Mercurial is doing is legitimate: using the paths listed in your .hgsub it's attempting to push to a directory called 'SubRepo' that exists one level up from Main. This is obviously not what you want, so you'll probably have to work some magic here. I can think of two options:
If you can support this, place the local copy of forbidden.org's repository at C:/Forbidden/Subrepo or something like that, and use this absolute path in your .hgsub. Mercurial will be able to push to this and it should work.
There's no problem including the actual forbidden.org url as your subrepo address if you don't make any modifications to this repo. If there are no changes to the subrepo, your push should succeed. Of course, this is a fairly manual option and on a larger team it would be impossible to enforce. If you did accidentally commit some modification to the subrepo, you'd have to go through and use histedit or MQueues to pull it out, and that can be tricky with subrepos.

Mercurial nested subrepos (subrepos in subrepos) not recursively commiting?

I've got a Mercurial repo set up like this, with a subrepo inside another subrepo:
Root
.hg
.hgsub
.hgsubstate
Nested
.hg
.hgsub
.hgsubstate
foo.txt
FurtherNested
.hg
bar.txt
If I change foo.txt and bar.txt and commit from inside Root then all is well and all the nested subrepos commit. However if I only change bar.txt and commit from Root then Hg thinks nothing is changed. I have to commit from inside Nested to get the FurtherNested changes to commit when there are only changes in FurtherNested. It seems that in order for nested subrepos to work, each nested level has to contain changes in order for the recursion to work.
Nothing I read in the Mercurial docs on subrepos seemed to imply that subrepo commits would only propagate if there were changes. In fact it says the opposite:
When we commit, Mercurial will attempt
to recursively commit in all defined
subrepos...
So my question is, is this to be expected or is something broken or just not done yet (Mercurial 1.5.4 on Windows)?
Looks to me like this is just something that's broken. The relevant source code (in subrepo.py) doesn't seem to recurse into subsubrepos, viz:
def dirty(self):
r = self._state[1]
if r == '':
return True
w = self._repo[None]
if w.p1() != self._repo[r]: # version checked out change
return True
return w.dirty() # working directory changed
Probably wouldn't be too hard to fix, though I don't know the code intimately enough yet. It would probably be worthwhile posting on the Mercurial mailing list and/or filing a bug. I doubt Matt and Benoit are reading this, but they definitely do read everything posted there.