The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

App::GitHooks - Extensible plugins system for git hooks.

VERSION

Version 1.9.0

DESCRIPTION

App::GitHooks is an extensible and easy to configure git hooks framework that supports many plugins.

Here's an example of it in action, running the pre-commit hook checks before the commit message can be entered:

Here is another example, with a Perl file that fails compilation this time:

SYNOPSIS

  1. Install this distribution (with cpanm or your preferred CPAN client):

            cpanm App::GitHooks
  2. Install the plugins you are interested in (with cpanm or your prefered CPAN client), as App::GitHooks does not bundle them. See the list of plugins below, but for example:

            cpanm App::GitHooks::Plugin::BlockNOCOMMIT
            cpanm App::GitHooks::Plugin::DetectCommitNoVerify
            ...
  3. Go to the git repository for which you want to set up git hooks, and run:

            githooks install
  4. Enjoy!

GIT REQUIREMENTS

App::GitHooks requires git v1.7.4.1 or above.

VALID GIT HOOK NAMES

  • applypatch-msg

  • pre-applypatch

  • post-applypatch

  • pre-commit

  • prepare-commit-msg

  • commit-msg

  • post-commit

  • pre-rebase

  • post-checkout

  • post-merge

  • pre-receive

  • update

  • post-receive

  • post-update

  • pre-auto-gc

  • post-rewrite

OFFICIALLY SUPPORTED PLUGINS

CONTRIBUTED PLUGINS

CONFIGURATION OPTIONS

Configuration format

App::GitHooks uses Config::Tiny, so the configuration should follow the following format:

        general_key_1 = value
        general_key_2 = value

        [section_1]
        section_1_key 1 = value

The file is divided between the global configuration options at the beginning of the file (such as general_key_1 above) and plugin specific configuration options which are located in distinct sections (such as section_1_key in the [section_1] section).

Configuration file locations

App::GitHooks supports setting custom options by creating one of the following files, which are searched in descending order of preference:

  • A file of any name anywhere on your system, if you set the environment variable GITHOOKSRC_FORCE to its path.

    Note that you should normally use GITHOOKSRC. This option is provided mostly for testing purposes, when configuration options for testing in a reliable manner are of the utmost importance and take precedence over any repository-specific settings.

  • A .githooksrc file at the root of the git repository.

    The settings will then only apply to that repository.

  • A file of any name anywhere on your system, if you set the environment variable GITHOOKSRC to its path.

    Note that .githooksrc files at the top of a repository or in a user's home directory will take precedence over a file specified by the GITHOOKSRC environment variable.

  • A .githooksrc file in the home directory of the current user.

    The settings will then apply to all the repositories that have hooks set up. Note that if .githooksrc file is defined at the root of a repository, that configuration file will take precedence over the one defined in the home directory of the current user (as it is presumably more specific). Auto-merge of options across multiple .githooksrc files in an inheritance fashion is not currently supported.

General configuration options

  • project_prefixes

    A comma-separated list of project prefixes, in case you want to use this in extract_ticket_id_from_commit or extract_ticket_id_from_branch.

            project_prefixes = OPS, DEV
  • extract_ticket_id_from_commit

    A regular expression with _one_ capturing group that will be applied to the first line of a commit message to extract the ticket ID referenced, if there is one.

            extract_ticket_id_from_commit = /^($project_prefixes-\d+|--): /
  • extract_ticket_id_from_branch

    A regular expression with _one_ capturing group that will be applied to branch names to extract a ticket ID. This allows creating one branch per ticket and having the hooks check that the commit messages and the branch names are in sync.

            extract_ticket_id_from_branch = /^($project_prefixes-?\d+)/
  • normalize_branch_ticket_id

    A replacement expression that normalizes the ticket ID captured with extract_ticket_id_from_branch.

            normalize_branch_ticket_id = s/^(.*?)-?(\d+)$/\U$1-$2/
  • skip_directories

    A regular expression to filter the directory names that should be skipped when analyzing files as part of file-level checks.

            skip_directories = /^cpan(?:-[^\/]+)?\//
  • force_plugins

    A comma-separated list of the plugins that must be present on the system and will be executed. If any plugins from this list are missing, the action will error out. If any other plugins not in this list are installed on the system, they will be ignored.

            force_plugins = App::GitHooks::Plugin::ValidatePODFormat, App::GitHooks::Plugin::RequireCommitMessage
  • min_app_githooks_version

    Specify the minimum version of App::GitHooks.

            min_app_githooks_version = 1.9.0

Testing-specific options

  • limit_plugins

    Deprecated. Use force_plugins instead.

  • force_interactive

    Force the application to consider that the terminal is interactive (`1`) or non-interactive (`0`) independently of whether the actual STDOUT is interactive or not.

  • force_use_colors

    Force the output to use colors (`1`) or to not use colors (`0`) independently of the ability of STDOUT to display colors.

  • force_is_utf8

    Allows the output to use utf-8 characters (`1`) or not (`0`), independently of whether the output declares supporting utf-8.

  • commit_msg_no_edit

    Allows skipping the loop to edit the message when the commit message checks failed.

ENVIRONMENT VARIABLES

GITHOOKS_SKIP

Comma separated list of hooks to skip. A warning is issued for each hook that would otherwise be triggered.

        GITHOOKS_SKIP=pre-commit,update

