Mercurial auto update problem - configuration

We are starting to use Mercurial for source control. We have configured the HGRC configuration file to do an auto update after we push to the "central" repository.
With some PCs we get this error msg:
warning: changegroup hook exited with status -1
HGRC looks like this:
[ui]
username=ADMIN
verbose=true
[hooks]
changegroup = hg update >&2
Later we perform the update manually and everything works right.

I had a very simmilar issue. This finally works now:
changegroup = cmd /c hg update
The bold cmd /c causes cmd.exe to spawn which will execute hg update as we want it to, but now the exit value from cmd.exe will be 0.
Longer Story:
setup: win 2008 server.
mercurial 1.9.3
hgwebdir via plain http, its an internal network
error:
my error was funnily not the -1 as in your case but
"warning: changegroup hook exited with status 1"
Anyway, the update was not performed.
I found out that I can put the hooks into either .hgrc or into hgweb.config the problem was the same here or there. I finally put it into hgweb.config as below, so all repositories are auto commiting, which is way better than having this loose branch all the time. The main reason I wanted auto commit is that the respositories on the vcs & build server hold now the latest version which makes admin tasks often simpler.
[web] push_ssl = False allow_push = *
[collections] c:\Dev\Reps = c:\Dev\Reps
[ui] debug=true
[hooks] changegroup = cmd /c hg update

It might be related with the user actually executing the hook, which might not be the one with the correct privileges.
Do you have a IIS webserver managing your Mercurial repos?
(from the thread:)
From experience with Mercurial/IIS, things I'd recommend trying:
(a) Does running a simple non-HG command work? Permissions on cmd.exe will
affect out-of-process python hooks.
(b) Does a simple hook like 'python -c "import sys; sys.exit(0)"' work?
(c) If you make it this far, can you confirm that the process is running as the
user you think it's running as, with a hook that does something like:
import win32api
username = win32api.GetUserName()
(write username to a file so you can read it)

Related

How do I prevent a commit using pre-commit and hg incoming?

Sometimes developers on my team forget to pull in other developer's changesets before committing their own (admittedly, I do this as well). For a week long project there could be dozens of changes in the tree that the new commit skips over. When trying to push, hg aborts with the new remote head message then they pull and merge in all those new commits. What I'm looking for is an easy way to test if there are any new changes before someone commits and if there are to prevent the commit from happening. Ideally, there would be a clear message stating why the commit failed.
This seems like it should be very easy for a hook to accomplish but the pre-commit hook will continue on a status code of 0 and hg incoming will return 1 when there are no changes. All I need to do is invert the status of the hg incoming command but I can't find the syntax to do it. Most of the search results that I've found dive right into writing python hooks but that seems like overkill for such a simple problem.
I'm looking for something like this:
[hooks]
pre-commit != hg incoming
or
pre-commit = hg incoming == 0
I'm not sure where the message would go, either.
On Windows you can use this command to check for incoming changes:
[hooks]
pre-commit.checkNew = CMD /V /C "hg incoming & IF !ErrorLevel! EQU 0 (Exit 1) Else (Exit 0)"
If new changes are found it will cancel the commit and you will need to pull (and possibly merge) the new changes.
You had it mostly right, but you got the hook wrong:
[hooks]
precommit = ! hg incoming
There's no dash in the hook that can cancel the commit.
If, however, you turn a DVCS system into something where people can't commit without being connected to the internet your coworkers will string you up. :)
I found a solution by rereading the docs again: control if hook can proceed. Where I found the grep command in use.
[hooks]
precommit.comment = REM Don't forget to pull first!
precommit.test = hg incoming | grep -q "no changes found"
When a developer gets a failed commit they can check the output log and see the note. Not too pretty but should suffice most of the time. -q prevents "no changes found" from appearing in the log which would be confusing after a failed commit. I added my own extensions .comment and .test so the hooks get run in the correct order (c before t).

