Mercurial: clone only a branch of a repository - mercurial

in my mercurial project I have some users that can clone the repository, but I need that they only can see some branches.
For example they can see only the "stable" branch so I can be sure they will never try unstable code.
Or customer X can see only the branch with his customizations.
I know I can extract the source code of the release and give it to them. But for "non technical" reasons they want access to the repository.
Is it possible?
Thanks,
Mario

You can use the ACL extension, in which you define [acl.deny.branches] and [acl.allow.branches].
The following sample config is taken from the ACL documentation page.
[hooks]
# Use this if you want to check access restrictions at commit time
pretxncommit.acl = python:hgext.acl.hook
# Use this if you want to check access restrictions for pull, push,
# bundle and serve.
pretxnchangegroup.acl = python:hgext.acl.hook
[acl]
# Check whether the source of incoming changes is in this list where
# "serve" == ssh or http, and "push", "pull" and "bundle" are the
# corresponding hg commands.
sources = serve
[acl.groups]
# If a group name is not defined here, and Mercurial is running under
# a Unix-like system, the list of users will be taken from the OS.
# Otherwise, an exception will be raised.
designers = user1, user2
[acl.deny.branches]
# Everyone is denied to the frozen branch:
frozen-branch = *
# A bad user is denied on all branches:
* = bad-user
[acl.allow.branches]
# A few users are allowed on branch-a:
branch-a = user-1, user-2, user-3
# Only one user is allowed on branch-b:
branch-b = user-1
# The super user is allowed on any branch:
* = super-user
# Everyone is allowed on branch-for-tests:
branch-for-tests = *

Related

Bitbucket: Enforce merge-only by pull request on branch workflow

Our team uses Bitbucket for hosting our Mercurial repository. We have a single repo which is cloned to our dev VM's upon provisioning them. We use a fairly typical feature branch -> pull request -> review -> merge feature into default from the PR workflow.
What we'd like: to be able to restrict things such that one cannot push to the default branch by command-line (to avoid accidental commits to that branch). Ie - we want to enforce it so that the only way default is modified is via a pull request.
Note that forking isn't really an option due to the VM setup (we'd have to add complexity to the VM provisioning to do the fork, and set all that up on the provisioned VM, and even then that just means that when someone accidentally pushes to default they're just messing up their fork).
Branch Restrictions seem promising, and while we can set it up that nobody can push via the command line, it then means only a single named user or group can do the actual merge of the PR (which we don't want, ideally anyone on the team can merge, just only through a Bitbucket PR).
Is this possible? Any suggestions?
So I ended up solving this with Mercurial hooks. Specifically I created the following file, which I named prevent_default_push.py and put in the .hg directory of my clone.
# branches to prevent being pushed to by command line.
# Separate branches by spaces
restricted_branches = "default".lower().split()
def branch_name(repo):
return repo[None].branch().lower()
def is_restricted(branch):
return branch in restricted_branches
def prevent_default(ui, repo, *args, **kwargs):
if is_restricted(branch_name(repo)):
print("Preventing push to default branch")
return True
return False
def prevent_commit(ui, repo, *args, **kwargs):
branch = branch_name(repo)
if is_restricted(branch):
print("You're on a restricted branch (%s), are you sure you want to commit? [YN]" % branch)
res = raw_input().strip().lower()
return res != "y"
return False
And then edited the .hg/hgrc file to use these hooks:
[hooks]
pre-push = python:.hg/prevent_default_push.py:prevent_default
pre-commit = python:.hg/prevent_default_push.py:prevent_commit
Then when trying to do a commit while on the default branch, you get a confirmation prompt, and if you try doing a push to default it's straight up rejected.
Example run:
$ hg commit
You're on a restricted branch (default), are you sure you want to commit? [YN]
n
abort: pre-commit hook failed
Where "n" is what I typed.
The plus side of this is that while the stuff in your .hg directory isn't under version control (so a clone won't get it), we can incorporate into our provisioning mechansims the automation of putting these hooks in place on a provisioned VM.

Mercurial deny clone exact branch in repository

I'm using http to serve two branches in HG.
I need one user to have access only for certain branch.
How can I deny cloning exact branch with AclExtension?
My .hg/hgrc is
pretxnchangegroup = python:hgext.acl.hook
[acl]
sources = http, pull, push
[acl.allow]
* = admin #admin has full access
release = baduser #baduser has access only to release branch
[acl.deny.branches]
default = baduser #deny this branch for user baduser
This doesn't work.

