How to push Mercurial subrepositories to their own origin - mercurial

I am using subrepositories to share code between multiple projects.
I keep the "master" version of these shared repositories in a central location.
That way I can easily push changes I made to them in one project and pull them in another.
That works, but ideally I want to just push the project repository and all subrepositories should be pushed to their origin. But Mercurial always pushes all subrepositories into the origin of the main repository.
This is my setup:
Project1 (default path = Project-Central-Location/Project1)
- lib-A (default path = Library-Central-Location/lib-A)
- lib-B (default path = Library-Central-Location/lib-B)
Project2 (default path = Project-Central-Location/Project2)
- lib-A (default path = Library-Central-Location/lib-A)
Library-Central-Location
- lib-A <= push of Project1 should push lib-A to this location
- lib-B
Project-Central-Location
- Project1
- lib-A <= push of Project1 pushes lib-A to this location instead
- lib-B
- Project 2
- lib-A

I ended up using hooks. First, the libraries inside the projects in the central location need to point to the corresponding central library repository:
Project-Central-Location
- Project1
- lib-A <= (default path = Library-Central-Location/lib-A)
- lib-B <= (default path = Library-Central-Location/lib-B)
- Project 2
- lib-A <= (default path = Library-Central-Location/lib-A)
Then you need to add this to their .hg/hgrc files:
[hooks]
changegroup.hg-push = hg push
That way I will trigger a push to the central libraries anytime I push the projects.

Related

Mercurial - repos with multiple ACL rules

I'm trying to use 2 set of rules for the ACL of my repos. I was thinking that maybe the action name could be useful from the hooks section but that not the case.
The rules are :
1) Only be able to commit on a specific branch (ex: acceptance)
2) Only be able to pull a specific branch. (Ex: bigNewFeature)
The second rule can look strange for a repo. We are in middle of releasing a big project where all the branches related to it had been merge under bigNewFeature for months on it. We are pushing it on our acceptance server and want to freeze the repos of any new branches except for bigNewFeature. That pretty much to avoid any mistake from one of the dev.
[extensions]
hgext.acl=
[hooks]
pretxncommit.acl = python:hgext.acl.hook
# Was expecting to be able to use any action name
pretxncommit.aclpull = python:hgext.acl.hook
# OR
pretxnchangegroup.aclpull = python:hgext.acl.hook
[acl]
sources = commit
[acl.allow.branches]
acceptance = *
[aclpull]
sources = pull
[aclpull.allow.branches]
bigNewFeature = *
My first rule work like usual but the second one don't look to be run at all. I have no error or what ever.

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

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

Mercurial [subpaths] containing absolute path is appended to main repo's default path when pushing

Running Mercurial 2.0.2 on Windows:
In my .hgrc:
[subpaths]
MYREPOS/(.*) = https://server/repos/\1
And in my .hgsub:
subrepo/lib = MYREPOS/lib
When I do a push, the push path of the sub repo is the concatenation of it's path to the main repo, rather than an absolute path - the output is:
pushing to https://server/repos/main
pushing subrepo subrepo\lib to https://server/repos/main/http%3A//server/repos/lib
I would have expected:
pushing to https://server/repos/main
pushing subrepo subrepo\lib to https://server/repos/lib
Is it because the 'absoluteness or relativeness' of the sub repo path is determined by right hand path in .hgsub and not the value it is mapped to? For example, MYREPOS/lib is relative, and therefore the mapped path will be treated as relative, whether it is or not?
The subrepository logic was changed between 1.9 and 2.0. The procedure is now:
if the path in .hgsub is relative, then join it with the main repository path
apply remapping rules to this final path
Before this change, we would:
apply remapping rules to the path from .hgsub
if the remapped path is relative, then join it with the main repository path
So you're right that MYREPOS/lib is seen as a relative path in the first step. The full path for the subrepository is therefore
https://server/repos/main/MYREPOS/lib
and your remapping pattern still triggers. This explains why you see http://... in the middle of the push URL. However, there is a fallback that will revert to the old behavior. If your pattern is
^MYREPOS/(.*) = https://server/repos/\1
then it wont match anything in the new step 2 — it will only remap MYREPOS at the beginning of the path. We notice this and use the old algorithm!

How to set up a mercurial repository which contains only some packages from different subrepositories projects?

I have a distant repository called http://myrepo
I also have 3 projects with 3 distinct packages (1 in each) stored in D:/Projects/Project[ABC]/src/pack[ABC].
I would like to create a local repo in D:/Mercurial which will reference the packages pack[ABC] as subrepositories, which are to be pushed to my distant repo.
Finally, I would like to have my packages stored in my distant repo so you read http://myrepo/pack[ABC], and they should reflect the changes made in D:/Projects/Project[ABC]/src/pack[ABC].
I can't manage tu push my subrepositories to my distant one. How to set-up such a thing?
You should be able to configure your subrepos in your top repo's .hgsub as:
LocalPathA = http://server/A
LocalPathB = http://server/B
LocalPathC = http://server/C
Then, on Server, you will have to create empty repositories (with appropriate permissions) A, B, C
Your local repositories A,B,C will need their [paths] default=http://server/A, etc set up.
hgrc for the subs
[paths]
default = source repo
hgsub for the surrounding repo
protocol://servername//absolute/path/to/repo = relative/path/from/surrounding/repo/root

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.