Automating Hg notify config updates

Hosting Mercurial on a windows box thru IIS.
I have a root directory where I put all of my repos
d:\repos
- ProjectA
- .hg
- hgrc
- ProjectB
- .hg
- hgrc
- ProjectC
- .hg
- hgrc
All of the repos' hgrc files setup the notify extension with:
config =d:\hg\Repositories\NotificationList.txt
That way I have a single file to manage all of the notification recipients, like the wiki describes:
https://www.mercurial-scm.org/wiki/NotifyExtension
But the wiki makes mention of controlling that NotificationList.txt file thru it's own repository? How can I do that? If I create a separate repo at d:\repos\HgNotify and have the NotificationList.txt file in there, users can change, commit and push back, but when the push occurs, NotificationList.txt does not get updated on the hg server.
Is there a way to update that file somehow? Am I missing a key setup on my Hg server? Or do I need to use a post-push hook to deploy that file?
Update 1
I added the details from Tim's answer and I kept getting HTTP 500: Server Error on the push. I finally figure out how to trace the python calls (python -m win32traceutil), and here is what seems to be the problem:
File "C:\Python27\lib\site-packages\mercurial\util.py", line 402, in hgexecutable
exe = findexe('hg') or os.path.basename(sys.argv[0]) AttributeError: 'module' object has no attribute 'argv'
It doesn't seem to be able to find hg.exe.
Update 2
I installed TortoiseHg and rebooted the system. Now I get:
emote: added 1 changesets with 1 changes to 1 files
remote: notify: sending 1 subscribers 1 changes
remote: warning: changegroup.update hook exited with status 1
So that makes be think that it has found the hg.exe, but it is not doing its job, because the file does not get updated
Update 3
Found my solution here: https://stackoverflow.com/a/8023594/698
The command line I ended up using was:
changegroup = cmd /c hg update
I also added:
[ui]
debug=true
To my hgrc. Those two combined gave me a lot more meaningful messages. In the end I saw "Access denied". I gave Users full permission, but I am not sure why giving IUSR full permission didn't work. Something I'll have to dig into at a later time.
On the server repo containing your notification list you need to add a changegroup hook:
[hooks]
changegroup.update = hg update -C
or if you want to ensure the repository is always clean:
[extensions]
purge =
[hooks]
changegroup.update = hg update -C && hg purge --all

Mercurial changegroup hook: repository URL

