From de608615091db4674b196034003341e1579afb97 Mon Sep 17 00:00:00 2001 From: Rich FitzJohn Date: Thu, 12 Oct 2023 18:14:51 +0100 Subject: [PATCH 1/4] Basic orderly_new implementation No real template support, but bits in place in case people want that back. --- DESCRIPTION | 2 +- NAMESPACE | 1 + R/orderly.R | 54 ++++++++++++++++++++++++++ _pkgdown.yml | 1 + man/orderly_new.Rd | 38 ++++++++++++++++++ tests/testthat/test-orderly.R | 72 +++++++++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 man/orderly_new.Rd diff --git a/DESCRIPTION b/DESCRIPTION index edbc8188..202e48c6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: orderly2 Title: Orderly Next Generation -Version: 1.99.6 +Version: 1.99.7 Authors@R: c(person("Rich", "FitzJohn", role = c("aut", "cre"), email = "rich.fitzjohn@gmail.com"), person("Robert", "Ashton", role = "aut"), diff --git a/NAMESPACE b/NAMESPACE index 4052d29b..1b22cabf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -28,6 +28,7 @@ export(orderly_location_rename) export(orderly_metadata) export(orderly_metadata_extract) export(orderly_metadata_read) +export(orderly_new) export(orderly_parameters) export(orderly_plugin_add_metadata) export(orderly_plugin_context) diff --git a/R/orderly.R b/R/orderly.R index 6ede1d3d..f7275f49 100644 --- a/R/orderly.R +++ b/R/orderly.R @@ -23,3 +23,57 @@ orderly_list_src <- function(root = NULL, locate = TRUE) { pos <- fs::dir_ls(file.path(root_path, "src"), type = "directory") basename(pos)[file_exists(file.path(pos, "orderly.R"))] } + + +##' Create a new empty report. +##' +##' @title Create a new report +##' +##' @param name The name of the report +##' +##' @param template The template to use. The only acceptable values +##' for now are `NULL` (uses the built-in default) and `FALSE` which +##' suppresses any default content. We may support customisable +##' templates in future - let us know if this would be useful. +##' +##' @param force Create an `orderly.R` file within an existing +##' directory `src/`; this may be useful if you have already +##' created the directory and some files first but want help +##' creating the orderly file. +##' +##' @inheritParams orderly_run +##' +##' @return Nothing, called for its side effects only +##' @export +orderly_new <- function(name, template = NULL, force = FALSE, + root = NULL, locate = TRUE) { + root <- root_open(root, locate, require_orderly = TRUE, call = environment()) + dest <- file.path(root$path, "src", name) + + if (file.exists(file.path(dest, "orderly.R"))) { + cli::cli_abort("'src/{name}/orderly.R' already exists") + } + if (file.exists(dest) && !fs::is_dir(dest)) { + cli::cli_abort( + c("'src/{name}' already exists, but is not a directory", + i = "This file really should not be here, you might need to tidy up")) + } + if (length(dir(dest, all.files = TRUE, no.. = TRUE)) > 0 && !force) { + cli::cli_abort( + c("'src/{name}/' already exists and contains files", + i = paste("If you want to add an orderly.R to this directory,", + "rerun {.code orderly_new()} with {.code force = TRUE}"))) + } + + if (is.null(template)) { + contents <- readLines(orderly2_file("template/default.R")) + } else if (isFALSE(template)) { + contents <- character() + } else { + cli::cli_abort("'template' must be 'NULL' or 'FALSE' for now") + } + + fs::dir_create(dest) + writeLines(contents, file.path(dest, "orderly.R")) + cli::cli_alert_success("Created 'src/{name}/orderly.R'") +} diff --git a/_pkgdown.yml b/_pkgdown.yml index 5be912d7..9711fb8d 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -68,6 +68,7 @@ reference: - orderly_location_rename - title: Help for developing contents: + - orderly_new - orderly_cleanup - orderly_cleanup_status - orderly_gitignore_update diff --git a/man/orderly_new.Rd b/man/orderly_new.Rd new file mode 100644 index 00000000..70061900 --- /dev/null +++ b/man/orderly_new.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/orderly.R +\name{orderly_new} +\alias{orderly_new} +\title{Create a new report} +\usage{ +orderly_new(name, template = NULL, force = FALSE, root = NULL, locate = TRUE) +} +\arguments{ +\item{name}{The name of the report} + +\item{template}{The template to use. The only acceptable values +for now are \code{NULL} (uses the built-in default) and \code{FALSE} which +suppresses any default content. We may support customisable +templates in future - let us know if this would be useful.} + +\item{force}{Create an \code{orderly.R} file within an existing +directory \verb{src/}; this may be useful if you have already +created the directory and some files first but want help +creating the orderly file.} + +\item{root}{The path to the root directory, or \code{NULL} (the +default) to search for one from the current working directory if +\code{locate} is \code{TRUE}. This function \strong{does} require that the +directory is configured for orderly, and not just outpack (see +\link{orderly_init} for details).} + +\item{locate}{Logical, indicating if the configuration should be +searched for. If \code{TRUE} and \code{config} is not given, +then orderly looks in the working directory and up through its +parents until it finds an \code{.outpack} directory} +} +\value{ +Nothing, called for its side effects only +} +\description{ +Create a new empty report. +} diff --git a/tests/testthat/test-orderly.R b/tests/testthat/test-orderly.R index f76e279c..e6260ec6 100644 --- a/tests/testthat/test-orderly.R +++ b/tests/testthat/test-orderly.R @@ -29,3 +29,75 @@ test_that("no candidates returns empty character vector", { expect_equal(withr::with_dir(path, orderly_list_src()), character()) expect_equal(orderly_list_src(path), character()) }) + + +test_that("can create empty orderly report", { + path <- test_prepare_orderly_example(character()) + expect_message( + orderly_new("foo", root = path), + "Created 'src/foo/orderly.R'") + path_orderly <- file.path(path, "src", "foo", "orderly.R") + expect_true(file.exists(path_orderly)) + txt <- readLines(path_orderly) + expect_match(txt[[1]], "This is an orderly script") +}) + + +test_that("can create a totally blank orderly report", { + path <- test_prepare_orderly_example(character()) + expect_message( + orderly_new("foo", template = FALSE, root = path), + "Created 'src/foo/orderly.R'") + path_orderly <- file.path(path, "src", "foo", "orderly.R") + expect_true(file.exists(path_orderly)) + expect_equal(readLines(path_orderly), character()) +}) + + +test_that("error if orderly.R exists already", { + path <- test_prepare_orderly_example("data") + expect_error(orderly_new("data", root = path), + "'src/data/orderly.R' already exists") + expect_error(orderly_new("data", force = TRUE, root = path), + "'src/data/orderly.R' already exists") +}) + + +test_that("error if a non-directory file is found in the src dir", { + path <- test_prepare_orderly_example(character()) + file.create(file.path(path, "src", "foo")) + err <- expect_error( + orderly_new("foo", template = FALSE, root = path), + "'src/foo' already exists, but is not a directory") + expect_equal( + err$body, + c(i = "This file really should not be here, you might need to tidy up")) +}) + + +test_that("allow creation of orderly.R in existing dir if force is given", { + path <- test_prepare_orderly_example(character()) + fs::dir_create(file.path(path, "src", "foo")) + file.create(file.path(path, "src", "foo", "bar")) + err <- expect_error( + orderly_new("foo", root = path), + "'src/foo/' already exists and contains files") + expect_equal( + err$body, + c(i = paste("If you want to add an orderly.R to this directory,", + "rerun `orderly_new()` with `force = TRUE`"))) + expect_message( + orderly_new("foo", force = TRUE, root = path), + "Created 'src/foo/orderly.R'") + expect_true(file.exists(file.path(path, "src/foo/orderly.R"))) +}) + + +test_that("allow creation of orderly.R in existing empty dir", { + path <- test_prepare_orderly_example(character()) + fs::dir_create(file.path(path, "src", "foo")) + expect_message( + orderly_new("foo", root = path), + "Created 'src/foo/orderly.R'") + expect_true(file.exists(file.path(path, "src/foo/orderly.R"))) +}) From 5ee272eebc3001a15cdd38f58112b58902b13118 Mon Sep 17 00:00:00 2001 From: Rich FitzJohn Date: Fri, 13 Oct 2023 07:56:11 +0100 Subject: [PATCH 2/4] Add template files --- inst/template/default.R | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 inst/template/default.R diff --git a/inst/template/default.R b/inst/template/default.R new file mode 100644 index 00000000..b4067052 --- /dev/null +++ b/inst/template/default.R @@ -0,0 +1,22 @@ +# This is an orderly script - edit it to suit your needs. You might include +# +# * orderly2::orderly_parameters(): +# declare parameters that your report accepts +# * orderly2::orderly_description(): +# describe your report with friendly names, descriptions and metadata +# * orderly2::orderly_resource(): +# declare files in your source tree that are inputs +# * orderly2::orderly_shared_resource(): +# use files from the root directory's 'shared/' directory +# * orderly2::orderly_dependency(): +# use files from a previously-run packet +# * orderly2::orderly_artefact(): +# declare files that you promise to produce, and describe them +# * orderly2::orderly_strict_mode(): +# enable some optional checks +# +# See the docs for more information: +# https://mrc-ide.github.io/orderly2/reference/ +# +# To generate templates without this header, pass template = FALSE to +# orderly_new(); this header can be safely deleted if you don't need it. From 947c4715254b16fb04fba588da57eaf99d5fc21d Mon Sep 17 00:00:00 2001 From: Rich FitzJohn Date: Fri, 13 Oct 2023 08:49:50 +0100 Subject: [PATCH 3/4] Ensure no template for now --- tests/testthat/test-orderly.R | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/testthat/test-orderly.R b/tests/testthat/test-orderly.R index e6260ec6..a05fc254 100644 --- a/tests/testthat/test-orderly.R +++ b/tests/testthat/test-orderly.R @@ -101,3 +101,12 @@ test_that("allow creation of orderly.R in existing empty dir", { "Created 'src/foo/orderly.R'") expect_true(file.exists(file.path(path, "src/foo/orderly.R"))) }) + + +test_that("disallow template arguments", { + path <- test_prepare_orderly_example(character()) + expect_error( + orderly_new("foo", template = "other", root = path), + "'template' must be 'NULL' or 'FALSE' for now") + expect_false(file.exists(file.path(path, "src/foo"))) +}) From 670c4c2558c636e3c44124ab6e53367628d6d606 Mon Sep 17 00:00:00 2001 From: Wes Hinsley Date: Thu, 19 Oct 2023 09:51:35 +0100 Subject: [PATCH 4/4] Bump description --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 202e48c6..5205d84e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: orderly2 Title: Orderly Next Generation -Version: 1.99.7 +Version: 1.99.8 Authors@R: c(person("Rich", "FitzJohn", role = c("aut", "cre"), email = "rich.fitzjohn@gmail.com"), person("Robert", "Ashton", role = "aut"),