Possible to override the blocking of a package's (re-)installation after it has been required/loaded?

梦想与她 提交于 2019-12-11 03:14:11

问题


Actual question

Is it possible to override the blocking of a package's (re-)installation after it has been required/loaded?

I understand that blocking a "true" re-installation to the same library that the package was loaded from makes perfect sense once the package is in use. But my use case is a bit different

Background

I like the idea of having a "sandbox library" to test own packages. Besides the package(s) to test, those sandbox libraries contain all base packages of a clean base R installation plus some contrib packages necessary in order for my whole package building and testing framework to work (e.g. digest, stringr etc.). However, my framework loads the latter packages from the standard lib and then needs to install them to the sandbox lib - which is blocked. Hence my question if it is possible to override this as I'm not really doing what people had in mind when implementing the block.

Illustration

Specify paths to the two libraries

lib         <- file.path(R.home(), "library")
lib.sandbox <- file.path(tempdir(), "library")

Create sandbox library

dir.create(lib.sandbox, showWarnings=FALSE)

Install a package to the standard library and load it

install.packages("digest", lib=lib)
require("digest", lib.loc=lib)

Then also install it to the sandbox library

> install.packages("digest", lib=lib.sandbox)
Warning: package 'digest' is in use and will not be installed

My framework figures certain stuff out after certain packages that should also be installed to the sandbox lib are loaded, so I can't put the "install-to-sandbox-lib" step before the initial loading step.


回答1:


Here's a general version of what you suggest in your answer. This will unload the package before installing and reload the package from the same location afterward.

install.packages.sandbox <- function(pkgs, lib, repos=getOption("repos"), ...) {
    if (is.null(repos)) 
        stop("Can't install from source. Need package name.")
    pkg.pos <- grep(pkgs, search())
    pkg.path <- searchpaths()[grep(pkgs, searchpaths())]
    in.use <- length(pkg.pos) > 0
    # detach
    if (in.use) do.call(detach, 
                  list(pkg.pos), 
                  envir=.GlobalEnv)
    # install
    utils::install.packages(pkgs, lib, repos, ...)
    # re-attach from original library location
    if (in.use) library(pkgs, 
                  character.only=TRUE, 
                  lib.loc=.libPaths()[sapply(.libPaths(), grepl, pkg.path)])
}



回答2:


Not what I was after conceptually, but a pragmatic workaround: detaching the package right before installing it

Specify paths to the two libraries

lib         <- file.path(R.home(), "library")
lib.sandbox <- file.path(tempdir(), "library")

Create sandbox library

dir.create(lib.sandbox, showWarnings=FALSE)

Install a package to the standard library and load it

install.packages("digest", lib=lib)
require("digest", lib.loc=lib)

Detach package

detach(package:digest)

Then also install it to the sandbox library

> install.packages("digest", lib=lib.sandbox)
trying URL 'http://cran.at.r-project.org/bin/windows/contrib/2.15/digest_0.5.2.zip'
Content type 'application/zip' length 79053 bytes (77 Kb)
opened URL
downloaded 77 Kb

package 'digest' successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\wwa418\AppData\Local\Temp\Rtmp6XSVYq\downloaded_packages


来源:https://stackoverflow.com/questions/13163248/possible-to-override-the-blocking-of-a-packages-re-installation-after-it-has

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!