Skip to content

Commit

Permalink
Rationalize nested projects (#1647)
Browse files Browse the repository at this point in the history
* Rationalize nested projects

Closes #1643

We discourage nested projects, but it is possible, mostly for developers. So we should at least behave correctly in this code path.

Previously, a nested project would put the name of the parent project in DESCRIPTION, which causes a variety of downstream problems.

* NEWS bullet

* Use an undocumented option to bypass the interactive challenge

Useful in tests (replaces the mock) and also to a developer, like @lionel-, who might need to do this often enough to set the option.
  • Loading branch information
jennybc authored Jun 14, 2022
1 parent 0cb76e6 commit 334971a
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 26 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# usethis (development version)

Although nested projects are discouraged, they can be useful in development contexts. `create_package()` now sets the correct package name and returns the correct package path for a package nested inside a project (#1647).

`git_vaccinated()` now treats a path configured as `core.excludesFile` like other user-supplied paths; in particular, any use of the `~/` home directory shortcut is expanded via [`fs::path_expand()`](https://fs.r-lib.org/reference/path_expand.html) (@dpprdan, #1560).

# usethis 2.1.6
Expand Down
12 changes: 5 additions & 7 deletions R/create.R
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ create_package <- function(path,
local_project(path, force = TRUE)

use_directory("R")
use_description(fields, check_name = FALSE, roxygen = roxygen)
use_description_impl_(name, fields, roxygen)
use_namespace(roxygen = roxygen)

if (rstudio) {
Expand Down Expand Up @@ -307,17 +307,15 @@ create_from_github <- function(repo_spec,
invisible(proj_get())
}

# creates a backdoor we can exploit in tests
allow_nested_project <- function() FALSE

challenge_nested_project <- function(path, name) {
if (!possibly_in_proj(path)) {
return(invisible())
}

# we mock this in a few tests, to allow a nested project
if (allow_nested_project()) {
return()
# creates an undocumented backdoor we can exploit when the interactive
# approval is impractical, e.g. in tests
if (isTRUE(getOption("usethis.allow_nested_package", FALSE))) {
return(invisible())
}

ui_line(
Expand Down
4 changes: 4 additions & 0 deletions R/description.R
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ use_description <- function(fields = list(),
check_package_name(name)
}

use_description_impl_(name = name, fields = fields, roxygen = roxygen)
}

use_description_impl_ <- function(name, fields = list(), roxygen = TRUE) {
desc <- build_description(name, roxygen = roxygen, fields = fields)

tf <- withr::local_tempfile(pattern = glue("use_description-{name}-"))
Expand Down
2 changes: 1 addition & 1 deletion R/proj.R
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ proj_get <- function() {
#' adding a `DESCRIPTION` file.
#' @export
proj_set <- function(path = ".", force = FALSE) {
if (dir_exists(path %||% "") && is_in_proj(path)) {
if (!force && dir_exists(path %||% "") && is_in_proj(path)) {
return(invisible(proj_get_()))
}

Expand Down
39 changes: 21 additions & 18 deletions tests/testthat/test-create.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,31 @@ test_that("nested project is disallowed, by default", {

test_that("nested package can be created if user really, really wants to", {
parent <- create_local_package()
with_mock(
# since user can't approve interactively, use the backdoor
allow_nested_project = function() TRUE,
{
child <- create_package(path(parent, "fghijk"))
}
)
expect_true(possibly_in_proj(child))
expect_true(is_package(child))
child_path <- path(parent, "fghijk")

# since user can't approve interactively, use the backdoor
withr::local_options("usethis.allow_nested_package" = TRUE)

child_result <- create_package(child_path)

expect_equal(child_path, child_result)
expect_true(possibly_in_proj(child_path))
expect_true(is_package(child_path))
expect_equal(project_name(child_path), "fghijk")
})

test_that("nested project can be created if user really, really wants to", {
parent <- create_local_project()
with_mock(
# since user can't approve interactively, use the backdoor
allow_nested_project = function() TRUE,
{
child <- create_project(path(parent, "fghijk"))
}
)
expect_true(possibly_in_proj(child))
expect_false(is_package(child))
child_path <- path(parent, "fghijk")

# since user can't approve interactively, use the backdoor
withr::local_options("usethis.allow_nested_package" = TRUE)

child_result <- create_project(child_path)

expect_equal(child_path, child_result)
expect_true(possibly_in_proj(child_path))
expect_equal(project_name(child_path), "fghijk")
})

test_that("can create package in current directory (literally in '.')", {
Expand Down

0 comments on commit 334971a

Please sign in to comment.