tortoise hg : how to get notified whe something pushed to a central repo

i am using Mercurial for version control. One central repo is shared among the team and any of us can push / pull to it.
How can i get notified when any other user push something to the central repo.
I have tried to edit my hgrc file as per the https://www.mercurial-scm.org/wiki/NotifyExtension
as below
[extensions]
hgext.notify =
[hooks]
# Enable either changegroup or incoming.
# changegroup will send one email for each push,
# whereas incoming sends one email per changeset.
changegroup.notify = python:hgext.notify.hook
#incoming.notify = python:hgext.notify.hook
[email]
from = **myemailaddresshere**
[smtp]
host = localhost
# presently it is necessary to specify the baseurl for the notify
# extension to work. It can be a dummy value if your repo isn't
# available via http
[web]
baseurl = **http://repoip:port/**
[notify]
# multiple sources can be specified as a whitespace separated list
sources = serve push pull bundle
# set this to False when you're ready for mail to start sending
test = True
[reposubs]
* = **toemailaddresshere**
#config = /path/to/subscription/file
# you can override the changeset template here, if you want.
# If it doesn't start with \n it may confuse the email parser.
# here's an example that makes the changeset template look more like hg log:
template = \ndetails: {baseurl}{webroot}/rev/{node|short}\nchangeset: {rev}:{node|short}\nuser: {author}\ndate: {date|date}\ndescription:\n{desc}\n
maxdiff = 300 # max lines of diffs to include (0=none, -1=all)
then i tried to push sme changes . But this didnt fire any email.
Can you please check what is error in my .hgrc file
Your Notify extension is configured to be in test mode. Maybe setting test = False will help?
template and maxdiff should be in the [notify] section. In your sample, they are in the [reposubs] section.
You can use hg help to check if the notify extension is enabled.

Mercurial does not send emails using changenotify

