How to perform action after aborted Mercurial commit? - mercurial

I'm using mercurial's pre-commit hook to write out some information to a file inside the repo.
If the commit fails/aborts (like when the user doesn't enter a commit message), I want the file to be removed.
I considered using the post-commit hook, but when I put the following code in the post-commit hook, it doesn't appear to run for an aborted commit:
post-commit = export | grep "export HG_"
Is there a better way to do this than to create a user alias (cmt)that checks the exit result of the hg commit and then use that instead of the commit command? The reason I ask is b/c I'm trying to write some triggers to help my coding team, but don't want to force them to use an alias in place of the standard commands (can't really enforce this easily; can't overload the commit either as an alias it seems or will be stuck in an infinite loop):
[hook]
pre-commit = echo "some info to a file" > info.out ;
[alias]
cmt = ! $HG commit "${HG_ARGS[#]:4}" ; if (($?)); then rm info.out ; fi

Could you use:
[hook]
pretxncommit = echo "some info to a file" > info.out ;
This hook is called after a changeset has been created, but before the transaction is committed.

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).

Mercurial hooks -- pass information between hooks?

I currently have a pre-commit hook in my mercurial project that gives the user the option to update the version number of the project if they wish (e.g. 1.0 to 1.0.1 or 1.1 or 2.0). They select one of these options, and the hook updates the version number in one of the project's files prior to the commit taking place.
When I run hg commit, this hook runs and updates the relevant file with the new version number, and then performs the commit.
I'd like to add to the hook such that it calls hg tag <new_verson_number> as well.
However, I can't add this to the pre-commit hook, because then the tag will be added before the commit is called, causing the tag to be one revision out of date.
I'd like to add the hg tag command to a commit hook (run after the commit), so that the sequence of events is like so:
hg commit -m "my commit message"
user says yes, I'd like to change the version number
version number is updated in the relevant file
commit occurs [everything up to here is fine]
if the user changed the version number, run a commit hook: hg tag <new_version_number>.
Now, I could add a commit hook that read off the new version number from the file it's stored in and run hg tag <new_version_number>, but what if the user decided not to change the version number? In that case, I don't want a tag added, and if I blindly run hg tag <new_version_number> I'll end up with tags I don't want.
So - is there some way I can tell the pre-commit hook to leave some information for the commit hook (a yes/no of whether to add the tag), and the commit hook can use this to determine whether to add the tag or not?
cheers.
How about a commit hook that checks if the last commit modified the file in which you store the version? Something like:
[hooks]
commit.tagversion = if hg log -r $HG_NODE --template '{files}' | grep -q VERSION_FILE ; then hg tag $(hg cat -r $HG_NODE VERSION_FILE) ; fi
I haven't tested it, but that or something like it should work.
You could extract the tag name that you would add and then check to see if it already exists in hg tags before you add it. That would also catch the case where the developer amends the version number manually.

How to disable pretxncommit hooks with mercurial queues or histedit?

I have some pretxncommit hooks in my local mercurial repository, those hooks are used to check that the commit message includes a reference to a ticket and some other sanity checks.
My problem is that when I try to use mercurial queues, commands like qnew try to run these hooks and the one of the ticket checking fails, I have seen the same problem with histedit and similar extensions.
Why are pretxncommit hooks executed with these commands? Do they run some kind of internal commit?
How can I make these hooks to be run only on commits?
Yes, a qnew creates a real commit and thus invokes all the relevant commit hooks. You can confirm this for yourself by temporarily disabling MQ while you have an MQ patch applied and looking at the log.
There is no way to make the pretxncommit hook apply to only some commands except by jury-rigging something with other hooks:
$ cat .hg/hgrc
[hooks]
pre-qnew = touch .hg/skiphook
post-qnew = rm .hg/skiphook
pretxncommit = test -e .hg/skiphook || echo not skipping
$ hg rm README # make some change
$ hg qnew asdf # no hook
$ hg qpop
$ hg rm README
$ hg ci -m asdf
not skipping
Here our pretxncommit hook makes sure a specific file doesn't exist before running its (trivial) hook, and the pre-/post-qnew hooks create the file and clean it up.
The function abort_commit_to_wrong_branch in https://stackoverflow.com/a/19349636/350713
shows an approach to run a hook only on a "real" commit, not an MQ commit.
The idea is to check for the attribute _committingpatch in repo.
If repo has '_committingpatch' attribute, then it is an MQ commit in progress.
The relevant line is
if hasattr(repo, "_committingpatch"):
This is mentioned in the function newcommit in
http://hg.intevation.org/mercurial/crew/file/7032dcff290c/hgext/mq.py#l293
pretxncommit works with all changes (recordable) inside repo
if you want ignore mq-operation, you could look for the changeset parents and see if that's a descendant
of the qparent/qbase tag or see at WC. Smth. like (dirty from head, not from test) hg id -tr .
Or (maybe delirium) - when you work with MQ, you work with qtip always, sn't it?
>hg parents
...
tag: qtip
tag: tip
..

Does Mercurial support empty commit messages?

Is there a way to configure Mercurial to allow for empty commit messages? If you try hg commit through the CLI without entering a commit message, the commit is canceled with: abort: empty commit message.
Now, I know that committing without a message is usually considered bad form, but does Mercurial allow it at all?
You can use just a space, but I'd really discourage it:
hg commit -m " "
If the problem is that you don't want to enter the -m "blah" part you can always set up an alias. e.g. in hgrc
[alias]
qcommit = commit -m "quick commit - no message"
If you don't like qcommit then you can alias to commit instead i.e.
[alias]
commit = commit -m "quick commit - no message"
this won't help you with TortoiseHG however which presumebly validates its entry fields before passing data to mercurial iteslf

Mercurial auto update problem

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)