How to read hgrc properties from Mercurial hook - mercurial

I did not find anything from the Mercurial hook documentation explaining how to get properties of the repository's hgrc file from a custom python hook.
As the documentation states that we have access to the full Mercurial API from hooks, I suppose this should be possible. But how?
Moreover I could not find a precise documentation on what are the objects (ui, repos, ...) passed in argument to the Mercurial hook.

Ok I find out the answer by myself.
This page gives some hints about the argument passed to the hook functions: https://www.mercurial-scm.org/wiki/MercurialApi#Reading_configuration_files
ui.config functions permit to read Mercurial configuration files, giving the section and property name.

Related

How to set up mercurial hooks in Kallithea

I've been at it for a while now and I can't seem to get it working.
As per Kallithea documentation:
To add another custom hook simply fill in the first textbox with <name>.<hook_type> and the second with the hook path. Example hooks can be found in kallithea.lib.hooks.
So my first attempt was to add a new method to hooks.py. Basically to test out the hook I want to prevent ALL push to the repo. So I'll use pretxnchangegroup and return non 0 non false value as Mercurial documentation states
A hook that executes successfully must exit with a status of zero if external, or return boolean “false” if in-process. Failure is indicated with a non-zero exit status from an external hook, or an in-process hook returning boolean “true”. If an in-process hook raises an exception, the hook is considered to have failed.
So I did this:
def myhook(ui, repo, **kwargs):
return True
And I added the hook to the GUI in Kallithea hook options:
pretxnchangegroup <=> python:kallithea.lib.hooks.myhook
This however failed because for some reason the method can't be found
abort: pretxnchangegroup hook is invalid ("kallithea.lib.hooks.myhook" is not defined)
So I tried putting it in another file ( in the same 'lib' folder where hooks.py is ). Created a file called canpush.py and added the same method there. I changed the hook path to target the new file name:
pretxnchangegroup <=> python:kallithea.lib.hooks.myhook
However the hook does not trigger, and I can push to my repo without a problem. I plan to change the actual hook implementation in the future, push will be allowed, but first I need to get any hook functional with Kallithea.
What am I doing wrong here ?
Also, if someone knows how to use hgrc settings from individual repo within Kallithea an example would be great. Original question here.
Answering my own question, but just to keep it as reference.
As it turned out the setup was fine, but in an act of desperation I decided to restart kallithea daemon ( which was nowhere in the documentation ), basically thinking 'what could go wrong' - and that did the trick!
I guess during the startup process things get compiled / cached and the hook definition methods are found and functional ( If someone has a better explanation as to what happens on kallithea restart please share it )
So bare in mind, after every change to the hooks files kallithea daemon must be restarted in order for hooks to have any effect.
sudo service kallithea restart
Something else that wasn't clear to me from reading the kallithea documentation is that the hooks are mercurial hooks, they're not really some kallithea/rhodecode API, it's mercurial all the way.
This means that the best source of documentation on how to write one is something like http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html

How to get the working directory of the command from an hg hook?

