From cf2e1184cf2103b68252cc8794739e057098ef95 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 17 Jul 2023 10:46:48 +0200 Subject: [PATCH 01/63] check_documentation() handles assignment function correctly --- R/check_documentation.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/check_documentation.R b/R/check_documentation.R index 633eb198..e2c3e5ac 100644 --- a/R/check_documentation.R +++ b/R/check_documentation.R @@ -88,7 +88,7 @@ check_documentation <- function(x = ".", quiet = FALSE) { namespace <- readLines(rd_files[1]) namespace[grepl("^export.*\\(", namespace)] |> - gsub(pattern = "export.*\\((.*)\\)", replacement = "\\1") -> exported + gsub(pattern = "export.*\\(\"?(.*?)\"?\\)", replacement = "\\1") -> exported vapply(rd_files[-1], rd_extract_function, vector("list", 1L)) |> unlist() |> unique() |> From b9198c02a4b23c63b9ddb56ac18d22739c68d3f8 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 17 Jul 2023 10:48:55 +0200 Subject: [PATCH 02/63] check_documentation() ignores "reexports" --- R/check_documentation.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/check_documentation.R b/R/check_documentation.R index e2c3e5ac..63fde41c 100644 --- a/R/check_documentation.R +++ b/R/check_documentation.R @@ -96,6 +96,7 @@ check_documentation <- function(x = ".", quiet = FALSE) { unexported <- documented[!documented %in% exported] datasets <- data(package = desc(x$get_path)$get_field("Package")) unexported <- unexported[!unexported %in% datasets$results[, "Item"]] + unexported <- unexported[unexported != "reexports"] paste(unexported, collapse = ", ") |> sprintf(fmt = "documented but unexported functions: %s") -> doc_warnings doc_warnings <- doc_warnings[length(unexported) > 0] From 3cdbb94e680baa291b6da85f3fc4bb276a9137df Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 17 Jul 2023 10:57:32 +0200 Subject: [PATCH 03/63] hide empty urls in CITATION.cff --- R/citation_meta_class.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/citation_meta_class.R b/R/citation_meta_class.R index f4beaaba..ed092dc4 100644 --- a/R/citation_meta_class.R +++ b/R/citation_meta_class.R @@ -353,7 +353,7 @@ citation_cff <- function(meta) { } else { identifiers <- list() } - if (has_name(input, "url")) { + if (has_name(input, "url") && length(input$url) > 0) { identifiers <- c(identifiers, list(list(type = "url", value = input$url))) } cff <- list( From f32e4142dca74409be259ccfc4559a180b4d2b18 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 17 Jul 2023 11:18:17 +0200 Subject: [PATCH 04/63] add double quotes around title and abstract in CITATION.cff fixes #115 --- R/citation_meta_class.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/citation_meta_class.R b/R/citation_meta_class.R index ed092dc4..6ce85724 100644 --- a/R/citation_meta_class.R +++ b/R/citation_meta_class.R @@ -365,6 +365,8 @@ citation_cff <- function(meta) { abstract = strip_markdown(input$description) |> paste(collapse = "\n") ) + attr(cff$title, "quoted") <- TRUE + attr(cff$abstract, "quoted") <- TRUE if (length(identifiers) > 0) { cff$identifiers <- identifiers } From ee2a1bfa02a23c2cb45015221a20d57829fef128 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 17 Jul 2023 11:20:45 +0200 Subject: [PATCH 05/63] bump package version --- .zenodo.json | 2 +- CITATION.cff | 6 +++--- DESCRIPTION | 2 +- NEWS.md | 6 ++++++ inst/CITATION | 4 ++-- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 980f4d0c..ad1dec91 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,6 +1,6 @@ { "title": "checklist: A Thorough and Strict Set of Checks for R Packages and Source Code", - "version": "0.3.5", + "version": "0.3.6", "license": "GPL-3.0", "upload_type": "software", "description": "

An opinionated set of rules for R packages and R source code\nprojects.<\/p>", diff --git a/CITATION.cff b/CITATION.cff index ee407f0c..04a46b08 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,6 +1,6 @@ cff-version: 1.2.0 message: If you use this software, please cite it using these metadata. -title: 'checklist: A Thorough and Strict Set of Checks for R Packages and Source Code' +title: "checklist: A Thorough and Strict Set of Checks for R Packages and Source Code" authors: - given-names: Thierry family-names: Onkelinx @@ -19,10 +19,10 @@ doi: 10.5281/zenodo.4028303 license: GPL-3.0 repository-code: https://github.com/inbo/checklist/ type: software -abstract: An opinionated set of rules for R packages and R source code projects. +abstract: "An opinionated set of rules for R packages and R source code projects." identifiers: - type: doi value: 10.5281/zenodo.4028303 - type: url value: https://inbo.github.io/checklist/ -version: 0.3.5 +version: 0.3.6 diff --git a/DESCRIPTION b/DESCRIPTION index 14a6a67e..bd1bd34e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: checklist Title: A Thorough and Strict Set of Checks for R Packages and Source Code -Version: 0.3.5 +Version: 0.3.6 Authors@R: c( person("Thierry", "Onkelinx", , "thierry.onkelinx@inbo.be", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-8804-4216", affiliation = "Research Institute for Nature and Forest (INBO)")), diff --git a/NEWS.md b/NEWS.md index bd075d50..2cf12f05 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,9 @@ +# checklist 0.3.6 + +* Put double quotes around the title and abstract fields of `CITATION.cff`. +* `check_documentation()` handles assignment functions and re-exported functions + correctly. + # checklist 0.3.5 * Fix release GitHub Action. diff --git a/inst/CITATION b/inst/CITATION index c74c6cd0..c32f0d38 100644 --- a/inst/CITATION +++ b/inst/CITATION @@ -2,12 +2,12 @@ citHeader("To cite `checklist` in publications please use:") # begin checklist entry bibentry( bibtype = "Manual", - title = "checklist: A Thorough and Strict Set of Checks for R Packages and Source Code. Version 0.3.5", + title = "checklist: A Thorough and Strict Set of Checks for R Packages and Source Code. Version 0.3.6", author = c( author = c(person(given = "Thierry", family = "Onkelinx"))), year = 2023, url = "https://inbo.github.io/checklist/", abstract = "An opinionated set of rules for R packages and R source code projects.", - textVersion = "Onkelinx, Thierry (2023) checklist: A Thorough and Strict Set of Checks for R Packages and Source Code. Version 0.3.5. https://inbo.github.io/checklist/", + textVersion = "Onkelinx, Thierry (2023) checklist: A Thorough and Strict Set of Checks for R Packages and Source Code. Version 0.3.6. https://inbo.github.io/checklist/", keywords = "quality control; documentation; publication", doi = "10.5281/zenodo.4028303", ) From 30f3dadab456cf2892f6c3a4f4461d5da9834061 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 18 Jul 2023 10:10:24 +0200 Subject: [PATCH 06/63] set_tag() handles # `package` style entries in NEWS.md --- R/set_tag.R | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/R/set_tag.R b/R/set_tag.R index f7bb7edd..0607dd73 100644 --- a/R/set_tag.R +++ b/R/set_tag.R @@ -43,12 +43,13 @@ set_tag <- function(x = ".") { path(x$get_path, "NEWS.md") |> readLines() -> news regex <- sprintf( - "^# %s [0-9]+\\.[0-9]+(\\.[0-9]+){0,1}$", + "^# `?%s`? [0-9]+\\.[0-9]+(\\.[0-9]+){0,1}$", description$get("Package") ) start <- grep(regex, news) end <- c(tail(start, -1) - 1, length(news)) - current <- grepl(paste("#", description$get("Package"), version), news[start]) + sprintf("# `?%s`? %s", description$get("Package"), version) |> + grepl(news[start]) -> current assert_that(any(current), msg = "Current version not found in NEWS.md") if (paste0("v", version) %in% git_tag_list(repo = repo)$name) { message("tag v", version, " already exists.") @@ -57,24 +58,17 @@ set_tag <- function(x = ".") { old_config <- git_config(repo = repo) defer( git_config_set( - "user.name", - old_config$value[old_config$name == "user.name"], - repo = repo) + "user.name", old_config$value[old_config$name == "user.name"], repo = repo + ) ) defer( git_config_set( - "user.email", - old_config$value[old_config$name == "user.email"], - repo = repo) - ) - git_config_set( - "user.name", "Checklist bot", - repo = repo - ) - git_config_set( - "user.email", "checklist@inbo.be", - repo = repo + "user.email", old_config$value[old_config$name == "user.email"], + repo = repo + ) ) + git_config_set("user.name", "Checklist bot", repo = repo) + git_config_set("user.email", "checklist@inbo.be", repo = repo) tag_message <- paste( news[seq(start[current] + 2, end[current])], collapse = "\n" From f6725f1684efe220a592decd40a54693d988de99 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 18 Jul 2023 10:10:38 +0200 Subject: [PATCH 07/63] bugfix in release.yml --- .github/workflows/release.yml | 25 +++++++++---------------- R/set_tag.R | 6 +++--- inst/package_template/release.yml | 25 +++++++++---------------- 3 files changed, 21 insertions(+), 35 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7d9b730d..9b10b9f6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,28 +10,21 @@ on: - completed jobs: - prepare: + publish: runs-on: ubuntu-latest - outputs: - tag: ${{ steps.gettag.outputs.tag }} - body: ${{ steps.gettag.outputs.body }} + permissions: + contents: write steps: - uses: actions/checkout@v3 - name: Get tag run: | git fetch --tags --force TAG=$(git tag --contains $(git rev-parse HEAD)) - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - echo "body=$TAG_BODY" >> "$GITHUB_OUTPUT" - id: gettag - publish: - runs-on: ubuntu-latest - permissions: - contents: write - needs: prepare - steps: + TAG_BODY=$(git tag --contains $(git rev-parse HEAD) --format='%(contents)') + echo "tag=$TAG" >> $GITHUB_ENV + echo "$TAG_BODY" > body.md - uses: ncipollo/release-action@v1 with: - name: Release ${{needs.prepare.outputs.tag}} - tag: ${{needs.prepare.outputs.tag}} - body: ${{needs.prepare.outputs.body}} + name: Release ${{ env.tag }} + tag: ${{ env.tag }} + bodyFile: body.md diff --git a/R/set_tag.R b/R/set_tag.R index 0607dd73..8714090c 100644 --- a/R/set_tag.R +++ b/R/set_tag.R @@ -70,9 +70,9 @@ set_tag <- function(x = ".") { git_config_set("user.name", "Checklist bot", repo = repo) git_config_set("user.email", "checklist@inbo.be", repo = repo) - tag_message <- paste( - news[seq(start[current] + 2, end[current])], collapse = "\n" - ) + body <- news[seq(start[current], end[current])] + body[nchar(body) > 0] |> + paste(collapse = "\n") -> tag_message git_tag_create( name = paste0("v", version), message = tag_message, repo = repo ) diff --git a/inst/package_template/release.yml b/inst/package_template/release.yml index 7d9b730d..9b10b9f6 100644 --- a/inst/package_template/release.yml +++ b/inst/package_template/release.yml @@ -10,28 +10,21 @@ on: - completed jobs: - prepare: + publish: runs-on: ubuntu-latest - outputs: - tag: ${{ steps.gettag.outputs.tag }} - body: ${{ steps.gettag.outputs.body }} + permissions: + contents: write steps: - uses: actions/checkout@v3 - name: Get tag run: | git fetch --tags --force TAG=$(git tag --contains $(git rev-parse HEAD)) - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - echo "body=$TAG_BODY" >> "$GITHUB_OUTPUT" - id: gettag - publish: - runs-on: ubuntu-latest - permissions: - contents: write - needs: prepare - steps: + TAG_BODY=$(git tag --contains $(git rev-parse HEAD) --format='%(contents)') + echo "tag=$TAG" >> $GITHUB_ENV + echo "$TAG_BODY" > body.md - uses: ncipollo/release-action@v1 with: - name: Release ${{needs.prepare.outputs.tag}} - tag: ${{needs.prepare.outputs.tag}} - body: ${{needs.prepare.outputs.body}} + name: Release ${{ env.tag }} + tag: ${{ env.tag }} + bodyFile: body.md From 20fb66ac4d3b1adda40f40458ac7d747e5748890 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 29 Aug 2023 12:02:35 +0200 Subject: [PATCH 08/63] remove timings for CRAN checks as requested by @hansvancalster --- R/check_cran.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/check_cran.R b/R/check_cran.R index a876f48e..9bf19d6e 100644 --- a/R/check_cran.R +++ b/R/check_cran.R @@ -78,6 +78,9 @@ Days since last update: [0-9]+", "", check_output$warnings[incoming] } # nocov end check_output$warnings <- gsub(" \\[\\d+s/\\d+s\\]", "", check_output$warnings) check_output$notes <- gsub(" \\[\\d+s/\\d+s\\]", "", check_output$notes) + # remove timing output from warnings and notes + check_output$warnings <- gsub(" \\[\\d+s\\]", "", check_output$warnings) + check_output$notes <- gsub(" \\[\\d+s\\]", "", check_output$notes) x$add_rcmdcheck( errors = check_output$errors, warnings = check_output$warnings, notes = check_output$notes From a3a9454e508add21578648a4c371088da42230b3 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 29 Aug 2023 12:04:02 +0200 Subject: [PATCH 09/63] update citation_description() --- R/citation_description.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/citation_description.R b/R/citation_description.R index 27809dfd..513e313f 100644 --- a/R/citation_description.R +++ b/R/citation_description.R @@ -43,7 +43,7 @@ citation_description <- function(meta) { list( meta = cit_meta, errors = c(urls$errors, keywords$errors), warnings = communities$warnings, - notes = authors$notes + notes = character(0) ) } From 00337ad7a8e7a63bd8c4c37d4cad0b50e80ae846 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 30 Aug 2023 19:48:24 +0200 Subject: [PATCH 10/63] check_filename() ignores the quarto _freeze folder --- R/check_filename.R | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/R/check_filename.R b/R/check_filename.R index d64d294b..b2c90d8d 100644 --- a/R/check_filename.R +++ b/R/check_filename.R @@ -33,7 +33,7 @@ #' #' @inheritParams read_checklist #' @export -#' @importFrom fs path +#' @importFrom fs path path_split #' @importFrom gert git_ls #' @family both check_filename <- function(x = ".") { @@ -56,8 +56,9 @@ check_filename <- function(x = ".") { ignored_dirs <- vapply( dirs, function(x) { - x[1] %in% c("", ".", ".git", ".Rproj.user") | - identical(x[1:4], c("inst", "local_tex", "fonts", "opentype")) + x[1] %in% c("", ".", ".git", ".Rproj.user") || + identical(x[1:4], c("inst", "local_tex", "fonts", "opentype")) || + "_freeze" %in% x }, logical(1) ) @@ -90,6 +91,7 @@ check_filename <- function(x = ".") { # ignore git and RStudio files files <- files[!grepl("\\.(git|Rproj.user)/.*", files)] + files <- files[!grepl("_freeze/.*", files)] # ignore some standardised files re <- sprintf( "^(%s)$", @@ -100,7 +102,8 @@ check_filename <- function(x = ".") { "README\\.R?md", "NEWS\\.md", "CODE_OF_CONDUCT\\.md", "CONTRIBUTING\\.md", "LICENSE(\\.md)?", "SUPPORT\\.md", "SECURITY\\.md", "FUNDING\\.yml", - "Dockerfile", "WORDLIST.*", "docker-compose.*\\.yml" + "Dockerfile", "WORDLIST.*", "docker-compose.*\\.yml", + "REVIEWING.md", "_redirects" ), collapse = "|" ) From 836692f6df2dbe25e3218b4e25d6bdbb742e8dbc Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 30 Aug 2023 20:49:30 +0200 Subject: [PATCH 11/63] lint qmd files in a project --- R/check_lintr.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/check_lintr.R b/R/check_lintr.R index e29795ec..7f81fec8 100644 --- a/R/check_lintr.R +++ b/R/check_lintr.R @@ -27,7 +27,7 @@ check_lintr <- function(x = ".", quiet = FALSE) { if (x$package) { linter <- lint_package(path = x$get_path) } else { - linter <- lint_dir(x$get_path, pattern = "\\.R(md|nw)?$") + linter <- lint_dir(x$get_path, pattern = "\\.(R|q)(md|nw)?$") } if (!quiet && length(linter) > 0) { print(linter) From d2986e4201536ea416a89025b09fad605af9a855 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 31 Aug 2023 13:42:32 +0200 Subject: [PATCH 12/63] add instructions to setup Github pages --- vignettes/getting_started.Rmd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vignettes/getting_started.Rmd b/vignettes/getting_started.Rmd index be2f0649..a9ca2105 100644 --- a/vignettes/getting_started.Rmd +++ b/vignettes/getting_started.Rmd @@ -81,6 +81,9 @@ _Add rule_ for _Branch name pattern_ `main` and select the following items and _ - `ubuntu (devel)` - `windows (release)` +1. Go in your package GitHub repository to _Settings_ > _Pages_. +Select _Deploy for branch_ as source, `gh-pages` as branch and save the changes. + ## Get it working with an existing package or update the checklist {#setup-package} ### Prerequisites @@ -131,6 +134,8 @@ _Add rule_ for _Branch name pattern_ `main` and select the following items and _ - `ubuntu (oldrel)` - `ubuntu (devel)` - `windows (release)` +1. Go in your package GitHub repository to _Settings_ > _Pages_. +Select _Deploy for branch_ as source, `gh-pages` as branch and save the changes. # Troubleshooting From 8b2b7975e6803408ec161cc024a171608e1ac166 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 26 Sep 2023 16:09:46 +0200 Subject: [PATCH 13/63] create_package() opens the RStudio project when run from within RStudio. requested by @damianooldoni --- R/create_package.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/create_package.R b/R/create_package.R index ba96329a..d2087de4 100644 --- a/R/create_package.R +++ b/R/create_package.R @@ -273,7 +273,11 @@ create_package <- function( ) message("package created at `", path, "`") - return(invisible(NULL)) + + if (!interactive() || !requireNamespace("rstudioapi", quietly = TRUE)) { + return(invisible(NULL)) + } + rstudioapi::openProject(path, newSession = TRUE) } valid_package_name <- function(x) { From 4630eb75b4395ca725470205d0377a47a646373f Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 28 Sep 2023 22:04:59 +0200 Subject: [PATCH 14/63] the organisation class can be initialised with different values --- R/organisation_class.R | 123 ++++++++++++++++++++++++++++++++++++++++- man/organisation.Rd | 32 ++++++++++- 2 files changed, 153 insertions(+), 2 deletions(-) diff --git a/R/organisation_class.R b/R/organisation_class.R index db927ff0..c97314ec 100644 --- a/R/organisation_class.R +++ b/R/organisation_class.R @@ -7,7 +7,116 @@ organisation <- R6Class( "organisation", public = list( #' @description Initialize a new `organisation` object. - initialize = function() { + #' @param ... The organisation settings. + #' See the details. + #' @details + #' - `community`: the mandatory Zenodo community. + #' Defaults to `"inbo"`. + #' Set to `NA_character_` in case you don't want a mandatory community. + #' - `email`: the e-mail of the organisation. + #' Defaults to `"info@inbo.be"`. + #' Set to `NA_character_` in case you don't want an organisation e-mail. + #' - `funder`: the funder. + #' Defaults to `"Research Institute for Nature and Forest (INBO)"`. + #' Set to `NA_character_` in case you don't want to set a funder. + #' - `rightsholder`: the rightsholder. + #' Defaults to `"Research Institute for Nature and Forest (INBO)"`. + #' Set to `NA_character_` in case you don't want to set a rightsholder. + #' - `organisation`: a named list with one or more organisation defaults. + #' The names of the element must match the e-mail domain name of the + #' organisation. + #' Every element should be a named list containing ´affiliation` and + #' `orcid`. + #' `affiliation` is a character vector with the approved organisation + #' names in one or more languages. + #' `orcid = TRUE` indicated a mandatory ORCiD for every member. + #' Use an empty list in case you don't want to set this. + #' @importFrom assertthat assert_that is.string is.flag + initialize = function(...) { + dots <- list(...) + private$community <- use_first_non_null(dots$community, "inbo") + stopifnot("`community` must be a string" = is.string(private$community)) + private$email <- use_first_non_null(dots$email, "info@inbo.be") + stopifnot("`email` must be a string" = is.string(private$email)) + private$github <- use_first_non_null(dots$github, "inbo") + stopifnot("`github` must be a string" = is.string(private$github)) + private$funder <- use_first_non_null( + dots$funder, "Research Institute for Nature and Forest (INBO)" + ) + stopifnot("`funder` must be a string" = is.string(private$funder)) + private$rightsholder <- use_first_non_null( + dots$rightsholder, "Research Institute for Nature and Forest (INBO)" + ) + stopifnot( + "`rightsholder` must be a string" = is.string(private$rightsholder) + ) + assert_that( + is.null(dots$organisation) || is.list(dots$organisation), + msg = "`organisation` must be a list" + ) + private$organisation <- dots$organisation + private$organisation[["inbo.be"]] <- list( + affiliation = c( + en = "Research Institute for Nature and Forest (INBO)", + nl = "Instituut voor Natuur- en Bosonderzoek (INBO)", + fr = "Institut de Recherche sur la Nature et les For\u00eats (INBO)", + de = "Institut f\u00fcr Natur- und Waldforschung (INBO)" + ), + orcid = TRUE + ) + stopifnot( + "`organisation` must be a named list or NULL" = + !is.null(names(private$organisation)) && + all(names(private$organisation) != "") + ) + vapply( + names(private$organisation), FUN.VALUE = logical(1), + FUN = function(x) { + assert_that( + is.list(private$organisation[[x]]), + msg = sprintf("`organisation[[\"%s\"]]` is not a list", x) + ) + assert_that( + all( + c("affiliation", "orcid") %in% names(private$organisation[[x]]) + ), + msg = sprintf( + "`organisation[[\"%s\"]]` must contain `affiliation` and `orcid`", + x + ) + ) + assert_that( + is.character(private$organisation[[x]][["affiliation"]]), + msg = sprintf( + "`organisation[[\"%s\"]][[\"affiliation\"]]` is not a character vector", + x + ) + ) + assert_that( + noNA(private$organisation[[x]][["affiliation"]]), + msg = sprintf( + "`organisation[[\"%s\"]][[\"affiliation\"]]` may not contain NA", + x + ) + ) + assert_that( + length(private$organisation[[x]][["affiliation"]]) > 0, + msg = sprintf( + "`organisation[[\"%s\"]][[\"affiliation\"]]` may not be empty", + x + ) + ) + assert_that( + is.flag(private$organisation[[x]][["orcid"]]), + noNA(private$organisation[[x]][["orcid"]]), + msg = paste( + "`organisation[[\"%s\"]][[\"orcid\"]]` is not a flag", + "(a length one logical vector)" + ) |> + sprintf(x) + ) + } + ) invisible(self) }, #' @description Print the `organisation` object. @@ -92,3 +201,15 @@ organisation <- R6Class( rightsholder = "Research Institute for Nature and Forest (INBO)" ) ) + +use_first_non_null <- function(...) { + dots <- list(...) + vapply(dots, is.null, logical(1)) |> + xor(TRUE) |> + which() |> + head(1) -> selected + stopifnot( + "please provide at least one non-NULL element" = length(selected) == 1 + ) + dots[[selected]] +} diff --git a/man/organisation.Rd b/man/organisation.Rd index 242d1a8f..46f264d9 100644 --- a/man/organisation.Rd +++ b/man/organisation.Rd @@ -46,7 +46,37 @@ Other class: \subsection{Method \code{new()}}{ Initialize a new \code{organisation} object. \subsection{Usage}{ -\if{html}{\out{

}}\preformatted{organisation$new()}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{organisation$new(...)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{...}}{The organisation settings. +See the details.} +} +\if{html}{\out{
}} +} +\subsection{Details}{ +\itemize{ +\item \code{community}: the mandatory Zenodo community. +Defaults to \code{"inbo"}. +Set to \code{NA_character_} in case you don't want a mandatory community. +\item \code{email}: the e-mail of the organisation. +Defaults to \code{"info@inbo.be"}. +Set to \code{NA_character_} in case you don't want an organisation e-mail. +\item \code{funder}: the funder. +Defaults to \code{"Research Institute for Nature and Forest (INBO)"}. +Set to \code{NA_character_} in case you don't want to set a funder. +\item \code{rightsholder}: the rightsholder. +Defaults to \code{"Research Institute for Nature and Forest (INBO)"}. +Set to \code{NA_character_} in case you don't want to set a rightsholder. +\item \code{organisation}: a named list with one or more organisation defaults. +The names of the element must match the e-mail domain name of the +organisation. +Every element should be a named list containing ´affiliation\code{and}orcid\code{. }affiliation\verb{is a character vector with the approved organisation names in one or more languages.}orcid = TRUE` indicated a mandatory ORCiD for every member. +Use an empty list in case you don't want to set this. +} } } From 045deb2f3aae0edde17212da7601ab00e8a94762 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Fri, 29 Sep 2023 10:44:56 +0200 Subject: [PATCH 15/63] add read_organisation() and write_organisation() --- NAMESPACE | 2 ++ R/organisation_class.R | 8 ++++++++ R/read_organisation.R | 20 +++++++++++++++++++ R/write_observation.R | 21 ++++++++++++++++++++ inst/package_template/rbuildignore | 1 + man/check_filename.Rd | 4 +++- man/check_lintr.Rd | 4 +++- man/check_spelling.Rd | 4 +++- man/custom_dictionary.Rd | 4 +++- man/organisation.Rd | 2 ++ man/print.checklist_spelling.Rd | 4 +++- man/read_checklist.Rd | 4 +++- man/read_organisation.Rd | 31 ++++++++++++++++++++++++++++++ man/write_checklist.Rd | 4 +++- man/write_organisation.Rd | 30 +++++++++++++++++++++++++++++ 15 files changed, 136 insertions(+), 7 deletions(-) create mode 100644 R/read_organisation.R create mode 100644 R/write_observation.R create mode 100644 man/read_organisation.Rd create mode 100644 man/write_organisation.Rd diff --git a/NAMESPACE b/NAMESPACE index 80a51fbd..c6784d43 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -34,6 +34,7 @@ export(orcid2person) export(organisation) export(prepare_ghpages) export(read_checklist) +export(read_organisation) export(set_tag) export(setup_package) export(setup_project) @@ -47,6 +48,7 @@ export(validate_email) export(validate_orcid) export(write_checklist) export(write_citation_cff) +export(write_organisation) export(write_zenodo_json) export(yesno) importFrom(R6,R6Class) diff --git a/R/organisation_class.R b/R/organisation_class.R index c97314ec..de737580 100644 --- a/R/organisation_class.R +++ b/R/organisation_class.R @@ -180,6 +180,14 @@ organisation <- R6Class( #' @field get_rightsholder The default rightsholder. get_rightsholder = function() { private$rightsholder + }, + #' @field template A list for a check list template. + template = function() { + list( + community = private$community, email = private$email, + github = private$github, funder = private$funder, + rightsholder = private$rightsholder, organisation = private$organisation + ) } ), private = list( diff --git a/R/read_organisation.R b/R/read_organisation.R new file mode 100644 index 00000000..13913b26 --- /dev/null +++ b/R/read_organisation.R @@ -0,0 +1,20 @@ +#' Read the organisation file +#' +#' The checklist package stores organisation information in the +#' `organisation.yml` file in the root of a project. +#' @inheritParams read_checklist +#' @return An `organisation` object. +#' @export +#' @importFrom assertthat assert_that has_name is.string +#' @importFrom fs is_dir is_file path path_real path_split +#' @importFrom yaml read_yaml +#' @family both +read_organisation <- function(x = ".") { + x <- read_checklist(x = x) + organisation_file <- path(x$get_path, "organisation.yml") + if (!is_file(organisation_file)) { + return(organisation$new()) + } + read_yaml(organisation_file) |> + do.call(what = organisation$new) +} diff --git a/R/write_observation.R b/R/write_observation.R new file mode 100644 index 00000000..fcd186d5 --- /dev/null +++ b/R/write_observation.R @@ -0,0 +1,21 @@ +#' Write organisation settings +#' +#' Store the organisation rules into `organisation.yml` file. +#' First run `org <- checklist::organisation$new()` with the appropriate argument. +#' Next you can store the configuration with +#' `checklist::write_organisation(org)`. +#' +#' @inheritParams read_checklist +#' @importFrom assertthat assert_that +#' @importFrom fs path +#' @importFrom yaml write_yaml +#' @export +#' @family both +write_organisation <- function(org, x = ".") { + assert_that(inherits(org, "organisation")) + x <- suppressMessages(read_checklist(x = x)) + + path(x$get_path, "organisation.yml") |> + write_yaml(x = org$template) + return(invisible(NULL)) +} diff --git a/inst/package_template/rbuildignore b/inst/package_template/rbuildignore index 121c6547..f837c604 100644 --- a/inst/package_template/rbuildignore +++ b/inst/package_template/rbuildignore @@ -11,5 +11,6 @@ ^docs$ ^LICENSE.md$ ^man-roxygen$ +^organisation.yml$ ^pkgdown$ ^README\.Rmd$ diff --git a/man/check_filename.Rd b/man/check_filename.Rd index 8fbd247d..d70100b3 100644 --- a/man/check_filename.Rd +++ b/man/check_filename.Rd @@ -70,6 +70,8 @@ Other both: \code{\link{custom_dictionary}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, -\code{\link{write_checklist}()} +\code{\link{read_organisation}()}, +\code{\link{write_checklist}()}, +\code{\link{write_organisation}()} } \concept{both} diff --git a/man/check_lintr.Rd b/man/check_lintr.Rd index 465f2ff1..88740e29 100644 --- a/man/check_lintr.Rd +++ b/man/check_lintr.Rd @@ -28,6 +28,8 @@ Other both: \code{\link{custom_dictionary}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, -\code{\link{write_checklist}()} +\code{\link{read_organisation}()}, +\code{\link{write_checklist}()}, +\code{\link{write_organisation}()} } \concept{both} diff --git a/man/check_spelling.Rd b/man/check_spelling.Rd index 145ab71c..d93e905f 100644 --- a/man/check_spelling.Rd +++ b/man/check_spelling.Rd @@ -28,6 +28,8 @@ Other both: \code{\link{custom_dictionary}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, -\code{\link{write_checklist}()} +\code{\link{read_organisation}()}, +\code{\link{write_checklist}()}, +\code{\link{write_organisation}()} } \concept{both} diff --git a/man/custom_dictionary.Rd b/man/custom_dictionary.Rd index 05bd297d..bc853585 100644 --- a/man/custom_dictionary.Rd +++ b/man/custom_dictionary.Rd @@ -19,6 +19,8 @@ Other both: \code{\link{check_spelling}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, -\code{\link{write_checklist}()} +\code{\link{read_organisation}()}, +\code{\link{write_checklist}()}, +\code{\link{write_organisation}()} } \concept{both} diff --git a/man/organisation.Rd b/man/organisation.Rd index 46f264d9..cf4b7c39 100644 --- a/man/organisation.Rd +++ b/man/organisation.Rd @@ -29,6 +29,8 @@ Other class: \item{\code{get_organisation}}{The organisation requirements.} \item{\code{get_rightsholder}}{The default rightsholder.} + +\item{\code{template}}{A list for a check list template.} } \if{html}{\out{}} } diff --git a/man/print.checklist_spelling.Rd b/man/print.checklist_spelling.Rd index d9d7ae22..cd6bf8d9 100644 --- a/man/print.checklist_spelling.Rd +++ b/man/print.checklist_spelling.Rd @@ -21,6 +21,8 @@ Other both: \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, \code{\link{read_checklist}()}, -\code{\link{write_checklist}()} +\code{\link{read_organisation}()}, +\code{\link{write_checklist}()}, +\code{\link{write_organisation}()} } \concept{both} diff --git a/man/read_checklist.Rd b/man/read_checklist.Rd index fb4f7f24..bb660214 100644 --- a/man/read_checklist.Rd +++ b/man/read_checklist.Rd @@ -31,6 +31,8 @@ Other both: \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, \code{\link{print.checklist_spelling}()}, -\code{\link{write_checklist}()} +\code{\link{read_organisation}()}, +\code{\link{write_checklist}()}, +\code{\link{write_organisation}()} } \concept{both} diff --git a/man/read_organisation.Rd b/man/read_organisation.Rd new file mode 100644 index 00000000..94fb7f84 --- /dev/null +++ b/man/read_organisation.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read_organisation.R +\name{read_organisation} +\alias{read_organisation} +\title{Read the organisation file} +\usage{ +read_organisation(x = ".") +} +\arguments{ +\item{x}{Either a \code{checklist} object or a path to the source code. +Defaults to \code{.}.} +} +\value{ +An \code{organisation} object. +} +\description{ +The checklist package stores organisation information in the +\code{organisation.yml} file in the root of a project. +} +\seealso{ +Other both: +\code{\link{check_filename}()}, +\code{\link{check_lintr}()}, +\code{\link{check_spelling}()}, +\code{\link{custom_dictionary}()}, +\code{\link{print.checklist_spelling}()}, +\code{\link{read_checklist}()}, +\code{\link{write_checklist}()}, +\code{\link{write_organisation}()} +} +\concept{both} diff --git a/man/write_checklist.Rd b/man/write_checklist.Rd index 6608a6ff..2e9b6aff 100644 --- a/man/write_checklist.Rd +++ b/man/write_checklist.Rd @@ -59,6 +59,8 @@ Other both: \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, \code{\link{print.checklist_spelling}()}, -\code{\link{read_checklist}()} +\code{\link{read_checklist}()}, +\code{\link{read_organisation}()}, +\code{\link{write_organisation}()} } \concept{both} diff --git a/man/write_organisation.Rd b/man/write_organisation.Rd new file mode 100644 index 00000000..8c66857d --- /dev/null +++ b/man/write_organisation.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/write_observation.R +\name{write_organisation} +\alias{write_organisation} +\title{Write organisation settings} +\usage{ +write_organisation(org, x = ".") +} +\arguments{ +\item{x}{Either a \code{checklist} object or a path to the source code. +Defaults to \code{.}.} +} +\description{ +Store the organisation rules into \code{organisation.yml} file. +First run \code{org <- checklist::organisation$new()} with the appropriate argument. +Next you can store the configuration with +\code{checklist::write_organisation(org)}. +} +\seealso{ +Other both: +\code{\link{check_filename}()}, +\code{\link{check_lintr}()}, +\code{\link{check_spelling}()}, +\code{\link{custom_dictionary}()}, +\code{\link{print.checklist_spelling}()}, +\code{\link{read_checklist}()}, +\code{\link{read_organisation}()}, +\code{\link{write_checklist}()} +} +\concept{both} From ddac34062b673e47ed6dbf12c73a93723edb9a13 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 9 Oct 2023 11:54:27 +0200 Subject: [PATCH 16/63] all functions use the information of organisation.yml when present --- R/check_description.R | 14 +++++--- R/citation_bookdown.R | 20 ++++++----- R/citation_description.R | 33 +++++++++++-------- R/citation_meta_class.R | 11 ++++--- R/create_package.R | 4 +-- R/read_organisation.R | 21 ++++++++---- R/setup_project.R | 22 +++++++------ R/use_author.R | 32 +++++++++++------- ...ite_observation.R => write_organisation.R} | 7 ++-- man/write_organisation.Rd | 10 +++--- tests/testthat/test_a_author.R | 30 +++++++++++------ tests/testthat/test_c_create_package.R | 6 +++- tests/testthat/test_d_check_spelling.R | 9 +++-- 13 files changed, 140 insertions(+), 79 deletions(-) rename R/{write_observation.R => write_organisation.R} (68%) diff --git a/R/check_description.R b/R/check_description.R index 564674ab..daa4f304 100644 --- a/R/check_description.R +++ b/R/check_description.R @@ -120,7 +120,9 @@ from the web. More info on https://github.com/github/renaming"[ x$add_error(desc_error, item = "DESCRIPTION", keep = FALSE) x$add_notes(notes, item = "DESCRIPTION") - x$add_warnings(check_authors(this_desc), item = "DESCRIPTION") + read_organisation(x$get_path) |> + check_authors(this_desc = this_desc) |> + x$add_warnings(item = "DESCRIPTION") check_license(x = x) } @@ -284,13 +286,15 @@ Please send a pull request if you need support for this license.", return(x) } +#' @importFrom assertthat assert_that #' @importFrom utils person -check_authors <- function(this_desc) { +check_authors <- function(this_desc, org) { + assert_that(inherits(org, "organisation")) authors <- this_desc$get_authors() - org <- organisation$new() stopifnot( "TO DO: handle funder not equal to rightsholder" = - org$get_rightsholder == org$get_funder + (is.na(org$get_rightsholder) && is.na(org$get_funder)) || + (org$get_rightsholder == org$get_funder) ) rightsholder <- person( given = org$get_rightsholder, role = c("cph", "fnd"), email = org$get_email @@ -298,7 +302,7 @@ check_authors <- function(this_desc) { problems <- sprintf( "`%s` must be listed as copyright holder and funder and use `%s` as email.", org$get_rightsholder, org$get_email - )[!rightsholder %in% authors] + )[!is.na(org$get_rightsholder) && !rightsholder %in% authors] authors <- authors[!authors %in% rightsholder] vapply( authors, FUN.VALUE = vector(mode = "list", length = 1L), diff --git a/R/citation_bookdown.R b/R/citation_bookdown.R index 3e2bbedf..be780a56 100644 --- a/R/citation_bookdown.R +++ b/R/citation_bookdown.R @@ -14,7 +14,8 @@ citation_bookdown <- function(meta) { ) } yaml <- yaml_front_matter(index_file) - cit_meta <- yaml_author(yaml) + read_organisation(meta$get_path) |> + yaml_author(yaml = yaml) -> cit_meta description <- bookdown_description(meta$get_path) cit_meta$meta$description <- description$description cit_meta$errors <- c(cit_meta$errors, description$errors) @@ -82,10 +83,13 @@ citation_bookdown <- function(meta) { } #' @inheritParams assertthat has_name -yaml_author <- function(yaml) { - author <- vapply(yaml$author, yaml_author_format, vector(mode = "list", 1)) +yaml_author <- function(yaml, org) { + author <- vapply( + X = yaml$author, FUN = yaml_author_format, + FUN.VALUE = vector(mode = "list", 1), org = org + ) yaml$reviewer |> - vapply(yaml_author_format, vector(mode = "list", 1)) -> reviewer + vapply(yaml_author_format, vector(mode = "list", 1), org = org) -> reviewer c(author, reviewer) |> vapply(attr, vector(mode = "list", 1), which = "errors") |> unlist() |> @@ -122,7 +126,7 @@ yaml_author <- function(yaml) { rbind(roles) -> roles data.frame( id = nrow(author) + 1, given = yaml$funder, family = "", orcid = "", - affiliation = "", organisation = known_affiliation(yaml$funder) + affiliation = "", organisation = known_affiliation(yaml$funder, org = org) ) |> rbind(author) -> author } @@ -132,7 +136,7 @@ yaml_author <- function(yaml) { data.frame( id = nrow(author) + 1, given = yaml$rightsholder, family = "", orcid = "", affiliation = "", - organisation = known_affiliation(yaml$rightsholder) + organisation = known_affiliation(yaml$rightsholder, org = org) ) |> rbind(author) -> author } @@ -142,7 +146,7 @@ yaml_author <- function(yaml) { } #' @inheritParams assertthat has_name is.flag -yaml_author_format <- function(person) { +yaml_author_format <- function(person, org) { person_df <- data.frame( given = character(0), family = character(0), orcid = character(0), affiliation = character(0), contact = logical(0), @@ -173,7 +177,7 @@ yaml_author_format <- function(person) { contact = ifelse( is.null(person$corresponding), FALSE, person$corresponding ), - organisation = known_affiliation(paste0(person$affiliation, "")) + organisation = known_affiliation(paste0(person$affiliation, ""), org = org) ) c( "person `name` element is missing a `given` element"[ diff --git a/R/citation_description.R b/R/citation_description.R index 513e313f..21a06404 100644 --- a/R/citation_description.R +++ b/R/citation_description.R @@ -6,12 +6,15 @@ citation_description <- function(meta) { assert_that(meta$get_type == "package") path(meta$get_path, "DESCRIPTION") |> description$new() -> descript + org <- read_organisation(meta$get_path) descript$get_field("Config/checklist/keywords", default = character(0)) |> description_keywords() -> keywords descript$get_field("Config/checklist/communities", default = character(0)) |> - description_communities() -> communities + description_communities(org = org) -> communities urls <- description_url(descript$get_urls()) - authors <- description_author(descript$get_authors()) + authors <- description_author( + descript$get_authors(), org = org$get_organisation + ) descript$get_field("License") |> gsub(pattern = " \\+ file LICENSE", replacement = "") |> gsub(pattern = "^GPL-3$", replacement = "GPL-3.0") -> license @@ -47,10 +50,10 @@ citation_description <- function(meta) { ) } -description_author <- function(authors) { +description_author <- function(authors, org) { vapply( seq_along(authors), FUN = description_author_format, x = authors, - FUN.VALUE = vector("list", 1) + org = org, FUN.VALUE = vector("list", 1) ) |> do.call(what = "rbind") -> roles data.frame( @@ -64,7 +67,7 @@ description_author <- function(authors) { list(authors = contributors, roles = roles[, c("contributor", "role")]) } -description_author_format <- function(i, x) { +description_author_format <- function(i, x, org) { formatted <- data.frame( contributor = i, role = c( @@ -87,17 +90,20 @@ description_author_format <- function(i, x) { is.na(x[[i]]$comment["affiliation"]), "", x[[i]]$comment["affiliation"] ) if (formatted$organisation[1] == "" && formatted$affiliation[1] != "") { - formatted$organisation <- known_affiliation(formatted$affiliation[1]) + formatted$organisation <- known_affiliation( + formatted$affiliation[1], org = org + ) } return(list(formatted)) } #' @importFrom assertthat assert_that -known_affiliation <- function(target) { +known_affiliation <- function(target, org) { + assert_that(inherits(org, "organisation")) target <- gsub("([.|()\\^{}+$*?]|\\[|\\])", "\\\\\\1", target) - org <- organisation$new()$get_organisation vapply( - names(org), FUN.VALUE = logical(1), target = target, org = org, + names(org), FUN.VALUE = logical(1), target = target, + org = org$get_organisation, FUN = function(x, org, target) { grepl(target, org[[x]]$affiliation) |> any() @@ -151,16 +157,17 @@ description_keywords <- function(keywords) { ) } -description_communities <- function(communities) { - if (length(communities) == 0) { - org <- organisation$new() +#' @importFrom assertthat assert_that +description_communities <- function(communities, org) { + assert_that(inherits(org, "organisation")) + if (length(communities) == 0 && any(!is.na(org$get_community))) { return( list( meta = list(), warnings = paste( "no communities found in `DESCRIPTION`.", "Please add them with `Config/checklist/communities:", - org$get_community + paste(org$get_community, collapse = "; ") ) ) ) diff --git a/R/citation_meta_class.R b/R/citation_meta_class.R index 6ce85724..16cf91af 100644 --- a/R/citation_meta_class.R +++ b/R/citation_meta_class.R @@ -167,17 +167,19 @@ citation_print <- function(errors, meta, notes, path, warnings) { #' @importFrom assertthat assert_that validate_citation <- function(meta) { assert_that(inherits(meta, "citation_meta")) - org <- organisation$new() + org <- read_organisation(meta$get_path) roles <- meta$get_meta$roles authors <- meta$get_meta$authors rightsholder_id <- roles$contributor[roles$role == "copyright holder"] funder_id <- roles$contributor[roles$role == "funder"] notes <- c( sprintf("rightsholder differs from `%s`", org$get_rightsholder)[ - authors$given[authors$id == rightsholder_id] != org$get_rightsholder + !is.na(org$get_rightsholder) && + authors$given[authors$id == rightsholder_id] != org$get_rightsholder ], sprintf("funder differs from `%s`", org$get_funder)[ - authors$given[authors$id == funder_id] != org$get_funder + !is.na(org$get_funder) && + authors$given[authors$id == funder_id] != org$get_funder ] ) errors <- c( @@ -185,7 +187,8 @@ validate_citation <- function(meta) { !validate_orcid(authors$orcid) ], sprintf("missing required Zenodo community `%s`", org$get_community)[ - !org$get_community %in% meta$get_meta$community + !is.na(org$get_community) && + !org$get_community %in% meta$get_meta$community ] ) authors <- authors[authors$given != org$get_rightsholder, ] diff --git a/R/create_package.R b/R/create_package.R index d2087de4..7a06db34 100644 --- a/R/create_package.R +++ b/R/create_package.R @@ -66,14 +66,14 @@ create_package <- function( } } assert_that(inherits(maintainer, "person")) - org <- organisation$new() - maintainer <- c(maintainer, org$as_person) assert_that(is_dir(path), msg = sprintf("`%s` is not a directory", path)) assert_that(is.string(package)) assert_that(valid_package_name(package)) assert_that(is.character(keywords), length(keywords) > 0) assert_that(is.character(communities)) + org <- read_organisation(path) + maintainer <- c(maintainer, org$as_person) path <- path(path, package) assert_that( !is_dir(path) || length(dir_ls(path, recurse = TRUE)) == 0, diff --git a/R/read_organisation.R b/R/read_organisation.R index 13913b26..3179530b 100644 --- a/R/read_organisation.R +++ b/R/read_organisation.R @@ -10,11 +10,20 @@ #' @importFrom yaml read_yaml #' @family both read_organisation <- function(x = ".") { - x <- read_checklist(x = x) - organisation_file <- path(x$get_path, "organisation.yml") - if (!is_file(organisation_file)) { - return(organisation$new()) + checklist <- try(read_checklist(x = x), silent = TRUE) + if (inherits(checklist, "checklist")) { + organisation_file <- path(checklist$get_path, "organisation.yml") + if (is_file(organisation_file)) { + read_yaml(organisation_file) |> + do.call(what = organisation$new) -> org + return(org) + } } - read_yaml(organisation_file) |> - do.call(what = organisation$new) + organisation_file <- path(x, "organisation.yml") + if (is_file(organisation_file)) { + read_yaml(organisation_file) |> + do.call(what = organisation$new) -> org + return(org) + } + return(organisation$new()) } diff --git a/R/setup_project.R b/R/setup_project.R index 41330416..e23b50d5 100644 --- a/R/setup_project.R +++ b/R/setup_project.R @@ -28,9 +28,10 @@ setup_project <- function(path = ".") { system.file(package = "checklist") |> file_copy(path(path, "source", "checklist.R")) } - repo <- setup_vc(path = path) + org <- read_organisation(path) + repo <- setup_vc(path = path, org = org) renv_activate(path = path) - files <- create_readme(path = path) + files <- create_readme(path = path, org = org) checks <- c( "checklist", "folder conventions"[isTRUE(ask_yes_no("Check folder conventions?"))], @@ -77,7 +78,7 @@ setup_project <- function(path = ".") { #' @importFrom fs dir_create file_copy file_exists is_file path #' @importFrom gert git_add git_find git_init git_remote_add -setup_vc <- function(path) { +setup_vc <- function(path, org) { if (is_repository(path)) { assert_that(is_workdir_clean(path)) repo <- git_find(path) @@ -86,7 +87,7 @@ setup_vc <- function(path) { return(invisible(NULL)) } repo <- git_init(path = path) - preferred_protocol() |> + preferred_protocol(org) |> sprintf(basename(path)) |> git_remote_add(repo = repo) } @@ -180,14 +181,15 @@ create_project <- function(path, project) { rstudioapi::openProject(newSession = TRUE) } -create_readme <- function(path) { +#' @importFrom fs file_exists path +create_readme <- function(path, org) { if (file_exists(path(path, "README.md"))) { return(character(0)) } cat("Which person to use as author and contact person?\n") - author <- author2badge(role = c("aut", "cre")) + author <- author2badge(role = c("aut", "cre"), org = org) while (isTRUE(ask_yes_no("add another author?", default = FALSE))) { - extra <- author2badge() + extra <- author2badge(org = org) attr(author, "footnote") |> c(attr(extra, "footnote")) |> unique() -> footnote @@ -226,7 +228,6 @@ create_readme <- function(path) { ) -> badges } } - org <- organisation$new() c( "", badges, "", "", paste("#", title), "", author, @@ -246,11 +247,13 @@ create_readme <- function(path) { return("README.md") } +#' @importFrom assertthat assert_that #' @importFrom fs dir_create path #' @importFrom tools R_user_dir #' @importFrom utils menu #' @importFrom yaml read_yaml write_yaml -preferred_protocol <- function() { +preferred_protocol <- function(org) { + assert_that(inherits(org, "organisation")) config <- list() R_user_dir("checklist", which = "config") |> path("config.yml") -> config_file @@ -267,7 +270,6 @@ preferred_protocol <- function() { dir_create() write_yaml(x = config, file = config_file, fileEncoding = "UTF-8") } - org <- organisation$new() sprintf("Which GitHub organisation. Leave empty for `%s`.", org$get_github) |> readline() -> config[["git"]][["organisation"]] ifelse( diff --git a/R/use_author.R b/R/use_author.R index da40cddb..e7d16440 100644 --- a/R/use_author.R +++ b/R/use_author.R @@ -10,6 +10,7 @@ #' @export use_author <- function() { root <- R_user_dir("checklist", which = "data") + org <- read_organisation() current <- stored_authors(root) assert_that( interactive() || nrow(current) > 0, @@ -27,7 +28,7 @@ use_author <- function() { next } if (selected > nrow(current)) { - current <- new_author(current = current, root = root) + current <- new_author(current = current, root = root, org = org) } cat( "given name: ", current$given[selected], @@ -36,13 +37,15 @@ use_author <- function() { "\norcid: ", current$orcid[selected], "\naffiliation:", current$affiliation[selected] ) - current <- validate_author(current = current, selected = selected) + current <- validate_author( + current = current, selected = selected, org = org + ) final <- menu_first(choices = c("use ", "update", "other")) if (final == 1) { break } if (final == 2) { - current <- update_author(current, selected, root) + current <- update_author(current, selected, root, org) next } } @@ -68,7 +71,7 @@ menu_first <- function(choices, graphics = FALSE, title = NULL) { #' @importFrom fs path #' @importFrom utils menu write.table -update_author <- function(current, selected, root) { +update_author <- function(current, selected, root, org) { original <- current item <- c("given", "family", "email", "orcid", "affiliation") while (TRUE) { @@ -79,7 +82,9 @@ update_author <- function(current, selected, root) { "\norcid: ", current$orcid[selected], "\naffiliation:", current$affiliation[selected] ) - current <- validate_author(current = current, selected = selected) + current <- validate_author( + current = current, selected = selected, org = org + ) command <- menu( choices = c(item, "save and exit", "undo changes and exit"), title = "\nWhich item to update?" @@ -106,7 +111,10 @@ update_author <- function(current, selected, root) { return(current) } -new_author <- function(current, root) { +#' @importFrom assertthat assert_that +new_author <- function(current, root, org) { + assert_that(inherits(org, "organisation")) + org <- org$get_organisation cat("Please provide person information.\n") data.frame( given = readline(prompt = "given name: "), @@ -114,7 +122,6 @@ new_author <- function(current, root) { email = readline(prompt = "e-mail: "), orcid = ask_orcid(prompt = "orcid: ") ) -> extra - org <- organisation$new()$get_organisation gsub(".*@", "", extra$email) |> grepl(names(org), ignore.case = TRUE) |> which() -> which_org @@ -164,8 +171,10 @@ author2person <- function(role = "aut") { ) } +#' @importFrom assertthat assert_that #' @importFrom utils tail -author2badge <- function(role = "aut") { +author2badge <- function(role = "aut", org) { + assert_that(inherits(org, "organisation")) df <- use_author() sprintf("[^%s]", role) |> paste(collapse = "") -> role_link @@ -186,7 +195,7 @@ author2badge <- function(role = "aut") { if (is.na(df$affiliation) || df$affiliation == "") { return(badge) } - org <- organisation$new()$get_organisation + org <- org$get_organisation vapply( names(org), FUN.VALUE = vector(mode = "list", length = 1L), FUN = function(x) { @@ -209,8 +218,9 @@ author2badge <- function(role = "aut") { ) } -validate_author <- function(current, selected) { - org <- organisation$new()$get_organisation +validate_author <- function(current, selected, org) { + assert_that(inherits(org, "organisation")) + org <- org$get_organisation names(org) |> gsub(pattern = "\\.", replacement = "\\\\.") |> paste(collapse = "|") |> diff --git a/R/write_observation.R b/R/write_organisation.R similarity index 68% rename from R/write_observation.R rename to R/write_organisation.R index fcd186d5..74af7eae 100644 --- a/R/write_observation.R +++ b/R/write_organisation.R @@ -1,10 +1,11 @@ #' Write organisation settings #' #' Store the organisation rules into `organisation.yml` file. -#' First run `org <- checklist::organisation$new()` with the appropriate argument. -#' Next you can store the configuration with -#' `checklist::write_organisation(org)`. +#' First run `org <- organisation$new()` with the appropriate argument. +#' Next you can store the configuration with `write_organisation(org)`. #' +#' @param org An `organisation` object. +#' Create it with `organisation$new()`. #' @inheritParams read_checklist #' @importFrom assertthat assert_that #' @importFrom fs path diff --git a/man/write_organisation.Rd b/man/write_organisation.Rd index 8c66857d..ef04e5de 100644 --- a/man/write_organisation.Rd +++ b/man/write_organisation.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/write_observation.R +% Please edit documentation in R/write_organisation.R \name{write_organisation} \alias{write_organisation} \title{Write organisation settings} @@ -7,14 +7,16 @@ write_organisation(org, x = ".") } \arguments{ +\item{org}{An \code{organisation} object. +Create it with \code{organisation$new()}.} + \item{x}{Either a \code{checklist} object or a path to the source code. Defaults to \code{.}.} } \description{ Store the organisation rules into \code{organisation.yml} file. -First run \code{org <- checklist::organisation$new()} with the appropriate argument. -Next you can store the configuration with -\code{checklist::write_organisation(org)}. +First run \code{org <- organisation$new()} with the appropriate argument. +Next you can store the configuration with \code{write_organisation(org)}. } \seealso{ Other both: diff --git a/tests/testthat/test_a_author.R b/tests/testthat/test_a_author.R index 64572c59..3f0f5c7f 100644 --- a/tests/testthat/test_a_author.R +++ b/tests/testthat/test_a_author.R @@ -12,13 +12,16 @@ test_that("author tools", { expect_is(stored_authors(root), "data.frame") stub(new_author, "readline", mock("John", "Doe", "", "")) stub(new_author, "ask_orcid", "") - expect_output(new_author(current = data.frame(), root = root)) + org <- read_organisation() + expect_output(new_author(current = data.frame(), root = root, org = org)) expect_true(file_exists(path(root, "author.txt"))) current <- stored_authors(root) stub(update_author, "interactive", TRUE) stub(update_author, "menu", 7) - expect_output(update_author(current = current, selected = 1, root = root)) + expect_output( + update_author(current = current, selected = 1, root = root, org = org) + ) expect_identical(current, stored_authors(root)) stub(author2person, "R_user_dir", root, depth = 2) @@ -31,13 +34,17 @@ test_that("author tools", { badge <- "Doe, John[^aut]" attr(badge, "footnote") <- "[^aut]: author" expect_output({ - ab <- author2badge() + ab <- author2badge(org = read_organisation()) }) expect_equal(ab, badge) stub(update_author, "menu", mock(4, 6)) stub(update_author, "readline", "0000-0002-1825-0097", depth = 2) - expect_output(update_author(current = current, selected = 1, root = root)) + expect_output( + update_author( + current = current, selected = 1, root = root, org = read_organisation() + ) + ) current$orcid <- "0000-0002-1825-0097" expect_identical(current, stored_authors(root)) badge <- paste0( @@ -46,17 +53,18 @@ test_that("author tools", { ) attr(badge, "footnote") <- "[^aut]: author" expect_output({ - ab <- author2badge() + ab <- author2badge(org = org) }) expect_equal(ab, badge) - org <- organisation$new() stub(update_author, "menu", mock(5, 6)) stub( update_author, "readline", org$get_organisation[["inbo.be"]]$affiliation[1], depth = 2 ) - expect_output(update_author(current = current, selected = 1, root = root)) + expect_output( + update_author(current = current, selected = 1, root = root, org = org) + ) current$affiliation <- org$get_organisation[["inbo.be"]]$affiliation[1] expect_identical(current, stored_authors(root)) badge <- paste0( @@ -69,7 +77,7 @@ test_that("author tools", { paste("[^inbo.be]:", org$get_organisation[["inbo.be"]]$affiliation[1]) ) expect_output({ - ab <- author2badge() + ab <- author2badge(org = org) }) expect_equal(ab, badge) expect_output({ @@ -79,7 +87,9 @@ test_that("author tools", { stub(update_author, "menu", mock(3, 6)) stub(update_author, "readline", "noreply@inbo.be", depth = 2) - expect_output(update_author(current = current, selected = 1, root = root)) + expect_output( + update_author(current = current, selected = 1, root = root, org = org) + ) current$email <- "noreply@inbo.be" expect_identical(current, stored_authors(root)) expect_output({ @@ -94,5 +104,5 @@ test_that("author tools", { stub(new_author, "readline", mock("Jane", "Doe", "noreply@inbo.be")) stub(new_author, "ask_orcid", mock("", "0000-0002-1825-0097")) - expect_output(new_author(current, root = root)) + expect_output(new_author(current, root = root, org = org)) }) diff --git a/tests/testthat/test_c_create_package.R b/tests/testthat/test_c_create_package.R index 76597b3d..4faba595 100644 --- a/tests/testthat/test_c_create_package.R +++ b/tests/testthat/test_c_create_package.R @@ -30,7 +30,11 @@ test_that("create_package() works", { dir.create(r_user_dir) stub(new_author, "readline", mock("John", "Doe", "john@doe.com", "")) stub(new_author, "ask_orcid", mock("")) - expect_output(new_author(current = data.frame(), root = r_user_dir)) + expect_output( + new_author( + current = data.frame(), root = r_user_dir, org = read_organisation() + ) + ) stub(store_authors, "R_user_dir", r_user_dir) expect_invisible(store_authors(repo)) diff --git a/tests/testthat/test_d_check_spelling.R b/tests/testthat/test_d_check_spelling.R index 386bcfc9..3407238e 100644 --- a/tests/testthat/test_d_check_spelling.R +++ b/tests/testthat/test_d_check_spelling.R @@ -125,7 +125,10 @@ test_that("check_spelling() on a project", { dir.create(r_user_dir) stub(new_author, "readline", mock("John", "Doe", "john@doe.com", "")) stub(new_author, "ask_orcid", mock("")) - expect_output(new_author(current = data.frame(), root = r_user_dir)) + org <- read_organisation() + expect_output( + new_author(current = data.frame(), root = r_user_dir, org = org) + ) stub(create_project, "R_user_dir", r_user_dir, depth = 5) stub(create_project, "readline", "test") expect_invisible( @@ -186,7 +189,9 @@ test_that("check_spelling() on a project", { dir.create(r_user_dir) stub(new_author, "readline", mock("John", "Doe", "john@doe.com", "")) stub(new_author, "ask_orcid", mock("")) - expect_output(new_author(current = data.frame(), root = r_user_dir)) + expect_output( + new_author(current = data.frame(), root = r_user_dir, org = org) + ) hide_author <- tempfile(fileext = ".txt") defer(file_delete(hide_author)) From 5a46559c9a12dcba0f3be35b681ea34cb7acef59 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 9 Oct 2023 14:09:01 +0200 Subject: [PATCH 17/63] check_spelling() handles
chunks in markdown files --- R/check_spelling.R | 10 ++++++++++ R/spelling_parse.R | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/R/check_spelling.R b/R/check_spelling.R index ef342315..411d3dbf 100644 --- a/R/check_spelling.R +++ b/R/check_spelling.R @@ -139,6 +139,16 @@ spelling_check <- function(text, filename, wordlist, raw_text = text) { text = text, i = i, FUN = function(word, text, i) { detect <- gregexpr(spelling_clean_problem(word), text[i])[[1]] + if (min(detect) == -1) { + return( + list( + data.frame( + line = integer(0), column = integer(0), + message = character(0) + ) + ) + ) + } list( data.frame(line = i, column = as.vector(detect), message = word) ) diff --git a/R/spelling_parse.R b/R/spelling_parse.R index 3a68d8c1..fdb8d054 100644 --- a/R/spelling_parse.R +++ b/R/spelling_parse.R @@ -152,6 +152,22 @@ spelling_parse_md <- function(md_file, wordlist, x) { text[chunks[1]:chunks[2]] <- "" chunks <- tail(chunks, -2) } + # keep only alt text and captions for
chunks + html_figures <- grep("^$", text) + assert_that( + length(html_figures) %% 2 == 0, + msg = paste("Odd number of
delimiters detected in", md_file) + ) + while (length(html_figures)) { + text[head(html_figures, 2)] <- "" + fig_chunk_loc <- seq(html_figures[1] + 1, html_figures[2] - 1) + fig_chunk <- text[fig_chunk_loc] + paste(fig_chunk, collapse = " ") |> + gsub(pattern = "", replacement = "\\1") |> + gsub(pattern = "(.*)", replacement = "\\1") |> + rep(length(fig_chunk_loc)) -> text[fig_chunk_loc] + html_figures <- tail(html_figures, -2) + } # remove in line chunks text <- gsub("\\`r .*?`", "", text) # remove ignored lines From 99884314e5c0c8e64d8461748f61b946da901681 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 9 Oct 2023 14:12:07 +0200 Subject: [PATCH 18/63] check_cran() handles a new maintainer --- R/check_cran.R | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/R/check_cran.R b/R/check_cran.R index 9bf19d6e..1e3c4cb4 100644 --- a/R/check_cran.R +++ b/R/check_cran.R @@ -64,18 +64,8 @@ Days since last update: [0-9]+", "", check_output$warnings[incoming] check_output$warnings <- check_output$warnings[!incoming] } } - if ( - length(check_output$notes) > 0 && - any(grepl("Days since last update", check_output$notes)) - ) { - last_update <- grep("Days since last update", check_output$notes) - check_output$notes[last_update] <- gsub( - "\n\nDays since last update: [0-9]+", "", check_output$notes[last_update] - ) - if (length(strsplit(check_output$notes[last_update], "\n")[[1]]) == 2) { - check_output$notes <- check_output$notes[-last_update] - } - } # nocov end + # nocov end + check_output$notes <- clean_incoming(check_output$notes) check_output$warnings <- gsub(" \\[\\d+s/\\d+s\\]", "", check_output$warnings) check_output$notes <- gsub(" \\[\\d+s/\\d+s\\]", "", check_output$notes) # remove timing output from warnings and notes @@ -87,3 +77,26 @@ Days since last update: [0-9]+", "", check_output$warnings[incoming] ) return(x) } + +clean_incoming <- function(issues) { + if (length(issues) == 0) { + return(issues) + } + if (any(grepl("Days since last update", issues))) { + last_update <- grep("Days since last update", issues) # nocov start + issues[last_update] <- gsub( + "\n\nDays since last update: [0-9]+", "", issues[last_update] + ) + if (length(strsplit(issues[last_update], "\n")[[1]]) == 2) { + issues <- issues[-last_update] + } # nocov end + } + if (any(grepl("New maintainer", issues))) { + # nocov start + issues <- gsub("\n\nNew maintainer:.*Old maintainer.*?<.*?>", "", issues) + if (length(strsplit(issues, "\n")[[1]]) == 2) { + issues <- character(0) + } # nocov end + } + return(issues) +} From c7d2fb061179d5e0c98d372ecba163b9967f32c5 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 12 Oct 2023 15:18:08 +0200 Subject: [PATCH 19/63] use only CRAN --- DESCRIPTION | 1 - checklist.yml | 3 --- 2 files changed, 4 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index bd1bd34e..7207eb10 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -53,7 +53,6 @@ Suggests: zen4R (>= 0.9) VignetteBuilder: knitr -Additional_repositories: https://inbo.r-universe.dev Config/checklist/communities: inbo Config/checklist/keywords: quality control; documentation; publication Encoding: UTF-8 diff --git a/checklist.yml b/checklist.yml index dedddd65..a853305b 100644 --- a/checklist.yml +++ b/checklist.yml @@ -9,9 +9,6 @@ allowed: Maintainer: 'Thierry Onkelinx ' New submission - - Availability using Additional_repositories specification: - ? ? https://inbo.r-universe.dev required: - CITATION - DESCRIPTION From 87eefa21df707d56f882cffc16b824cd24d329d4 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 7 Dec 2023 16:41:23 +0100 Subject: [PATCH 20/63] new add_badges() function --- NAMESPACE | 1 + R/add_badges.R | 48 +++++++++++++++++++++++++++++++++ man/add_badges.Rd | 40 +++++++++++++++++++++++++++ man/check_filename.Rd | 1 + man/check_lintr.Rd | 1 + man/check_spelling.Rd | 1 + man/custom_dictionary.Rd | 1 + man/print.checklist_spelling.Rd | 1 + man/read_checklist.Rd | 1 + man/read_organisation.Rd | 1 + man/write_checklist.Rd | 1 + man/write_organisation.Rd | 1 + 12 files changed, 98 insertions(+) create mode 100644 R/add_badges.R create mode 100644 man/add_badges.Rd diff --git a/NAMESPACE b/NAMESPACE index c6784d43..4f3a1f3c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,6 +2,7 @@ S3method(print,checklist_language) S3method(print,checklist_spelling) +export(add_badges) export(ask_yes_no) export(bookdown_zenodo) export(c_sort) diff --git a/R/add_badges.R b/R/add_badges.R new file mode 100644 index 00000000..baf097e0 --- /dev/null +++ b/R/add_badges.R @@ -0,0 +1,48 @@ +#' add badges to a README +#' +#' - `doi`: add a DOI badge +#' - `url`: add a website badge +#' @inheritParams read_checklist +#' @param ... Aditional arguments +#' @importFrom assertthat assert_that +#' @importFrom fs dir_ls path +#' @export +#' @family both +#' @examples +#' \dontrun{ +#' add_badges(url = "https://www.inbo.be") +#' add_badges(doi = "10.5281/zenodo.8063503") +#' add_badges(url = "https://www.inbo.be", doi = "10.5281/zenodo.8063503") +#' } +add_badges <- function(x = ".", ...) { + x <- read_checklist(x = x) + dir_ls(x$get_path, regexp = "README.R?md$") |> + sort() |> + tail(1) -> readme + assert_that(length(readme) == 1, msg = "No README.md or README.Rmd found") + text <- readLines(readme) + badges_start <- grep("", text) + assert_that( + length(badges_start) == 1, msg = "Problematic badge delimiters in README" + ) + dots <- list(...) + formats <- c( + url = + "[![website](https://img.shields.io/badge/website-%1$s-c04384)](%1$s)", + doi = +"[![DOI](https://https://zenodo.org/badge/DOI/%1$s.svg)](https://doi.org/%1$s)" + ) + dots <- dots[names(formats)] + formats <- formats[names(dots)] + vapply( + names(dots), FUN.VALUE = character(1), formats = formats, dots = dots, + FUN = function(i, formats, dots) { + list(fmt = formats[i]) |> + c(dots[i]) |> + do.call(what = sprintf) + } + ) -> new_badge + head(text, badges_start) |> + c(new_badge, tail(text, - badges_start)) |> + writeLines(readme) +} diff --git a/man/add_badges.Rd b/man/add_badges.Rd new file mode 100644 index 00000000..2d1bc901 --- /dev/null +++ b/man/add_badges.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/add_badges.R +\name{add_badges} +\alias{add_badges} +\title{add badges to a README} +\usage{ +add_badges(x = ".", ...) +} +\arguments{ +\item{x}{Either a \code{checklist} object or a path to the source code. +Defaults to \code{.}.} + +\item{...}{Aditional arguments} +} +\description{ +\itemize{ +\item \code{doi}: add a DOI badge +\item \code{url}: add a website badge +} +} +\examples{ +\dontrun{ + add_badges(url = "https://www.inbo.be") + add_badges(doi = "10.5281/zenodo.8063503") + add_badges(url = "https://www.inbo.be", doi = "10.5281/zenodo.8063503") +} +} +\seealso{ +Other both: +\code{\link{check_filename}()}, +\code{\link{check_lintr}()}, +\code{\link{check_spelling}()}, +\code{\link{custom_dictionary}()}, +\code{\link{print.checklist_spelling}()}, +\code{\link{read_checklist}()}, +\code{\link{read_organisation}()}, +\code{\link{write_checklist}()}, +\code{\link{write_organisation}()} +} +\concept{both} diff --git a/man/check_filename.Rd b/man/check_filename.Rd index d70100b3..d1057125 100644 --- a/man/check_filename.Rd +++ b/man/check_filename.Rd @@ -65,6 +65,7 @@ These are fonts files which often require their own file name scheme. \seealso{ Other both: +\code{\link{add_badges}()}, \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, diff --git a/man/check_lintr.Rd b/man/check_lintr.Rd index 88740e29..899cb8cc 100644 --- a/man/check_lintr.Rd +++ b/man/check_lintr.Rd @@ -23,6 +23,7 @@ Please have a look at \code{vignette("philosophy")} for more details on the rule } \seealso{ Other both: +\code{\link{add_badges}()}, \code{\link{check_filename}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, diff --git a/man/check_spelling.Rd b/man/check_spelling.Rd index d93e905f..39b409a1 100644 --- a/man/check_spelling.Rd +++ b/man/check_spelling.Rd @@ -23,6 +23,7 @@ details. } \seealso{ Other both: +\code{\link{add_badges}()}, \code{\link{check_filename}()}, \code{\link{check_lintr}()}, \code{\link{custom_dictionary}()}, diff --git a/man/custom_dictionary.Rd b/man/custom_dictionary.Rd index bc853585..18307220 100644 --- a/man/custom_dictionary.Rd +++ b/man/custom_dictionary.Rd @@ -14,6 +14,7 @@ Add words to custom dictionaries } \seealso{ Other both: +\code{\link{add_badges}()}, \code{\link{check_filename}()}, \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, diff --git a/man/print.checklist_spelling.Rd b/man/print.checklist_spelling.Rd index cd6bf8d9..f723336b 100644 --- a/man/print.checklist_spelling.Rd +++ b/man/print.checklist_spelling.Rd @@ -16,6 +16,7 @@ Display a \code{checklist_spelling} summary } \seealso{ Other both: +\code{\link{add_badges}()}, \code{\link{check_filename}()}, \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, diff --git a/man/read_checklist.Rd b/man/read_checklist.Rd index bb660214..fd919176 100644 --- a/man/read_checklist.Rd +++ b/man/read_checklist.Rd @@ -26,6 +26,7 @@ finding a \code{checklist.yml} file. } \seealso{ Other both: +\code{\link{add_badges}()}, \code{\link{check_filename}()}, \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, diff --git a/man/read_organisation.Rd b/man/read_organisation.Rd index 94fb7f84..62a38077 100644 --- a/man/read_organisation.Rd +++ b/man/read_organisation.Rd @@ -19,6 +19,7 @@ The checklist package stores organisation information in the } \seealso{ Other both: +\code{\link{add_badges}()}, \code{\link{check_filename}()}, \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, diff --git a/man/write_checklist.Rd b/man/write_checklist.Rd index 2e9b6aff..30fd3171 100644 --- a/man/write_checklist.Rd +++ b/man/write_checklist.Rd @@ -54,6 +54,7 @@ That will result in an error when checking the package on an other machine \seealso{ Other both: +\code{\link{add_badges}()}, \code{\link{check_filename}()}, \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, diff --git a/man/write_organisation.Rd b/man/write_organisation.Rd index ef04e5de..ad5dd3fb 100644 --- a/man/write_organisation.Rd +++ b/man/write_organisation.Rd @@ -20,6 +20,7 @@ Next you can store the configuration with \code{write_organisation(org)}. } \seealso{ Other both: +\code{\link{add_badges}()}, \code{\link{check_filename}()}, \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, From b39890701f4df55773e667e057f5ff17bec62798 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Fri, 8 Dec 2023 10:57:41 +0100 Subject: [PATCH 21/63] use_author() gains an optional email argument --- R/use_author.R | 14 ++++++++++++-- man/use_author.Rd | 7 ++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/R/use_author.R b/R/use_author.R index e7d16440..c13fab05 100644 --- a/R/use_author.R +++ b/R/use_author.R @@ -3,12 +3,16 @@ #' Reuse existing author information or add a new author. #' Allows to update existing author information. #' @return A data.frame with author information. +#' @param email An optional email address. +#' When given and it matches with a single person, the function immediately +#' returns the information of that person. +#' @importFrom assertthat assert_that is.string noNA #' @importFrom fs path #' @importFrom tools R_user_dir #' @importFrom utils write.table #' @family utils #' @export -use_author <- function() { +use_author <- function(email) { root <- R_user_dir("checklist", which = "data") org <- read_organisation() current <- stored_authors(root) @@ -19,7 +23,13 @@ use_author <- function() { current <- current[ order(-current$usage, current$family, current$given, current$orcid), ] - while (TRUE) { + run_loop <- TRUE + if (!missing(email)) { + assert_that(is.string(email), noNA(email)) + selected <- which(current$email == email) + run_loop <- length(selected) != 1 + } + while (run_loop) { sprintf("%s, %s", current$family, current$given) |> c("new person") |> menu_first("Which person information do you want to use?") -> selected diff --git a/man/use_author.Rd b/man/use_author.Rd index 4132a779..d832fbd8 100644 --- a/man/use_author.Rd +++ b/man/use_author.Rd @@ -4,7 +4,12 @@ \alias{use_author} \title{Which author to use} \usage{ -use_author() +use_author(email) +} +\arguments{ +\item{email}{An optional email address. +When given and it matches with a single person, the function immediately +returns the information of that person.} } \value{ A data.frame with author information. From 1aeb25915cba88b0d210c905141f92ca9a3b09a2 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 18 Jan 2024 13:53:52 +0100 Subject: [PATCH 22/63] skip unit test with old versions of zen4R At the time of of this commit, the zen4R package is broken due to changes in the Zenodo API. --- tests/testthat/test_e_bookdown_zenodo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test_e_bookdown_zenodo.R b/tests/testthat/test_e_bookdown_zenodo.R index d3b7962c..6ebd7271 100644 --- a/tests/testthat/test_e_bookdown_zenodo.R +++ b/tests/testthat/test_e_bookdown_zenodo.R @@ -1,5 +1,5 @@ test_that("bookdown_zenodo() works", { - skip_if_not_installed("zen4R") + skip_if_not_installed("zen4R", minimum_version = "0.10") skip_if_not_installed("bookdown") skip_if(Sys.getenv("MY_UNIVERSE") != "") # skip test on r-universe.dev expect_match(Sys.getenv("ZENODO_SANDBOX"), "^\\w{60}$") From 4deb3f33c53115bfc9c7ff536c92149dc6fb45ea Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 18 Jan 2024 13:54:13 +0100 Subject: [PATCH 23/63] upgrade to Roxygen 7.3.0 --- DESCRIPTION | 2 +- NAMESPACE | 1 - R/create_package.R | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 7207eb10..adbee854 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -58,5 +58,5 @@ Config/checklist/keywords: quality control; documentation; publication Encoding: UTF-8 Language: en-GB Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.0 SystemRequirements: Pandoc (>= 1.17.2) diff --git a/NAMESPACE b/NAMESPACE index 4f3a1f3c..687f1bf4 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -54,7 +54,6 @@ export(write_zenodo_json) export(yesno) importFrom(R6,R6Class) importFrom(assertthat,"on_failure<-") -importFrom(assertthat,`on_failure<-`) importFrom(assertthat,assert_that) importFrom(assertthat,has_name) importFrom(assertthat,is.flag) diff --git a/R/create_package.R b/R/create_package.R index 7a06db34..00db8229 100644 --- a/R/create_package.R +++ b/R/create_package.R @@ -284,7 +284,7 @@ valid_package_name <- function(x) { grepl("^[a-zA-Z][a-zA-Z0-9.]+$", x) && !grepl("\\.$", x) } -#' @importFrom assertthat `on_failure<-` +#' @importFrom assertthat on_failure<- on_failure(valid_package_name) <- function(call, env) { paste(deparse(call$x), "is not a valid package name.") } From 82fbe2ceec73cc197a3bfe1d29e59eb57cea5980 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 18 Jan 2024 14:20:35 +0100 Subject: [PATCH 24/63] fix checklist errors --- NEWS.md | 2 +- inst/CITATION | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2cf12f05..0d47ee10 100644 --- a/NEWS.md +++ b/NEWS.md @@ -125,7 +125,7 @@ # checklist 0.2.3 -* Add `vignette("zenodo")` on how to set up the integration with [Zenodo](https://www.zenodo.org) and +* Add `vignette("zenodo")` on how to set up the integration with [Zenodo](https://zenodo.org) and [ORCID](https://orcid.org) * `check_environment()` makes sure that the required repository secrets are set. `check_package()` performs this check when it runs in a GitHub Action. diff --git a/inst/CITATION b/inst/CITATION index c32f0d38..01945119 100644 --- a/inst/CITATION +++ b/inst/CITATION @@ -4,10 +4,10 @@ bibentry( bibtype = "Manual", title = "checklist: A Thorough and Strict Set of Checks for R Packages and Source Code. Version 0.3.6", author = c( author = c(person(given = "Thierry", family = "Onkelinx"))), - year = 2023, + year = 2024, url = "https://inbo.github.io/checklist/", abstract = "An opinionated set of rules for R packages and R source code projects.", - textVersion = "Onkelinx, Thierry (2023) checklist: A Thorough and Strict Set of Checks for R Packages and Source Code. Version 0.3.6. https://inbo.github.io/checklist/", + textVersion = "Onkelinx, Thierry (2024) checklist: A Thorough and Strict Set of Checks for R Packages and Source Code. Version 0.3.6. https://inbo.github.io/checklist/", keywords = "quality control; documentation; publication", doi = "10.5281/zenodo.4028303", ) From 7517fc5c70a87023c4dd0dc05c3add4058d72e85 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 18 Jan 2024 17:40:24 +0100 Subject: [PATCH 25/63] add unit test to replicate the problem declared in issue #118 --- tests/testthat/test_d_check_lintr.R | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/testthat/test_d_check_lintr.R diff --git a/tests/testthat/test_d_check_lintr.R b/tests/testthat/test_d_check_lintr.R new file mode 100644 index 00000000..a6579c54 --- /dev/null +++ b/tests/testthat/test_d_check_lintr.R @@ -0,0 +1,35 @@ +test_that("check_lintr() works on a project with renv", { + old_option <- getOption("checklist.rstudio_source_markers", TRUE) + options("checklist.rstudio_source_markers" = FALSE) + defer(options("checklist.rstudio_source_markers" = old_option)) + + path <- tempfile("check_lintr") + dir_create(path) + defer(unlink(path, recursive = TRUE)) + + # create a minimal empty project + x <- checklist$new(x = path, language = "en-GB", package = FALSE) + x$set_required("lintr") + write_checklist(x) + expect_false(check_lintr(path)$fail) + + # setup renv at the root of the project + renv::init(path, bare = TRUE, load = FALSE, restart = FALSE) + # add a file within the renv folder that fails lintr + path(path, "renv", "WRONG-name style.r") |> + writeLines(text = "lowerCamelCase<-function(base_name.style){return(T)}") + # test that lintr ignores files within the renv folder + expect_false(check_lintr(path)$fail) + + # setup renv at a subfolder of the project + path(path, "source", "targets", "pipeline1") |> + dir_create() + path(path, "source", "targets", "pipeline1") |> + renv::init(bare = TRUE, load = FALSE, restart = FALSE) + # add a file within this folder that fails lintr + path |> + path("source", "targets", "pipeline1", "renv", "WRONG-name style.r") |> + writeLines(text = "lowerCamelCase<-function(base_name.style){return(T)}") + # test that lintr ignores files within the renv folder + expect_false(check_lintr(path)$fail) +}) From 283d21f0d6580411994bf0233e932be6d05998b8 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Fri, 19 Jan 2024 10:04:21 +0100 Subject: [PATCH 26/63] check_lintr() ignores all renv folders in a project solves #118 --- R/check_lintr.R | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/R/check_lintr.R b/R/check_lintr.R index 7f81fec8..8a55366f 100644 --- a/R/check_lintr.R +++ b/R/check_lintr.R @@ -14,6 +14,7 @@ #' @export #' @importFrom assertthat assert_that is.flag noNA #' @importFrom lintr lint_dir lint_package +#' @importFrom fs dir_ls #' @importFrom withr defer #' @family both check_lintr <- function(x = ".", quiet = FALSE) { @@ -27,7 +28,14 @@ check_lintr <- function(x = ".", quiet = FALSE) { if (x$package) { linter <- lint_package(path = x$get_path) } else { - linter <- lint_dir(x$get_path, pattern = "\\.(R|q)(md|nw)?$") + dir_ls( + path = x$get_path, recurse = TRUE, regexp = "/renv$", type = "directory" + ) |> + as.list() |> + unname() -> exclude_renv + linter <- lint_dir( + x$get_path, pattern = "\\.(R|q)(md|nw)?$", exclusions = exclude_renv + ) } if (!quiet && length(linter) > 0) { print(linter) From 8d1c64cfb1441fb38b06b6ca2a9b1b28bad24e56 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Fri, 19 Jan 2024 10:41:08 +0100 Subject: [PATCH 27/63] fix typo --- R/add_badges.R | 2 +- man/add_badges.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/add_badges.R b/R/add_badges.R index baf097e0..81b23ffe 100644 --- a/R/add_badges.R +++ b/R/add_badges.R @@ -3,7 +3,7 @@ #' - `doi`: add a DOI badge #' - `url`: add a website badge #' @inheritParams read_checklist -#' @param ... Aditional arguments +#' @param ... Additional arguments #' @importFrom assertthat assert_that #' @importFrom fs dir_ls path #' @export diff --git a/man/add_badges.Rd b/man/add_badges.Rd index 2d1bc901..f01c9251 100644 --- a/man/add_badges.Rd +++ b/man/add_badges.Rd @@ -10,7 +10,7 @@ add_badges(x = ".", ...) \item{x}{Either a \code{checklist} object or a path to the source code. Defaults to \code{.}.} -\item{...}{Aditional arguments} +\item{...}{Additional arguments} } \description{ \itemize{ From 940bbdeabcbdd1c3440c229c3bd022044372aa23 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Fri, 19 Jan 2024 14:03:42 +0100 Subject: [PATCH 28/63] add default_organisation() --- NAMESPACE | 1 + R/default_organisation.R | 20 ++++++++++++++++++++ R/read_organisation.R | 15 +++++++++------ man/add_badges.Rd | 1 + man/check_filename.Rd | 1 + man/check_lintr.Rd | 1 + man/check_spelling.Rd | 1 + man/custom_dictionary.Rd | 1 + man/default_organisation.Rd | 31 +++++++++++++++++++++++++++++++ man/print.checklist_spelling.Rd | 1 + man/read_checklist.Rd | 1 + man/read_organisation.Rd | 1 + man/write_checklist.Rd | 1 + man/write_organisation.Rd | 1 + vignettes/zenodo.Rmd | 4 ++-- 15 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 R/default_organisation.R create mode 100644 man/default_organisation.Rd diff --git a/NAMESPACE b/NAMESPACE index 687f1bf4..7346b664 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -26,6 +26,7 @@ export(create_hexsticker) export(create_package) export(create_project) export(custom_dictionary) +export(default_organisation) export(execshell) export(is_repository) export(is_workdir_clean) diff --git a/R/default_organisation.R b/R/default_organisation.R new file mode 100644 index 00000000..dc53ead2 --- /dev/null +++ b/R/default_organisation.R @@ -0,0 +1,20 @@ +#' Write default organisation settings +#' +#' Store the default organisation rules. +#' First run `org <- organisation$new()` with the appropriate argument. +#' Next you can store the configuration with `default_organisation(org)`. +#' +#' @param org An `organisation` object. +#' Create it with `organisation$new()`. +#' @importFrom assertthat assert_that +#' @importFrom fs path +#' @importFrom yaml write_yaml +#' @export +#' @family both +default_organisation <- function(org = organisation$new()) { + assert_that(inherits(org, "organisation")) + R_user_dir("checklist", which = "config") |> + path("organisation.yml") |> + write_yaml(x = org$template) + return(invisible(NULL)) +} diff --git a/R/read_organisation.R b/R/read_organisation.R index 3179530b..0bd8b2f1 100644 --- a/R/read_organisation.R +++ b/R/read_organisation.R @@ -12,12 +12,7 @@ read_organisation <- function(x = ".") { checklist <- try(read_checklist(x = x), silent = TRUE) if (inherits(checklist, "checklist")) { - organisation_file <- path(checklist$get_path, "organisation.yml") - if (is_file(organisation_file)) { - read_yaml(organisation_file) |> - do.call(what = organisation$new) -> org - return(org) - } + x <- checklist$get_path } organisation_file <- path(x, "organisation.yml") if (is_file(organisation_file)) { @@ -25,5 +20,13 @@ read_organisation <- function(x = ".") { do.call(what = organisation$new) -> org return(org) } + R_user_dir("checklist", which = "config") |> + path("organisation.yml") -> organisation_default + if (is_file(organisation_default)) { + read_yaml(organisation_default) |> + do.call(what = organisation$new) -> org + write_organisation(org = org, x = x) + return(org) + } return(organisation$new()) } diff --git a/man/add_badges.Rd b/man/add_badges.Rd index f01c9251..4ce55ee5 100644 --- a/man/add_badges.Rd +++ b/man/add_badges.Rd @@ -31,6 +31,7 @@ Other both: \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, +\code{\link{default_organisation}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, \code{\link{read_organisation}()}, diff --git a/man/check_filename.Rd b/man/check_filename.Rd index d1057125..32a0ae44 100644 --- a/man/check_filename.Rd +++ b/man/check_filename.Rd @@ -69,6 +69,7 @@ Other both: \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, +\code{\link{default_organisation}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, \code{\link{read_organisation}()}, diff --git a/man/check_lintr.Rd b/man/check_lintr.Rd index 899cb8cc..625a64a5 100644 --- a/man/check_lintr.Rd +++ b/man/check_lintr.Rd @@ -27,6 +27,7 @@ Other both: \code{\link{check_filename}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, +\code{\link{default_organisation}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, \code{\link{read_organisation}()}, diff --git a/man/check_spelling.Rd b/man/check_spelling.Rd index 39b409a1..a535aa10 100644 --- a/man/check_spelling.Rd +++ b/man/check_spelling.Rd @@ -27,6 +27,7 @@ Other both: \code{\link{check_filename}()}, \code{\link{check_lintr}()}, \code{\link{custom_dictionary}()}, +\code{\link{default_organisation}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, \code{\link{read_organisation}()}, diff --git a/man/custom_dictionary.Rd b/man/custom_dictionary.Rd index 18307220..3ca6ddb4 100644 --- a/man/custom_dictionary.Rd +++ b/man/custom_dictionary.Rd @@ -18,6 +18,7 @@ Other both: \code{\link{check_filename}()}, \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, +\code{\link{default_organisation}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, \code{\link{read_organisation}()}, diff --git a/man/default_organisation.Rd b/man/default_organisation.Rd new file mode 100644 index 00000000..13166f13 --- /dev/null +++ b/man/default_organisation.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/default_organisation.R +\name{default_organisation} +\alias{default_organisation} +\title{Write default organisation settings} +\usage{ +default_organisation(org = organisation$new()) +} +\arguments{ +\item{org}{An \code{organisation} object. +Create it with \code{organisation$new()}.} +} +\description{ +Store the default organisation rules. +First run \code{org <- organisation$new()} with the appropriate argument. +Next you can store the configuration with \code{default_organisation(org)}. +} +\seealso{ +Other both: +\code{\link{add_badges}()}, +\code{\link{check_filename}()}, +\code{\link{check_lintr}()}, +\code{\link{check_spelling}()}, +\code{\link{custom_dictionary}()}, +\code{\link{print.checklist_spelling}()}, +\code{\link{read_checklist}()}, +\code{\link{read_organisation}()}, +\code{\link{write_checklist}()}, +\code{\link{write_organisation}()} +} +\concept{both} diff --git a/man/print.checklist_spelling.Rd b/man/print.checklist_spelling.Rd index f723336b..4bc4e1e9 100644 --- a/man/print.checklist_spelling.Rd +++ b/man/print.checklist_spelling.Rd @@ -21,6 +21,7 @@ Other both: \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, +\code{\link{default_organisation}()}, \code{\link{read_checklist}()}, \code{\link{read_organisation}()}, \code{\link{write_checklist}()}, diff --git a/man/read_checklist.Rd b/man/read_checklist.Rd index fd919176..adf8cea1 100644 --- a/man/read_checklist.Rd +++ b/man/read_checklist.Rd @@ -31,6 +31,7 @@ Other both: \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, +\code{\link{default_organisation}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_organisation}()}, \code{\link{write_checklist}()}, diff --git a/man/read_organisation.Rd b/man/read_organisation.Rd index 62a38077..3502f02d 100644 --- a/man/read_organisation.Rd +++ b/man/read_organisation.Rd @@ -24,6 +24,7 @@ Other both: \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, +\code{\link{default_organisation}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, \code{\link{write_checklist}()}, diff --git a/man/write_checklist.Rd b/man/write_checklist.Rd index 30fd3171..a1a10ca4 100644 --- a/man/write_checklist.Rd +++ b/man/write_checklist.Rd @@ -59,6 +59,7 @@ Other both: \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, +\code{\link{default_organisation}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, \code{\link{read_organisation}()}, diff --git a/man/write_organisation.Rd b/man/write_organisation.Rd index ad5dd3fb..c79900d5 100644 --- a/man/write_organisation.Rd +++ b/man/write_organisation.Rd @@ -25,6 +25,7 @@ Other both: \code{\link{check_lintr}()}, \code{\link{check_spelling}()}, \code{\link{custom_dictionary}()}, +\code{\link{default_organisation}()}, \code{\link{print.checklist_spelling}()}, \code{\link{read_checklist}()}, \code{\link{read_organisation}()}, diff --git a/vignettes/zenodo.Rmd b/vignettes/zenodo.Rmd index c17d5e00..6aba7c66 100644 --- a/vignettes/zenodo.Rmd +++ b/vignettes/zenodo.Rmd @@ -16,7 +16,7 @@ opts_chunk$set( ) ``` -## What is [Zenodo](https://www.zenodo.org)? +## What is [Zenodo](https://zenodo.org)? Built and developed by researchers, to ensure that everyone can join in Open Science. @@ -72,7 +72,7 @@ Setting up the integration has the benefit that a new package version automatica #### Once per repository -1. Log-in to [Zenodo](https://www.zenodo.org). +1. Log-in to [Zenodo](https://zenodo.org). 1. Go the to drop-down box associated to your account (top right) and choose GitHub. 1. Find the repository in the list of repositories. Use the "Sync now" button if you can't find the repository. From 4d70747623c6d6ae94be04ddb15d5c41885b0e1b Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 22 Jan 2024 14:30:59 +0100 Subject: [PATCH 29/63] display git diff as a part of checklist summary fixes #77 --- DESCRIPTION | 1 + NAMESPACE | 4 ++++ R/utils.R | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/DESCRIPTION b/DESCRIPTION index adbee854..6324b7a0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -21,6 +21,7 @@ Depends: R (>= 4.1.0) Imports: assertthat, + cli, codemetar, desc, devtools (> 2.4.0), diff --git a/NAMESPACE b/NAMESPACE index 7346b664..987b10ad 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -61,6 +61,10 @@ importFrom(assertthat,is.flag) importFrom(assertthat,is.number) importFrom(assertthat,is.string) importFrom(assertthat,noNA) +importFrom(cli,cli_h1) +importFrom(cli,cli_text) +importFrom(cli,col_green) +importFrom(cli,col_red) importFrom(codemetar,give_opinions) importFrom(desc,desc) importFrom(desc,description) diff --git a/R/utils.R b/R/utils.R index 2bd40082..d661fff9 100644 --- a/R/utils.R +++ b/R/utils.R @@ -162,6 +162,7 @@ checklist_print <- function( ), type = "missing", variable = "note" ), + checklist_diff(path), checklist_summarise_linter(linter), checklist_summarise_spelling(spelling), checklist_format_error(errors) @@ -323,3 +324,40 @@ is_tracked_not_modified <- function(file, repo = ".") { is_not_modified <- !file %in% status$file[status$status == "modified"] return(is_tracked && is_not_modified) } + +#' @importFrom gert git_info +#' @importFrom cli cli_h1 cli_text col_green col_red +checklist_diff <- function(root) { + if (inherits(try(git_info(repo = root), silent = TRUE), "try-error")) { + return(invisible(NULL)) + } + changes <- git_diff(repo = root) + if (length(changes) == 0) { + return(invisible(NULL)) + } + cli_h1("git diff") + changes$patch |> + gsub(pattern = "^.*?index.*?\n.*?\n", replacement = "") |> + strsplit(split = "\n") |> + unlist() -> changes + changes <- changes[grepl("^[\\+-]", changes)] + display_col <- character(length(changes)) + files <- grepl("^\\+\\+\\+ b/", changes) + display_col[!files & grepl("^\\+", changes)] <- "green" + display_col[grepl("^\\-", changes)] <- "red" + vapply( + seq_along(display_col), FUN.VALUE = logical(1), + display_col = display_col, changes = changes, + FUN = function(i, display_col, changes) { + switch( + display_col[i], + "red" = col_red(changes[i]), + "green" = col_green(changes[i]), + cli_text(changes[i]) + ) |> + cat(sep = "\n") + return(TRUE) + } + ) + return(invisible(NULL)) +} From ce98f1aab627d283672917a6c0bb26f2533d6e72 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 22 Jan 2024 14:36:30 +0100 Subject: [PATCH 30/63] use correct gha badge see #116 --- R/setup_project.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/setup_project.R b/R/setup_project.R index e23b50d5..56982c06 100644 --- a/R/setup_project.R +++ b/R/setup_project.R @@ -221,8 +221,8 @@ create_readme <- function(path, org) { sprintf( fmt = paste0( "![GitHub](https://img.shields.io/github/license/%1$s)\n", - "![GitHub Workflow Status](https://img.shields.io/github/workflow/", - "status/%1$s/check-project)\n", + "![GitHub Workflow Status](https://img.shields.io/github/actions/", + "workflow/status/%1$s/check-project)\n", "![GitHub repo size](https://img.shields.io/github/repo-size/%1$s)" ) ) -> badges From 2efb98f21659ee4bda0268c8be53e6234085a892 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 22 Jan 2024 14:46:32 +0100 Subject: [PATCH 31/63] add checklist badges to README fixes #116 --- R/add_badges.R | 14 ++++++++++++-- man/add_badges.Rd | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/R/add_badges.R b/R/add_badges.R index 81b23ffe..5d49cd3d 100644 --- a/R/add_badges.R +++ b/R/add_badges.R @@ -12,6 +12,8 @@ #' \dontrun{ #' add_badges(url = "https://www.inbo.be") #' add_badges(doi = "10.5281/zenodo.8063503") +#' add_badges(check_project = "inbo/checklist") +#' add_badges(check_package = "inbo/checklist") #' add_badges(url = "https://www.inbo.be", doi = "10.5281/zenodo.8063503") #' } add_badges <- function(x = ".", ...) { @@ -30,7 +32,15 @@ add_badges <- function(x = ".", ...) { url = "[![website](https://img.shields.io/badge/website-%1$s-c04384)](%1$s)", doi = -"[![DOI](https://https://zenodo.org/badge/DOI/%1$s.svg)](https://doi.org/%1$s)" +"[![DOI](https://https://zenodo.org/badge/DOI/%1$s.svg)](https://doi.org/%1$s)", + check_package = paste0( + "[![R build status](https://github.com/%1$s/workflows/", + "check%20package%20on%20main/badge.svg)](https://github.com/%1$s/actions)" + ), + check_project = paste0( + "![GitHub Workflow Status](https://img.shields.io/github/actions/", + "workflow/status/%1$s/check_project.yml)" + ) ) dots <- dots[names(formats)] formats <- formats[names(dots)] @@ -43,6 +53,6 @@ add_badges <- function(x = ".", ...) { } ) -> new_badge head(text, badges_start) |> - c(new_badge, tail(text, - badges_start)) |> + c(new_badge, tail(text, -badges_start)) |> writeLines(readme) } diff --git a/man/add_badges.Rd b/man/add_badges.Rd index 4ce55ee5..7f440df0 100644 --- a/man/add_badges.Rd +++ b/man/add_badges.Rd @@ -22,6 +22,8 @@ Defaults to \code{.}.} \dontrun{ add_badges(url = "https://www.inbo.be") add_badges(doi = "10.5281/zenodo.8063503") + add_badges(check_project = "inbo/checklist") + add_badges(check_package = "inbo/checklist") add_badges(url = "https://www.inbo.be", doi = "10.5281/zenodo.8063503") } } From 319d07ec9320dfa7827f061a645dc10f94481a7b Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 22 Jan 2024 14:54:41 +0100 Subject: [PATCH 32/63] Don't try to open an RStudio project when not running from within RStudio fixes #119 --- R/create_package.R | 5 ++++- R/setup_project.R | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/R/create_package.R b/R/create_package.R index 00db8229..cc5ed074 100644 --- a/R/create_package.R +++ b/R/create_package.R @@ -274,7 +274,10 @@ create_package <- function( message("package created at `", path, "`") - if (!interactive() || !requireNamespace("rstudioapi", quietly = TRUE)) { + if ( + !interactive() || !requireNamespace("rstudioapi", quietly = TRUE) || + !rstudioapi::isAvailable() + ) { return(invisible(NULL)) } rstudioapi::openProject(path, newSession = TRUE) diff --git a/R/setup_project.R b/R/setup_project.R index 56982c06..fff5e9f0 100644 --- a/R/setup_project.R +++ b/R/setup_project.R @@ -174,7 +174,10 @@ create_project <- function(path, project) { setup_project(path(path, project)) - if (!interactive() || !requireNamespace("rstudioapi", quietly = TRUE)) { + if ( + !interactive() || !requireNamespace("rstudioapi", quietly = TRUE) || + !rstudioapi::isAvailable() + ) { return(invisible(NULL)) } path(path, project) |> From b96efcd132e6b13bbfb493cc82e8cad5409fefce Mon Sep 17 00:00:00 2001 From: Hans Van Calster Date: Tue, 19 Dec 2023 10:11:26 +0100 Subject: [PATCH 33/63] Update citation_meta_class.R This should fix a bug where `.zenodo.json` file was incorrectly flagged as modified. The relative path to the file should be relative to the root of the git repository. This failed in cases where `meta$path` is a child directory beneath the git root repository. The `gert` package uses `gert::git_find` to find the git parent directory in case a child directory is passed to the `repo = ` argument. --- R/citation_meta_class.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/citation_meta_class.R b/R/citation_meta_class.R index 16cf91af..9b02da96 100644 --- a/R/citation_meta_class.R +++ b/R/citation_meta_class.R @@ -229,6 +229,7 @@ validate_citation <- function(meta) { #' @importFrom fs path #' @importFrom jsonlite toJSON #' @importFrom knitr pandoc +#' @importFrom gert git_find citation_zenodo <- function(meta) { assert_that(inherits(meta, "citation_meta")) assert_that(length(meta$get_errors) == 0) @@ -300,7 +301,7 @@ citation_zenodo <- function(meta) { "Please commit changes." )[ !is_tracked_not_modified( - path_rel(citation_file, meta$get_path), meta$get_path + path_rel(citation_file, git_find(meta$get_path)), meta$get_path ) ] return(errors) From f9bbd9db788205c35fe49b5ac0a4e91ab12ee3bb Mon Sep 17 00:00:00 2001 From: hansvancalster Date: Fri, 12 Jan 2024 16:24:57 +0100 Subject: [PATCH 34/63] first check if git controlled repo --- R/citation_meta_class.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/citation_meta_class.R b/R/citation_meta_class.R index 9b02da96..f795ecc6 100644 --- a/R/citation_meta_class.R +++ b/R/citation_meta_class.R @@ -300,6 +300,7 @@ citation_zenodo <- function(meta) { "Run `checklist::update_citation()` locally."[!interactive()], "Please commit changes." )[ + is_repository(meta$get_path) && !is_tracked_not_modified( path_rel(citation_file, git_find(meta$get_path)), meta$get_path ) From 8993cbeae7711b0b9631bd71e8731e94647e2551 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 22 Jan 2024 21:16:00 +0100 Subject: [PATCH 35/63] add unit test --- tests/testthat/test_e_bookdown_zenodo.R | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/testthat/test_e_bookdown_zenodo.R b/tests/testthat/test_e_bookdown_zenodo.R index 6ebd7271..fe70bd69 100644 --- a/tests/testthat/test_e_bookdown_zenodo.R +++ b/tests/testthat/test_e_bookdown_zenodo.R @@ -1,10 +1,6 @@ test_that("bookdown_zenodo() works", { - skip_if_not_installed("zen4R", minimum_version = "0.10") skip_if_not_installed("bookdown") skip_if(Sys.getenv("MY_UNIVERSE") != "") # skip test on r-universe.dev - expect_match(Sys.getenv("ZENODO_SANDBOX"), "^\\w{60}$") - sandbox_token <- Sys.getenv("ZENODO_SANDBOX") - root <- tempfile("bookdown") dir_create(root) system.file("bookdown", package = "checklist") |> @@ -19,6 +15,9 @@ test_that("bookdown_zenodo() works", { expect_is(x, "citation_meta") expect_identical(x$get_errors, "No LICENSE.md file found") + skip_if_not_installed("zen4R", minimum_version = "0.10") + expect_match(Sys.getenv("ZENODO_SANDBOX"), "^\\w{60}$") + sandbox_token <- Sys.getenv("ZENODO_SANDBOX") system.file("generic_template", "cc_by_4_0.md", package = "checklist") |> file_copy(path(root, "LICENSE.md")) zenodo_out <- tempfile(fileext = ".txt") From 3923a8fd9dda72f4291d889771c5a998c17afd74 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 22 Jan 2024 21:19:25 +0100 Subject: [PATCH 36/63] update checklist settings --- .Rbuildignore | 1 + .github/CODE_OF_CONDUCT.md | 4 +-- .github/CONTRIBUTING.md | 14 ++++---- .github/workflows/check_on_branch.yml | 2 +- .github/workflows/check_on_different_r_os.yml | 33 +++---------------- .github/workflows/check_on_main.yml | 6 ++-- .gitignore | 28 ++++++++++++---- 7 files changed, 39 insertions(+), 49 deletions(-) diff --git a/.Rbuildignore b/.Rbuildignore index c3044ac4..34c12525 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -18,5 +18,6 @@ ^docker-compose.test.yml$ ^docs$ ^man-roxygen$ +^organisation.yml$ ^pkgdown$ ^test_docker.sh$ diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index 24aa0a3c..3236635c 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -8,7 +8,7 @@ We are committed to making participation in this project a harassment-free exper everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. -Examples of unacceptable behavior by participants include the use of sexual language or +Examples of unacceptable behaviour by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. @@ -17,7 +17,7 @@ commits, code, wiki edits, issues, and other contributions that are not aligned Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by +Instances of abusive, harassing, or otherwise unacceptable behaviour may be reported by opening an issue or contacting one or more of the project maintainers. This Code of Conduct is adapted from the Contributor Covenant diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index f05e327a..0eeb16cb 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -3,22 +3,22 @@ ### Fixing typos Small typos or grammatical errors in documentation may be edited directly using the GitHub web interface, so long as the changes are made in the _source_ file. -E.g. edit a roxygen comment in a `.R` file below `R/`, not in an `.Rd` file below `man/`. +E.g. edit a `roxygen2` comment in a `.R` file below `R/`, not in an `.Rd` file below `man/`. ### Prerequisites Before you make a substantial pull request, you should always file an issue and make sure someone from the team agrees that it’s a problem. -If you’ve found a bug, create an associated issue and illustrate the bug with a minimal [reprex](https://www.tidyverse.org/help/#reprex). +If you’ve found a bug, create an associated issue and illustrate the bug with a minimal [reproducible example](https://www.tidyverse.org/help/#reprex). ### Pull request process * We recommend that you create a Git branch for each pull request (PR). * Look at the GitHub Actions build status before and after making changes. The `README` should contain badges for any continuous integration services used by the package. -* We require the tidyverse [style guide](http://style.tidyverse.org). -You can use the [styler](https://CRAN.R-project.org/package=styler) package to apply these styles, but please don't restyle code that has nothing to do with your PR. -* We use [roxygen2](https://cran.r-project.org/package=roxygen2). -* We use [testthat](https://cran.r-project.org/package=testthat). +* We require the `tidyverse` [style guide](http://style.tidyverse.org). +You can use the [`styler`](https://CRAN.R-project.org/package=styler) package to apply these styles, but please don't restyle code that has nothing to do with your PR. +* We use [`roxygen2`](https://cran.r-project.org/package=roxygen2). +* We use [`testthat`](https://cran.r-project.org/package=testthat). Contributions with test cases included are easier to accept. * For user-facing changes, add a bullet to the top of `NEWS.md` below the current development version header describing the changes made followed by your GitHub username, and links to relevant issue(s)/PR(s). @@ -36,4 +36,4 @@ email is totally warranted if it's a sensitive problem of any kind. ### Thanks for contributing! -This contributing guide is adapted from the tidyverse contributing guide available at https://raw.githubusercontent.com/r-lib/usethis/master/inst/templates/tidy-contributing.md +This contributing guide is adapted from the `tidyverse` contributing guide available at https://raw.githubusercontent.com/r-lib/usethis/master/inst/templates/tidy-contributing.md diff --git a/.github/workflows/check_on_branch.yml b/.github/workflows/check_on_branch.yml index 35c6fca6..6a2b8c0f 100644 --- a/.github/workflows/check_on_branch.yml +++ b/.github/workflows/check_on_branch.yml @@ -4,7 +4,7 @@ on: - main - ghpages -name: "check package" +name: "check package with checklist" jobs: check-package: diff --git a/.github/workflows/check_on_different_r_os.yml b/.github/workflows/check_on_different_r_os.yml index ea4f0ade..10c4a14f 100644 --- a/.github/workflows/check_on_different_r_os.yml +++ b/.github/workflows/check_on_different_r_os.yml @@ -7,8 +7,6 @@ on: branches: - main - master - schedule: - - cron: '6 0 * * 1' name: R-CMD-check-OS @@ -22,17 +20,16 @@ jobs: fail-fast: false matrix: config: - - {os: macOS-latest, r: 'release', skip_test: 'false'} - - {os: windows-latest, r: 'release', skip_test: 'true'} - - {os: ubuntu-22.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest", skip_test: 'false'} - - {os: ubuntu-22.04, r: 'oldrel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest", skip_test: 'false'} + - {os: macOS-latest, r: 'release'} + - {os: windows-latest, r: 'release'} + - {os: ubuntu-22.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest"} + - {os: ubuntu-22.04, r: 'oldrel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest"} env: R_REMOTES_NO_ERRORS_FROM_WARNINGS: true _R_CHECK_SYSTEM_CLOCK_: false RSPM: ${{ matrix.config.rspm }} GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - ZENODO_SANDBOX: ${{ secrets.ZENODO_SANDBOX }} steps: - uses: actions/checkout@v3 @@ -44,26 +41,7 @@ jobs: - uses: r-lib/actions/setup-pandoc@v2 - - name: linux dependencies - if: runner.os == 'linux' - run: | - sudo apt update - sudo apt install -y --no-install-recommends libcurl4-openssl-dev \ - libfontconfig1-dev libfreetype6-dev libfribidi-dev libharfbuzz-dev \ - libjpeg-dev libmagick++-dev libpng-dev libpoppler-cpp-dev \ - libsecret-1-dev libtiff5-dev - sudo apt install -y --no-install-recommends r-cran-assertthat \ - r-cran-bookdown r-cran-covr r-cran-curl r-cran-desc \ - r-cran-devtools r-cran-fs r-cran-gert r-cran-httr r-cran-hunspell \ - r-cran-jsonlite r-cran-knitr r-cran-mockery r-cran-pdftools \ - r-cran-r6 r-cran-rcmdcheck r-cran-remotes r-cran-rmarkdown \ - r-cran-roxygen2 r-cran-rstudioapi r-cran-sessioninfo \ - r-cran-testthat r-cran-withr r-cran-yaml - Rscript --no-save --no-restore -e 'install.packages("remotes")' - Rscript --no-save --no-restore -e 'remotes::install_cran(c("assertthat", "bookdown", "codemetar", "covr", "curl", "desc", "devtools", "fs", "gert", "hexSticker", "httr", "hunspell", "jsonlite", "knitr", "lintr", "mockery", "pdftools", "pkgdown", "R6", "rcmdcheck", "renv", "rmarkdown", "roxygen2", "rstudioapi", "sessioninfo", "showtext", "sysfonts", "testthat", "withr", "yaml"))' - - uses: r-lib/actions/setup-r-dependencies@v2 - if: runner.os != 'linux' with: extra-packages: any::rcmdcheck needs: check @@ -71,6 +49,3 @@ jobs: - uses: r-lib/actions/check-r-package@v2 with: error-on: '"error"' - env: - ZENODO_SANDBOX: ${{ secrets.ZENODO_SANDBOX }} - SKIP_TEST: ${{ matrix.config.skip_test }} diff --git a/.github/workflows/check_on_main.yml b/.github/workflows/check_on_main.yml index ac9d760d..f25f486b 100644 --- a/.github/workflows/check_on_main.yml +++ b/.github/workflows/check_on_main.yml @@ -3,13 +3,11 @@ on: branches: - main - master - schedule: - - cron: '6 0 15 * *' - -name: "check package on main" permissions: contents: write +name: "check package on main with checklist" + jobs: check-package: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 02fbaef5..2c8e285d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,28 @@ + +# OAuth tokens # Rstudio -.Rproj.user -.Rhistory +# pkgdown +*.dbf +*.doc* +*.gddoc +*.gdsheet +*.gpkg +*.html +*.mdb +*.shp* +*.shx +*.xls* +*_files +.DS_Store .RData +.Renviron +.Rhistory +.Rproj.user .Ruserdata - -# OAuth tokens .httr-oauth - -# pkgdown +docs docs/* inst/doc +libs +output +renv/library From 1bf53dfdf1484739b6e4e6a16678573491226725 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 23 Jan 2024 15:30:03 +0100 Subject: [PATCH 37/63] add unit tests --- R/add_badges.R | 2 +- R/citation_bookdown.R | 4 +- R/write_organisation.R | 8 ++-- tests/testthat/test_a_author.R | 9 +++++ tests/testthat/test_a_organisation.R | 18 +++++++++ tests/testthat/test_d_check_spelling.R | 2 +- tests/testthat/test_d_setup_package.R | 9 +++++ tests/testthat/test_e_bookdown_zenodo.R | 53 ++++++++++++++++++++++++- 8 files changed, 96 insertions(+), 9 deletions(-) diff --git a/R/add_badges.R b/R/add_badges.R index 5d49cd3d..0c69f696 100644 --- a/R/add_badges.R +++ b/R/add_badges.R @@ -42,7 +42,7 @@ add_badges <- function(x = ".", ...) { "workflow/status/%1$s/check_project.yml)" ) ) - dots <- dots[names(formats)] + dots <- dots[names(dots) %in% names(formats)] formats <- formats[names(dots)] vapply( names(dots), FUN.VALUE = character(1), formats = formats, dots = dots, diff --git a/R/citation_bookdown.R b/R/citation_bookdown.R index be780a56..53b22f71 100644 --- a/R/citation_bookdown.R +++ b/R/citation_bookdown.R @@ -82,7 +82,7 @@ citation_bookdown <- function(meta) { return(cit_meta) } -#' @inheritParams assertthat has_name +#' @importFrom assertthat has_name yaml_author <- function(yaml, org) { author <- vapply( X = yaml$author, FUN = yaml_author_format, @@ -145,7 +145,7 @@ yaml_author <- function(yaml, org) { ) } -#' @inheritParams assertthat has_name is.flag +#' @importFrom assertthat has_name is.flag yaml_author_format <- function(person, org) { person_df <- data.frame( given = character(0), family = character(0), orcid = character(0), diff --git a/R/write_organisation.R b/R/write_organisation.R index 74af7eae..0548f070 100644 --- a/R/write_organisation.R +++ b/R/write_organisation.R @@ -14,9 +14,11 @@ #' @family both write_organisation <- function(org, x = ".") { assert_that(inherits(org, "organisation")) - x <- suppressMessages(read_checklist(x = x)) - - path(x$get_path, "organisation.yml") |> + checklist <- try(read_checklist(x = x), silent = TRUE) + if (inherits(checklist, "checklist")) { + x <- checklist$get_path + } + path(x, "organisation.yml") |> write_yaml(x = org$template) return(invisible(NULL)) } diff --git a/tests/testthat/test_a_author.R b/tests/testthat/test_a_author.R index 3f0f5c7f..dc61a566 100644 --- a/tests/testthat/test_a_author.R +++ b/tests/testthat/test_a_author.R @@ -105,4 +105,13 @@ test_that("author tools", { stub(new_author, "readline", mock("Jane", "Doe", "noreply@inbo.be")) stub(new_author, "ask_orcid", mock("", "0000-0002-1825-0097")) expect_output(new_author(current, root = root, org = org)) + + stub(use_author, "R_user_dir", root) + zenodo_out <- tempfile(fileext = ".txt") + defer(file_delete(zenodo_out)) + sink(zenodo_out) + expect_s3_class(x <- use_author("noreply@inbo.be"), "data.frame") + sink() + expect_equal(x$given, "Jane") + expect_equal(x$family, "Doe") }) diff --git a/tests/testthat/test_a_organisation.R b/tests/testthat/test_a_organisation.R index eb84267a..06ba0a5d 100644 --- a/tests/testthat/test_a_organisation.R +++ b/tests/testthat/test_a_organisation.R @@ -1,4 +1,22 @@ +library(mockery) test_that("organisation class", { org <- organisation$new() expect_output(print(org), regexp = "rightsholder") + + root <- tempdir() + dir_create(root) + x <- checklist$new(x = root, package = FALSE, language = "en-GB") + write_checklist(x = x) + expect_invisible(write_organisation(org = org, x = x)) + expect_equal(read_organisation(x), org) + + r_user_dir <- tempdir() + dir_create(r_user_dir) + stub(default_organisation, "R_user_dir", r_user_dir) + expect_invisible(default_organisation(org = org)) + + root2 <- tempdir() + dir_create(root2) + stub(read_organisation, "R_user_dir", r_user_dir) + expect_equal(read_organisation(root2), org) }) diff --git a/tests/testthat/test_d_check_spelling.R b/tests/testthat/test_d_check_spelling.R index 3407238e..bb938449 100644 --- a/tests/testthat/test_d_check_spelling.R +++ b/tests/testthat/test_d_check_spelling.R @@ -18,7 +18,7 @@ test_that("check_spelling() on a package", { path = path, package = package, maintainer = maintainer, title = "testing the ability of checklist to create a minimal package", description = "A dummy package.", language = "en-GB", keywords = "dummy", - communities = "inbo", + communities = "inbo" ) ) skip_if(identical(Sys.getenv("SKIP_TEST"), "true")) diff --git a/tests/testthat/test_d_setup_package.R b/tests/testthat/test_d_setup_package.R index 9788dffc..65b664f4 100644 --- a/tests/testthat/test_d_setup_package.R +++ b/tests/testthat/test_d_setup_package.R @@ -56,4 +56,13 @@ test_that("setup_package() works", { setup_package(path(path, package)), "package prepared for checklist::check_package()" ) + + path(path, package, "README.Rmd") |> + readLines() -> old_readme + expect_equal(length(grep("10.5281/zenodo.8063503", old_readme)), 0) + expect_null(add_badges(path(path, package), doi = "10.5281/zenodo.8063503")) + path(path, package, "README.Rmd") |> + readLines() -> new_readme + expect_equal(length(grep("10.5281/zenodo.8063503", new_readme)), 1) + expect_equal(length(old_readme) + 1, length(new_readme)) }) diff --git a/tests/testthat/test_e_bookdown_zenodo.R b/tests/testthat/test_e_bookdown_zenodo.R index fe70bd69..f68ddb99 100644 --- a/tests/testthat/test_e_bookdown_zenodo.R +++ b/tests/testthat/test_e_bookdown_zenodo.R @@ -6,6 +6,24 @@ test_that("bookdown_zenodo() works", { system.file("bookdown", package = "checklist") |> dir_ls() |> file_copy(root) + path(root, "index.Rmd") |> + file_delete() + expect_error( + x <- bookdown_zenodo( + root, logger = NULL, sandbox = TRUE, token = sandbox_token + ), + "index.Rmd not found" + ) + expect_warning( + meta <- citation_meta$new(root), + "Errors found parsing citation meta data. Citation files not updated." + ) + expect_s3_class(meta, c("citation_meta", "R6")) + expect_true(grepl("index.Rmd not found", meta$get_errors)) + + system.file("bookdown", package = "checklist") |> + dir_ls() |> + file_copy(root, overwrite = TRUE) expect_warning( x <- bookdown_zenodo( root, logger = NULL, sandbox = TRUE, token = sandbox_token @@ -15,11 +33,33 @@ test_that("bookdown_zenodo() works", { expect_is(x, "citation_meta") expect_identical(x$get_errors, "No LICENSE.md file found") + skip_if_not_installed("zen4R") + system.file("generic_template", "mit.md", package = "checklist") |> + file_copy(path(root, "LICENSE.md")) + expect_warning( + x <- bookdown_zenodo(root, logger = NULL, sandbox = TRUE, token = "junk"), + "Errors found parsing citation meta data. Citation files not updated." + ) + expect_equal(x$get_errors, "LICENSE.md doesn't match with CC-BY-4.0 license") + + system.file("generic_template", "cc_by_4_0.md", package = "checklist") |> + file_copy(path(root, "LICENSE.md"), overwrite = TRUE) + path(root, "index.Rmd") |> + readLines() |> + tail(-2) -> index + c("---", "embargo: 2024-01-23", index) |> + writeLines(path(root, "index.Rmd")) + zenodo_out <- tempfile(fileext = ".txt") + defer(file_delete(zenodo_out)) + sink(zenodo_out) + expect_error( + bookdown_zenodo(root, logger = NULL, sandbox = TRUE, token = "junk") + ) + sink() + skip_if_not_installed("zen4R", minimum_version = "0.10") expect_match(Sys.getenv("ZENODO_SANDBOX"), "^\\w{60}$") sandbox_token <- Sys.getenv("ZENODO_SANDBOX") - system.file("generic_template", "cc_by_4_0.md", package = "checklist") |> - file_copy(path(root, "LICENSE.md")) zenodo_out <- tempfile(fileext = ".txt") defer(file_delete(zenodo_out)) sink(zenodo_out) @@ -96,3 +136,12 @@ test_that("bookdown_zenodo() works", { ) expect_match(x$get_errors, "index.Rmd not found") }) + +test_that("yaml_author_format", { + x <- yaml_author_format(person = "me") + expect_identical(class(x), "list") + expect_identical(attr(x[[1]], "errors")[[1]], "person must be a list") + x <- yaml_author_format(person = list("me")) + expect_identical(class(x), "list") + expect_identical(attr(x[[1]], "errors")[[1]], "person has no `name` element") +}) From 789b0986ad98ef452e73093ce7d145726aa5971b Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 24 Jan 2024 10:22:00 +0100 Subject: [PATCH 38/63] update GHA --- .github/workflows/check_on_different_r_os.yml | 9 +++++---- DESCRIPTION | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/check_on_different_r_os.yml b/.github/workflows/check_on_different_r_os.yml index 10c4a14f..3200bd0e 100644 --- a/.github/workflows/check_on_different_r_os.yml +++ b/.github/workflows/check_on_different_r_os.yml @@ -20,16 +20,17 @@ jobs: fail-fast: false matrix: config: - - {os: macOS-latest, r: 'release'} - - {os: windows-latest, r: 'release'} - - {os: ubuntu-22.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest"} - - {os: ubuntu-22.04, r: 'oldrel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest"} + - {os: macOS-latest, r: 'release', skip_test: 'false'} + - {os: windows-latest, r: 'release', skip_test: 'true'} + - {os: ubuntu-22.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest", skip_test: 'false'} + - {os: ubuntu-22.04, r: 'oldrel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest", skip_test: 'false'} env: R_REMOTES_NO_ERRORS_FROM_WARNINGS: true _R_CHECK_SYSTEM_CLOCK_: false RSPM: ${{ matrix.config.rspm }} GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + ZENODO_SANDBOX: ${{ secrets.ZENODO_SANDBOX }} steps: - uses: actions/checkout@v3 diff --git a/DESCRIPTION b/DESCRIPTION index 6324b7a0..07620a34 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -59,5 +59,5 @@ Config/checklist/keywords: quality control; documentation; publication Encoding: UTF-8 Language: en-GB Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.0 +RoxygenNote: 7.3.1 SystemRequirements: Pandoc (>= 1.17.2) From 14c4896e2a9c9c95802f1c907170ca0f483b8d36 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 24 Jan 2024 12:23:30 +0100 Subject: [PATCH 39/63] add vignette on the organisation class --- R/organisation_class.R | 3 ++ _pkgdown.yml | 1 + man/organisation.Rd | 3 ++ vignettes/organisation.Rmd | 78 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 vignettes/organisation.Rmd diff --git a/R/organisation_class.R b/R/organisation_class.R index de737580..f9ee83ab 100644 --- a/R/organisation_class.R +++ b/R/organisation_class.R @@ -10,6 +10,9 @@ organisation <- R6Class( #' @param ... The organisation settings. #' See the details. #' @details + #' - `github`: the name of the github organisation. + #' Set to `NA_character_` in case you don't want a mandatory github + #' organisation. #' - `community`: the mandatory Zenodo community. #' Defaults to `"inbo"`. #' Set to `NA_character_` in case you don't want a mandatory community. diff --git a/_pkgdown.yml b/_pkgdown.yml index b48526ec..28062222 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -57,6 +57,7 @@ articles: - getting_started_project - spelling - zenodo + - organisation authors: Thierry Onkelinx: diff --git a/man/organisation.Rd b/man/organisation.Rd index cf4b7c39..a76835a4 100644 --- a/man/organisation.Rd +++ b/man/organisation.Rd @@ -61,6 +61,9 @@ See the details.} } \subsection{Details}{ \itemize{ +\item \code{github}: the name of the github organisation. +Set to \code{NA_character_} in case you don't want a mandatory github +organisation. \item \code{community}: the mandatory Zenodo community. Defaults to \code{"inbo"}. Set to \code{NA_character_} in case you don't want a mandatory community. diff --git a/vignettes/organisation.Rmd b/vignettes/organisation.Rmd new file mode 100644 index 00000000..e831c3bd --- /dev/null +++ b/vignettes/organisation.Rmd @@ -0,0 +1,78 @@ +--- +title: "Organisations" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Organisations} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +bibliography: references.bib +--- + +```{r setup, include = FALSE} +library(knitr) +opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +## What is an `organisation` in the `checklist` context + +The `organisation` object defines rules about the organisation related to the project (or package). +`checklist` assumes by default that a project is a part of the [Research Institute for Nature and Forest (INBO)](https://www.vlaanderen.be/inbo/). +And it will enforce to mention INBO as copyright holder and funder. + +Such a rule limits to use of `checklist` outside of INBO. +Therefore we added the `organisation` object. +It contains the following elements: + +- [GitHub](https://github.com) organisation +- copyright holder +- funder +- organisation e-mail +- [Zenodo](https://zenodo.org) community +- a list of organisation affiliations + +The organisation affiliations must be a named list using the email domain names as names. +Every element is a list containing the elements `affiliation` and `orcid`. +`affiliation` is a character vector with one or more allowed organisation names. +Use multiple values to add optional translations of the organisation name. +`orcid` must be either `TRUE` or `FALSE`. +Setting `orcid` to `TRUE` requires every author with matching e-mail to have an [ORCID](https://orcid.org/) number. + +## Defining a specific `organisation` for a project + +First generate the object with `organisation$new()`. +The store this object in your project with `write_organisation()`. +The function stores the information in `organisation.yml`, a plain text file in YAML format. + +```{r} +library(checklist) +# create a dummy project +my_project_path <- tempfile("my_project") +dir.create(my_project_path) +# create an organisation object +org <- organisation$new( + rightsholder = "Vlaamse overheid", funder = "Vlaamse overheid", + email = "info@vlaanderen.be", github = "vlaanderen", + community = NA_character_, + organisation = list( + "vlaanderen.be" = list( + affiliation = "Vlaamse overheid", orcid = FALSE + ) + ) +) +# store the organisation in the dummy project +write_organisation(org, my_project_path) +``` + +## Defining a default `organisation` object for your machine + +Store the organisation as a default with `default_organisation(org = org)`. + +Whenever `checklist` needs the `organisation` information, it will retrieve it with `read_organisation()`. +It first looks at project root folder for the `organisation.yml` file. +When missing it looks for the machines default `organisation.yml`. +In this case it will copy the machines default `organisation.yml` into the project. +Hence the `organisation` information is a part of the project, which is required to use the information during checks on other machines. +When `read_organisation()` find neither a project `organisation.yml` nor a machines default `organisation.yml`, it reverts to the INBO `organisation`. From 07ef5ccd522afca701d512b71eb21802c3aece6e Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 24 Jan 2024 12:25:57 +0100 Subject: [PATCH 40/63] update NEWS --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 0d47ee10..2be2cfa2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,13 @@ # checklist 0.3.6 +* Add an `organisation` class to store organisation rules different from those + of the Research Institute for Nature and Forest (INBO). + See `vignette("organisation", package = "checklist")` for more information. +* `add_badges()` helps to add badges to the `README`. * Put double quotes around the title and abstract fields of `CITATION.cff`. * `check_documentation()` handles assignment functions and re-exported functions correctly. +* `check_lintr()` ignores `renv` subdirectories (#118). # checklist 0.3.5 From a98613edaf4e886b30906c8d651c9edff2d623ec Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 24 Jan 2024 13:19:11 +0100 Subject: [PATCH 41/63] add unit test --- tests/testthat/test_d_check_spelling.R | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/testthat/test_d_check_spelling.R b/tests/testthat/test_d_check_spelling.R index bb938449..be2ff5c0 100644 --- a/tests/testthat/test_d_check_spelling.R +++ b/tests/testthat/test_d_check_spelling.R @@ -382,3 +382,7 @@ test_that("check_spelling() works on a quarto project", { expect_output(quiet_cat("test", quiet = FALSE), "test") expect_silent(quiet_cat("test", quiet = TRUE)) }) + +test_that("strip_eqn() works", { + expect_equal(strip_eqn("\\eqn{\\alpha}"), "") +}) From 0d3e69e467f72c9dac2eb8d79c65caf645cee2ba Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 24 Jan 2024 13:28:42 +0100 Subject: [PATCH 42/63] update GHA --- .github/workflows/check_on_different_r_os.yml | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check_on_different_r_os.yml b/.github/workflows/check_on_different_r_os.yml index 3200bd0e..0f697540 100644 --- a/.github/workflows/check_on_different_r_os.yml +++ b/.github/workflows/check_on_different_r_os.yml @@ -2,11 +2,9 @@ on: push: branches: - main - - master pull_request: branches: - main - - master name: R-CMD-check-OS @@ -42,7 +40,27 @@ jobs: - uses: r-lib/actions/setup-pandoc@v2 + + - name: linux dependencies + if: runner.os == 'linux' + run: | + sudo apt update + sudo apt install -y --no-install-recommends libcurl4-openssl-dev \ + libfontconfig1-dev libfreetype6-dev libfribidi-dev libharfbuzz-dev \ + libjpeg-dev libmagick++-dev libpng-dev libpoppler-cpp-dev \ + libsecret-1-dev libtiff5-dev + sudo apt install -y --no-install-recommends r-cran-assertthat \ + r-cran-bookdown r-cran-covr r-cran-curl r-cran-desc \ + r-cran-devtools r-cran-fs r-cran-gert r-cran-httr r-cran-hunspell \ + r-cran-jsonlite r-cran-knitr r-cran-mockery r-cran-pdftools \ + r-cran-r6 r-cran-rcmdcheck r-cran-remotes r-cran-rmarkdown \ + r-cran-roxygen2 r-cran-rstudioapi r-cran-sessioninfo \ + r-cran-testthat r-cran-withr r-cran-yaml + Rscript --no-save --no-restore -e 'install.packages("remotes")' + Rscript --no-save --no-restore -e 'remotes::install_cran(c("assertthat", "bookdown", "codemetar", "covr", "curl", "desc", "devtools", "fs", "gert", "hexSticker", "httr", "hunspell", "jsonlite", "knitr", "lintr", "mockery", "pdftools", "pkgdown", "R6", "rcmdcheck", "renv", "rmarkdown", "roxygen2", "rstudioapi", "sessioninfo", "showtext", "sysfonts", "testthat", "withr", "yaml"))' + - uses: r-lib/actions/setup-r-dependencies@v2 + if: runner.os != 'linux' with: extra-packages: any::rcmdcheck needs: check @@ -50,3 +68,6 @@ jobs: - uses: r-lib/actions/check-r-package@v2 with: error-on: '"error"' + env: + ZENODO_SANDBOX: ${{ secrets.ZENODO_SANDBOX }} + SKIP_TEST: ${{ matrix.config.skip_test }} From 808cf1647ad95e24d12017699db526387a9aa447 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 2 Apr 2024 15:31:40 +0200 Subject: [PATCH 43/63] bugfix in use_author() --- R/use_author.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/use_author.R b/R/use_author.R index c13fab05..0702ce11 100644 --- a/R/use_author.R +++ b/R/use_author.R @@ -167,7 +167,7 @@ author2person <- function(role = "aut") { if (is.na(df$orcid) || df$orcid == "") { comment <- character(0) } else { - comment <- c(orcid = df$orcid) + comment <- c(ORCID = df$orcid) } if (!is.na(df$affiliation) && df$affiliation != "") { comment <- c(comment, affiliation = df$affiliation) From eb53440d72ddd92bfb33da7c4b72c50df67049a7 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 2 Apr 2024 15:43:01 +0200 Subject: [PATCH 44/63] update_citation() doesn't insert newline characters in description of .zenodo.json fixes #124 --- .zenodo.json | 2 +- R/citation_meta_class.R | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index ad1dec91..70bbc796 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -3,7 +3,7 @@ "version": "0.3.6", "license": "GPL-3.0", "upload_type": "software", - "description": "

An opinionated set of rules for R packages and R source code\nprojects.<\/p>", + "description": "

An opinionated set of rules for R packages and R source code projects.<\/p>", "keywords": [ "quality control", "documentation", diff --git a/R/citation_meta_class.R b/R/citation_meta_class.R index f795ecc6..8cebff3b 100644 --- a/R/citation_meta_class.R +++ b/R/citation_meta_class.R @@ -291,7 +291,8 @@ citation_zenodo <- function(meta) { suppressMessages(pandoc(desc, format = "html")) gsub("\\.md", ".html", desc) |> readLines() |> - paste(collapse = "\n") -> zenodo$description + paste(collapse = " ") |> + gsub(pattern = " +", replacement = " ") -> zenodo$description citation_file <- path(meta$get_path, ".zenodo.json") toJSON(zenodo, pretty = TRUE, auto_unbox = TRUE) |> writeLines(citation_file) From 7710ecabf3ddc54960f219385720c6a63867e928 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 2 Apr 2024 17:44:02 +0200 Subject: [PATCH 45/63] update docker --- Dockerfile | 209 ++++++++++++----------------------------------------- 1 file changed, 47 insertions(+), 162 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3d904b51..327b7c56 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM rocker/verse +FROM rocker/verse:latest ARG BUILD_DATE ARG VCS_REF @@ -18,174 +18,59 @@ ENV DEBCONF_NONINTERACTIVE_SEEN true ## Install nano RUN apt-get update \ + && apt upgrade -y \ && apt-get install -y --no-install-recommends \ nano COPY docker/.Rprofile $R_HOME/etc/Rprofile.site -## install assertthat -RUN apt update \ - && apt install -y --no-install-recommends r-cran-assertthat \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("assertthat")' - -## install desc -RUN apt update \ - && apt install -y --no-install-recommends r-cran-desc \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("desc")' - -## install fs -RUN apt update \ - && apt install -y --no-install-recommends r-cran-fs \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("fs")' - -## install jsonlite -RUN apt update \ - && apt install -y --no-install-recommends r-cran-jsonlite \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("jsonlite")' - -## install hunspell -RUN apt update \ - && apt install -y --no-install-recommends r-cran-hunspell \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("hunspell")' - -## install R6 -RUN apt update \ - && apt install -y --no-install-recommends r-cran-r6 \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("R6")' - -## install httr -RUN apt update \ - && apt install -y --no-install-recommends r-cran-httr \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("httr")' - -## install gert -RUN apt update \ - && apt install -y --no-install-recommends r-cran-gert \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("gert")' - -## install knitr -RUN apt update \ - && apt install -y --no-install-recommends r-cran-knitr \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("knitr")' - -## install sessioninfo -RUN apt update \ - && apt install -y --no-install-recommends r-cran-sessioninfo \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("sessioninfo")' - -## install withr -RUN apt update \ - && apt install -y --no-install-recommends r-cran-withr \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("withr")' - -## install yaml -RUN apt update \ - && apt install -y --no-install-recommends r-cran-yaml \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("yaml")' - -## install curl -RUN apt update \ - && apt install -y --no-install-recommends r-cran-curl \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("curl")' - -## install renv -RUN Rscript --no-save --no-restore -e 'remotes::install_cran("renv")' - -## install covr -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - libharfbuzz-dev \ - libfribidi-dev \ - r-cran-covr \ - && apt-get clean \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("covr")' - -## install lintr -RUN Rscript --no-save --no-restore -e 'remotes::install_cran("lintr")' - -## install rcmdcheck -RUN apt update \ - && apt install -y --no-install-recommends r-cran-rcmdcheck \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("rcmdcheck")' - -## install rmarkdown -RUN apt update \ - && apt install -y --no-install-recommends r-cran-rmarkdown \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("rmarkdown")' - -## install roxygen2 -RUN apt update \ - && apt install -y --no-install-recommends r-cran-roxygen2 \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("roxygen2")' - ## install INLA -RUN Rscript --no-save --no-restore -e 'remotes::install_cran("INLA", type = "source")' - -## install bookdown -RUN apt update \ - && apt install -y --no-install-recommends r-cran-bookdown \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("bookdown")' - -## install mockery -RUN apt update \ - && apt install -y --no-install-recommends r-cran-mockery \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("mockery")' - -## install pdftools -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - libpoppler-cpp-dev \ - r-cran-pdftools \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("pdftools")' - -## install rstudioapi RUN apt update \ - && apt install -y --no-install-recommends r-cran-rstudioapi \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("rstudioapi")' - -## install codemetar -RUN Rscript --no-save --no-restore -e 'remotes::install_cran("codemetar")' - -## install testthat -RUN apt update \ - && apt install -y --no-install-recommends r-cran-testthat \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("testthat")' - -## install pkgdown -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - libfontconfig1-dev \ - libfreetype6-dev \ - libjpeg-dev \ - libpng-dev \ - libtiff5-dev \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("pkgdown")' - -## install sysfonts -RUN Rscript --no-save --no-restore -e 'remotes::install_cran("sysfonts")' - -## install showtext -RUN Rscript --no-save --no-restore -e 'remotes::install_cran("showtext")' - -## install hexSticker -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - libmagick++-dev \ - && apt-get clean \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("hexSticker")' - -## install devtools -RUN apt update \ - && apt install -y --no-install-recommends r-cran-devtools \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("devtools")' - -## install zen4R -RUN apt update \ - && apt install -y --no-install-recommends libsecret-1-dev \ - && Rscript --no-save --no-restore -e 'remotes::install_cran("zen4R")' - -## install microbenchmark -RUN Rscript --no-save --no-restore -e 'remotes::install_cran("microbenchmark")' + && apt install -y --no-install-recommends \ + gdal-bin libgdal-dev libproj-dev libudunits2-dev r-cran-class \ + r-cran-classint r-cran-cli r-cran-dbi r-cran-e1071 r-cran-fansi \ + r-cran-units r-cran-dplyr r-cran-generics r-cran-glue \ + r-cran-kernsmooth r-cran-lattice r-cran-lifecycle r-cran-magrittr \ + r-cran-matrix r-cran-pillar r-cran-pkgconfig r-cran-proxy \ + r-cran-r6 r-cran-rcpp r-cran-rlang r-cran-s2 r-cran-sf r-cran-sp \ + r-cran-tibble r-cran-tidyselect r-cran-utf8 r-cran-vctrs r-cran-withr \ + r-cran-wk \ + && Rscript --no-save --no-restore -e 'update.packages(ask = FALSE)' \ + && Rscript --no-save --no-restore -e 'remotes::install_cran("fmesher")' \ + && Rscript --no-save --no-restore -e 'remotes::install_cran("INLA", type = "source")' + +## install sn +RUN apt update \ + && apt install -y --no-install-recommends \ + r-cran-matrixmodels r-cran-mnormt r-cran-numderiv r-cran-quantreg \ + r-cran-sn r-cran-sparsem \ + && Rscript --no-save --no-restore -e 'update.packages(ask = FALSE)' \ + && Rscript --no-save --no-restore -e 'remotes::install_cran("sn")' + +## install checklist dependencies +RUN apt update \ + && apt install -y --no-install-recommends \ + r-cran-askpass r-cran-assertthat r-cran-backports r-cran-base64enc \ + r-cran-brew r-cran-brio r-cran-cachem r-cran-callr r-cran-clipr \ + r-cran-commonmark r-cran-crayon r-cran-credentials r-cran-crul r-cran-curl \ + r-cran-desc r-cran-devtools r-cran-diffobj r-cran-digest r-cran-downlit \ + r-cran-ellipsis r-cran-evaluate r-cran-fastmap r-cran-fs r-cran-gert \ + r-cran-gh r-cran-gitcreds r-cran-highr r-cran-htmltools r-cran-htmlwidgets \ + r-cran-httpcode r-cran-httpuv r-cran-httr r-cran-hunspell r-cran-ini \ + r-cran-jsonlite r-cran-jquerylib r-cran-knitr r-cran-later r-cran-lazyeval \ + r-cran-memoise r-cran-mime r-cran-miniui r-cran-openssl r-cran-pingr \ + r-cran-pkgbuild r-cran-pkgload r-cran-praise r-cran-prettyunits \ + r-cran-processx r-cran-promises r-cran-ps r-cran-purrr r-cran-ragg \ + r-cran-rappdirs r-cran-rcmdcheck r-cran-rematch2 r-cran-rex \ + r-cran-rmarkdown r-cran-roxygen2 r-cran-remotes r-cran-rprojroot \ + r-cran-rstudioapi r-cran-rversions r-cran-sass r-cran-sessioninfo \ + r-cran-shiny r-cran-sourcetools r-cran-stringi r-cran-stringr r-cran-sys \ + r-cran-systemfonts r-cran-testthat r-cran-textshaping r-cran-tinytex \ + r-cran-triebeard r-cran-urltools r-cran-usethis r-cran-waldo \ + r-cran-whisker r-cran-xfun r-cran-xml2 r-cran-xopen r-cran-xtable \ + r-cran-yaml r-cran-zip \ + && Rscript --no-save --no-restore -e 'update.packages(ask = FALSE)' \ + && Rscript --no-save --no-restore -e 'remotes::install_cran(c("bslib", "codemeta", "codemetar", "cyclocompt", "fontawesome", "httr2", "lintr", "pkgdown", "profvis", "renv", "urlchecker", "xmlparsedata"))' ## install checklist COPY . /checklist/ From ddebda1ae21cabf8d4027ff9df90e849bb8fe7fd Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Fri, 26 Apr 2024 11:17:34 +0200 Subject: [PATCH 46/63] check_spelling() adds the package name to the whitelist --- R/check_spelling.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/R/check_spelling.R b/R/check_spelling.R index 411d3dbf..5ec14ec5 100644 --- a/R/check_spelling.R +++ b/R/check_spelling.R @@ -88,9 +88,11 @@ spelling_wordlist <- function(lang = "en_GB", root = ".", package = FALSE) { format(include = c("given", "family")) |> strsplit(split = " ") |> unlist() |> - c(dependencies(root, progress = FALSE)$Package) |> - unique() |> - c(add_words) -> add_words + c( + dependencies(root, progress = FALSE)$Package, add_words, + descr$get_field("Package") + ) |> + unique() -> add_words } path("spelling", gsub("(.*)_.*", "stats_\\1.dic", lang)) |> From f923337ac83b4894a33002e55b69248234f00ad7 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 21 May 2024 09:58:58 +0200 Subject: [PATCH 47/63] Apply suggestions from code review Co-authored-by: Hans Van Calster --- vignettes/organisation.Rmd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vignettes/organisation.Rmd b/vignettes/organisation.Rmd index e831c3bd..f14da5b2 100644 --- a/vignettes/organisation.Rmd +++ b/vignettes/organisation.Rmd @@ -22,7 +22,7 @@ The `organisation` object defines rules about the organisation related to the pr `checklist` assumes by default that a project is a part of the [Research Institute for Nature and Forest (INBO)](https://www.vlaanderen.be/inbo/). And it will enforce to mention INBO as copyright holder and funder. -Such a rule limits to use of `checklist` outside of INBO. +Such a rule limits the use of `checklist` outside of INBO. Therefore we added the `organisation` object. It contains the following elements: @@ -43,7 +43,7 @@ Setting `orcid` to `TRUE` requires every author with matching e-mail to have an ## Defining a specific `organisation` for a project First generate the object with `organisation$new()`. -The store this object in your project with `write_organisation()`. +Then store this object in your project with `write_organisation()`. The function stores the information in `organisation.yml`, a plain text file in YAML format. ```{r} @@ -75,4 +75,4 @@ It first looks at project root folder for the `organisation.yml` file. When missing it looks for the machines default `organisation.yml`. In this case it will copy the machines default `organisation.yml` into the project. Hence the `organisation` information is a part of the project, which is required to use the information during checks on other machines. -When `read_organisation()` find neither a project `organisation.yml` nor a machines default `organisation.yml`, it reverts to the INBO `organisation`. +When `read_organisation()` finds neither a project `organisation.yml` nor a machines default `organisation.yml`, it reverts to the INBO `organisation`. From 7ba69718b9235f6312345f80b3e9738fab4ace5a Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 21 May 2024 16:01:43 +0200 Subject: [PATCH 48/63] update to zen4R 0.10 --- DESCRIPTION | 2 +- R/citation_bookdown.R | 15 ++++++++--- R/citation_meta_class.R | 4 +-- R/upload_zenodo.R | 33 ++++++++++++++++--------- inst/bookdown/index.Rmd | 2 +- tests/testthat/test_e_bookdown_zenodo.R | 21 ++++++++-------- 6 files changed, 47 insertions(+), 30 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 07620a34..cdcb61c2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -51,7 +51,7 @@ Suggests: showtext, sysfonts, testthat, - zen4R (>= 0.9) + zen4R (>= 0.10) VignetteBuilder: knitr Config/checklist/communities: inbo diff --git a/R/citation_bookdown.R b/R/citation_bookdown.R index 53b22f71..cdc564a5 100644 --- a/R/citation_bookdown.R +++ b/R/citation_bookdown.R @@ -57,10 +57,17 @@ citation_bookdown <- function(meta) { extra <- extra[extra %in% names(yaml)] cit_meta$meta <- c(cit_meta$meta, yaml[extra]) publication_type <- c( - "annotationcollection", "book", "section", "conferencepaper", - "datamanagementplan", "article", "patent", "preprint", "deliverable", - "milestone", "proposal", "report", "softwaredocumentation", - "taxonomictreatment", "technicalnote", "thesis", "workingpaper", "other" + "publication", "publication-annotationcollection", "publication-article", + "publication-book", "publication-conferencepaper", + "publication-conferenceproceeding", "publication-datamanagementplan", + "publication-datapaper", "publication-deliverable", + "publication-dissertation", "publication-journal", "publication-milestone", + "publication-other", "publication-patent", "publication-peerreview", + "publication-preprint", "publication-proposal", "publication-report", + "publication-section", "publication-softwaredocumentation", + "publication-standard", "publication-taxonomictreatment", + "publication-technicalnote", "publication-thesis", + "publication-workingpaper" ) c( "no `keywords` element found"[!has_name(yaml, "keywords")], diff --git a/R/citation_meta_class.R b/R/citation_meta_class.R index 8cebff3b..ed3ab6d8 100644 --- a/R/citation_meta_class.R +++ b/R/citation_meta_class.R @@ -244,12 +244,12 @@ citation_zenodo <- function(meta) { "reviewer" ), labels = c( - "author", "ContactPerson", "ProjectMember", "RightsHolder", "Funder", + "author", "contactperson", "projectmember", "rightsholder", "funder", "Other" ) ) relevant <- zenodo$roles$role %in% c( - "ContactPerson", "ProjectMember", "RightsHolder", "Other" + "contactperson", "projectmember", "rightsholder", "other" ) zenodo$contributors <- merge( zenodo$authors, zenodo$roles[relevant, ], by.x = "id", by.y = "contributor" diff --git a/R/upload_zenodo.R b/R/upload_zenodo.R index 036a05ca..4df19b21 100644 --- a/R/upload_zenodo.R +++ b/R/upload_zenodo.R @@ -16,21 +16,20 @@ upload_zenodo <- function(path, token, sandbox = TRUE, logger = NULL) { zen_rec <- zen4R::ZenodoRecord$new() zen_rec$setTitle(cit_meta$title) zen_rec$setDescription(cit_meta$description) - zen_rec$setUploadType(cit_meta$upload_type) + zen_rec$setResourceType(cit_meta$upload_type) if ( has_name(cit_meta, "embargo_date") && as.Date(cit_meta$embargo_date) > Sys.Date() ) { - zen_rec$setEmbargoDate(as.Date(cit_meta$embargo_date)) + zen_rec$setAccessPolicyEmbargo(TRUE, as.Date(cit_meta$embargo_date)) } - zen_rec$setAccessRight(cit_meta$access_right) - zen_rec$setLicense(cit_meta$license, sandbox = sandbox) - zen_rec$setLanguage(cit_meta$language) + zen_rec$setLicense(tolower(cit_meta$license), sandbox = sandbox) + zen_rec$addLanguage(cit_meta$language) zen_creator(zen_rec, cit_meta$creator) |> zen_contributor(cit_meta$contributors) |> zen_communities(cit_meta$communities, sandbox = sandbox) -> zen_rec - zen_rec$setKeywords(cit_meta$keywords) - zen_rec$setPublicationType(cit_meta$publication_type) + zen_rec$setSubjects(cit_meta$keywords) + zen_rec$setResourceType(cit_meta$publication_type) if (has_name(cit_meta, "doi")) { zen_rec$setDOI(cit_meta$doi) } @@ -55,7 +54,7 @@ zen_contributor <- function(zen_rec, contributors) { for (x in contributors) { zen_rec$addContributor( firstname = character(0), lastname = x$name, affiliation = x$affiliation, - orcid = x$orcid, type = x$type + orcid = x$orcid, role = x$type ) } return(zen_rec) @@ -73,17 +72,29 @@ zen_communities <- function(zen_rec, communities, sandbox) { #' @importFrom utils browseURL zen_upload <- function(zenodo, zen_rec, path) { zen_rec <- zenodo$depositRecord(zen_rec, publish = FALSE) - assert_that(!has_name(zen_rec, "status"), msg = zen_rec$message) + assert_that( + has_name(zen_rec, "status"), + msg = "Unexpected error uploading to Zenodo. Please contact the maintainer." + ) + assert_that( + zen_rec$status == "draft", + msg = ifelse( + zen_rec$status == "400", + "Problem authenticating to Zenodo. Check the Zenodo token.", + zen_rec$message %||% "Error uploading to Zenodo without error message." + ) + ) + to_upload <- dir_ls(path, recurse = TRUE, all = TRUE) for (filename in to_upload) { zenodo$uploadFile(filename, record = zen_rec) } message( - "Draft uploaded to Zenodo. Please visit ", zen_rec$links$html, + "Draft uploaded to Zenodo. Please visit ", zen_rec$links$self_html, " to publish." ) if (interactive()) { - browseURL(zen_rec$links$html) + browseURL(zen_rec$links$self_html) } return(zen_rec) } diff --git a/inst/bookdown/index.Rmd b/inst/bookdown/index.Rmd index 00ded660..d55fcd80 100644 --- a/inst/bookdown/index.Rmd +++ b/inst/bookdown/index.Rmd @@ -18,7 +18,7 @@ reviewer: lang: nl keywords: checklist; unit test community: inbo -publication_type: report +publication_type: publication-report funder: Research Institute for Nature and Forest (INBO) rightsholder: Research Institute for Nature and Forest (INBO) site: bookdown::bookdown_site diff --git a/tests/testthat/test_e_bookdown_zenodo.R b/tests/testthat/test_e_bookdown_zenodo.R index f68ddb99..05f99ff5 100644 --- a/tests/testthat/test_e_bookdown_zenodo.R +++ b/tests/testthat/test_e_bookdown_zenodo.R @@ -46,8 +46,8 @@ test_that("bookdown_zenodo() works", { file_copy(path(root, "LICENSE.md"), overwrite = TRUE) path(root, "index.Rmd") |> readLines() |> - tail(-2) -> index - c("---", "embargo: 2024-01-23", index) |> + tail(-1) -> index + c("---", "embargo: 2030-01-23", index) |> writeLines(path(root, "index.Rmd")) zenodo_out <- tempfile(fileext = ".txt") defer(file_delete(zenodo_out)) @@ -57,12 +57,11 @@ test_that("bookdown_zenodo() works", { ) sink() - skip_if_not_installed("zen4R", minimum_version = "0.10") expect_match(Sys.getenv("ZENODO_SANDBOX"), "^\\w{60}$") sandbox_token <- Sys.getenv("ZENODO_SANDBOX") - zenodo_out <- tempfile(fileext = ".txt") - defer(file_delete(zenodo_out)) - sink(zenodo_out) + zenodo_out2 <- tempfile(fileext = ".txt") + defer(file_delete(zenodo_out2)) + sink(zenodo_out2) suppressMessages( x <- bookdown_zenodo( root, logger = NULL, sandbox = TRUE, token = sandbox_token @@ -71,14 +70,14 @@ test_that("bookdown_zenodo() works", { sink() manager <- zen4R::ZenodoManager$new(sandbox = TRUE, token = sandbox_token) expect_true( - manager$deleteRecord(x$record_id), - label = paste("Remove Zenodo sandbox record", x$links$html) + manager$deleteRecord(x$id), + label = paste("Remove Zenodo sandbox record", x$links$self_html) ) path(root, "index.Rmd") |> readLines() -> index - head(index, 3) |> - c(" - Josiah Carberry", tail(index, -10)) |> + head(index, 4) |> + c(" - Josiah Carberry", tail(index, -11)) |> writeLines(path(root, "index.Rmd")) expect_warning( x <- citation_meta$new(root), @@ -88,7 +87,7 @@ test_that("bookdown_zenodo() works", { x$get_errors, c("no author with `corresponding: true`", "person must be a list") ) - head(index, 3) |> + head(index, 4) |> c(" - name: Josiah Carberry", tail(index, -10)) |> writeLines(path(root, "index.Rmd")) expect_warning( From 70568a7883fe1b9d629d315e57b6ffa85a1de0b3 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 22 May 2024 11:51:35 +0200 Subject: [PATCH 49/63] replace %||% with custom function. %||% requires 4.4.0 or later. --- .zenodo.json | 8 ++++---- R/upload_zenodo.R | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 70bbc796..bea93658 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -16,23 +16,23 @@ "name": "Onkelinx, Thierry", "affiliation": "Research Institute for Nature and Forest (INBO)", "orcid": "0000-0001-8804-4216", - "type": "ContactPerson" + "type": "contactperson" }, { "name": "Lommelen, Els", "affiliation": "Research Institute for Nature and Forest (INBO)", "orcid": "0000-0002-3481-5684", - "type": "ProjectMember" + "type": "projectmember" }, { "name": "Van Calster, Hans", "affiliation": "Research Institute for Nature and Forest (INBO)", "orcid": "0000-0001-8595-8426", - "type": "ProjectMember" + "type": "projectmember" }, { "name": "Research Institute for Nature and Forest (INBO)", - "type": "RightsHolder" + "type": "rightsholder" } ], "creators": [ diff --git a/R/upload_zenodo.R b/R/upload_zenodo.R index 4df19b21..ecbc3e73 100644 --- a/R/upload_zenodo.R +++ b/R/upload_zenodo.R @@ -81,7 +81,9 @@ zen_upload <- function(zenodo, zen_rec, path) { msg = ifelse( zen_rec$status == "400", "Problem authenticating to Zenodo. Check the Zenodo token.", - zen_rec$message %||% "Error uploading to Zenodo without error message." + first_non_null( + zen_rec$message, "Error uploading to Zenodo without error message." + ) ) ) @@ -98,3 +100,14 @@ zen_upload <- function(zenodo, zen_rec, path) { } return(zen_rec) } + +first_non_null <- function(...) { + dots <- list(...) + if (length(dots) == 0) { + return(NULL) + } + if (!is.null(dots[[1]])) { + return(dots[[1]]) + } + do.call(first_non_null, tail(dots, -1)) +} From e9caee86977a2834d70151850251ba74870ccd35 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 22 May 2024 15:18:09 +0200 Subject: [PATCH 50/63] update GHA --- .github/workflows/check_on_branch.yml | 2 +- .github/workflows/check_on_main.yml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check_on_branch.yml b/.github/workflows/check_on_branch.yml index 6a2b8c0f..f6ae1ebd 100644 --- a/.github/workflows/check_on_branch.yml +++ b/.github/workflows/check_on_branch.yml @@ -17,4 +17,4 @@ jobs: permissions: contents: read steps: - - uses: inbo/actions/check_pkg@main + - uses: inbo/actions/check_pkg@checklist-0.3.6 diff --git a/.github/workflows/check_on_main.yml b/.github/workflows/check_on_main.yml index f25f486b..87c925a8 100644 --- a/.github/workflows/check_on_main.yml +++ b/.github/workflows/check_on_main.yml @@ -2,7 +2,6 @@ on: push: branches: - main - - master permissions: contents: write @@ -17,4 +16,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ZENODO_SANDBOX: ${{ secrets.ZENODO_SANDBOX }} steps: - - uses: inbo/actions/check_pkg@main + - uses: inbo/actions/check_pkg@checklist-0.3.6 From 01e1ee2199566f64e008bccf512143ebc7d43b31 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 27 May 2024 14:08:47 +0200 Subject: [PATCH 51/63] upload_zenodo() doesn't add communities Fixes #125 --- NAMESPACE | 2 ++ R/upload_zenodo.R | 22 ++++++++++------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 987b10ad..596822b0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -61,6 +61,8 @@ importFrom(assertthat,is.flag) importFrom(assertthat,is.number) importFrom(assertthat,is.string) importFrom(assertthat,noNA) +importFrom(cli,cli_alert_info) +importFrom(cli,cli_alert_warning) importFrom(cli,cli_h1) importFrom(cli,cli_text) importFrom(cli,col_green) diff --git a/R/upload_zenodo.R b/R/upload_zenodo.R index ecbc3e73..f9b3a76a 100644 --- a/R/upload_zenodo.R +++ b/R/upload_zenodo.R @@ -26,8 +26,7 @@ upload_zenodo <- function(path, token, sandbox = TRUE, logger = NULL) { zen_rec$setLicense(tolower(cit_meta$license), sandbox = sandbox) zen_rec$addLanguage(cit_meta$language) zen_creator(zen_rec, cit_meta$creator) |> - zen_contributor(cit_meta$contributors) |> - zen_communities(cit_meta$communities, sandbox = sandbox) -> zen_rec + zen_contributor(cit_meta$contributors) -> zen_rec zen_rec$setSubjects(cit_meta$keywords) zen_rec$setResourceType(cit_meta$publication_type) if (has_name(cit_meta, "doi")) { @@ -60,14 +59,8 @@ zen_contributor <- function(zen_rec, contributors) { return(zen_rec) } -zen_communities <- function(zen_rec, communities, sandbox) { - for (x in communities) { - zen_rec$addCommunity(x$identifier, sandbox = sandbox) - } - return(zen_rec) -} - #' @importFrom assertthat assert_that has_name +#' @importFrom cli cli_alert_info cli_alert_warning #' @importFrom fs dir_ls #' @importFrom utils browseURL zen_upload <- function(zenodo, zen_rec, path) { @@ -91,9 +84,14 @@ zen_upload <- function(zenodo, zen_rec, path) { for (filename in to_upload) { zenodo$uploadFile(filename, record = zen_rec) } - message( - "Draft uploaded to Zenodo. Please visit ", zen_rec$links$self_html, - " to publish." + c( + "Draft uploaded to Zenodo.", + "Please visit {zen_rec$links$self_html} to publish." + ) |> + paste(collapse = " ") |> + cli_alert_info() + cli_alert_warning( + "Remember to add the publication to the relevant communities." ) if (interactive()) { browseURL(zen_rec$links$self_html) From d5e05ca46bdbecaf8122d2e6b139321df63f9456 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 28 May 2024 09:42:06 +0200 Subject: [PATCH 52/63] set publication date when uploading a bookdown to Zenodo --- R/citation_bookdown.R | 7 +++++++ R/upload_zenodo.R | 3 +++ 2 files changed, 10 insertions(+) diff --git a/R/citation_bookdown.R b/R/citation_bookdown.R index cdc564a5..a1f0be89 100644 --- a/R/citation_bookdown.R +++ b/R/citation_bookdown.R @@ -24,10 +24,17 @@ citation_bookdown <- function(meta) { ifelse(has_name(yaml, "subtitle"), paste0(". ", yaml$subtitle, "."), ".") ) cit_meta$meta$upload_type <- "publication" + if (has_name(yaml, "publication_date")) { + cit_meta$meta$publication_date <- string2date(yaml$publication_date) |> + format("%Y-%m-%d") + } if (has_name(yaml, "embargo")) { cit_meta$meta$embargo_date <- string2date(yaml$embargo) |> format("%Y-%m-%d") cit_meta$meta$access_right <- "embargoed" + if (!has_name(yaml, "publication_date")) { + cit_meta$meta$publication_date <- cit_meta$meta$embargo_date + } } else { cit_meta$meta$access_right <- "open" } diff --git a/R/upload_zenodo.R b/R/upload_zenodo.R index f9b3a76a..1d807119 100644 --- a/R/upload_zenodo.R +++ b/R/upload_zenodo.R @@ -35,6 +35,9 @@ upload_zenodo <- function(path, token, sandbox = TRUE, logger = NULL) { if (has_name(cit_meta, "version")) { zen_rec$setVersion(cit_meta$version) } + zen_rec$setPublicationDate( + first_non_null(cit_meta$publication_date, Sys.Date()) + ) zen_rec <- zen_upload(zenodo, zen_rec, path) return(invisible(zen_rec)) From 0df293b4952fa6ac98756deed7ab086a2be1fbd4 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 28 May 2024 10:57:27 +0200 Subject: [PATCH 53/63] require publisher information in bookdown --- R/citation_bookdown.R | 9 +++++---- R/upload_zenodo.R | 1 + inst/bookdown/index.Rmd | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/R/citation_bookdown.R b/R/citation_bookdown.R index a1f0be89..e41a9fde 100644 --- a/R/citation_bookdown.R +++ b/R/citation_bookdown.R @@ -59,7 +59,7 @@ citation_bookdown <- function(meta) { cit_meta$meta$language <- yaml$lang } extra <- c( - "community", "doi", "keywords", "publication_type" + "community", "doi", "keywords", "publication_type", "publisher" ) extra <- extra[extra %in% names(yaml)] cit_meta$meta <- c(cit_meta$meta, yaml[extra]) @@ -77,7 +77,8 @@ citation_bookdown <- function(meta) { "publication-workingpaper" ) c( - "no `keywords` element found"[!has_name(yaml, "keywords")], + "No `keywords` element found"[!has_name(yaml, "keywords")], + "No `publisher` element found"[!has_name(yaml, "publisher")], paste( "`publication_type` must be one of following:", paste(publication_type, collapse = ", "), @@ -89,8 +90,8 @@ citation_bookdown <- function(meta) { ) |> c(cit_meta$errors) -> cit_meta$errors c( - "no `community` element found"[!has_name(yaml, "community")], - "no `publication_type` element found"[!has_name(yaml, "publication_type")] + "No `community` element found"[!has_name(yaml, "community")], + "No `publication_type` element found"[!has_name(yaml, "publication_type")] ) |> c(cit_meta$notes) -> cit_meta$notes return(cit_meta) diff --git a/R/upload_zenodo.R b/R/upload_zenodo.R index 1d807119..9d77ef71 100644 --- a/R/upload_zenodo.R +++ b/R/upload_zenodo.R @@ -38,6 +38,7 @@ upload_zenodo <- function(path, token, sandbox = TRUE, logger = NULL) { zen_rec$setPublicationDate( first_non_null(cit_meta$publication_date, Sys.Date()) ) + zen_rec$setPublisher(cit_meta$publisher) zen_rec <- zen_upload(zenodo, zen_rec, path) return(invisible(zen_rec)) diff --git a/inst/bookdown/index.Rmd b/inst/bookdown/index.Rmd index d55fcd80..c0f5a2b4 100644 --- a/inst/bookdown/index.Rmd +++ b/inst/bookdown/index.Rmd @@ -19,6 +19,7 @@ lang: nl keywords: checklist; unit test community: inbo publication_type: publication-report +publisher: Research Institute for Nature and Forest (INBO) funder: Research Institute for Nature and Forest (INBO) rightsholder: Research Institute for Nature and Forest (INBO) site: bookdown::bookdown_site From e78f8e63ca2d51eaf6a9be6228b0179fcd600919 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Tue, 28 May 2024 16:56:14 +0200 Subject: [PATCH 54/63] bookdown_zenodo() creates a review request when the community is defined thanks to @eblondel for the feedback via https://github.com/eblondel/zen4R/discussions/158 --- R/bookdown_zenodo.R | 3 ++ R/citation_bookdown.R | 12 +++++++ R/upload_zenodo.R | 42 ++++++++++++++++++------- inst/bookdown/index.Rmd | 2 +- man/bookdown_zenodo.Rd | 3 ++ tests/testthat/test_e_bookdown_zenodo.R | 41 +++++++++++++++++++++--- 6 files changed, 86 insertions(+), 17 deletions(-) diff --git a/R/bookdown_zenodo.R b/R/bookdown_zenodo.R index 734824fd..d6b8738e 100644 --- a/R/bookdown_zenodo.R +++ b/R/bookdown_zenodo.R @@ -3,6 +3,9 @@ #' First clears all the existing files in the `output_dir` set in #' `_bookdown_.yml`. #' Then renders all required output formats and uploads them to Zenodo. +#' `bookdown_zenodo()` creates a draft record when you don't specify a community +#' in the yaml. +#' Otherwise it creates a review request for the first community. #' @param path The root folder of the report #' @param zip_format A vector with output formats that generate multiple files. #' The function will bundle all the files in a zip file for every format. diff --git a/R/citation_bookdown.R b/R/citation_bookdown.R index e41a9fde..8470a64a 100644 --- a/R/citation_bookdown.R +++ b/R/citation_bookdown.R @@ -94,9 +94,21 @@ citation_bookdown <- function(meta) { "No `publication_type` element found"[!has_name(yaml, "publication_type")] ) |> c(cit_meta$notes) -> cit_meta$notes + cit_meta$meta$community <- split_community(cit_meta$meta$community) return(cit_meta) } +#' @importFrom assertthat assert_that +split_community <- function(community) { + if (is.null(community)) { + return(NULL) + } + assert_that(is.character(community)) + strsplit(community, split = "\\s*;\\s*") |> + unlist() |> + unique() +} + #' @importFrom assertthat has_name yaml_author <- function(yaml, org) { author <- vapply( diff --git a/R/upload_zenodo.R b/R/upload_zenodo.R index 9d77ef71..ce1e61ff 100644 --- a/R/upload_zenodo.R +++ b/R/upload_zenodo.R @@ -40,7 +40,9 @@ upload_zenodo <- function(path, token, sandbox = TRUE, logger = NULL) { ) zen_rec$setPublisher(cit_meta$publisher) - zen_rec <- zen_upload(zenodo, zen_rec, path) + zen_rec <- zen_upload( + zenodo, zen_rec, path, community = cit_meta$communities + ) return(invisible(zen_rec)) } @@ -63,11 +65,11 @@ zen_contributor <- function(zen_rec, contributors) { return(zen_rec) } -#' @importFrom assertthat assert_that has_name +#' @importFrom assertthat assert_that has_name is.string noNA #' @importFrom cli cli_alert_info cli_alert_warning #' @importFrom fs dir_ls #' @importFrom utils browseURL -zen_upload <- function(zenodo, zen_rec, path) { +zen_upload <- function(zenodo, zen_rec, path, community = NULL) { zen_rec <- zenodo$depositRecord(zen_rec, publish = FALSE) assert_that( has_name(zen_rec, "status"), @@ -88,15 +90,33 @@ zen_upload <- function(zenodo, zen_rec, path) { for (filename in to_upload) { zenodo$uploadFile(filename, record = zen_rec) } - c( - "Draft uploaded to Zenodo.", - "Please visit {zen_rec$links$self_html} to publish." - ) |> - paste(collapse = " ") |> - cli_alert_info() - cli_alert_warning( - "Remember to add the publication to the relevant communities." + + if (is.null(community)) { + c( + "Draft uploaded to Zenodo.", + "Please visit {zen_rec$links$self_html} to publish." + ) |> + paste(collapse = " ") |> + cli_alert_info() + if (interactive()) { + browseURL(zen_rec$links$self_html) + } + return(zen_rec) + } + + zenodo$createReviewRequest( + record = zen_rec, community = unlist(head(community, 1)) ) + zenodo$submitRecordForReview( + recordId = zen_rec$id, + message = paste( + "Automated review request created by the checklist package.", + "More information at https://inbo.github.io/checklist/." + ) + ) + if (length(community) > 1) { + cli_alert_warning("Remember to add the additional communities.") + } if (interactive()) { browseURL(zen_rec$links$self_html) } diff --git a/inst/bookdown/index.Rmd b/inst/bookdown/index.Rmd index c0f5a2b4..f79c6270 100644 --- a/inst/bookdown/index.Rmd +++ b/inst/bookdown/index.Rmd @@ -17,7 +17,7 @@ reviewer: affiliation: Wesleyan University lang: nl keywords: checklist; unit test -community: inbo +community: checklist; inbo publication_type: publication-report publisher: Research Institute for Nature and Forest (INBO) funder: Research Institute for Nature and Forest (INBO) diff --git a/man/bookdown_zenodo.Rd b/man/bookdown_zenodo.Rd index 897e0c09..768f4248 100644 --- a/man/bookdown_zenodo.Rd +++ b/man/bookdown_zenodo.Rd @@ -40,6 +40,9 @@ Use \code{NULL} to hide the logs. First clears all the existing files in the \code{output_dir} set in \verb{_bookdown_.yml}. Then renders all required output formats and uploads them to Zenodo. +\code{bookdown_zenodo()} creates a draft record when you don't specify a community +in the yaml. +Otherwise it creates a review request for the first community. } \seealso{ Other utils: diff --git a/tests/testthat/test_e_bookdown_zenodo.R b/tests/testthat/test_e_bookdown_zenodo.R index 05f99ff5..b342f208 100644 --- a/tests/testthat/test_e_bookdown_zenodo.R +++ b/tests/testthat/test_e_bookdown_zenodo.R @@ -69,6 +69,38 @@ test_that("bookdown_zenodo() works", { ) sink() manager <- zen4R::ZenodoManager$new(sandbox = TRUE, token = sandbox_token) + zen_com <- manager$getCommunityById("checklist") + sprintf( + "status:submitted AND receiver.community:%s AND topic.record:%s", + zen_com$id, x$id + ) |> + manager$getRequests() -> reqs + expect_true( + manager$cancelRequest(reqs[[1]]$id), + label = paste("Failed to delete review request", reqs[[1]]$id) + ) + expect_true( + manager$deleteRecord(x$id), + label = paste("Remove Zenodo sandbox record", x$links$self_html) + ) + + # test without community + c("---", index[!grepl("^community:", index)]) |> + writeLines(path(root, "index.Rmd")) + organisation$new( + github = NA_character_, community = NA_character_, email = NA_character_, + funder = NA_character_, rightsholder = NA_character_ + ) |> + write_organisation(root) + zenodo_out3 <- tempfile(fileext = ".txt") + defer(file_delete(zenodo_out3)) + sink(zenodo_out3) + suppressMessages( + x <- bookdown_zenodo( + root, logger = NULL, sandbox = TRUE, token = sandbox_token + ) + ) + sink() expect_true( manager$deleteRecord(x$id), label = paste("Remove Zenodo sandbox record", x$links$self_html) @@ -76,18 +108,17 @@ test_that("bookdown_zenodo() works", { path(root, "index.Rmd") |> readLines() -> index - head(index, 4) |> - c(" - Josiah Carberry", tail(index, -11)) |> + head(index, 3) |> + c(" - Josiah Carberry", tail(index, -10)) |> writeLines(path(root, "index.Rmd")) expect_warning( - x <- citation_meta$new(root), - "Errors found parsing citation meta data" + x <- citation_meta$new(root), "Errors found parsing citation meta data" ) expect_identical( x$get_errors, c("no author with `corresponding: true`", "person must be a list") ) - head(index, 4) |> + head(index, 3) |> c(" - name: Josiah Carberry", tail(index, -10)) |> writeLines(path(root, "index.Rmd")) expect_warning( From 09e8044a54217f063346a421b667a05e918a54b8 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 29 May 2024 06:28:48 +0200 Subject: [PATCH 55/63] display warning on windows about a potentially hidden dialog box --- R/create_package.R | 6 ++++++ R/setup_project.R | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/R/create_package.R b/R/create_package.R index cc5ed074..fda4f424 100644 --- a/R/create_package.R +++ b/R/create_package.R @@ -25,6 +25,7 @@ #' @param communities An optional vector of Zenodo community id's. #' @export #' @importFrom assertthat assert_that is.string +#' @importFrom cli cli_alert_info #' @importFrom desc description #' @importFrom fs dir_create dir_ls file_copy is_dir path #' @importFrom gert git_add git_init @@ -61,6 +62,11 @@ create_package <- function( if (missing(maintainer)) { cat("Please select the maintainer") maintainer <- author2person(role = c("aut", "cre")) + if (.Platform$OS.type == "windows") { + cli_alert_info( +"This function opens a dialog box which might be hidden behind another window." + ) + } while (isTRUE(ask_yes_no("Add another author?", default = FALSE))) { maintainer <- c(maintainer, author2person()) } diff --git a/R/setup_project.R b/R/setup_project.R index fff5e9f0..3c350591 100644 --- a/R/setup_project.R +++ b/R/setup_project.R @@ -6,6 +6,7 @@ #' @param path the project root folder #' @export #' @importFrom assertthat assert_that is.string +#' @importFrom cli cli_alert_info #' @importFrom fs dir_create file_copy is_dir path path_real path_rel #' @family setup setup_project <- function(path = ".") { @@ -13,6 +14,12 @@ setup_project <- function(path = ".") { path <- path_real(path) checklist_file <- path(path, "checklist.yml") + if (.Platform$OS.type == "windows") { + cli_alert_info( +"This function opens a dialog box which might be hidden behind another window." + ) + } + if (is_file(checklist_file)) { x <- read_checklist(path) } else { From 0ebd61b86fd244d22f52c319a2cad23d163c55a2 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 29 May 2024 07:26:32 +0200 Subject: [PATCH 56/63] bugfix in renv::init() --- R/setup_project.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/R/setup_project.R b/R/setup_project.R index 3c350591..88c0e810 100644 --- a/R/setup_project.R +++ b/R/setup_project.R @@ -318,8 +318,8 @@ renv_activate <- function(path) { ) { return(invisible(NULL)) } - # nocov start - sprintf("Rscript -e 'renv::init(\"%s\", restart = FALSE)'", path) |> - execshell() - # nocov end + c( + "if (!utils::file_test(\"-f\", \"renv.lock\")) {", " renv::init()", "}" + ) |> + writeLines(path(path, ".Rprofile")) } From 5aa9542803ba0b75966cc6104456538fa38a0748 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 29 May 2024 15:27:02 +0200 Subject: [PATCH 57/63] allows multiple affilications fixes #123 --- R/citation_meta_class.R | 11 +++++++---- R/citation_readme.R | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/R/citation_meta_class.R b/R/citation_meta_class.R index ed3ab6d8..6ff32c58 100644 --- a/R/citation_meta_class.R +++ b/R/citation_meta_class.R @@ -199,14 +199,17 @@ validate_citation <- function(meta) { FUN.VALUE = vector(mode = "list", length = 1), org = org$get_organisation, FUN = function(i, org) { paste( - "Non standard affiliation for %s %s as member of `%s`. ", - "Please use any of the following", collapse = "" + "Non standard affiliation for %s %s as member of `%s`.", + "Please use one of the following:\n%s", collapse = "" ) |> sprintf( - authors$given[i], authors$family[i], authors$organisation[i] + authors$given[i], authors$family[i], authors$organisation[i], + paste(org[[authors$organisation[i]]]$affiliation, collapse = "\n") ) -> error + strsplit(authors$affiliation[i], split = "\\s*;\\s*") |> + unlist() -> aff error <- error[ - !authors$affiliation[i] %in% org[[authors$organisation[i]]]$affiliation + !any(aff %in% org[[authors$organisation[i]]]$affiliation) ] if (org[[authors$organisation[i]]]$orcid) { error <- c( diff --git a/R/citation_readme.R b/R/citation_readme.R index 79d611c4..6267160e 100644 --- a/R/citation_readme.R +++ b/R/citation_readme.R @@ -275,13 +275,13 @@ readme_author <- function(text) { ] ) - orgs[vapply(orgs, length, integer(1)) == 0] <- NA + orgs[vapply(orgs, length, integer(1)) == 0] <- NA_character_ text$text <- text$text[!grepl("\\[\\^.*?\\]:", text$text)] text$meta$authors <- data.frame( id = seq_along(authors), given = gsub(".*,\\s*(.*)", "\\1", authors), family = ifelse(grepl(",", authors), gsub("(.*),.*", "\\1", authors), ""), affiliation = authors_aff, orcid = authors_orcid, - organisation = unlist(orgs) + organisation = vapply(orgs, FUN = head, FUN.VALUE = character(1), n = 1) ) return(text) } From dd06b7ca68a907868fb7004d72be191af3669b27 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 29 May 2024 15:53:33 +0200 Subject: [PATCH 58/63] project README get by default a badge with a concept project status --- R/setup_project.R | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/R/setup_project.R b/R/setup_project.R index 88c0e810..113bbdbc 100644 --- a/R/setup_project.R +++ b/R/setup_project.R @@ -216,17 +216,20 @@ create_readme <- function(path, org) { sprintf(fmt = "**keywords**: %s") -> keywords c("[^cph]: copyright holder", "[^fnd]: funder", attr(author, "footnote")) |> unique() -> footnote - if (!is_repository(path)) { - badges <- character(0) - } else { + paste0( + "[![Project Status: Concept - Minimal or no implementation has been done ", + "yet, or the repository is only intended to be a limited example, demo, ", + "or proof-of-concept.]", + "(https://www.repostatus.org/badges/latest/concept.svg)]", + "(https://www.repostatus.org/#concept)" + ) -> badges + if (is_repository(path)) { remotes <- git_remote_list(repo = path) remotes$url[remotes$name == "origin"] |> gsub(pattern = "git@(.*?):(.*)", replacement = "https://\\1/\\2") |> gsub(pattern = "https://.*?@", replacement = "https://") |> gsub(pattern = "\\.git$", replacement = "") -> repo_url - if (length(repo_url) > 0 && !grepl("github.com", repo_url)) { - badges <- character(0) - } else { + if (length(repo_url) > 0 && grepl("github.com", repo_url)) { gsub("https://github.com/", "", repo_url) |> sprintf( fmt = paste0( From 45ddbfad886cf2bba80aa453c9c450d9edb0bd15 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 29 May 2024 16:38:04 +0200 Subject: [PATCH 59/63] check_spelling() ignores leading or trailing double backwards slashes in markdown files fixes #107 --- R/spelling_parse.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/spelling_parse.R b/R/spelling_parse.R index fdb8d054..a613b4cf 100644 --- a/R/spelling_parse.R +++ b/R/spelling_parse.R @@ -269,6 +269,9 @@ spelling_parse_md <- function(md_file, wordlist, x) { text <- gsub("\\s[/\\\\]\\s", " ", text) text <- gsub("\\s[/\\\\]$", " ", text) text <- gsub("^[/\\\\]\\s", " ", text) + # remove double backward slashes at the start or end of a line + text <- gsub("^\\\\\\\\", " ", text) + text <- gsub("\\\\\\\\$", " ", text) # remove quarto anchors text <- gsub("\\{#.*?\\}", "", text) # remove quarto caption options From 5eeb2eeb430626d9f479a044fc4328433aa51fdf Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 29 May 2024 17:48:34 +0200 Subject: [PATCH 60/63] calculate diff relative to current main or master branch --- R/utils.R | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/R/utils.R b/R/utils.R index d661fff9..331f4f36 100644 --- a/R/utils.R +++ b/R/utils.R @@ -325,13 +325,19 @@ is_tracked_not_modified <- function(file, repo = ".") { return(is_tracked && is_not_modified) } -#' @importFrom gert git_info +#' @importFrom gert git_branch_list git_diff git_info #' @importFrom cli cli_h1 cli_text col_green col_red checklist_diff <- function(root) { if (inherits(try(git_info(repo = root), silent = TRUE), "try-error")) { return(invisible(NULL)) } - changes <- git_diff(repo = root) + branch_info <- git_branch_list(repo = root) + branch_info$ref[ + grep("/main$", branch_info$ref) |> + c(grep("/master$", branch_info$ref)) |> + head(1) + ] |> + git_diff(repo = root) -> changes if (length(changes) == 0) { return(invisible(NULL)) } From 70a0242c2b61d8b262cda9d649d3c143714ebcc4 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Wed, 29 May 2024 17:48:48 +0200 Subject: [PATCH 61/63] update NEWS --- NEWS.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/NEWS.md b/NEWS.md index 2be2cfa2..b56cd011 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,11 +3,22 @@ * Add an `organisation` class to store organisation rules different from those of the Research Institute for Nature and Forest (INBO). See `vignette("organisation", package = "checklist")` for more information. +* The output of the check shows the git diff (#77). * `add_badges()` helps to add badges to the `README`. * Put double quotes around the title and abstract fields of `CITATION.cff`. * `check_documentation()` handles assignment functions and re-exported functions correctly. * `check_lintr()` ignores `renv` subdirectories (#118). +* Update to [`zen4R`](https://github.com/eblondel/zen4R/wiki) version 0.10 to + reflect the Zenodo API changes (#125). +* `update_citation()` no longer introduces new lines (#124) and handles single + quotes in titles (#115). +* You can add multiple affiliations per author (#123). + Separate them by a semi-colon (;) in a `DESCRIPTION` or the yaml of a + bookdown. + Use multiple footnotes is a `README.md`. +* `check_spelling()` handles leading or trailing backwards slashes (#107). +* `check_cran()` ignores irrelevant CRAN notes. # checklist 0.3.5 From 69c947a3fca3f492f9ad5b9c9da0940e9c4dd06f Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 30 May 2024 07:02:31 +0200 Subject: [PATCH 62/63] replace prompt defaults to avoid the dialog box on Windows as suggested by @hansvancalster --- R/create_package.R | 8 +------- R/setup_project.R | 10 +--------- man/ask_yes_no.Rd | 7 +------ 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/R/create_package.R b/R/create_package.R index fda4f424..806b792d 100644 --- a/R/create_package.R +++ b/R/create_package.R @@ -25,12 +25,11 @@ #' @param communities An optional vector of Zenodo community id's. #' @export #' @importFrom assertthat assert_that is.string -#' @importFrom cli cli_alert_info #' @importFrom desc description #' @importFrom fs dir_create dir_ls file_copy is_dir path #' @importFrom gert git_add git_init #' @importFrom tools toTitleCase -#' @importFrom utils askYesNo installed.packages +#' @importFrom utils installed.packages #' @family setup #' @examples #' # maintainer in `utils::person()` format @@ -62,11 +61,6 @@ create_package <- function( if (missing(maintainer)) { cat("Please select the maintainer") maintainer <- author2person(role = c("aut", "cre")) - if (.Platform$OS.type == "windows") { - cli_alert_info( -"This function opens a dialog box which might be hidden behind another window." - ) - } while (isTRUE(ask_yes_no("Add another author?", default = FALSE))) { maintainer <- c(maintainer, author2person()) } diff --git a/R/setup_project.R b/R/setup_project.R index 113bbdbc..576f82eb 100644 --- a/R/setup_project.R +++ b/R/setup_project.R @@ -6,7 +6,6 @@ #' @param path the project root folder #' @export #' @importFrom assertthat assert_that is.string -#' @importFrom cli cli_alert_info #' @importFrom fs dir_create file_copy is_dir path path_real path_rel #' @family setup setup_project <- function(path = ".") { @@ -14,12 +13,6 @@ setup_project <- function(path = ".") { path <- path_real(path) checklist_file <- path(path, "checklist.yml") - if (.Platform$OS.type == "windows") { - cli_alert_info( -"This function opens a dialog box which might be hidden behind another window." - ) - } - if (is_file(checklist_file)) { x <- read_checklist(path) } else { @@ -298,8 +291,7 @@ preferred_protocol <- function(org) { #' @export #' @family utils ask_yes_no <- function( - msg, default = TRUE, - prompts = getOption("askYesNo", gettext(c("Yes", "No", "Cancel"))), ... + msg, default = TRUE, prompts = c("Yes", "No", "Cancel"), ... ) { if (!interactive()) { return(default) diff --git a/man/ask_yes_no.Rd b/man/ask_yes_no.Rd index 44c2679b..7235c8ad 100644 --- a/man/ask_yes_no.Rd +++ b/man/ask_yes_no.Rd @@ -4,12 +4,7 @@ \alias{ask_yes_no} \title{Function to ask a simple yes no question} \usage{ -ask_yes_no( - msg, - default = TRUE, - prompts = getOption("askYesNo", gettext(c("Yes", "No", "Cancel"))), - ... -) +ask_yes_no(msg, default = TRUE, prompts = c("Yes", "No", "Cancel"), ...) } \arguments{ \item{msg}{ From 46775286440df6daac4ef9340ebba8d13682a7e3 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Thu, 30 May 2024 07:41:37 +0200 Subject: [PATCH 63/63] bugfix in preferred_protocol() --- R/setup_project.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/setup_project.R b/R/setup_project.R index 576f82eb..9e448fdc 100644 --- a/R/setup_project.R +++ b/R/setup_project.R @@ -282,7 +282,11 @@ preferred_protocol <- function(org) { config$git$protocol == "https", "https://github.com/%s/%%s.git", "git@github.com:%s/%%s.git" ) |> - sprintf(config$git$organisation) + sprintf( + ifelse( + config$git$organisation == "", org$get_github, config$git$organisation + ) + ) } #' Function to ask a simple yes no question