Mercurial Acl Extension deny pull of some files - mercurial

I'm new mercurial user. I setup the acl extension adding this into my hgrc file:
[hooks]
pretxnchangegroup.acl = python:hgext.acl.hook
[acl]
sources = serve pull push
[acl.deny]
** = mercurial
So with this code above I deny access to all files to user "mercurial". I successfully tested the acl extension and it works perfectly when I try to push to my central repository on which I put the code above. As expected I receive message that the access for the user "mercurial" is denied.
Now the problem is when I'm start pulling from central repository I don't have any restriction so I can pull anything without any restriction. What I want is to deny pull access for some files like I can do when I tried push comand. Is there any way I can do this?

Mercurial, unlike Subversion, doesn't allow controls on individual files, and for good reason. The DVCS model puts the entire repo on every developer's machine, so even if you restrict files on push and pull, the user could still just hg cat the file to get its contents.
Instead of trying to do this on the client side, I would instead break your repos based on who needs what and set permissions to individual repos. See my answer on the Kiln stack exchange Should I use more than one repository?. You can set permissions via http(s) or SSH, or if you happen to be using Kiln, through our permissions interface.

As came out in the comments with tghw, it sounds like what you really want is partial cloning by filepath, so that a person can clone or pull down only certain files or directories, but that's not possible in Mercurial (or git). That's the case because every revision is identified by a unique hash that includes, among other things, the hash of all the file changes. If you don't have all the files, you don't have all the changes, and you can't verify the hash.
If you really need to hide read access for some files from some people you'll need to split them up into separate repositories.

I have a solution:
convert your repo to git:
https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools#Mercurial

Related

mercurial: how to update production files without a server (EDIT: workaround + non-MS Windows solution)

I need to control the version of a few files accessible via an SMB share. These files will be modified by several people. The files themselves are directly used by a web server.
Since these are production files I wanted to force the users to pull a local copy, edit them, commit and push them back. Unfortunately there is no Mercurial server on that machine.
What would be the appropriate way to configure Mercurial on my side so that:
the versioning (.hg directory) is kept on the share
and that the files on the share are at the latest version?
I do not have access to this server (other than via the share). If I could have a mercurial server on that machine I would have used a hook to update the files in the production directory (I am saying this just to highlight what I want to achieve - this approach is not possible as I do not control that server)
Thanks!
UPDATE: I ended up using an intermediate server (which I have control over). A hook on changegroup triggers a script which i) hg update to have fresh local files ii) copies them to the SMB share
EDIT 1 Following discussions in comments with alex I have looked at the verbose version of the command line output. The \\srv\hg\test1 repo has a [hooks] section with changegroup = hg update. The output from a hg push -v gives some insights:
pushing to \\srv\hg\test1
query 1; heads
(...)
updating the branch cache
running hook changegroup: hg update
'\\srv\hg\test1'
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported. Defaulting to Windows directory.
abort: no repository found in 'C:\Windows' (.hg not found)!
warning: changegroup hook exited with status 255
checking for updated bookmarks
listing keys for "bookmarks"
If I understand correctly the output above:
a cmd.exe was triggered on the client, even though the [hook] was on the receiving server
it tried to update the remote repo
... but failed because UNC are not supported
So alex's answer was correct - it just does not work (yet?) on MS Windows. (Alex please correct me in the comments if I am wrong)
If I understood correctly, you are looking for two things:
A repository hook that will automatically update the production repo to the latest version whenever someone pushes to it. This is simple: You're looking for the answer to this question.
If you can rely on your co-workers to always go through the pull-commit-push process, you're done. If that's not the case, you need a way to prevent people from modifying the production files in place and never committing them.
Unfortunately, I don't think you can selectively withhold write permissions to the checked-out files (but not to the repo) on an SMB share. But you could discourage direct modification by making the location of the files less obvious. Perhaps you could direct people to a second repository, configured so that everything pushed to it is immediately pushed on to the production repository. This repo need not have a checked-out version of the files at all (create it with hg clone -U, or do an hg update -r 0 afterwards), eliminating the temptation to bypass mercurial.
What prevents you from mount your Samba share and run hg init there? You don't need mercurial server (hg serve or more sophisticated things) to perform push/pull operations.

Mercurial: create local copy of a remote repository at the remote respository

I use Mercurial on desktops, and then push local repositories to a centralized server. I noticed that this remote server does not hold local copies of files in its repositories (the directory is empty, except obviously for the .hg one).
What is the preferred way to populate these directories with local copies? (which in turn are used by various unrelated services on that server).
What I came up so far is to use a hook and hg archive to create a local copy. This would be a satisfactory solution but I need to configure a per-repository hgrc file (which is tedious but I did not find a way to centralize this in /etc/mercurial/hgrc). Maybe a global script (in /etc/mercurial/hgrc, run for each changegroup event)? (in that case how can I get the repository name to use in a if...then scenario?)
If you can get access to the remote repository, you could install a hook for when changegroups come in, and perform an hg update when that happens.
A quick check shows this in the FAQ (question 4.21), but to summarize/duplicate: edit the .hg/hgrc file on the remote repository, and add the following lines:
[hooks]
changegroup = hg update
Whenever the remote repository gets pushed to (or when it performs a pull), it will update to the latest changeset.
Some caveats - this may fail if any changes have been made to the files on the remote side (you could use hg update -C instead). Also, if you have pushed any anonymous branches (which you would have to consciously force), you may not update to what you want to update to.

push to configured hg repository from web interface