I'm working on a commit hook for Mercurial and running into problems with relative paths.
Say my hook wants to look at the contents of the files being committed and warn if any contain the phrase "xyzzy". However, the user has decided to call commit from a subfolder and pass in the name of the file as a pattern...
C:\clone\subdir> hg commit file.txt -m 'test'
My hook is called with C:\clone as the working directory, but HG_PATS contains simply file.txt with no subdir\ prefix. How can I get the working directory of the hg command itself? I can't find a way to do this in docs.
The only way I can figure out how to get it is look up the process tree to find the first hg.exe and get its working directory. But that's not exactly portable to other OS's. (And I know I could write an extension, but would really like to avoid that.)
If you use the pretxncommit hook then you are given $HG_NODE which is the commit id, but the commit hasn't been finalized at that point so you can still return 1 to cancel it.
Then you could use
hg log -r $HG_NODE --template '{files}'
to get the list of files in the commit, and it gives you the full path relative to the repo root.
It's not exactly what you were after but it might get you close enough to let you do the content examination you want.
Thanks for the answers and comments, but after some more research I determined there's no clean way to do what I want from an external hook. I did implement the CWD hack I mentioned in my question. Not a ton of code, but quite nasty, and on Windows it requires undocumented access to external process CWD via tlist.exe. It works, but..yuck.
The right way to do this appears to be to write an in-process hook (example library at hghooklib). Usual versioning caveats apply as with writing any extension, though I think for our hooks the interface to hg is simple enough that we'll be ok.
(In my question I mentioned I didn't want to write an extension, but I was thinking of a full extension like hgeol. A hook-only extension with a single function entry point feels more constrained and simple, which is what I want at this point.)

mercurial pre-push hook parameter to obtain the remote repo path

I'm trying to implement a mercurial pre-push hook which checks the target repo path and adds the appropriate id by ssh-add. The not so nice solution would be checking the command line parameters and if the path isn't forced, then reading the default from the hgrc file but is there a cleaner way to just obtain the remote path?
I printed the kwargs passed into the hook method but there isn't any which seem to hold what I need. I also tried googling but the info available is next to nothing and this appears to be a bit like a black art really. So, any reference to a decent documentation and/or examples would be appreciated too.
Cheers,
Looking in hg help config, it seems like you can use the 'prechangegroup' hook and the HG_URL environment variable:
"prechangegroup"
Run before a changegroup is added via push, pull or unbundle. Exit
status 0 allows the changegroup to proceed. Non-zero status will cause
the push, pull or unbundle to fail. URL from which changes will come is
in "$HG_URL".
You should be able to use the 'pre-changegroup' and 'pre-push' hook (mind the dash). Which supplies the command line arguments as $HG_ARGS.
If the $HG_ARGS is a valid url you can use that url. If nothing is supplied use the ui object that is given as a keyword argument to the hook.
Use the following to retreive the default path from the configuration: ui.config('paths', 'default')
As you can also write other named urls/paths in the configuration file you should also be able to verify the $HG_ARGS if it doesn't contain a valid url a a keyword to the ui.config paths object

Mercurial: how to add a hook on pull

I've searched awhile for this and haven't seen anything. Which could mean, it's not supposed to be done or it just can't be done.
I looked at a list of hooks for mercurial and I could not seem to find (or get one working) that executed a script after you give the hg pull command.
Thank you
From the hgrc docs section on "hooks" -
"incoming"
Run after a changeset has been pulled, pushed, or unbundled into the
local repository. The ID of the newly arrived changeset is in
"$HG_NODE". URL that was source of changes came is in "$HG_URL".
or...
"post-<command>"
Run after successful invocations of the associated command. The contents
of the command line are passed as "$HG_ARGS" and the result code in
"$HG_RESULT". Parsed command line arguments are passed as "$HG_PATS" and
"$HG_OPTS". These contain string representations of the python data
internally passed to <command>. "$HG_OPTS" is a dictionary of options
(with unspecified options set to their defaults). "$HG_PATS" is a list
of arguments. Hook failure is ignored.
(The documentation also goes into detail about what the config should actually look like and how hook scripts are called.)

Mercurial API: How can I get the coming content of the file which was pulled but has not been updated yet?

I'm a complete noob at Mercurial API and Python, but I'm trying to write a useful extension for myself and my colleagues now.
Let's assume I have a repository which contains some code and an auxiliary file .hgdata. The code and .hgdata are both under Mercurial's control. When I execute a command pull-extended which is provided by my extension, I want it to make a pull and then to analyze the state of a .hgdata and probably make some additional actions. The problem is that when my command is invoked, it just pulls the incoming changesets, but it can't look into the actual .hgdata without making a preceding repository update. Is there any way to watch the after update .hgdata besides repository update?
I've received an answer on the Mercurial's official IRC channel:
In order to get an actual file state after making a pull, we may use repo[revision][file].data().
P.S. I haven't checked that yet. If it works, I will close the question.