## called as # .install.winbinary(pkgs = pkgs, lib = lib, contriburl = contriburl, # method = method, available = available, # destdir = destdir, # installWithVers = installWithVers, # dependencies = dependencies) .install.winbinary <- function(pkgs, lib, repos = getOption("repos"), contriburl = contrib.url(repos), method, available = NULL, destdir = NULL, installWithVers = FALSE, dependencies = FALSE) { unpackPkg <- function(pkg, pkgname, lib, installWithVers = FALSE) { ## Create a temporary directory and unpack the zip to it ## then get the real package & version name, copying the ## dir over to the appropriate install dir. lib <- normalizePath(lib) tmpDir <- tempfile(, lib) if (!dir.create(tmpDir)) stop(gettextf("unable to create temporary directory '%s'", normalizePath(tmpDir)), domain = NA, call. = FALSE) cDir <- getwd() on.exit(setwd(cDir), add = TRUE) res <- zip.unpack(pkg, tmpDir) setwd(tmpDir) res <- tools::checkMD5sums(pkgname, file.path(tmpDir, pkgname)) if(!is.na(res) && res) { cat(gettextf("package '%s' successfully unpacked and MD5 sums checked\n", pkgname)) flush.console() } ## Check to see if this is a bundle or a single package if (file.exists("DESCRIPTION")) { ## Bundle conts <- read.dcf("DESCRIPTION", fields="Contains")[1,] if (is.na(conts)) stop("malformed bundle DESCRIPTION file, no Contains field") else pkgs <- strsplit(conts," ")[[1]] ## now check the MD5 sums res <- TRUE for (curPkg in pkgs) res <- res & tools::checkMD5sums(pkgname, file.path(tmpDir, curPkg)) if(!is.na(res) && res) { cat(gettextf("bundle '%s' successfully unpacked and MD5 sums checked\n", pkgname)) flush.console() } } else pkgs <- pkgname for (curPkg in pkgs) { desc <- read.dcf(file.path(curPkg, "DESCRIPTION"), c("Package", "Version", "Type")) if(desc[1, "Type"] %in% "Translation") { fp <- file.path(curPkg, "share", "locale") if(file.exists(fp)) { langs <- dir(fp) for(lang in langs) { path0 <- file.path(fp, lang, "LC_MESSAGES") mos <- dir(path0, full.names = TRUE) path <- file.path(R.home("share"), "locale", lang, "LC_MESSAGES") if(!file.exists(path)) if(!dir.create(path, FALSE, TRUE)) warning(gettextf("failed to create '%s'", path), domain = NA) res <- file.copy(mos, path, overwrite = TRUE) if(any(!res)) warning(gettextf("failed to create '%s'", paste(mos[!res], collapse=",")), domain = NA) } } fp <- file.path(curPkg, "library") if(file.exists(fp)) { spkgs <- dir(fp) for(spkg in spkgs) { langs <- dir(file.path(fp, spkg, "po")) for(lang in langs) { path0 <- file.path(fp, spkg, "po", lang, "LC_MESSAGES") mos <- dir(path0, full.names = TRUE) path <- file.path(R.home(), "library", spkg, "po", lang, "LC_MESSAGES") if(!file.exists(path)) if(!dir.create(path, FALSE, TRUE)) warning(gettextf("failed to create '%s'", path), domain = NA) res <- file.copy(mos, path, overwrite = TRUE) if(any(!res)) warning(gettextf("failed to create '%s'", paste(mos[!res], collapse=",")), domain = NA) } } } } else { if (installWithVers) { instPath <- file.path(lib, paste(desc[1,1], desc[1,2], sep="_")) } else instPath <- file.path(lib, desc[1,1]) ## If the package is already installed w/ this ## instName, remove it. If it isn't there, the unlink call will ## still return success. ret <- unlink(instPath, recursive=TRUE) if (ret == 0) { ## Move the new package to the install lib and ## remove our temp dir ret <- file.rename(file.path(tmpDir, curPkg), instPath) if(!ret) warning(gettextf("unable to move temporary installation '%s' to '%s'", normalizePath(file.path(tmpDir, curPkg)), normalizePath(instPath)), domain = NA, call. = FALSE, immediate. = TRUE) } else { warning(gettextf("cannot remove prior installation of package '%s'", curPkg), domain = NA, call. = FALSE, immediate. = TRUE) } } } setwd(cDir) unlink(tmpDir, recursive=TRUE) } if(!length(pkgs)) return(invisible()) oneLib <- length(lib) == 1 ## look for packages/bundles in use. pkgnames <- basename(pkgs) pkgnames <- sub("\\.zip$", "", pkgnames) pkgnames <- sub("_[0-9.-]+$", "", pkgnames) ## there is no guarantee we have got the package name right: ## foo.zip might contain package bar or Foo or FOO or .... ## but we can't tell without trying to unpack it. inuse <- search() inuse <- sub("^package:", "", inuse[grep("^package:", inuse)]) if(!is.null(contriburl)) { # otherwise no info on bundles if(is.null(available)) available <- available.packages(contriburl = contriburl, method = method) bundles <- .find_bundles(available) for(bundle in names(bundles)) if(any(bundles[[bundle]] %in% inuse)) inuse <- c(inuse, bundle) } inuse <- pkgnames %in% inuse if(any(inuse)) { warning(sprintf(ngettext(sum(inuse), "package '%s' is in use and will not be installed", "packages '%s' are in use and will not be installed"), paste(pkgnames[inuse], collapse=", ")), call. = FALSE, domain = NA, immediate. = TRUE) pkgs <- pkgs[!inuse] pkgnames <- pkgnames[!inuse] } if(is.null(contriburl)) { for(i in seq(along=pkgs)) unpackPkg(pkgs[i], pkgnames[i], lib, installWithVers) link.html.help(verbose=TRUE) return(invisible()) } tmpd <- destdir nonlocalcran <- length(grep("^file:", contriburl)) < length(contriburl) if(is.null(destdir) && nonlocalcran) { tmpd <- file.path(tempdir(), "downloaded_packages") if (!file.exists(tmpd) && !dir.create(tmpd)) stop(gettextf("unable to create temporary directory '%s'", normalizePath(tmpd)), domain = NA) } for(bundle in names(bundles)) pkgs[ pkgs %in% bundles[[bundle]] ] <- bundle depends <- is.character(dependencies) || (is.logical(dependencies) && dependencies) if(depends && is.logical(dependencies)) dependencies <- c("Depends", "Imports", "Suggests") if(depends && !oneLib) { warning("Do not know which element of 'lib' to install dependencies into\nskipping dependencies") depends <- FALSE } if(depends) { # check for dependencies, recursively p0 <- p1 <- unique(pkgs) # this is ok, as 1 lib only have <- .packages(all.available = TRUE) repeat { if(any(miss <- ! p1 %in% row.names(available))) { cat(sprintf(ngettext(sum(miss), "dependency '%s' is not available", "dependencies '%s' are not available"), paste(sQuote(p1[miss]), sep=", ")), "\n\n", sep ="") flush.console() } p1 <- p1[!miss] deps <- as.vector(available[p1, dependencies]) deps <- .clean_up_dependencies(deps, available) if(!length(deps)) break toadd <- deps[! deps %in% c("R", have, pkgs)] if(length(toadd) == 0) break pkgs <- c(toadd, pkgs) p1 <- toadd } for(bundle in names(bundles)) pkgs[ pkgs %in% bundles[[bundle]] ] <- bundle pkgs <- unique(pkgs) pkgs <- pkgs[pkgs %in% row.names(available)] if(length(pkgs) > length(p0)) { added <- setdiff(pkgs, p0) cat(ngettext(length(added), "also installing the dependency ", "also installing the dependencies "), paste(sQuote(added), collapse=", "), "\n\n", sep="") flush.console() pkgnames <- pkgs # not zips, now } } foundpkgs <- download.packages(pkgs, destdir = tmpd, available = available, contriburl = contriburl, method = method, type = "win.binary") if(length(foundpkgs)) { update <- unique(cbind(pkgs, lib)) colnames(update) <- c("Package", "LibPath") for(lib in unique(update[,"LibPath"])) { oklib <- lib==update[,"LibPath"] for(p in update[oklib, "Package"]) { okp <- p == foundpkgs[, 1] if(any(okp)) unpackPkg(foundpkgs[okp, 2], foundpkgs[okp, 1], lib, installWithVers) } } if(!is.null(tmpd) && is.null(destdir)) ## tends to be a long path on Windows cat("\n", gettextf("The downloaded packages are in\n\t%s", normalizePath(tmpd)), "\n", sep = "") link.html.help(verbose = TRUE) } else if(!is.null(tmpd) && is.null(destdir)) unlink(tmpd, TRUE) invisible() } menuInstallPkgs <- function(type = getOption("pkgType")) { install.packages(NULL, .libPaths()[1], dependencies=TRUE, type = type) } menuInstallLocal <- function() { install.packages(choose.files('',filters=Filters[c('zip','All'),]), .libPaths()[1], repos = NULL) } ### the following function supports .install.winbinaries() zip.unpack <- function(zipname, dest) { if(file.exists(zipname)) { if((unzip <- getOption("unzip")) != "internal") { system(paste(unzip, "-oq", zipname, "-d", dest), show = FALSE, invisible = TRUE) } else { .Internal(int.unzip(zipname, NULL, dest)) } } else stop(gettextf("zipfile '%s' not found", zipname), domain = NA) }