34

I am wondering if there's a way to use install.packages() or other related functions to do the following: only download the sources (i.e. tar.gz files) of the specified packages and all their dependencies into a specified folder (on Windows).

One reason to do this is: say I have a Linux account that is not enabled for internet access. In order to install the packages on the Linux machine, I would first download all the needed sources on my Windows machine, then ftp them over to the Linux machine, and install them on the Linux machine using

  install.packages('/home/me/R/Packages/blah.tar.gz', repos = NULL)
zx8754
  • 52,746
  • 12
  • 114
  • 209
Prasad Chalasani
  • 19,912
  • 7
  • 51
  • 73

4 Answers4

45

I recently had a problem where I wanted to download all dependencies and I've solved it thus:

Say I want all the dependencies and imports of ggplot2 and MASS:

getPackages <- function(packs){
  packages <- unlist(
    tools::package_dependencies(packs, available.packages(),
                         which=c("Depends", "Imports"), recursive=TRUE)
  )
  packages <- union(packs, packages)
  packages
}

packages <- getPackages(c("ggplot2", "MASS"))

I can now download the packages to another directory.

download.packages(packages, destdir="whereyouactuallywantthefiles", 
                  type="source")

From there if you want to make a local repo on your Linux PC, follow the instructions here.

Community
  • 1
  • 1
sebastian-c
  • 15,057
  • 3
  • 47
  • 93
17

Try download.packages(c("xts", "rms"), "c:/TEMP", .....) instead of install.packages(); you can directly give it a target directory in the 2nd argument.

Edit several years later: As stated above on other answers and comments, by now several helper functions have been added to R's tools and utils packages. R 3.4.0 will have tools::CRAN_package_db() to download the top-level PACKAGES.rds file (and of course you could just combine download.file() and readRDS() for that too).

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • That's what I was thinking, but how do you pick up the dependencies too? – Joshua Ulrich Jun 08 '11 at 15:36
  • 1
    Possibly "by hand" using `read.dcf()` and friends to parse the control file (which you hit directly off CRAN, e.g. that's what CRANberries does). Oh, and `cran2deb` will have the logic as it even builds dependencies first. – Dirk Eddelbuettel Jun 08 '11 at 15:39
  • I was hoping that since `install.packages` automagically finds all dependencies, there would be some way to shut off the "install" phase somehow, so that we have the right set of downloaded files. – Prasad Chalasani Jun 08 '11 at 15:42
  • 2
    @PrasadChalasani check source of `install.packages`. There is non exported function `getDependencies`. – Marek Jun 08 '11 at 15:59
  • @Marek - You got there as I was writing my Answer – Gavin Simpson Jun 08 '11 at 16:09
  • 1
    +1 thanks for pointing to `download.packages` -- combined with a tweaked version of `utils:::getDependencies()` should get me there. – Prasad Chalasani Jun 08 '11 at 16:32
16

There are now better options for this in the tools package that comes with base R: package_dependencies(). See for example, the Answer from @sebastian-c and this recent Q&A for a related use-case.


There is an unexported getDependencies() function in the utils package. I haven't studied how it works, but combining that with @Dirk's Answer should get you most of the way there.

Basically though, it appears you use it like:

utils:::getDependencies(pkgs, dependencies, available, lib)

where pkgs is the character vector of packages to install, dependencies is a character vector of types of dependencies (Depends, Enhances etc) that you want, available is the output from available.packages() and lib is the library location for the packages within which dependencies are evaluated.

If you debug install.packages() it is basically doing the getDependencies() step then @Dirk's download.packages() step before it actually starts installing anything.

Community
  • 1
  • 1
Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
  • +1 Thanks! -- I'm tweaking `utils:::getDependencies` to just get me the list of dependent packages and ignore what I've already installed. This plus `download.packages` should do it. – Prasad Chalasani Jun 08 '11 at 16:31
  • @Prasad Isn't that what `getDependencies()` does anyway - at least for me, it only lists packages I don't already have installed in `lib`? – Gavin Simpson Jun 08 '11 at 18:06
  • right, but remember I already have everything installed on my Win machine, and I'm trying to get the list of dependent packages for an existing package, so that I can get their sources, ftp to the Linux machine, and install them there. Once I ftp over all the `tar.gz` files to the Linux machine, I then install them in the appropriate sequence, using `install.packages('blah.tar.gz',...)` so that everything works. – Prasad Chalasani Jun 08 '11 at 18:28
  • 1
    actually figuring out the right order to install the pkgs requires a topological sort of the dependency-graph between packages -- I just put together a fn to do this using the `igraph` pkg. – Prasad Chalasani Jun 08 '11 at 18:29
  • @install.packages() does something similar IIRC there is a `.make()` function called in there somewhere. And yes, sorry, I forgot about the Windows/Linux thing. Might it be easier if you have to do this repeatedly, to set up a local repository of packages on your Linux machine, populated from the Windows machine via ftp, then you can do whatever to get the packages in place on the linux machine and just use `install.packages()` as usual to install them, letting it get the installation priority in order? – Gavin Simpson Jun 08 '11 at 18:46
0

For the completeness: I needed to create a folder "Raw_packages" that includes all packages from p.names (vector of names), their dependencies, dependencies of their dependencies and so on. The purpose was to use this folder to install necessary packages on a PC that is not connected to the Internet. This solution helped: https://www.r-bloggers.com/2017/05/installing-packages-without-internet/ . The most important part is to use recursive = TRUE in tools::package_dependencies().

ArseniyW
  • 13
  • 3
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 13 '23 at 14:58