Title: | Pre-Commit Hooks |
Version: | 0.4.3 |
Author: | Lorenz Walthert |
Maintainer: | Lorenz Walthert <lorenz.walthert@icloud.com> |
Description: | Useful git hooks for R building on top of the multi-language framework 'pre-commit' for hook management. This package provides git hooks for common tasks like formatting files with 'styler' or spell checking as well as wrapper functions to access the 'pre-commit' executable. |
License: | GPL-3 |
URL: | https://lorenzwalthert.github.io/precommit/, https://github.com/lorenzwalthert/precommit |
Imports: | cli, fs, here, magrittr, purrr, R.cache, rlang, rprojroot, withr, yaml |
Suggests: | desc, docopt (≥ 0.7.1), git2r, glue, knitr, lintr, pkgload, pkgdown, reticulate (≥ 1.16), rmarkdown, roxygen2, rstudioapi, spelling, styler, testthat (≥ 2.1.0), tibble, usethis (≥ 2.0.0) |
VignetteBuilder: | knitr |
Encoding: | UTF-8 |
RoxygenNote: | 7.3.1 |
SystemRequirements: | git |
Config/testthat/parallel: | true |
Config/testthat/edition: | 3 |
NeedsCompilation: | no |
Packaged: | 2024-07-22 13:56:23 UTC; lorenz |
Repository: | CRAN |
Date/Publication: | 2024-07-22 22:20:05 UTC |
precommit: Pre-Commit Hooks
Description
Useful git hooks for R building on top of the multi-language framework 'pre-commit' for hook management. This package provides git hooks for common tasks like formatting files with 'styler' or spell checking as well as wrapper functions to access the 'pre-commit' executable.
See Also
Useful links:
Auto-update your hooks
Description
Runs pre-commit autoupdate
.
Usage
autoupdate(root = here::here())
Arguments
root |
The path to the root directory of your project. |
Value
The exit status from pre-commit autoupdate
(invisibly).
Examples
## Not run:
autoupdate()
## End(Not run)
Make a call with system2()
and capture the effects.
Description
Make a call with system2()
and capture the effects.
Usage
call_and_capture(command, args, ..., wait = TRUE)
Arguments
command |
The command to issue. A character string of length one. |
args |
The command line arguments. |
... |
Arguments passed to |
wait |
Passed to |
Value
A list with:
content of stderr
content of stdout
exit status
Call pre-commit
Description
Either via conda run
(because conda env needs to be activated in general to
ensure an executable to runs successfully) or, if the installation method was
not conda, as a plain bash command.
Usage
call_precommit(..., wait = TRUE)
Arguments
... |
Arguments passed to the command line call |
wait |
Passed to |
Communicate a captured call
Description
Communicates a captured call.
Usage
communicate_captured_call(x, preamble = "")
Arguments
x |
The output of |
Copy some file to the test directory that must be present, but are not passed to the hook as a file argument.
Description
Copy some file to the test directory that must be present, but are not passed to the hook as a file argument.
Usage
copy_artifacts(artifacts, tempdir)
Arguments
artifacts |
Artifacts to copy. |
tempdir |
The temporary directory. |
Check if we should run roxygen.
Description
This is the case if a new or replaced/removed line contains a roxygen2 comment in a file that is staged. This function is only exported for use in hook scripts, but it's not intended to be called by the end-user directly.
Usage
diff_requires_run_roxygenize(root = ".")
Arguments
root |
The root of the git repo. |
Value
A logical vector of length 1.
See Also
Other hook script helpers:
dirs_R.cache()
,
may_require_permanent_cache()
,
precommit_docopt()
,
robust_purl()
,
roxygen_assert_additional_dependencies()
,
roxygenize_with_cache()
Examples
## Not run:
diff_requires_run_roxygenize()
## End(Not run)
Create the path to the precommit R.cache cache
Description
This function is only exported for use in hook scripts, but it's not intended to be called by the end-user directly.
Usage
dirs_R.cache(hook_id)
Arguments
hook_id |
The id of the hook for which we want the relative cache directory. |
See Also
Other hook script helpers:
diff_requires_run_roxygenize()
,
may_require_permanent_cache()
,
precommit_docopt()
,
robust_purl()
,
roxygen_assert_additional_dependencies()
,
roxygenize_with_cache()
Reduce a check to the empty string on CRAN
Description
In testing, we don't want to rely on exact error messages or stdout on CRAN for third-party packages, since this would complicate the release process for dependencies of {precommit}.
Usage
empty_on_cran(string)
Arguments
string |
The string to test. |
Name the input
Description
Name the input
Usage
ensure_named(x, candidate_name = NULL, f = identity)
Arguments
x |
A vector. |
f |
How to transform the input |
Fallback doc
Description
Fallback doc
Arguments
root |
The path to the root directory of your project. |
Generate a random package name that is not installed
Description
Generate a random package name that is not installed
Usage
generate_uninstalled_pkg_name(n = 10)
Arguments
n |
The number of times we should try |
Get the operating System
Description
Can't mock base package (either because it's an .Internal
or for some other
reason).
Usage
get_os()
Initiate git and configure it
Description
In particular, to avoid CRAN errors lorenzwalthert/precommit#320.
Usage
git_init(path = ".")
Arguments
path |
The root of the repo. |
Check if the hook produced what you want
Description
Match the resulting state after the hook run with the expected state
Usage
hook_state_assert(
path_candidate,
tempdir,
path_candidate_temp,
file_transformer,
path_stdout,
path_stderr,
expect_success,
std_err,
std_out,
exit_status
)
Create a hook state
Description
Runs the hook script to create a hook state, i.e. exit code, transformed files and emitted messages of the hook run.
Usage
hook_state_create(
tempdir,
path_candidate_temp,
path_executable,
cmd_args,
path_stdout,
path_stderr,
env
)
Install pre-commit on your system with conda
Description
Install pre-commit on your system with conda
Usage
install_impl()
Install pre-commit on your system
Description
This installs pre-commit in the conda environment r-precommit. It
will be available to use across different git repositories. To update,
refer to update_precommit()
.
Usage
install_precommit(force = FALSE)
Arguments
force |
Whether or not to force a re-installation. |
Value
The path to the pre-commit executable (invisibly).
See Also
Other executable managers:
uninstall_precommit()
,
update_precommit()
,
version_precommit()
Examples
## Not run:
install_precommit()
## End(Not run)
Testing utilities
Description
Similar to the local_()
family from {withr}
, this function creates a
temporary directory and optionally initiates git and pre-commit in it.
Usage
local_test_setup(
git = TRUE,
use_precommit = FALSE,
package = FALSE,
quiet = TRUE,
autoupdate = FALSE,
...,
.local_envir = parent.frame()
)
Arguments
git |
Whether or not to init git in the local directory. |
use_precommit |
Whether or not to |
autoupdate |
Whether or not to run |
.local_envir |
|
Issue a warning if {R.cache} uses temporary cache only
Description
This function used to check if a permanent cache was available and issue a
warning if not, but since {R.cache} version 0.15.0
(release date
2021-04-27), a permanent directory will be used automatically, so this check
if redundant. the function is kept in the package for compatibility, i.e.
if someone updates the R package {precommit} but not the hook revisions.
Usage
may_require_permanent_cache(temp_cache_is_enough = FALSE)
Arguments
temp_cache_is_enough |
ignored. |
See Also
Other hook script helpers:
diff_requires_run_roxygenize()
,
dirs_R.cache()
,
precommit_docopt()
,
robust_purl()
,
roxygen_assert_additional_dependencies()
,
roxygenize_with_cache()
The testing environment does not use a conda environment if the env variable PRECOMMIT_INSTALLATION_METHOD is not 'conda'.
Description
The testing environment does not use a conda environment if the env variable PRECOMMIT_INSTALLATION_METHOD is not 'conda'.
Usage
not_conda()
Open pre-commit related files
Description
Open pre-commit related files
Usage
open_config(root = here::here())
open_wordlist(root = here::here())
Arguments
root |
The path to the root directory of your project. |
Details
-
open_config()
: opens the pre-commit config file. -
open_wordlist()
: opens the the WORDLIST file for the check-spelling hook in inst/WORDLIST.
Value
NULL
(invisibly). The function is called for its side effects.
See Also
Other helpers:
use_precommit()
Examples
## Not run:
open_config()
## End(Not run)
## Not run:
open_wordlist()
## End(Not run)
Derive the path to the pre-commit executable
Description
Returns "" if search was not successful, the path otherwise.
Usage
path_derive_precommit_exec()
Heuristic
First check if there is an executable on the
$PATH
usingpath_derive_precommit_exec_path()
Search os dependent for other possible locations for common installation methods.
If not, check if we can find one in a conda environment with
path_derive_precommit_exec_conda()
. Do this last as it's the slowest.
Derive the path to the conda pre-commit executable
Description
Only checks the conda env r-precommit
.
If we can't find the executable, the empty string is returned.
Usage
path_derive_precommit_exec_conda()
Find an executable
Description
Evaluates if the pre-commit executable exists in one or more candidate locations. If so, return one, else return the empty string
Usage
path_derive_precommit_exec_impl(candidate)
Arguments
candidate |
A directory to check for the pre-commit executable. The directory may also not exist. |
Derive the pre-commit executable from the path
Description
Tries to derive the pre-commit
executable from the $PATH
.
Returns ""
if no executable is found.
Usage
path_derive_precommit_exec_path()
Where are executables on Windows for Python 3 and higher?
Description
Heuristic to determine the directory where the pre-commit executable on Windows lives for Python versions 3 and above.
Usage
path_derive_precommit_exec_win_python3plus_base()
Locate the pre-commit executable
Description
path_precommit_exec()
simply reads the R option precommit.executable
,
path_pre_commit_exec()
is the old spelling and deprecated.
Usage
path_precommit_exec(check_if_exists = TRUE)
path_pre_commit_exec(check_if_exists = TRUE)
Arguments
check_if_exists |
Whether or not to make sure the returned path also exists. |
Value
A character vector of length one with the path to the pre-commit executable.
See Also
path_derive_precommit_exec()
for the heuristic to derive it from scratch.
Examples
## Not run:
path_precommit_exec()
## End(Not run)
## Not run:
path_pre_commit_exec()
## End(Not run)
Provide a singular interface for hook calls to docopt
Description
docopt provides different processing for a single string
than an array/vector. As "string"`` and
c("string")'
are semantically equivalent in R, this can create problems
when a single parameter is provided. Thus, this function
wraps docopt to ensure that the args will always be
interpreted as a vector.
Usage
precommit_docopt(doc, args = commandArgs(trailingOnly = TRUE), ...)
Arguments
doc |
|
args |
|
... |
Additional parameters passed to |
Details
This function is only exported for use in hook scripts, but it's not intended to be called by the end-user directly.
See Also
Other hook script helpers:
diff_requires_run_roxygenize()
,
dirs_R.cache()
,
may_require_permanent_cache()
,
robust_purl()
,
roxygen_assert_additional_dependencies()
,
roxygenize_with_cache()
The name of the executable file
Description
This is platform dependent.
Usage
precommit_executable_file()
Complete the release
Description
Bumps the version to devel.
Usage
release_complete(ask = TRUE, is_cran = ask, tag = NULL)
Arguments
tag |
The tag to push. |
Create a new release on GitHub
Description
This must be done before a CRAN release.
Usage
release_gh(bump = "dev", is_cran = bump != "dev")
Arguments
bump |
The bump increment, either "dev", "patch", "minor" or "major". |
is_cran |
Is this release a CRAN release? |
Details
This function does the following:
bump description.
update default config in inst/
commit
git tag
run
inst/hooks/local/consistent-release-tag.R
hook with –release-mode (passing args to hooks not possible interactively, hence we run in advance).commit and push with skipping
inst/hooks/local/consistent-release-tag.R
.autoupdate own config file
bump description with dev
commit and push DESCRIPTION and .pre-commit-config.yaml
CRAN release
If is_cran
is TRUE
, the workflow is changed slightly:
push to release branch, not main.
doesn't run
release_complete()
. This must be done manually after accepted on CRAN.
Read the refs corresponding to a hooks repo
Description
Read the refs corresponding to a hooks repo
Usage
rev_read(path = ".pre-commit-config.yaml", repo = hooks_repo)
Run knitr::purl()
, setting the chunk option purl
to TRUE
if it's not
already set to a literal value.
Description
This function is only exported for use in hook scripts, but it's not intended to be called by the end-user directly.
Usage
robust_purl(path)
Arguments
path |
The path to the file you want to |
See Also
Other hook script helpers:
diff_requires_run_roxygenize()
,
dirs_R.cache()
,
may_require_permanent_cache()
,
precommit_docopt()
,
roxygen_assert_additional_dependencies()
,
roxygenize_with_cache()
Assert if all dependencies are installed
Description
This function is only exported for use in hook scripts, but it's not intended to be called by the end-user directly.
Usage
roxygen_assert_additional_dependencies()
See Also
Other hook script helpers:
diff_requires_run_roxygenize()
,
dirs_R.cache()
,
may_require_permanent_cache()
,
precommit_docopt()
,
robust_purl()
,
roxygenize_with_cache()
Roxygen and add a cache entry
Description
This function is only exported for use in hook scripts, but it's not intended to be called by the end-user directly.
Usage
roxygenize_with_cache(key, dirs)
Arguments
key |
An optional object from which a hexadecimal hash code will be generated and appended to the filename. |
dirs |
A |
See Also
Other hook script helpers:
diff_requires_run_roxygenize()
,
dirs_R.cache()
,
may_require_permanent_cache()
,
precommit_docopt()
,
robust_purl()
,
roxygen_assert_additional_dependencies()
Run a test
Description
Tests for the executables used as pre-commit hooks via entrypoint
in
.pre-commit-config.yaml
. Set's the env variable R_PRECOMMIT_HOOK_ENV
to
when running.
Usage
run_test(
hook_name,
file_name = hook_name,
suffix = ".R",
std_err = NULL,
std_out = NULL,
cmd_args = NULL,
artifacts = NULL,
file_transformer = function(files) files,
env = character(),
expect_success = is.null(std_err),
read_only = FALSE
)
Arguments
hook_name |
The name of the hook in |
file_name |
The file to test in |
suffix |
The suffix of |
std_err |
An expected error message. If no error is expected, this
can be |
std_out |
The expected stdout message. If |
cmd_args |
More arguments passed to the file. Pre-commit handles it as described here. |
artifacts |
Path with artifact files to copy to the temp directory root where the test is run. If you don't target the root, this can be a named vector of length one where the name is the target location relative to the temporary location and the value is the source of the file. |
file_transformer |
A function that takes the file names as input and is
ran right before the hook script is invoked, returning the path to the
files, potentially modified (if renamed). This can be useful if you need to
make in-place modifications to the file, e.g. to test hooks that operate on
|
env |
The environment variables to set with |
expect_success |
Whether or not an exit code 0 is expected. This can
be derived from |
read_only |
If |
Details
Two potential outcomes of a hooks are pass or fail. This is reflected on the level of the executable: Fail means the executable fails or the file is changed. Pass means the executable succeeds and the file is unchanged. We check if the executable passes as follows:
If we expect success (by setting
std_err
toNULL
), we make sure nothing was written to sterr and the file content does not change.If we expect failure, it can be due to changed file or due to failed executable. To check for failed executable, we set
std_err
to the message we expect. To check changed file content, we setstd_err
toNA
.
Implement a test run
Description
Implement a test run
Usage
run_test_impl(
path_executable,
path_candidate,
std_err,
std_out,
cmd_args,
artifacts,
file_transformer,
env,
expect_success,
read_only
)
Arguments
path_executable |
The path to the executable bash script. |
path_candidate |
The path to a file that should be modified by the executable. |
std_err |
An expected error message. If no error is expected, this
can be |
std_out |
The expected stdout message. If |
cmd_args |
More arguments passed to the file. Pre-commit handles it as described here. |
artifacts |
Path with artifact files to copy to the temp directory root where the test is run. If you don't target the root, this can be a named vector of length one where the name is the target location relative to the temporary location and the value is the source of the file. |
env |
The environment variables to set with |
expect_success |
Whether or not an exit code 0 is expected. This can
be derived from |
read_only |
If |
Set the location to a config file
Description
If a remote location is specified, the file is downloaded to a temporary
location and the path to this location is returned. If NULL
, we'll resort
to a default config. We'll perform some checks on the existence of the file
too.
Usage
set_config_source(config_source, root, verbose = TRUE)
Generate code snippets
Description
Utility function to generate code snippets:
Usage
snippet_generate(
snippet = "",
open = rstudioapi::isAvailable(),
root = here::here()
)
Arguments
snippet |
Name of the snippet. |
open |
Whether or not to open the .pre-commit-config.yaml. The default
is |
root |
The path to the root directory of your project. |
Details
Currently supported:
additional-deps-roxygenize: Code to paste into
.pre-commit-config.yaml
for the additional dependencies required by the roxygenize hook.
Uninstall pre-commit
Description
Remove pre-commit from a repo or from your system.
Usage
uninstall_precommit(scope = "repo", ask = "user", root = here::here())
Arguments
scope |
Either "repo" or "user". "repo" removes pre-commit from your project, but you will be able to use it in other projects. With "user", you remove the pre-commit executable in the virtual python environment r-precommit so it won't be available in any project. When you want to do the latter, you should first do the former. |
ask |
Either "user", "repo" or "none" to determine in which case a prompt should show up to let the user confirm his action. |
root |
The path to the root directory of your project. |
Value
NULL
(invisibly). The function is called for its side effects.
See Also
Other executable managers:
install_precommit()
,
update_precommit()
,
version_precommit()
Examples
## Not run:
uninstall_precommit()
## End(Not run)
Updates pre-commit on your system with conda
Description
Updates pre-commit on your system with conda
Usage
update_impl()
Update the pre-commit executable
Description
Updates the conda installation of the upstream framework pre-commit. This
does not update the R package {precommit}
and only works if you choose
conda as your installation method. If you have problems updating, we suggest
deleting the conda environment r-precommit
(if you are sure nothing but
pre-commit depend on it) and do a fresh installation with
install_precommit()
.
Usage
update_precommit()
Value
The exit status of the conda update command (invisible).
See Also
Other executable managers:
install_precommit()
,
uninstall_precommit()
,
version_precommit()
Updates the hook version ref of {precommit} in a .pre-commit-config
file
Description
This is useful in the release process because when releasing a new version,
we must make sure the template that is used with precommit::use_precommit()
is up-to date. Also, after we pushed the release to GitHub, we want to update
the hooks from our own hook repo in the source repo too (we could also do that
with precommit::autoupdate()
though).
Usage
update_rev_in_config(new_version, path = "inst/pre-commit-config.yaml")
Arguments
new_version |
The version string of the new version. |
path |
The path to a pre-commit config file. |
Use continuous integration with pre-commit
Description
Sets up continuous integration, or prompts the user to do it manually.
Usage
use_ci(
ci = getOption("precommit.ci", "native"),
force = FALSE,
open = rstudioapi::isAvailable(),
root = here::here()
)
Arguments
ci |
Specifies which continuous integration service to use. See
|
force |
Whether or not to overwrite an existing ci config file (only
relevant for |
open |
Whether or not to open pre-commit.ci
(if |
root |
The path to the root directory of your project. |
Get started with pre-commit
Description
This function sets up pre-commit for your git repo.
Usage
use_precommit(
config_source = getOption("precommit.config_source"),
force = FALSE,
legacy_hooks = "forbid",
open = rstudioapi::isAvailable(),
install_hooks = TRUE,
ci = getOption("precommit.ci", "native"),
autoupdate = install_hooks,
root = here::here()
)
Arguments
config_source |
Path or URL to a |
force |
Whether or not to overwrite an existing ci config file (only
relevant for |
legacy_hooks |
How to treat hooks already in the repo which are not
managed by pre-commit. "forbid", the default, will cause |
open |
Whether or not to open |
install_hooks |
Whether to install environments for all available hooks.
If |
ci |
Specifies which continuous integration service to use. See
|
autoupdate |
Whether or not to run |
root |
The path to the root directory of your project. |
Value
NULL
(invisibly). The function is called for its side effects.
When to call this function?
You want to add pre-commit support to a git repo which does not have a
.pre-commit-config.yaml
. This involves adding a pre-commit config file and making sure git will call the hooks before the next commit.You cloned a repo that has a
.pre-commit-config.yaml
already. You need to make sure git calls the hooks before the next commit.
What does the function do?
Sets up a template
.pre-commit-config.yaml
.Autoupdates the template to make sure you get the latest versions of the hooks.
Installs the pre-commit script along with the hook environments with
$ pre-commit install --install-hooks
.Opens the config file if RStudio is running.
Copying an existing config file
You can use an existing .pre-commit-config.yaml
file when initializing
pre-commit with use_precommit()
using the argument config_source
to
copy an existing config file into your repo. This argument defaults to the R
option precommit.config_source
, so you may want to set this option in
your .Rprofile
for convenience. Note that this is not equivalent to the
--config
option in the CLI command pre-commit install
and similar,
which do not copy a config file into a project root (and allow to put it
under version control), but rather link it in some more or less transparent
way.
See Also
Other helpers:
open_config()
Examples
## Not run:
use_precommit()
## End(Not run)
Initiate a pre-commit config file
Description
Initiate a pre-commit config file
Usage
use_precommit_config(
config_source = getOption("precommit.config_source"),
force = FALSE,
open = rstudioapi::isAvailable(),
verbose = FALSE,
root = here::here()
)
Arguments
config_source |
Path or URL to a |
force |
Whether to replace an existing config file. |
open |
Whether or not to open the .pre-commit-config.yaml after
it's been placed in your repo. The default is |
verbose |
Whether or not to communicate what's happening. |
root |
The path to the root directory of your project. |
Value
Character vector of length one with the path to the config file used.
Copying an existing config file
You can use an existing .pre-commit-config.yaml
file when initializing
pre-commit with use_precommit()
using the argument config_source
to
copy an existing config file into your repo. This argument defaults to the R
option precommit.config_source
, so you may want to set this option in
your .Rprofile
for convenience. Note that this is not equivalent to the
--config
option in the CLI command pre-commit install
and similar,
which do not copy a config file into a project root (and allow to put it
under version control), but rather link it in some more or less transparent
way.
Examples
## Not run:
use_precommit_config()
## End(Not run)
Retrieve the version of the pre-commit executable used
Description
Retrieves the version of the pre-commit executable used.
Usage
version_precommit()
See Also
Other executable managers:
install_precommit()
,
uninstall_precommit()
,
update_precommit()