GITHOOKS_DISABLE

Works similarly to GITHOOKS_SKIP, but it skips all the possible hooks. Set it to a true value, e.g. 1.

        GITHOOKS_DISABLE=1

GITHOOKSRC

Contains path to a custom configuration file, see "Configuration file locations" above.

GITHOOKSRC_FORCE

Similar to GITHOOKSRC but with a higher priority. See "Configuration file locations" above.

FUNCTIONS

run()

Run the specified hook.

        App::GitHooks::run(
                name      => $name,
                arguments => \@arguments,
        );

Arguments:

  • name (mandatory)

    The name of the git hook calling this class. See the "VALID GIT HOOK NAMES" section for acceptable values.

  • arguments (optional)

    An arrayref of arguments passed originally to the git hook.

  • exit (optional, default 1)

    Indicate whether the method should exit (1) or simply return the exit status without actually exiting (0).

METHODS

new()

Create a new App::GitHooks object.

        my $app = App::GitHooks->new(
                name      => $name,
                arguments => \@arguments,
        );

Arguments:

  • name (mandatory)

    The name of the git hook calling this class. See the "VALID GIT HOOK NAMES" section for acceptable values.

  • arguments (optional)

    An arrayref of arguments passed originally to the git hook.

clone()

Clone the current object and override its properties with the arguments specified.

        my $cloned_app = $app->clone(
                name => $hook_name, # optional
        );
  • name (optional)

    The name of the invoking hook.

get_hook_plugins()

Return an arrayref of all the plugins installed and available for a specific git hook on the current system.

        my $plugins = $app->get_hook_plugins(
                $hook_name
        );

Arguments:

  • $hook_name

    The name of the git hook for which to find available plugins.

get_all_plugins()

Return a hashref of the plugins available for every git hook.

        my $all_plugins = $self->get_all_plugins();

get_config()

Retrieve the configuration information for the current project.

        my $config = $app->get_config();

force_non_interactive()

By default App::GitHooks detects whether it is running in interactive mode, but this allows forcing it to run in non-interactive mode.

        # Retrieve the current setting.
        my $force_non_interactive = $app->force_non_interactive();

        # Force non-interactive mode.
        $app->force_non_interactive( 1 );

        # Go back to the default behavior of detecting the current mode.
        $app->force_non_interactive( 0 );

get_failure_character()

Return a character to use to indicate a failure.

        my $failure_character = $app->get_failure_character()

get_success_character()

Return a character to use to indicate a success.

        my $success_character = $app->get_success_character()

get_warning_character()

Return a character to use to indicate a warning.

        my $warning_character = $app->get_warning_character()

get_staged_changes()

Return a App::GitHooks::StagedChanges object corresponding to the changes staged in the current project.

        my $staged_changes = $app->get_staged_changes();

use_colors()

Allows disabling the use of colors in App::GitHooks's output.

        # Retrieve the current setting.
        my $use_colors = $app->use_colors();

        # Disable colors in the output.
        $app->use_colors( 0 );

ACCESSORS

get_repository()

Return the underlying Git::Repository object for the current project.

        my $repository = $app->get_repository();

get_remote_name()

Get the name of the repository.

        my $remote_name = $app->get_remote_name();

get_hook_name

Return the name of the git hook that called the current instance.

        my $hook_name = $app->get_hook_name();

get_command_line_arguments()

Return the arguments passed originally to the git hook.

        my $command_line_arguments = $app->get_command_line_arguments();

get_terminal()

Return the App::GitHooks::Terminal object associated with the current instance.

        my $terminal = $app->get_terminal();

DISPLAY METHODS

wrap()

Format information while respecting the format width and indentation.

        my $string = $app->wrap( $information, $indent );

color()

Print text with colors.

        $app->color( $color, $text );

PRIVATE FUNCTIONS

_to_camelcase()

Convert a dash-separated string to camelcase.

        my $camelcase_string = App::GitHooks::_to_camelcase( $string );

This function is useful to convert git hook names (commit-msg) to module names (CommitMsg).

_should_skip()

See the environment variables GITHOOKS_SKIP and GITHOOKS_DISABLE above. This function returns the variable name that would be the reason to skip the given hook, or nothing.

        return if _should_skip( $name );

NOTES

Manual installation

Symlink your git hooks under .git/hooks to a file with the following content:

        #!/usr/bin/env perl

        use strict;
        use warnings;

        use App::GitHooks;

        App::GitHooks->run(
                        name      => $0,
                        arguments => \@ARGV,
        );

All you need to do then is install the plugins you are interested in!

This distribution also includes a hooks/ directory that you can symlink / copy to .git/hooks/ instead , to get all the hooks set up properly in one swoop.

Important: adjust /usr/bin/env perl as needed, if that line is not a valid interpreter, your git actions will fail with error: cannot run .git/hooks/[hook name]: No such file or directory.

BUGS

Please report any bugs or feature requests through the web interface at https://github.com/guillaumeaubert/App-GitHooks/issues/new. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

        perldoc App::GitHooks

You can also look for information at:

AUTHOR

Guillaume Aubert, <aubertg at cpan.org>.

COPYRIGHT & LICENSE

Copyright 2013-2017 Guillaume Aubert.

This code is free software; you can redistribute it and/or modify it under the same terms as Perl 5 itself.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file for more details.