What are the hook parameters passed to external hook program/script? - mercurial

The title says it: I am looking for the variable names (HG_*) so I can make use of them in my hook script..

Oben has your best answer, but for specific cases or poorly documented options you can easily test specific hooks using a hook that just prints variables:
hg --config hooks.pre-commit="export| grep HG_" commit
Where pre-commit can be any hook you want to test and commit can be any command you want to test.
For example that one showed:
export HG_ARGS='commit'
export HG_OPTS='{'"'"'exclude'"'"': [], '"'"'message'"'"': '"''"', '"'"'addremove'"'"': None, '"'"'include'"'"': [], '"'"'close_branch'"'"': None, '"'"'user'"'"': '"''"', '"'"'date'"'"': '"''"', '"'"'logfile'"'"': '"''"', '"'"'mq'"'"': None}'
export HG_PATS='[]'

The hooks section in the hgrc manpage lists all defined hooks, including the environment variables available for each hook.

Related

How to pass options to UglifyJS through html-minifier on Windows command line?

HTMLMinifier (html-minifier) (3.5.14) for Node.js (v8.11.1), installed with npm install html-minifier -g, can be run via command line (Windows CMD), e.g. html-minifier --help produces the usage info (excerpts):
Usage: html-minifier [options] [files...]
Options:
-V, --version output the version number
...
--minify-js [value] Minify Javascript in script elements and on* attributes (uses uglify-js)
...
-c --config-file <file> Use config file
--input-dir <dir> Specify an input directory
--output-dir <dir> Specify an output directory
--file-ext <text> Specify an extension to be read, ex: html
-h, --help output usage information
The option --minify-js [value] relies on UglifyJS to "compress" the JavaScript embedded inside the HTML file(s) passed to html-minifier. UglifyJS can remove console.log() function calls (Can uglify-js remove the console.log statements?) from the JavaScript, by enabling the drop_console option (also see pure_funcs).
But --minify-js drop_console=true does not have an effect, nor does something like "uglify:{options:{compress:{drop_console:true}}}" or "compress:{pure_funcs:['console.log']}".
How can such an option be set, ideally via the html-minifier command line (alternatively by config-file, though it just sets "minifyJS": true)?
I was very close.
I started digging through the code (installed in %appdata%\npm\node_modules\html-minifier) to see what happens with the options provided, i.e. adding debug output with console.log(xyz); (using an actual debugger probably would be a better idea).
So, here's my "trace":
option: https://github.com/kangax/html-minifier/blob/gh-pages/cli.js#L118
option handling: https://github.com/kangax/html-minifier/blob/gh-pages/cli.js#L144
argument parsing using [commander][2]
createOptions() https://github.com/kangax/html-minifier/blob/gh-pages/cli.js#L197
options then contains e.g. minifyJS: 'compress:{pure_funcs:[\'console.log\']}',
passed on to minify() https://github.com/kangax/html-minifier/blob/gh-pages/src/htmlminifier.js#L806 which immediately runs
processOptions() https://github.com/kangax/html-minifier/blob/gh-pages/src/htmlminifier.js#L616
where finally in line https://github.com/kangax/html-minifier/blob/gh-pages/src/htmlminifier.js#L667 options.minifyJS is handled, before it's run as var result = UglifyJS.minify(code, minifyJS); in https://github.com/kangax/html-minifier/blob/gh-pages/src/htmlminifier.js#L680.
But there our option string compress:{pure_funcs:['console.log']} gets cleaned because it's not yet an object, resulting in {}.
Or, in a different trial with a different string you may encounter the error Could not parse JSON value '{compress:{pure_funcs:'console.log']}}'
At least it gets that far! But why doesn't it work?
First, it's a good time to revisit the JSON spec: https://www.json.org/index.html
Second, see if the string could be parsed as valid JSON, e.g. with the JSON.parse() demo at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
Third, figure out how to get that string through the CMD as argument (escaping the double quotes).
Finally, make sure the data structure to configure UgliFyJS is correct. That's quite easy, since it's documented: https://github.com/mishoo/UglifyJS2#minify-options-structure
And behold, simply escaping the double quotes with a backslash works for me:
html-minfier ... --minify-js {\"compress\":{\"pure_funcs\":[\"console.log\"]}} ...
and it properly shows up in the options as
...
{ compress:
{ pure_funcs: [ 'console.log' ],
...
For ex. curl can read config from a file, like proxies, etc...
Many programs do so. git, maven, gradle.... No matter how and where you call them, they look for the config you or the system provides: first from the current directory, then from the user home and then the system /etc/...
If no batteries included with these node packages, they can only be used on separate html and js files.

Babel cli preset config

Due to some certain reason I don't wish to use .babelrc file even though I'm well aware of the fact that I'm supposed to follow the rules. Anyways, for the run time I'm using the following code
require('babel-register')({
babelrc: false,
presets: [
'stage-0',
['env', {
targets: {
node: 'current'
}
}]
],
plugins: [
'transform-async-to-generator',
'syntax-async-functions'
]
});
require('../server/core');
Now I need the same config to be executed from shell. E.g.
babel config --out-dir
Thanks for your help
There is currently no way to pass plugin/preset options via CLI arguments. https://github.com/babel/babel/issues/4161 so if you don't wish to use a .babelrc then there's no easy way to get args in via the CLI command.
Given that, your next best bet would be to use something like gulp-babel to put together your own build pipeline with programmatic arguments like babel-register has.

How can I turn off ESLint's no-restricted-syntax rule just for ForOfStatement?

I am using ESLint for my ES6 program, with the AirBNB rule-set. For good and adequate reasons, I am using the for...of construction in my code, but ESLint objects to it, issuing a no-restricted-syntax error.
The documentation at http://eslint.org/docs/rules/no-restricted-syntax explains how I can specify in my .eslint file the set of syntax-tree nodes that it objects to: for example, if all I dislike is the with statement, I can use:
"no-restricted-syntax": ["warn", "WithStatement"]
But I don't want to specify a whole set of unapproved constructions, I just want to say that I consider one such construction OK. Something conceptually similar to
ESlint.rules['no-restricted-syntax'].removeEntry('ForOfStatement');
Is there a way to do this in the ESLint file? Or, failing that, is there at least a way to get it to tell me what its current no-restricted-syntax configuration is, so I can manually remove ForOfStatement from it?
Check existing config
Based on the current master branch, eslint-config-airbnb currently disables four syntax forms:
ForInStatement
ForOfStatement
LabeledStatement
WithStatement
You can verify this or see if there are any differences by using ESLint's --print-config CLI flag:
$ eslint --print-config file.js
ESLint will print out the config it would use to lint file.js, and you can find the config for the no-restricted-syntax rule there.
Override no-restricted-syntax
If you want to override Airbnb's preset, you can do so in the rules section of your .eslintrc.json file:
{
"rules": {
"no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"]
}
}
There's no way to configure the rule to use the no-restricted-syntax config inherited from Airbnb's preset excepting only a single syntax form.
Add the below lines of code to restrict this error in your application in .eslintrc.js file
module.exports = {
extends: ['airbnb-base', 'plugin:prettier/recommended'],
plugins: ['no-only-tests'],
rules: {
'no-only-tests/no-only-tests': 2,
"no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"]
},
};

How to show hook output in Tortoise Hg log window?

I need simple hook for mercurial that checks commit comment using pattern. Here is my hook:
#!/usr/bin/env python
#
# save as .hg/check_whitespace.py and make executable
import re
def check_comment(comment):
#
print 'Checking comment...'
pattern = '^((Issue \d+:)|(No Issue:)).+'
if re.match(pattern, comment, flags=re.IGNORECASE):
return 1
else:
print >> sys.stderr, 'Comment does not match pattern. You must start it with "Issue 12323:" or "No Issue:"'
return 0
if __name__ == '__main__':
import os, sys
comment=os.popen('hg tip --template "{desc}"').read()
if not check_comment(comment):
sys.exit(1)
sys.exit(0)
It works. It even shows error message 'Comment does not match pattern. You must start it with "Issue 12323:" or "No Issue:"' when I commit from console. But when I trying to commit from Tortoise Hg Workbench, only system message is shown: abort: pretxncommit.check_comment hook exited with status 1.
I need to inform user what is wrong. Is there any way to force Tortoise Hg to show output from hook?
I got it to work by making it an in-process hook rather than an external hook. In-process hooks are defined quite differently, however.
First, the python file needs only a single function that will be called by the name in the hook definition. The hook function is passed ui, repo, and hooktype objects. It is also passed additional objects based on the type of hook. For pretrxncommit, it is passed node, parent1, and parent2, but you're only interested in node, so the rest are gathered in kwargs. The ui object is used to give the status and error messages.
Contents of check_comment.py:
#!/usr/bin/env python
import re
def check_comment(ui, repo, hooktype, node=None, **kwargs):
ui.status('Checking comment...\n')
comment = repo[node].description()
pattern = '^((Issue \d+:)|(No Issue:)).+'
if not re.match(pattern, comment, flags=re.IGNORECASE):
ui.warn('Comment does not match pattern. You must start it with "Issue 12323:" or "No Issue:"\n')
return True
In the hgrc, the hook would be defined with python:/path/to/file.py:function_name, like this:
[hooks]
pretxncommit.check_comment = python:/path/to/check_comment.py:check_comment
The .suffix_name on pretxncommit is to avoid overriding any globally defined hook, especially if this is defined in the repository's hgrc rather than the global one. Suffixes are how one allows multiple responses to the same hook.
In case the hook runs on a repository that is served via e.g. hgserve:
I use this small Python function in a pretxnchangegroup script to show the same output
in the server log
in the TortoiseHg workbench Log pan or the cmd line
:
def log(ui, string):
print(string) # will show up as "remote:" on the client
ui.status("{0}\n".format(string)) # will show up in the same hg process: hgserve ; append newline
return

How do I write my hgrc so that Mercurial detects my hooks?

've written two functions in a file commit_hooks.py that I want to run before any commit is made persistent, but I can't figure out how to write my hgrc to detect them.
The function headers are:
def precommit_bad_merge(ui, repo, parent1=None, parent2=None, **kwargs):
...
def precommit_bad_branching(ui, repo, **kwargs):
...
I've tried using this "guide", but the documentation is too "man pagey" for me. The following is an outcast which doesn't work.
[hooks]
precommit = ..\..\mno2\commit_hooks.py
Update!
Rewriting the hook line to:
precommit = D:\environments\next\mno2\commit_hooks.py
make Mercurial detect the precommit hook, but it always exits with status 1 for some reason.
Set up your [hooks] section like this:
[hooks]
precommit.foo = python:D:\environments\next\mno2\commit_hooks.py:precommit_bad_merge
precommit.bar = python:D:\environments\next\mno2\commit_hooks.py:precommit_bad_branching
The syntax for the precommit line that you used is for external hooks, so it was treating your python file as a self-contained script (which I'm assuming it's not since you're using the function signatures for in-process hooks).
You may need to have the python executable in your path (I do).
For more information, see the definitive guide's section on in-process hooks; there's some useful information hidden in the comments.
The "man pagey" documentation has a section on python hook syntax:
The syntax for Python hooks is as
follows:
hookname = python:modulename.submodule.callable
hookname = python:/path/to/python/module.py:callable
Python hooks are run within the
Mercurial process. Each hook is called
with at least three keyword arguments:
a ui object (keyword ui), a repository
object (keyword repo), and a hooktype
keyword that tells what kind of hook
is used. Arguments listed as
environment variables above are passed
as keyword arguments, with no HG_
prefix, and names in lower case.
If a Python hook returns a "true"
value or raises an exception, this is
treated as a failure.