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.)
Related
We are looking for a way to add / update a custom tag at the beginning of each file being committed during a commit. Its some kind of local timestamp we need.
I was thinking of hooks.
Unfortunately I cannot find a useful hook for that:
precommit: unsuitable as it fires before hg knows any metadata of the commit
pretxncommit: unsuitable, as the documentation clearly states that we should not change the working dir at this point
commit: unsuitable, as it fires when the commit has already happened.
EDIT:
I can not use hg's inline changeset-hash and / or datetime. For the following reason:
Our files get later imported into an external system (we do not have control over) which does not support any kind of versioning.
To simplify stuff: let's say tag is an ever-incrementing no. (everytime we commit). This tag is then used to help getting an idea of the version / status of the file on the system in respect to the file in the repo - like "no. of changes we're missing" and such.
Any ideas?
I would suggest a two-stage solution. First, create an alias along the following lines:
[alias]
tcommit = !tag-changed-files && $HG commit "$#"
Here, tag-changed-files would retrieve a list of modified and added/moved files via $HG status -ma -n or $HG status -ma -n -0 and tag them. I am assuming that re-tagging files that have been modified but aren't being committed yet is a harmless operation; more on that below. Note that you can even redefine commit if you absolutely want to via:
[alias]
commit = !tag-changed-files && $HG --config alias.commit=commit commit "$#"
However, this is potentially problematic, because it may confuse scripts.
You could also integrate the commit step in the program if you wanted to, and even try and parse the command line arguments to only tag those files that you are committing. For this approach, using hglib might be appropriate to avoid the overhead of invoking Mercurial multiple times. (Note that hglib and other tools that use the command server ignore aliases and command defaults, so this works even if you alias commit).
Second, you'd install a pretxncommit hook that verifies that files that are being committed have indeed been tagged appropriately (to ensure that the tag-changed-files program hasn't been bypassed by accident).
This should work without a problem on full commits; for partial commits, any files that were changed but have not been committed would also have been retagged, but since they will be either committed later (and get tagged properly at that point) or reverted, that should be harmless.
an idea of the version / status of the file on the system in respect to the file in the repo
Just one idea
Stop reinvent the wheel
Incremental counter is just shit, if you task is "to know, which version is on LIVE and which - in Mercurial's tip" (and this is your real business-task, yes?!)
Keyword Extension give you last changes per file.
If you want to inject changeset of repository into files (it's reasonable good way), re-read this part of wiki-page
If you just want to version your entire repo, do not use this
extension but let your build system take care of it. Something along
the lines of
hg -q id > version
before distribution might be well enough if file-wise keyword
expansion in the source is not absolutely required
You can insert hg id output into files at export stage (in planetmaker's sed-style), bu you can also have this additional metadata in files permanently in VCS with special encode|decode filters
There is - to my knowledge - no intrinsic system in mercurial which supports what you describe. However I can recommend an approach which somewhat is adopted from building a software release package from the repository: Make a small export script which replaces a certain KEYWORD in your files with the version information you need. A Makefile target could look like which creates a zip export for revision XXX with version information in all files which support it (thus contain the verbatim KEYWORD - use something truely unique here):
VERSION=$(hg log -rXXX --template="Version: {node|short} from {date|isodate}")
export:
hg archive -rXXX -t files export
for i in $(hg ma -rXXX); do sed -i "s/KEYWORD/$VERSION/g" $i; done
zip -9rq export.zip export
I use a similar approach in my Makefiles where I create versioned export for the source of a particular revision of my software.
EDIT: if your purpose (as stated by the comment) is only to implant the number of commits made to that file: then you can use indeed a pre-commit hook and modify the file. You can count the number of modifications made to a file with hg log FILENAME --template="{node}\n" | wc -l. Do that for every file and do the sed replacement in the header of each file in the pre-commit 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.)
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
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.
I have a "central" repository that I want to ensure that no one pushes changes in to with a wrong user name.
But I can not figure out how to make a hook that tests the user name against a positive list. I have found in the Mercurial API a ctx.user() call that seems to be what I want to test my positive list against.
Also the hook could be a precommit hook that is distributed as part of the repository clone or it could be a hook on the central repository as a pre-incoming or something like that.
Any help or pointers would be greatly appreciated.
I have posted two functional examples on Bitbucket. Both examples are for searching a commit message for some specifically formatted text (like an issue tracked case ID), but could be easily modified to check a user against a list of valid users.
The first example is actually a Mercurial extension that wraps the 'commit' command. If it fails to find the appropriate text (or valid user in your case), it will prevent the commit from occurring at all. You can enable this in your .hgrc file by adding these lines:
[extensions]
someName = path/to/script/commit-msg-check.py
The second example uses a in-process pretxncommit hook, which runs between when the commit has been made, but before it becomes permanent. If this check fails it will automatically roll back the commit. You can enable this in your .hgrc file by adding these lines (assuming you kept the same file/function names):
[hooks]
pretxncommit.example = python:commit-msg-check-hook.CheckForIssueRecord
You can execute any Python code you like inside of these hooks, so user validation could be done in many ways.
Thanks for the examples dls.
In the end I decided to run it as a pretxnchangegroup hook and then use the hg log and grep to test the author field of the commits:
[hooks]
pretxnchangegroup.usercheck = hg log --template '{author}\n' -r \
$HG_NODE: | grep -qe 'user1\|user2\|etc'
It does of course not provide a very good feedback other than usercheck failed. But I think it is good enough for now.