diff --git a/.github/workflows/end-to-end.yml b/.github/workflows/end-to-end.yml index 11f317445..d694b3ac2 100644 --- a/.github/workflows/end-to-end.yml +++ b/.github/workflows/end-to-end.yml @@ -63,6 +63,7 @@ jobs: run: | echo 'one' > README.Rmd echo 'one' >> codemeta.json + echo 'one' >> CITATION.cff echo 'one' > README.md echo "#' some code\n#'\n#' @param here.\n#' @name somethings\nNULL" > R/test.R # overwrite if anything there brew install pre-commit diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 40d48d011..7e70e0043 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -113,3 +113,10 @@ language: script minimum_pre_commit_version: "2.13.0" files: '^man/|_pkgdown\.yml' +- id: cff-description-updated + name: cff-description-updated + description: make sure `CITATION.cff` is in sync with `DESCRIPTION`. It should be run after use-tidy-description + entry: Rscript inst/hooks/exported/cff-description-updated.R + language: r + files: '^DESCRIPTION$' + minimum_pre_commit_version: "2.13.0" diff --git a/inst/hooks/exported/cff-description-updated.R b/inst/hooks/exported/cff-description-updated.R new file mode 100755 index 000000000..a1af611dd --- /dev/null +++ b/inst/hooks/exported/cff-description-updated.R @@ -0,0 +1,32 @@ +#!/usr/bin/env Rscript + +"A hook to make sure DESCRIPTION hasn't been edited more recently than +CITATION.cff. + +Usage: + cff-description-updated [--root=] ... + +Options: + --root= Path relative to the git root that contains the R package + root [default: .]. + +" -> doc + + +arguments <- docopt::docopt(doc) +setwd(arguments$root) + +# adapted from https://github.com/lorenzwalthert/precommit/blob/d2dcd45f30b6c52469665c89cb7cba53e716a62a/inst/hooks/exported/codemeta-description-updated.R +if (!file.exists("DESCRIPTION")) { + rlang::abort("No `DESCRIPTION` found in repository.") +} + +if (!file.exists("CITATION.cff")) { + rlang::abort("No `CITATION.cff` found in repository.") +} + + +codemeta_outdated <- file.info("DESCRIPTION")$mtime > file.info("CITATION.cff")$mtime +if (codemeta_outdated) { + rlang::abort("CITATION.cff is out of date; please re-run cffr::cff_write().") +} diff --git a/inst/pre-commit-config-pkg.yaml b/inst/pre-commit-config-pkg.yaml index 4ecff80ff..7850793d4 100644 --- a/inst/pre-commit-config-pkg.yaml +++ b/inst/pre-commit-config-pkg.yaml @@ -8,7 +8,9 @@ repos: args: [--style_pkg=styler, --style_fun=tidyverse_style] - id: roxygenize # codemeta must be above use-tidy-description when both are used + # same for cff-description-updated # - id: codemeta-description-updated + # - id: cff-description-updated - id: use-tidy-description - id: spell-check exclude: > diff --git a/inst/pre-commit-hooks.yaml b/inst/pre-commit-hooks.yaml index 40d48d011..7e70e0043 100644 --- a/inst/pre-commit-hooks.yaml +++ b/inst/pre-commit-hooks.yaml @@ -113,3 +113,10 @@ language: script minimum_pre_commit_version: "2.13.0" files: '^man/|_pkgdown\.yml' +- id: cff-description-updated + name: cff-description-updated + description: make sure `CITATION.cff` is in sync with `DESCRIPTION`. It should be run after use-tidy-description + entry: Rscript inst/hooks/exported/cff-description-updated.R + language: r + files: '^DESCRIPTION$' + minimum_pre_commit_version: "2.13.0" diff --git a/tests/testthat/in/CITATION.cff b/tests/testthat/in/CITATION.cff new file mode 100644 index 000000000..e69de29bb diff --git a/tests/testthat/test-hooks.R b/tests/testthat/test-hooks.R index ae167fc6f..c1d5da4a1 100644 --- a/tests/testthat/test-hooks.R +++ b/tests/testthat/test-hooks.R @@ -557,6 +557,94 @@ run_test("codemeta-description-update", } ) +### . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. +### codemeata #### +run_test("cff-description-updated", + file_name = c("CITATION.cff"), + suffix = "", + std_err = "No `DESCRIPTION` found in repository.", + std_out = NULL, +) + +run_test("cff-description-updated", + file_name = c("DESCRIPTION"), + suffix = "", + std_err = "No `CITATION.cff` found in repository.", + std_out = NULL, +) + +# outdated +run_test("cff-description-updated", + file_name = c("DESCRIPTION", "CITATION.cff"), + suffix = "", + std_err = "out of date", + std_out = NULL, + file_transformer = function(files) { + if (length(files) > 1) { + # transformer is called once on all files and once per file + content_2 <- readLines(files[1]) + Sys.sleep(2) + writeLines(content_2, files[1]) + } + files + } +) + +# succeed +run_test("cff-description-updated", + file_name = c("DESCRIPTION", "CITATION.cff"), + suffix = "", + file_transformer = function(files) { + if (length(files) > 1) { + # transformer is called once on all files and once per file + content_2 <- readLines(files[2]) + Sys.sleep(2) + writeLines(content_2, files[2]) + } + files + } +) + +# succeed in correct root +run_test("cff-description-updated", + file_name = c( + "rpkg/DESCRIPTION" = "DESCRIPTION", + "rpkg/CITATION.cff" = "CITATION.cff" + ), + cmd_args = "--root=rpkg", + suffix = "", + file_transformer = function(files) { + if (length(files) > 1) { + # transformer is called once on all files and once per file + content_2 <- readLines(files[2]) + Sys.sleep(2) + writeLines(content_2, files[2]) + } + files + } +) + +# # fail in wrong root +run_test("cff-description-updated", + file_name = c( + "rpkg/DESCRIPTION" = "DESCRIPTION", + "rpkg/CITATION.cff" = "CITATION.cff", + "rpkg2/CITATION.cff" = "README.md" + ), + cmd_args = "--root=rpkg2", + std_err = "No `DESCRIPTION` found in repository.", + suffix = "", + file_transformer = function(files) { + if (length(files) > 1) { + # transformer is called once on all files and once per file + content_2 <- readLines(files[2]) + Sys.sleep(2) + writeLines(content_2, files[2]) + } + files + } +) + ### . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. ### pgkdown check #### diff --git a/vignettes/available-hooks.Rmd b/vignettes/available-hooks.Rmd index 818c77640..4b8cb8f5f 100644 --- a/vignettes/available-hooks.Rmd +++ b/vignettes/available-hooks.Rmd @@ -306,9 +306,7 @@ This hook does not modify any file. ## `codemeta-description-updated` Make sure `DESCRIPTION` hasn't been edited more recently than -`codemeta.json`, - -i.e. remind you to run `codemetar::write_codemeta()` in order to keep +`codemeta.json`, i.e. remind you to run `codemetar::write_codemeta()` in order to keep `codemeta.json` in sync with `DESCRIPTION`. This hook does not modify any file. @@ -325,6 +323,24 @@ This hook does not modify any file. repos, the git and R package root coincide. Added in version 0.3.3.00000. +## `cff-description-updated` + +Make sure `DESCRIPTION` hasn't been edited more recently than +`CITATION.cff`, i.e. remind you to run `cffr::cff_write()` in order to keep +`CITATION.cff` in sync with `DESCRIPTION`. + +This hook does not modify any file. + +**Arguments** + + id: cff-description-updated + args: [--root=] + + + +- Argument `root` specifies the directory in the git repo that + contains the R package. Defaults to `.` since for most R package git + repos, the git and R package root coincide. Added in version 0.3.2.9004. ## `pkgdown`