I have a small group of developers and we all develop on our own machines. When we have code that is ready for testing, we merge and push to a RhodeCode installation. The hgrc file for my central RhodeCode repo is set up like this:
[paths]
test_env = /www/mysite/test
prod_env = /www/mysite/prod
[hooks]
changegroup = hg push test_env
so when a person checks code into RhodeCode, the changes are automatically pushed to the test environment. (There's a hg update in the test repo hgrc file, so the code updates there). This is perfect.
BUT.. I would like our RhodeCode admins to be able to push to prod without needing shell access on the server. Is there a way to allow someone to run a "hg push prod_env" from the RhodeCode interface? I figure since RhodeCode has full control over hg, it should be possible, but does this ability exists somewhere in RhodeCode? would it be a huge task to add it?
If not, how would you go about allowing an authenticated user to push a repository to production without shell access? I have been googling, but I can't seem to find anything. I know I could write a php script with a passthru("hg push test_env), but that seems like a permissions nightmare as apache runs as "nobody" and rhodecode owns the repo.
Thoughts?
Obviously, you cannot push nothing. But you can try to add or edit some file from the RhodeCode interface (which allows this to do) at the prod_env. This should cause local commit and push without accessing a shell.
For those looking at this question, here's how I solved it:
Wrote a passworded page in PHP with a button that executes this code:
shell_exec('hg pull -R ../wp-content/themes/2014');
I then put hg update in the hgrc file for the prod website, and made the web user and authorized user of the repository.
It works pretty good - i have slight security concerns because of the resulting file ownership, but assuming the PHP follows proper practice, there aren't any problems.

I have a slight confusion with setting up Mercurial on my webserver

I'm starting to use Mercurial on my web server (in this case MediaTemple's Grid). I've used SVN previously, though I'm not an expert of version control systems. I'm just needing a little help with clearing up some confusion with getting it set up optimally.
I have a 'data' folder which is outside the web server root and that the browser cannot access. It was recommended to me before to have my Mercurial repositories setup here, then I would clone from here locally on my computer. I would also have a 'domains' folder that is basically the web server root and inside there is my actual domains where my websites are actually served to the browser - these would need to be updated from the 'data' repositories too.
But with this in mind, after setting it up, it seems inefficient... I'm cloning to my local (that makes sense), adding, committing, pushing. That's fine... But then I'm then updating in my data repository folder and then updating in my domains folder to actually update my websites.
Surely, I don't actually need this 'data' folder for repositories? Wouldn't my actual live 'domains' folders be the main repositories themselves? So I'm cloning locally and updating from these? Please help me clear some confusions with all this (if you can).
It's strictly a matter of personal preference. Some folks make their live websites also the "master" repo, and some make it a clone of an elsewhere located repo. What you're doing right is serving your sites from directory in the repo, that's a good choice.
Some considerations as to whether you might want separate 'data' clones independent from the web root clones are:
do you want to have multiple heads in the same branch which might confuse the person updating the main repo?
do you want a repo to which people you don't trust with editing the live website can push so that a trusted admin (you?) does the push/pull from data to webroot?
One thing to note is that in the 'data' repo you can do hg update -r null which gets rid of the working copy (but keeps the repo!), so that the diskspace used is almost zero (assuming it's a clone of the webroot they'll share the same underlying files at the FS hardlink level).
I do have a repos (data) folder outside the website root, containing various repositories, and served through hgwebdir on a separate domain (hg.mywebsite.com).
However, my website’s repository I do store in the httpdocs directory of the main domain. I test on my local environment and then pushing my changes to the server will also publish them.
To achieve this I have this in my hgweb.config:
private/mywebsite = ../../../httpdocs
And this in that repository’s hgrc:
[hooks]
changegroup.update = hg update
This hook will update the working directory to the tip whenever changes are pushed. Of course I have also added a rule to the Apache configuration to ignore the .hg directory, and on the subdomain hg runs on, a rule to require authorisation for accesses to the private/ paths.
An alternative would be to instead host the repository together with the others, and then ‘hg archive’ into the httpdocs directory. A little more secure, a little slower, and as for convenience I would say it’s 50-50.
p.s. also adding a hook to forbid creation of remote branches may be a good idea, if people who might do push -f can access your repositories.

hg access control to central repository

We come from a subversion background where we have a QA manager who gives commit rights to the central repository once he has verified that all QC activities have been done.
Me and a couple of colleagues are starting to use mercurial, and we want to have a shared repository that would contain our QC-ed changes. Each of the developers hg clones the repository and pushes his changes back to the shared repository. I've read the HG init tutorial and skimmed through the red bean book, but could not find how to control who is allowed to push changes to the shared repository.
How would our existing model of QA-manager controlled commits translate to a mercurial 'central' repository?
HenriW's comment asking how you are serving up the repositories is exactly the right question. How you set up authentication depends entirely on how you're serving your repo (HTTP via Apache, HTTP via hg-serve,, ssh, etc.). The transport mechanism provides the authentication and then mercurial uses that with the commands from Mr. Cat's link (useless in and of themselves) to handle access control.
Since you didn't mention how you're serving the repo, it was probably someting easy to set up (you'd have remembered to mention the hassle fo an apache or ssh setup :). So I'll ugess those two:
If you're using hg serve then you don't have authentication setup. You need to use apache, lighttp, or nginx in front of hgweb or hgwebdir to provide authentication. Until you do the allow_* and deny_* options are strictly everyone or no one.
If you're using ssh then you're already getting your authentication fromm ssh (and probably your OS), so you can use the allow_* and deny_* directives (and file system access controls if you'd like).
serverfault.com has a relevant question and links to the Publishing Repositories Mercurial Wiki page. The first shows how to configure per-repository access when using hgweb on the server. I get a feeling that you're using ssh which the wiki page labels as "private" and am therefore inclined to believe you would have to fall back to file-system access control, i.e. make all the files in the repository belong to the group "commiters", give group members write access and everyone else read/only.