How can I, on a Mercurial repository server, figure out the current repository URL or at least name (subpath) in a changegroup — or somewhat equivalent — hook? I'm running HgWeb on IIS.
$HG_URL returns the pushers URL, not the receiving repository's. $HG_SOURCE only returns serve.
Context: I'm trying to write a changegroup hook for Jenkins using /mercurial/notifyCommit?url=<url> that tells Jenkins to perform an SCM poll, and if I can't get this to work, I have to do about 50 cURL calls (once for every repository on the server) on every changegroup trigger, and then remember to maintain this list in hgweb.config for all eternity.
Your hook will be executed inside the root folder of that specific repository, you can use the following command in bash to get the current folder name:
${PWD##*/}
As per Ton's answer, this is what I ended up doing since I'm on Windows:
changegroup.jenkins.cmd:
#for /f "delims=\" %%a in ("%CD%") do #set TOPMOST=%%~nxa
#curl.exe "http://jenkins/mercurial/notifyCommit?url=http://hgweb/%TOPMOST%" -s -S

Authenticating across mercurial subrepositories

I've got a mercurial repository, which pulls in dependencies using the subrepository functionality (as defined in the .hgsub file), but I'm struggling to get this working in TeamCity.
I've enabled the mercurial_keyring extension in order to save credentials (so when TeamCity provides authentication details for the root repository, it remembers them for the subrepositories). I've added an [auth] section to mercurial.ini too:
[auth]
bitbucket.schemes = https
bitbucket.prefix = https://bitbucket.org/xyz
bitbucket.username = xyz
If I run hg clone from the command line, I get prompted for a password once, and all is good. But the initial checkout when run via TeamCity fails with
VCS root: mercurial: https://bitbucket.org/xyz/projectA {instance id=23, parent id=1}, due to error: 'cmd /c hg update -C -r 4a08f587bb1f' command failed. stderr: abort: http authorization required stdout: pulling subrepo src\Common.Library from https://bitbucket.org/xyz/common.library
What am I missing, or am I going about this in completely the wrong way? Many thanks!
It seems that passing in credentials directly from TeamCity doesn't work with mercurial_keyring, but if I specify both username and password in plaintext in the mercurial.ini file (making sure it's accessible under the account the TeamCity build agent is running under), then this works.
The mercurial.ini file can be placed under <mercurial install path>\mercurial.ini if it does not work under user path.
Not ideal, but a solution... if anyone else finds a better one, please let me know.
May be it got fixed in last versions of TeamCity, but the following works for me:
Configure build agent service to run under domain account with
access to HG repositories (both root and subrepos)
Enable mercurial_keyring on build agent and add [auth] section
to mercurial config
Try to clone repository manually, enter
password. No need to wait until the whole repo is cloned -- it could
be terminated when "requesting all changes" message is shown.
Have fun -- now service will use keyring.
Probably the [auth] section shouldn't be added at all to the mercurial.ini for the TC agent. Team City uses --config auth... options to hg. I would also recommend not to use the mercurial_keyring but to set the username and password in VCS root - this is both secure and shared between different TC agents.
Not sure about the bitbucket, but in other cases usage of https scheme can require certificates configuration. This can be configured in mercurial.ini:
[web]
cacerts =
[hostfingerprints]
# hides mercurial warnings
domain-name = ab:cd:...:01
And last part: depending on .hgsub it might be needed to use VCS checkout mode "Automatically on agent" in Team City Version Control Settings.

Creating new repositories using mercurial-server

According to the "Creating repositories" at http://dev.lshift.net/paul/mercurial-server/docbook.html all we need to do to create new repository - is to clone not existent one.
But in 1.1 I doesn't work. And if we look at code:
if cmd is None:
fail("direct logins on the hg account prohibited")
elif cmd.startswith('hg -R ') and cmd.endswith(' serve --stdio'):
repo = getrepo("read", cmd[6:-14])
if not os.path.isdir(repo + "/.hg"):
fail("no such repository %s" % repo)
dispatch.dispatch(['-R', repo, 'serve', '--stdio'])
elif cmd.startswith('hg init '):
repo = getrepo("init", cmd[8:])
if os.path.exists(repo):
fail("%s exists" % repo)
d = os.path.dirname(repo)
if d != "" and not os.path.isdir(d):
os.makedirs(d)
dispatch.dispatch(['init', repo])
else:
fail("illegal command %r" % cmd)
we can see, that to create we need to pass specifically init command.
This command works as expected:
"TortoisePlink.exe" -ssh -2 hg#mercurial "hg init tst"
but I hope it is some more elegant command to do so.
Well, is it a "bug" in documentation or am I doing something wrong?
UPDATE:
My question is only about creating repositories remotely using mercurial-server.
UPDATE 2:
It was my misunderstanding, since it was not clear for me that there should be already created local repository, that will be cloned remotely.
I find it very straightforward to create a new repo using Mercurial-server. Assuming that you have the rights and that the path "/dir1/dir2/" already exist on the server, simply (using command line):
mkdir new
cd new
hg init
hg clone . ssh://hg#server/dir1/dir2/new
Cheers,
Christophe.
The page you reference is for sharing existing repositories, not specifically for creating new, empty ones. The command you give hg init tst is correct for initializing a new, empty repository. I think the only 'inelegant' thing about it is that you are doing it remotely and thus need to give the additional ssh commands. The repository creation command itself hg init is quite simple.