Glerbl is a tool to help manage git hooks and promote consistent coding standards among contributors to a repository.
Python
Switch branches/tags
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
features
glerbl
.gitignore
COPYING.txt
MANIFEST.in
README.rst
pylintrc
setup.cfg
setup.py
tox.ini

README.rst

Glerbl is a tool to help manage git hooks and promote consistent coding standards among contributors to a repository.

Let's say you maintain a github repository for which you want to ensure the following coding standards:

  • No trailing spaces.
  • No non-ascii file names.
  • All python code must conform to pep8.

You can hope that contributors will remember to run the necessary checks before they send in pull requests or push code to the repository.

Or you can use glerbl to formalize your requirements and provide all collaborators with the means to detect problems and fix these problems before they commit.

Requirements

Glerbl currently requires a POSIX-compliant system to run. There's nothing that would inherently prevent it from running on other systems, though.

Using

Readers should keep the following distinctions in mind while reading:

Git hook
A hook as git understands it. Git supports multiple hooks but each hook is unique. That is, git supports multiple hook in the sense that there can be a pre-commit and a post-commit hook. These are two different hooks. However there can be one and only one pre-commit hook at at time, and one post-commit hook at a time, etc.
Glerbl check
A glerbl check runs when a specific git hook runs, but there may be multiple glerbl checks per git hook.

Warning

Glerbl will completely take over any git hook you ask it to manage. So if you ask glerbl to install any glerbl pre-commit check, it will remove .git/hooks/pre-commit and install its own script. Glerbl is not designed to work well with any other hook management system. However, glerbl is designed to leave alone any git hook you don't ask it to manage.

Create a directory named .glerbl in the root of your git repository and in it a file named repo_conf.py. That file must assign a dictionary to a top level variable named check. Each key of this dictionary must be a git hook type (pre-commit and so on). Each value must be a list of checks to perform. Checks are modules under glerbl.check. The list of checks in the configuration file can be the name of the module which performs the check, relative to glerbl.check. To get a list of available checks you can use:

$ glerbl listchecks

A .glerbl/repo_conf.py file could look like:

checks = {
    "pre-commit": ["no_before_commit", "no_non_ascii_filenames",
                   "no_trailing_whitespace", "python_no_trailing_semicolon",
                   "python_pep8"]
}

Once your file is set, you can issue:

$ glerbl install

at the top of your working tree. Glerbl will ask whether you want to proceed with the installation. Type "yes" (the whole word) if you want to proceed. Anything else will abort the installation. Glerbl will report errors if there are a problems.

Configuration Files

The file .glerbl/repo_conf.py has already been mentioned. This file is meant to record the standards under which a repository operates. Therefore, this file should be tracked by git and should reflect the minimum standards everyone who contribute to the repository must follow. But what if a contributor wants to add more checks to fit his or her local needs? This contributor could edit repo_conf.py, but then this file would keep showing up in git as modified. Committing the changes would be risky because these local changes should not propagate upstream. There could be a command line option to point glerbl to a different configuration file but then the contributor would have to remember to pass this option.

Glerbl solves this problem by looking for a file named .glerbl/local_conf.py. If this file is present, then this file is read as configuration instead of .glerbl/repo_conf.py The file .glerbl/local_conf.py can safely be put in .gitignore.

Design Notes

Glerbl is a collection of checks, written in Python. If you want to use another language, convert glerbl to your language or choice, or use another tool.

Those hooks that check the data about to be committed are run on what HEAD will look like once what is staged is committed. So if file X is staged but file Y is not, glerbl's hooks won't check file Y. Also if you staged only some hunks of file X, then only those hunks that are staged will get checked. Glerbl does this by duplicating the working tree into a temporary location, extracting the contents of the files from the staging area onto those files at this location, and deleting those that are to be deleted in the commit. I've seen quite a few hooks on the internet that would run tools like pylint on the working tree itself. Imagine the following scenario. You've added import foo to file X. You've staged this modification but you erroneously forgot to stage the new file foo.py. If pylint is run against the working tree, you won't get an error regarding this problem because your working tree is fine. If pylint is run against what HEAD will look like instead of the working tree, pylint will report being unable to import foo.

FAQ

Q:

I get why glerbl does not run checks against the working tree but when I stage files partially, the error reports I get are useless because the files I have access to in the working tree are different from those files that are staged.

A:

git stash is your friend. Stash what you are not committing. This way your working tree is identical to what HEAD will look like once the commit goes through. Try to commit again. Fix the problems. Commit. Pop the stash.

Another way to solve this problem is using tools that prevent the problems reported by glerbl's hooks form happening in the first place. For instance, Emacs can be configured to automatically strip trailing space. Or if the issues cannot be automatically fixed, then using tools that show problems as they occur can also help.

Q:

I need to commit automatically generated code which violates some of the checks I've asked glerbl to perform. For instance, code generated by South.

A:

Stage only the automatically generated code and use git commit --no-verify to temporarily bypass the pre-commit checks. (Glerbl might eventually acquire a way to disable checks more selectively than this.)

Note that if glerbl checked the files in the working tree rather than against the post-commit HEAD you'd have to actually remove files from your working tree to get around this problem. Or you'd have to use --no-verify while committing files that should be checked, thereby risking letting errors slip through.

Q:

What about someone who wants to cause trouble? They just won't run glerbl on their "contribution".

A:

See the next question.

Q:

Why not use server-side hooks to ensure my standards? That seems safer to me because there's no guarantee that a contributor will run glerbl at all.

A:

Repository hosting services rarely allow you to set your own custom server-side hooks. A prime example is github.

Supporting server-side hooks would also require glerbl to be more sophisticated than it is right now. Consider the case where you want to exclude file F form hook's H's checks because F is generated by a third-party tool. You'd have to have a way to tell the server that H is not to be run on F.

There is a way to simulate server-side checks designed to prevent letting inadequate code enter a repository. For instance, a pull request has been issued on github. On your computer, check out the branch onto which the code is to be pulled, pull onto it the code in the request. Run:

GIT_DIR=`pwd`/.git .git/hooks/pre-commit

Fix errors as needed. (This could mean telling the contributor that they did not use glerbl properly, etc.)

Since github allows you to install hooks to get notification of events like pull requests, this could conceivably be automated.

All of glerbl's code and documentation is Copyright 2013 Louis-Dominique Dubeau.