Conversation
`find_package_root_file()` now also finds a package that lives in a
subdirectory of a multi-language repository, e.g. a repository holding an
R package, a Python package and a JavaScript library side by side.
For each directory in the hierarchy, the following are consulted in order:
1. the directory itself, if it contains a `DESCRIPTION` file;
2. the directory given by the `PackagePath:` field of an RStudio project
file (`.Rproj`) in that directory;
3. the new `subdirs` argument, by default `r_package_subdirs()`, i.e.
`pkg-r`, `r`, and `R`.
Pass `subdirs = NULL` for the previous behavior. Criteria are untouched, so
`find_root(is_r_package)` and `criteria$is_r_package` are unaffected.
The `pkg-r`/`r`/`R` convention matches pkgdepends, so that a repository
installable with `pak::pkg_install("owner/repo")` can also be developed
with `devtools::load_all()` from the repository root.
Warns and falls through when a `PackagePath:` field points to a directory
without a `DESCRIPTION` file, and when a directory holds more than one
`.Rproj` file.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
find_package_root_file()now also finds an R package that lives in asubdirectory of a multi-language repository — one holding, say, an R package, a
Python package and a JavaScript library side by side. Today such a repository
can be installed with
pak::pkg_install("owner/repo")(r-lib/pkgdepends#466)but cannot be developed with
devtools::load_all()from the repository root,because
pkgload:::pkg_path()calls this function.Motivating example, posit-dev/shinychat:
Behavior
For each directory in the hierarchy, in order:
DESCRIPTIONmatching^Package:;PackagePath:field of an RStudio project file(
.Rproj) in that directory, if it contains such aDESCRIPTION;subdirsargument — by defaultr_package_subdirs(), i.e.pkg-r,r,R— first match wins.Step 1 always wins, so any repository with a root
DESCRIPTIONresolves exactlyas before. Because the rules are applied at every level of the upward walk,
load_all()also works from a sibling directory such asshinychat/js/.Step 3's candidate list matches pkgdepends, so a repository installable with
pak::pkg_install("owner/repo")resolves the same way locally. Step 2 is theexisting explicit escape hatch:
PackagePath:is already used in the wild fordirectories the convention can't express —
PackagePath: rkeopsingetkeops/keops,
PackagePath: release/missRangerin mayer79/missRanger.Two warnings, per review discussion:
PackagePath:field pointing at a directory with noDESCRIPTIONwarns andfalls through to step 3;
.Rprojfile in a directory warns and skips step 2.Compatibility
subdirs = NULLrestores the behavior of rprojroot 2.1.1 and earlier exactly.subdirs = character()consults.Rprojfiles only.is_r_package,criteria,find_root(),get_root_desc()andis_r_package$find_fileare all untouched, sofind_root(is_r_package)keeps returning the directory that matched.warning().Downstream, this makes
devtools::load_all(),document(),test()andcheck()work in such repositories with no changes to pkgload (verified againstan unmodified pkgload/devtools with this branch installed), and gives
rcmdcheck()the same reach. usethis is the one caller that needs a companionchange:
usethis:::is_package()uses this function's error as a predicate, andr-lib/usethis will be pinned to
find_root(is_r_package, path)so that theactive project — which in a monorepo is the repository root — is not mistaken
for a package. That PR is coming separately.
Notes for review
root_criterion(subdir =)already exists, andis_testthatuses it todescend into
tests/testthat. I didn't build on it becauseget_start_path()rewrites only the starting directory (so
cwd = repo/js/wouldn't resolve)and descends whenever the directory merely exists (so
pkg-r/could outrank aroot
DESCRIPTION). Happy to revisit if you'd rather extend that mechanism.randRare the same directory on case-insensitive filesystems, solocally they are effectively one candidate; GitHub's trees are case-sensitive,
so pkgdepends can distinguish them. Worth documenting if this lands.
subdirsargument carries two modes (NULLvscharacter()). A separateflag for step 2 may read better — happy to change.
Test plan
tests/testthat/test-package-root.Rplus one snapshot: root winsover a subdirectory, subdirectory found from the root and from a sibling,
candidate order,
PackagePath:winning over a subdirectory, both warnings andtheir fallbacks,
subdirs = NULL/character(), emptyDESCRIPTIONnotcounting, no package anywhere, absolute-path passthrough.
pkg-r, keops'PackagePath).Not-found cases use isolated temporary directories so they don't accidentally
find rprojroot's own
DESCRIPTIONunderR CMD check.R CMD check: Status OK. Full existing suite unchanged.feat:commit message.Filed as a draft for discussion of the API shape.