21
votes

I'm trying to port some packages to an R installation on an offline (Windows) computer.

From CRAN (let's say data.table), the process: 1) download .zip on separate online computer 2) thumb drive -> offline computer 3) install via install.packages("....zip"...) works exactly as expected.

However, this process broke down when I tried to install from GitHub.

When I run install.packages (note: I'm using type="binary" and repos=NULL; type="win.binary" does nothing either) on the zip file (obtained by going to the package page, e.g. https://github.com/Rdatatable/data.table, and using the "Download .zip" function), something goes wrong.

There's no error message (and nothing new from setting verbose=TRUE), and the package folder is added to my library (i.e., I can see the folder named "data.table-master" when I navigate there), but library(data.table) results in the error: "there is no package called data.table". I also noticed that, while the installation from CRAN finishes with "package data.table successfully unpacked and MD5 sums checked", I get no such message from an attempted GitHub installation.

What's going on here? I tried all possible leads in ?install.packages, but given I'm not really getting an error message it's been hard to diagnose what exactly is the issue.

More background: R version is 3.2.0. Hard to copy-paste sessionInfo since that computer's not online, not sure what else may be relevant.

Update:

Given @r2evans' comments below, I also tried using type="source" with install.packages, and this didn't work either (same problem--despite having "data.table-master" folder in one of my .libPaths() addresses, library(data.table) gives the error that there's no such package).

I did get some more output from using verbose=TRUE this time, however:

system (cmd0): C:/PROGRA~1/R/R-32~1.0/bin/x64/R CMD INSTALL

1): succeeded 'C:/PROGRA~1/R/R-32~1.0/bin/x64/R CMD INSTALL -l "C:\Users\Mike\Documents\R\win-library\3.2" "E:/data.table-master.zip"'

5
Aren't packages downloaded from GH in "source" form, not "binary"? - r2evans
@r2evans I'll have to try that out. I can't say I understand the difference well, given both CRAN and GH produce .zip folders. My initial pass was to use type="both" but this is an error when repos="NULL", so I wouldn't have caught this. - MichaelChirico
R typically distributes binary packages in zip files and source packages in tar.gz files, but that does not mean that everything distributed in a zip file is a binary package. Look at another package (not from GH) in both formats and see the difference internally. - r2evans
downloading a zip from github is just a compressed folder with the files in the repo. install_github downloads those and installs from source (which is why you must also have the development tools installed for this to work). perhaps confusingly, when building from windows (binary) you also get a .zip file which can be used to install packages because those files have been through R CMD build/R CMD check, but those are not the same .zip files you git from gethub. Is that the gist of the question? - rawr
@MichaelChirico that will work for binary .zip packages. for source .tar.gz or a folder from github, you need to install r tools or whatever is necessary to build r packages for a particular platform - rawr

5 Answers

20
votes

Let's assume that you have Rtools and devtools on the win machine.

Step 1: Download the source zip.

Step 2: Copy to the win machine and unzip the content there.

Step 3: Run the following code (adjust the path as necessary):

library(devtools)
source <- devtools:::source_pkg("E:/temp/data.table-master")
install(source)

library(data.table)
#loads 1.9.7
9
votes

You can use install_local from devtools to install a Github package with the zip you've downloaded, e.g. :

library("devtools")
install_local(path = "data.table-master.zip")

But you'll have to install all dependancies first.

7
votes

Not sure if this is a solution or a workaround. Given a zip file of the source of an R package directory structure:

On a shell:

~$ unzip data.table-master.zip
## optional renaming
~$ mv data.table-master data.table
## create the new
~$ tar czf data.table.tar.gz data.table

There are likely other tools that allow you to extract and re-archive them in a different format. Since I tend towards shell-level access and control, I tend towards these simple tools.

In R:

install.packages("data.table.tar.gz", type="source", repos=NULL)

(This will not succeed unless all dependencies are already installed.)

3
votes

The following function extracts a GitHub .zip file located at path to a temporary directory and installs the package straight from there, i.e. does not create an interim .tar.gz archive. The function tries to guess the package name but it can also be given through pkg. Temporary files are removed at exit.

This function does not install any dependencies.

install_zip <- function(path,
                        pkg = sub("(-[^-]+)?\\.[^.]+$", "", basename(path))) {
    dir1 <- tempfile()
    dir2 <- file.path(dir1, pkg)
    dir.create(dir2, recursive = TRUE)
    on.exit(unlink(dir1, recursive = TRUE, force = TRUE))
    suppressMessages(unzip(path, exdir = dir2,
                           unzip = getOption("unzip")))
    temp_contents <- dir(dir2)
    if (length(temp_contents) == 1L) {
        dir3 <- file.path(dir2, temp_contents)
        if (file.info(dir3, extra_cols=FALSE)[["isdir"]]) {
            dir2 <- file.path(dir2, pkg)
            file.rename(dir3, dir2)
        }
    }
    install.packages(dir2, repos = NULL, type = "source")
}
2
votes

So I've finally come up with a workaround that works in some cases... but it's admittedly a bit macgyvered. Would love to hear some feedback about how to make this approach work for any package.

Since I have a package where all of the code is in one .R file, I spoofed a package environment for that package and sourced the functions into that environment. Suppose the package is all in test.R:

#add an appropriately named package to the search() path
attach(environment(), name = "package:pkg")

#source the functions
sys.source("test.R", envir = as.environment("package:pkg"))

Voila. I don't know enough about how packages are loaded to say how to do this, for example, if the package has src code in C or something else.