Learn R Programming

⚠️There's a newer version (0.4.3) of this package.Take me there.

Useful git pre-commit hooks for R

Pre-commit hooks are tests that run each time you attempt to commit. If the tests pass, the commit will be made, otherwise not. A very basic test is to check if the code is parsable, making sure you have not forgotten a comma, brace or quote.

The goal of this package is to twofold:

  • Provide a set of hooks that are useful when your git repo contains R code.

  • Provide usethis-like functionality for common tasks such as installation and set-up and config file modification.

The following online docs are available:

These only cover the functionality added on top of the pre-commit framework by this package. Everything else is covered in the extensive online documentation of the pre-commit framework itself, including how to create hooks for actions like git push or git checkout, create local hooks etc.

Installation

You can install the package from CRAN:

install.packages("precommit")

To access pre-commit functionality from R, you also need to install the pre-commit framework on which the hook from this repo build. The following command line methods are tested to work with this R package (and accessing them from outside R is easier and use is slightly faster):

  • $ pip3 install pre-commit --user (macOS, Linux and Windows) outside a conda or virtual environment.

  • $ brew install pre-commit (macOS).

Alternatively, you can handle the installation from R using miniconda:

  • install miniconda if you don’t have it already: reticulate::install_miniconda(). This needs reticulate >= 1.14.

  • install the pre-commit framework with precommit::install_precommit() into the conda environment r-precommit. Do not install other packages into this environment.

Then, in a fresh R session:

# once in every git repo either
# * after cloning a repo that already uses pre-commit or
# * if you want introduce pre-commit to this repo
precommit::use_precommit()

The last command initializes pre-commit in your repo and performs some set-up tasks like creating the config file .pre-commit-config.yaml, where the hooks that will be run on git commit are specified. See ?precommit::use_precommit() to see how you can use a custom .pre-commit-config.yaml instead of the default at initialization. You can (obviously) change edit the file manually at any time.

Usage

The next time you run git commit, the hooks listed in your .pre-commit-config.yaml will get executed before the commit. The helper function precommit::open_config() let’s you open and edit the .pre-commit-config.yaml conveniently from the RStudio console. When any file is changed due to running a hook or the hook script errors, the commit will fail. You can inspect the changes introduced by the hook and if satisfied, you can add the changes made by the hook to the index with git add path/to/file and attempt to commit again. Some hooks change files, like the styler hook, so all you need to do to make the hook pass is git add the changes introduced by the hook. Other hooks, like the parsable-R hook, will need your action, e.g. add a missing closing brace to a call like library(styler, before they pass at the next attempt. If all hooks pass, the commit is made. You can also temporarily disable hooks. If you succeed, it should look like this:

See the hooks provided by this repo under vignette("available-hooks"). You can also add other hooks from other repos, by extending the .pre-commit-config.yaml file, e.g. like this:

-   repo: https://github.com/pre-commit/precommit
    rev: v1.2.3
    hooks: 
    -   id: check-added-large-files

To update the hook revisions, run precommit::autoupdate().

Caution

Do not abort while hooks are running in RStudio git tab. Non-staged changes are stashed to a temp directory and when you abort in RStudio, these changes are not brought back to you repo. Upvote this issue to change this. We hope that in the future, the changes will be recovered in RStudio too. Note that this is only an issue with RStudio. Stashes are restored when you abort a git commit with INT (e.g. Ctrl+C) on the command line. To restore stashes, manually after hitting abort in the RStudio git tab, you can git apply /path/to/patch_with_id whereas you find the patch under your pre-commit cache, which is usually under $HOME/.cache/pre-commit/.

Update

If you used {precommit} before, upgrade these three components for maximal compatibility:

  • the R package {precommit} from CRAN with install.packages("precommit").

  • the hook revisions in your .pre-commit-config.yaml with precommit::autoupdate(). Hook revision updates are released in sync with R package updates (exception: Patch releases for hooks don’t have a corresponding CRAN release).

  • the upstream pre-commit framework. Use the update utilities provided by your installation method (i.e. pip3 or brew). If you chose conda, you can use precommit::update_precommit(). If you don’t remember the installation method you chose, just choose any and then upgrade. We’ll warn you if you have multiple executables installed and point you to their location so you can get rid of all but one. You can check the version of you executable with precommit::version_precommit(). Updates to the pre-commit framework are not released in sync with the R or hook revision updates.

Uninstallation

uninstall_precommit("repo") # just for the repo you are in.
uninstall_precommit("user") # remove the pre-commit conda executable.

Copy Link

Version

Install

install.packages('precommit')

Monthly Downloads

512

Version

0.2.2

License

GPL-3

Issues

Pull Requests

Stars

Forks

Maintainer

Lorenz Walthert

Last Published

December 14th, 2021

Functions in precommit (0.2.2)

hook_state_create

Create a hook state
install_impl

Install pre-commit on your system with conda
local_test_setup

Testing utilities
path_precommit_exec

Locate the pre-commit executable
install_precommit

Install pre-commit on your system
precommit-package

precommit: Pre-Commit Hooks
release_gh

Create a new release on GitHub
rev_read

Read the refs corresponding to a hooks repo
may_require_permanent_cache

Issue a warning if {R.cache} uses temporary cache only
not_conda

The testing environment does not use a conda environment if the env variable PRECOMMIT_INSTALLATION_METHOD is not 'conda'.
extract_diff_root

Extract old and new lines from git diff --cached
ensure_named

Name the input
git_init

Initiate git and configure it
generate_uninstalled_pkg_name

Generate a random package name that is not installed
fallback_doc

Fallback doc
open_config

Open pre-commit related files
path_derive_precommit_exec

Derive the path to the pre-commit executable
path_derive_precommit_exec_path

Derive the pre-commit executable from the path
precommit_executable_file

The name of the executable file
hook_state_assert

Check if the hook produced what you want
path_derive_precommit_exec_conda

Derive the path to the conda pre-commit executable
path_derive_precommit_exec_impl

Find an executable
update_impl

Updates pre-commit on your system with conda
uninstall_precommit

Uninstall pre-commit
release_complete

Complete the release
roxygen_assert_additional_dependencies

Assert if all dependencies are installed
roxygenize_with_cache

Roxygen depending on cache state
version_precommit

Retrieve the version of the pre-commit executable used
use_precommit_config

Initiate a pre-commit config file
path_derive_precommit_exec_win_python3plus_base

Where are executables on Windows for Python 3 and higher?
update_precommit

Update the pre-commit executable
set_config_source

Set the location to a config file
update_rev_in_config

Updates the hook version ref of precommit in a .pre-commit-config file
snippet_generate

Generate code snippets
use_ci

Use continuous integration with pre-commit
use_precommit

Get started with pre-commit
run_test_impl

Implement a test run
run_test

Run a test
call_precommit

Call pre-commit
diff_requires_run_roxygenize

Check if we should run roxygen.
dirs_R.cache

Create the path to the precommit R.cache cache
copy_artifacts

Copy some file to the test directory that must be present, but are not passed to the hook as a file argument.
autoupdate

Auto-update your hooks
call_and_capture

Make a call with system2() and capture the effects.