I set up a http central Mercurial repository and try to send emails on every push. I follow instructions from mercurial page and from http://morecode.wordpress.com/2007/08/03/setting-up-mercurial-to-e-mail-on-a-commit/.
Push works fine, but I don't see any notify message at all. Please help me.
My .hg/hgrc in my repository folder of my client looks like this
[extensions]
hgext.notify=
[hooks]
changegroup.notify = python:hgext.notify.hook
[email]
from = what#gmail.com
[smtp]
host = smtp.gmail.com
username = what#gmail.com
password = ohyea
port = 587
tls = true
[web]
baseurl = http://1.1.1.1/repo_name
[notify]
sources = serve push pull bundle
# set this to False when you're ready for mail to start sending
test = False
config = /home/myhome/something/subscription.conf
template = \ndetails: {baseurl}{webroot}/rev/{node|short}\nchangeset:{rev}:node|short}\nuser: {author}\ndate: {date|date}\ndescription:\n{desc}\n
maxdiff = 300
My /home/myhome/something/subscription.conf looks like
[reposubs]
# key is glob pattern, value is comma-separated list of subscriber emails
* = sometestemail#gmail.com
I save and my result looks like below, if you notice I don't see any notify message at all
pushing to http://1.1.1.1/repo_name
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 2 changesets with 7376 changes to 7376 files
[Update:]
I found that there was no hgext folder in my system. So I manually downloaded the source matching my hg version and updated my hgrc as below, and still it does not work. Any help please.
[extensions]
notify= /path/to/notify.py
[Update 2:]
Thanks Ry4an - I tried it, still no luck.
In my webserver
Under /var/www and /var/www/hg
I created .hgrc files, just not sure which one is my webroot, so I did at both places with contents
[trusted]
users=user_name
this user name is the username in my client from where I'm trying to push to the repo.
on my client
in the .hg/hgrc of my repo, I added trusted section
[trusted]
users=user_name
The above procedure did not help
Second approach
on my client,
under my repo's .hg, I did
chown www-data:www-data hgrc
and when I tried to push I got some message while pushing saying
sending capabilities command
capabilities: changegroupsubset stream lookup pushkey unbundle=HG10GZ,HG10BZ,HG10UN branchmap
sending heads command
searching for changes
common changesets up to 6ef19c49143a
sending branchmap command
ignoring untrusted configuration option hooks.changegroup.notify = python:hgext.notify.hook
This ignoring command does not appear during the first approach, only after I change the ownership of hgrc, this pops up.
It's likely a trust issue, but let's hit a few other things first:
A) Switch the extension load to:
[extensions]
notify=
The hgext part is no longer necessary, but doesn't hurt. Giving the full path to the extension is more fragile in the case of future updates. The raw notify= syntax is sufficient for extensions that come with Mercurial and notify always does.
B) Switch the test = false to test = true it will help you debug this -- it sends the email to Stdout, which is handy.
Okay, those two done, let's look at trust. Mercurial's trust system is built around the idea that not just anyone should be able to get you to run code. Imagine if your repo's .hg/hgrc file had a section in it like:
[hooks]
pre-push = rm -rf ~
When I pushed to it it would delete my home directory. That would bum me out. To avoid that happening Mercurial will only load/run hgrc files that it trusts, and you tell it what to trust with [trusted] sections in your hgrc. When you're pushing over ssh you're effectively logging into the remote machine and it's your own ~/.hgrc that probably states what other hgrc files you're willing to execute.
HTTP is special though. Even though you may be authenticating you're probably not running Mercurial on the remote system as yourself. It's probably some some non-user user like www-data, www, apache, or noone depending on how your web server is configured, so... you need to make that repo's .hg/hgrc' owned (or group-owned) by an user (or group) that the webserver user trusts. To achieve that you can eitherchwownthe.hg/hgrcfile over to the web server user, or find the web server's home directory (often/var/www) and create a.hgrcfile in there with a[trusted]block saying that the web server user trusts whomever it is that owns the repo's.hg/hgrc` file.
If I'm right about what's going on the tell tale sign would be in your webserver's errors log where you'd see a lot of messages like "Not trusting /path/to/repo/.hg/hgrc owned by someuser".
TL;DR: Make sure your web server user trusts (in the hgrc sense) the owner of the .hg/hgrc that's specifying the hook.
This worked for me when communicating with an Exchange Server:
[hostfingerprints]
<my exchange FQDN> = 2a:f3:89:69:13:b2:1e:3a:c2:fe:f9:7f:de:b3:39:e7:82:8e:99:93
[extensions]
notify =
[hooks]
changegroup.notify = python:hgext.notify.hook
[email]
from = Mercurial Notification <noreply#mydomain>
[smtp]
host = <exchange FQDN>
tls = true
[notify]
sources = serve push pull bundle
test = False
maxdiff = 300
[reposubs]
* = Cameron Rich <cameron.rich#mydomain.com>
Put the above in the hgrc file in your repository.
e.g. C:\repositories\test.hg\hgrc

How to configure multiple user access control setting by acl extension in Mercurial repository

I have main mercurial repository (A) with 2 folders "depot1" and "depot2" in Windows Machine
Following configuration is done in .hg/hgrc file of A repo.
[ui]
username = praveen
[extensions]
hgext.acl=
[hooks]
changegroup.update = hg update
pretxnchangegroup.acl = python:hgext.acl.hook
[acl]
sources = serve push pull commit
Then I created 2 clones of mercurial A repository. X and Y on windows machines
X .hg/hgrc file is:
[ui]
username = clone1
Y .hg/hgrc file is:
[ui]
username = clone2
My Question:
1- Restrict all push operations from user="clone2".
2- user="clone1" will be able to perform push on only "depot1".
Please suggest me how this configuration is possible.
Thanks,
Praveen
Unfortunately, you're misunderstanding what the username in the [ui] section does. It's strictly a client-side setting that says "If a server asks me for a username for authentication here's what I want to send", so what you have in the ui.username in repos A, X, and Y will have no affect on what remote users can to to/with those repositories.
Instead, you need to use the [acl.allow] and [acl.deny] sections in the Y and X repositories' .hg/hgrc files to specify access controls for them.
The usernames that you use in those section, ('clone1' and 'clone2') in your examples need to be backed by a real authentication system too. The built-in hg-serve doesn't provide one, so you need to be using either ssh or Apache/ISS with a hgweb or hgwebdir. See the publishing repositories wiki page for a great overview.