2

I have been given access to a beefy machine on which to run a large simulation. I have developed the code in an RStudio project with renv. Renv makes a local copy of all the packages and stores versions thereof in a lock file.

The target machine (which runs Windows) does not have access to the internet. I have copied the project file, the code files, the renv folder (which includes all the local copies of the packages, the lock file, and the .RProfile file, to a folder on the target machine.

When I open the project on the target machine, the .RProfile executes source("renv/activate.R"). However, this fails to load the projects, instead giving me the following message

The following package(s) are missing their DESCRIPTION files:

... Long list of packages ... 

These may be left over from a prior, failed installation attempt.
Consider removing or re-installing these packages.

Trouble is I can't reinstall them since this machine does not have access to the internet. I could manually go through each package and download the binaries on my work machine, then transfer them over to the target machine, then install them one by one, but this seems like a very painful thing to do.

Is there a way for me to convince renv, or R itself, to just use the packages in the local renv folder?

Chechy Levas
  • 2,206
  • 1
  • 13
  • 28
  • 1
    I think I already have a partial answer. The local copies of the packages in the renv folder are just shortcuts to elsewhere. So what I have copied over is just empty folders. – Chechy Levas Jun 28 '21 at 15:58
  • Actually I have no idea what I am looking at. Each package folder has the shortcut icon in Windows, but it's type is listed as "File Folder" and when I tried to copy it, it only copes over empty folders. – Chechy Levas Jun 28 '21 at 16:06
  • I haven't used `renv` before (but just watched this [lecture](https://youtu.be/yjlEbIDevOs)), but if it stores the packages locally, then, you might could try to figure out how to `install.packages` from [the local source](https://stackoverflow.com/questions/1474081/how-do-i-install-an-r-package-from-source). Another option, not using `renv`, would be to use [Docker](https://colinfay.me/docker-r-reproducibility/) to move packages, which you can do [without internet](https://stackoverflow.com/questions/48125169/how-run-docker-images-without-connect-to-internet). – AndrewGB Jun 28 '21 at 16:15
  • I like the docker idea, but would have to convince the IT overlords to give me docker. The problem with the renv storage is that each package is somehow stored as a shortcut/folder to itself, such that when you try to copy it somewhere, all you get is an empty folder. – Chechy Levas Jun 28 '21 at 16:21
  • I was thinking more of copying the actual folders for the packages that are needed (moving them to the typical package folder on the new machine), then update the path in `renv` to almost kind of trick it. But maybe it's not possible to change those shortcut paths (& perhaps too complicated). – AndrewGB Jun 28 '21 at 16:28

2 Answers2

3

From the Cache section of https://rstudio.github.io/renv/articles/renv.html:

When using renv with the global package cache, the project library is instead formed as a directory of symlinks (or, on Windows, junction points) into the renv global package cache. Hence, while each renv project is isolated from other projects on your system, they can still re-use the same installed packages as required.

I think that implies trying to copy the renv folder means copying those junction points (which are something like shortcuts / symlinks), not the actual underlying folder.

It looks like you already have a solution, but another option would be to call renv::isolate() to ensure that your project doesn't link to packages within the global cache, and instead just maintains an isolated library directly.

Kevin Ushey
  • 20,530
  • 5
  • 56
  • 88
0

In the end I just wrote an small script to copy the files over.

sourceFolder = "some/path"
targetFolder = "some/other/path"
subFolders = list.files(sourceFolder)
for (i in seq_along(subFolders)) {
    subFolder = subFolders[i]
    file.copy(
        from = paste0(sourceFolder, subFolder),
        to = targetFolder,
        overwrite = TRUE,
        recursive = TRUE
    )
    paste(subFolder) |> message()
}
Chechy Levas
  • 2,206
  • 1
  • 13
  • 28