r-lib / remotes

Install R packages from GitHub, GitLab, Bitbucket, git, svn repositories, URLs
https://remotes.r-lib.org/
Other
331 stars 152 forks source link

Feature request: install CRAN dependencies before remote depencies #636

Closed bersbersbers closed 2 years ago

bersbersbers commented 3 years ago

devtools::install calls remotes::install_deps which calls remotes::dev_package_deps which calls remotes::combine_remote_deps which returns rbind(remote_deps, cran_deps): https://github.com/r-lib/remotes/blob/90fb6a252e442322482e29fdbdde0bb12be94532/R/deps.R#L157-L163

This means that remote packages are installed before CRAN packages. I'd argue that it would be safer to install CRAN packages first because these can be assumed to be more thoroughly tested than development packages.

Context: We are currently writing a package DESCRIPTION file depending on a GitHub remote. This GitHub remote is badly maintained, so it does not specify all CRAN dependencies it needs during installation. Therefore, installation of our package on a clean R library fails because devtools/remotes tries to install the remote dependency first, even if we include all that GitHub remote's CRAN dependencies into our own DESCRIPTION file. The second call to devtools::install() then works, because all CRAN dependencies have been fulfilled.

So, could CRAN dependencies be installed before remote dependencies? Or is there another workaround that I can choose in the DESCRIPTION file to ensure that a single remote dependency is installed last?

jimhester commented 3 years ago

It is done this way so you don't have to install dependencies twice. e.g. if you have Imports: ggplot2 and 'Remotes: tidyverse/ggplot2' you would not want to first install the CRAN version of ggplot2 and then install the remote version.

One way to handle your situation would be to fork the GitHub remote repository yourself and add the missing dependencies. Then you could contribute the changes back to the repository or alternatively maintain your fork when the upstream version changes.

bersbersbers commented 3 years ago

Thanks, I see!

It is done this way so you don't have to install dependencies twice. e.g. if you have Imports: ggplot2 and 'Remotes: tidyverse/ggplot2' you would not want to first install the CRAN version of ggplot2 and then install the remote version.

For the record, I think the example that you describe is completely handled by these two lines:

https://github.com/r-lib/remotes/blob/90fb6a252e442322482e29fdbdde0bb12be94532/R/deps.R#L160-L161

and that is orthogonal to returning CRAN and remote dependencies in reverse order

rbind(cran_deps, remote_deps)

instead of

https://github.com/r-lib/remotes/blob/90fb6a252e442322482e29fdbdde0bb12be94532/R/deps.R#L163

But the example makes a lot of sense when I have Imports: tidyverse and Remotes: tidyverse/ggplot2 - in that case, one would want to install Remotes: tidyverse/ggplot2 first, I agree.

One way to handle your situation would be to fork the GitHub remote repository yourself and add the missing dependencies. Then you could contribute the changes back to the repository or alternatively maintain your fork when the upstream version changes.

Something like this seems doable, yes. An empty (remote) helper package that includes the missing (CRAN) dependencies and comes before the remote package in question would also work, avoid the need to fork the whole repository.

bersbersbers commented 3 years ago

@jimhester a nice solution I came up with was to simply place a lone DESCRIPTION file into a package_depends subdir of my package, and then use Remote: local::package_depends in the base DESCRIPTION file. However, it seems the local path is relative to the users current working directory when installing, not relative to the package directory (as I had assumed). Is there a way to install a dependency from a subdirectory of the package just being installed?