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.
Related
I'm facing problems fetch HG/Mercurial repo in Bitbake recipe.
can't fetch the source URL reported in logs
tested with env hg clone repo_url works fine
testet with hg:// and http:// headers
The right format of SRC_URI is:
SRCREV = "tip"
SRCMODULE = "myapp"
SRC_URI = "hg://hg_server_url;rev=${SRCREV};protocol=http;branch=${SRCBRANCH};module=${SRCMODULE}"
The key is that hg_server_url shouldn't include target repo subname, but include it as SRCMODULE !
Also you could pull latest commit not with AUTOREV as per git repo but SRCREV = "tip"
Edit: Working 100% tip
Due to logic of bitbake classes and nature of Mercurial repo above statement should work but just once. It's that way cause when bitbake checks for cached files it finds "tip" already in cache instead git's HEAD wich is translatet to uniq hash.
To avoid that behaviour we should avoid completly (Mercurial repo) cache when fetch hg repo. This is simple as put in recipe:
do_install[nostamp] = "1"
That way bitbake always think the recipe is executed for the first time. We not useing cache but always get latest repo commit.
Is it possible to create a subrepository using a sibling path?
Subversion is our "chosen" VCS here, but I've already had quite a few issues with out of date commits. It's much more convenient for me to dual version my files under Hg and SVN, and I have had great success with it. However, I've got a few other co-workers using Hg, and we've had no problems there except for one they probably haven't noticed.
Our SVN layout looks like this
Area/
trunk/
Program1/
Program2/
...
Services/
Program1ServiceA/
Program1ServiceB/
branches/
Program/
Program/
...
Services/
Program1ServiceA/
Program1ServiceB/
tags/
Program1/
Program2/
...
Services/
Program1ServiceA/
Program1ServiceB/
Which makes it kind of stupid when you're working on a project, because if your main project is comprised of Program1 and Program2, and a few more services... I can't get all of the changesets in one go, because we've got a repository that matches the directories. So I have to make sure 4 or 5 repos are in sync, especially with some service references.
I've had some good luck using subrepos beneath a single directory:
MainRepo/
Subrepo1/
Subrepo2/
But what I would like to do is specify a relative path so I can use sibling directories to the subrepository, so I could have something like this:
Area/
Project1/
Program1/ (points to ../trunk/Program1)
Program2/ (points to ../trunk/Program2)
Service1/ (... You get the idea)
Service2/
trunk/
Program1/
Program2/
Services/
Service1/
Service2/
But so far it hasn't worked like I expected it to. trunk/Program1 is an Hg repo, and my Project1/.hgsub file contains
Program1 = ../trunk/Program1
I've also tried ../../trunk/Program1
But the result of either of those is that a new directory is created: Area/Program1/Project1 that is empty.
So far, the only search results I've been able to find use http based repositories for subrepos, so I'm not sure where to go from here. Our dev env is Windows 7, so the "easy" answer is to create junctions, but my primary concern is to make things like this easy to do, so the barrier to entry is as low as possible, and even something as easy as mklink /J Program1 ..\trunk\Program1 from an administrator cmd window is one more thing that would prevent people from migrating to a better workflow.
Is it possible to add a subrepository like I want, or is there a better way to do what we're doing?
Subrepositories are always inside another repository. In other words, subrepositories lets you version a collection of repositories where some repositories are nested inside other repositories. Subrepositories can thus not be siblings without creating an outer repository.
The relative paths you're talking about are used when Mercurial needs to figure out where to get a new subrepository from. That is, when you run hg update (or when it's run for you as part of hg clone) and Mercurial notices a .hgsub file, then it needs to create the subrepositories mentioned there. To create the subrepo, Mercurial uses the path on right-hand side:
sub-A = relative/path
sub-B = C:/absolute/path
Here sub-A will be checked out in the root of your working copy using the command
hg clone <default path for main repo>/relative/path sub-A
and sub-B is checked out using the command
hg clone C:/absolute/path sub-B
That's all — it's a very simple mechanism. I've tried to describe this in my subrepository guide and it's also explained in the wiki.
For your case, you can make a thin shell repository for the parts that belong together. This repo will be like Project1 above and have Program1, Program2, Service1, etc as subrepos. The .hgsub will look like this:
Program1 = Program1
Program2 = Program2
Service1 = Service1
Service2 = Service2
By using "trivial subrepo paths" you make things easy: a clone looks just like the clone source and everything is kept together.
A final note: unless you use Program1 or Service1 in other projects, then you should just put everything into a single repository.
The setup:
a laptop L
an office server hosting various repositories SOffice
a customer's database server SCustomer
I'm writing code on L for a customer, and regularly want to push it both to SOffice as well as SCustomer.
I know I could use a changegroup hook to push to a third repository from the second (as described in this answer), but this requires that the second can reach the third network-wise.
In my case, each is behind a firewall, and only my laptop typically accesses both through a VPN (or by being physically there). I could set up the VPN on SOffice to get to SCustomer, but I'd rather not.
Is there a way I can, say, set default to two repositories?
You can't default to two repositories, but you can define more than one repository in your hgrc file :
[paths]
default= /path/to/first/repo
scustomer = /path/to/second/repo
You can then push to the scustomer repository explicitly :
hg push scustomer
If you want to automate the process of pushing to both repository at once, I'm not aware of a Mercurial method to do it, but it is really easy to create a shell script, alias or something else to run both commands one after the other.
You can even use a hook on the repository to automatically push to the other one, but you will have to discriminate between a "manual" push and the automatic push in the hook, and I'm supposing this will be really messy.
Could you create a second clone of the repository with a hook that automatically pushes to both of the external repositories? Then push from your working clone to the second clone.
There's a MultirepoExtension that adds commands for doing any operation on multiple repositories.
Or you could create an alias to push to both like:
[aliases]
pushboth = !$HG push http://first ; $HG push http://second
or you could create a pre-push hook that pushes to the other one. Something like:
[hooks]
pre-push = hg push http://second
But I like (and upvoted) krtek's answer the most. Just give each a path alias and run push twice with the short names instead of the URLs.
I have a need for a hook to run after update (this will build the solution they have updated) and I don't want to have to add that hook manually for each person that clones my central repository.
When someone first clones my central repository, is it possible to include hooks into that clone? It seems that the .hgrc file doesn't get cloned automatically.
I did read about site-wide hooks, but as far as I understand it, they work on each created repository, where I only want to have the hooks on some repos.
As Rudi already said, this is (thankfully) not possible for security reasons.
However, you can reduce the per-clone workload to set up hooks manually: Ship the hook scripts as part of your repository, e.g. in a directory .hghooks, and additionally include a script in your repo which sets up these hooks in a clone's hgrc. Each coworker now only needs to call the setup script once per clone.
This is not possible, since that hooks do not propagate to clones is a security measure. If this were possible, one could set up a rouge repository, which runs arbitrary commands on any machine where the repo is cloned.
See http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html#id402330 for more details.
This will allow for centralised per-repo hooks, with a single setup step per user. It will however cause problems for users who are disconnected from the network. An alternative if you tend to have disconnected developers (or ones over high-latency/low bandwidth links) would be to have a repo containing the hooks, and set up each user's global hgrc to point into that repo (and require regular pulls from a central hook repo).
Note that I treat the ID of the first commit as the "repo ID" - this assumes that the first commit in each repository is unique in some way - contents or commit message. If this is not the case you could do the same thing but applying it over the first N commits - but you would then have to account for repos that have fewer than N commits - can't just take repo[:5] for example as newer commits would then change the repo ID. I'd personally suggest that the first commit should probably be a standard .ignore file with a commit message unique to that repo.
Have a central shared_hgrc file, accessible from a network share (or in a hook repo).
Each user's global hgrc has:
%include /path/to/shared_hgrc
Create a shared repository of python hook modules. The hooks must be written in python.
Create your hook functions. In each function, check which repo the hook has been called on by checking the ID of the first commit:
# hooktest.py
import mercurial.util
FOOBAR_REPO = 'b88c69276866d73310be679b6a4b40d875e26d84'
ALLOW_PRECOMMIT_REPOS = set((
FOOBAR_REPO,
))
def precommit_deny_if_wrong_repo(ui, repo, **kwargs):
"""Aborts if the repo is not allowed to do this.
The repo ID is the ID of the first commit to the repo."""
repo_id = repo[0].hex().lower()
if repo_id not in ALLOW_PRECOMMIT_REPOS:
raise mercurial.util.Abort('Repository denied: %s' % (repo_id,))
ui.status('Repository allowed: %s\n' % (repo_id,))
def precommit_skip_if_wrong_repo(ui, repo, **kwargs):
"""Skips the hook if the repo is not allowed to do this.
The repo ID is the ID of the first commit to the repo."""
repo_id = repo[0].hex().lower()
if repo_id not in ALLOW_PRECOMMIT_REPOS:
ui.debug('Repository hook skipped: %s\n' % (repo_id,))
return
ui.status('Repository hook allowed: %s\n' % (repo_id,))
In the shared_hgrc file, set up the hooks you need (make sure you qualify the hook names to prevent conflicts):
[hooks]
pre-commit.00_skip = python:/path/to/hooktest.py:precommit_skip_if_wrong_repo
pre-commit.01_deny = python:/path/to/hooktest.py:precommit_deny_if_wrong_repo
As #Rudi said first, it can't be done for security reasons.
With some prior setup you can make it so that hooks are run on clone, but putting a hook with a repo-relative path in /etc/mercurial or in each user's ~/.hgrc, which in a corporate setting can be done via your system management tools or by building a custom Mercurial installer. In a non-corporate setting follow #Oben's advice and provide the scripts and a readme.
I have a "central" repository that I want to ensure that no one pushes changes in to with a wrong user name.
But I can not figure out how to make a hook that tests the user name against a positive list. I have found in the Mercurial API a ctx.user() call that seems to be what I want to test my positive list against.
Also the hook could be a precommit hook that is distributed as part of the repository clone or it could be a hook on the central repository as a pre-incoming or something like that.
Any help or pointers would be greatly appreciated.
I have posted two functional examples on Bitbucket. Both examples are for searching a commit message for some specifically formatted text (like an issue tracked case ID), but could be easily modified to check a user against a list of valid users.
The first example is actually a Mercurial extension that wraps the 'commit' command. If it fails to find the appropriate text (or valid user in your case), it will prevent the commit from occurring at all. You can enable this in your .hgrc file by adding these lines:
[extensions]
someName = path/to/script/commit-msg-check.py
The second example uses a in-process pretxncommit hook, which runs between when the commit has been made, but before it becomes permanent. If this check fails it will automatically roll back the commit. You can enable this in your .hgrc file by adding these lines (assuming you kept the same file/function names):
[hooks]
pretxncommit.example = python:commit-msg-check-hook.CheckForIssueRecord
You can execute any Python code you like inside of these hooks, so user validation could be done in many ways.
Thanks for the examples dls.
In the end I decided to run it as a pretxnchangegroup hook and then use the hg log and grep to test the author field of the commits:
[hooks]
pretxnchangegroup.usercheck = hg log --template '{author}\n' -r \
$HG_NODE: | grep -qe 'user1\|user2\|etc'
It does of course not provide a very good feedback other than usercheck failed. But I think it is good enough for now.