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.
Related
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.
I have a local mercurial repository. And I back it up with a clone in a separate folder that lives in my google drive folder. Every now and again I'll go into the google drive repo and do an hg pull, and google drive takes care of backing it up. But I'd like to swap those responsibilities, so that my local is a clone of the one in google drive. In other words, today I do this:
From my local c:\source folder:
do stuff
hg commit
cd c:\googledrive\source
hg pull
I would rather:
From my local c:\source folder:
do stuff
hg commit
hg push
I don't know what to do in my hgrc files to make that happen. Can someone help?
Here's the contents of my c:\source hgrc:
# Generated by TortoiseHg settings dialog
[tortoisehg]
summarylen = 80
engmsg = True
editor = notepad
tabwidth = 2
forcerepotab = False
monitorrepo = localonly
[ui]
username = *****
And this is the contents of the clone in google drive
[paths]
default = c:\source\SwissArmyKnife
Your question reveals an illuminating misconception. When one says that Mercurial is a Distributed Version Control System (DVCS), it means that there is no ‘master‘ repository.
When you type hg push <repo> or hg pull <repo>, then Mercurial compares the changesets in the current repository with those in <repo>, and pushes or pulls changesets to make this one and the remote one consistent. The <repo> can be indicated by a URL (that is, ssh://..., or http://...) or else by a shorthand named in your .hg/hgrc: thus in your case you might add
[paths]
gdrive = c:\googledrive\source
and that would mean that you could write hg push gdrive or hg pull gdrive and Mercurial would know what you meant. You can have multiple paths listed here.
There's one ‘magic’ path, however. If you have a path default then that's the path that Mercurial uses if you don't specify a <repo>.
Thus (finally), if you adjust the .hg/hgrc in your c:\source folder to include
[paths]
default = c:\googledrive\source
then in that directory plain hg push will sync changesets with that drive.
When you clone a repository (hg clone) Mercurial generally adds to your .hg/hgrc a default = ... which indicates the location from which you cloned the repository. Given that default behaviour, it's very natural to think of that repository as the ‘master’ one, but there's nothing fundamentally special about it.
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 = *
I keep all my personal projects on my Kiln account and I also have a bitbucket account where I push repositories when I need to share them with people. Is there some way for me to setup an alias for a repo URL so I can do something like
hg push kiln
or
hg push bitbucket
instead of typing in the entire URL each time:
hg push https://path/to/repo
Yes, you can do this in your repo's hgrc file using the paths section.
[paths]
default = https://path/to/repo
kiln = https://path/to/kiln
bitbucket = https://path/to/bitbucket
If you create new repos often, you can also add this to your ~/.hgrc file.
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.