blob: 5f0ed876f2b865c84ca23af996ce815eedfbbe51 [file] [log] [blame]
# File src/library/utils/R/packageStatus.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1995-2017 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available at
# https://www.R-project.org/Licenses/
packageStatus <- function(lib.loc = NULL, repositories = NULL, method,
type = getOption("pkgType"), ...)
{
newestVersion <- function(x)
{
vers <- package_version(x)
max <- vers[1L]
for (i in seq_along(vers)) if (max < vers[i]) max <- vers[i]
which.max(vers == max)
}
if(is.null(lib.loc))
lib.loc <- .libPaths()
if(is.null(repositories))
repositories <- contrib.url(getOption("repos"), type = type)
## convert character matrices to dataframes
char2df <- function(x)
{
y <- list()
for(k in 1L:ncol(x)) y[[k]] <- x[,k]
attr(y, "names") <- colnames(x)
attr(y, "row.names") <- make.unique(y[[1L]])
class(y) <- "data.frame"
y
}
y <- char2df(installed.packages(lib.loc = lib.loc, ...))
y[, "Status"] <- "ok"
z <- available.packages(repositories, method, ...)
## only consider the newest version of each package
## in the first repository where it appears
ztab <- table(z[,"Package"])
for(pkg in names(ztab)[ztab>1]){
zrow <- which(z[,"Package"] == pkg)
znewest <- newestVersion(z[zrow,"Version"])
## and now exclude everything but the newest
z <- z[-zrow[-znewest],]
}
z <- cbind(z, Status = "not installed")
z[z[,"Package"] %in% y$Package, "Status"] <- "installed"
z <- char2df(z)
attr(z, "row.names") <- z$Package
for(k in 1L:nrow(y)){
pkg <- y[k, "Package"]
if(pkg %in% z$Package) {
if(package_version(y[k, "Version"]) <
package_version(z[pkg, "Version"])) {
y[k, "Status"] <- "upgrade"
}
} else {
if(!(y[k, "Priority"] %in% "base")) y[k, "Status"] <- "unavailable"
}
}
y$LibPath <- factor(y$LibPath, levels=lib.loc)
y$Status <- factor(y$Status, levels=c("ok", "upgrade", "unavailable"))
z$Repository <- factor(z$Repository, levels=repositories)
z$Status <- factor(z$Status, levels=c("installed", "not installed"))
retval <- list(inst=y, avail=z)
class(retval) <- "packageStatus"
retval
}
summary.packageStatus <- function(object, ...)
{
Libs <- levels(object$inst$LibPath)
Repos <- levels(object$avail$Repository)
Libs <- lapply(split(object$inst, object$inst$LibPath),
function(x) tapply(x$Package, x$Status,
function(x) sort(as.character(x))))
Repos <- lapply(split(object$avail, object$avail$Repository),
function(x) tapply(x$Package, x$Status,
function(x) sort(as.character(x))))
object$Libs <- Libs
object$Repos <- Repos
class(object) <- c("summary.packageStatus", "packageStatus")
object
}
print.summary.packageStatus <- function(x, ...)
{
cat("\nInstalled packages:\n")
cat( "-------------------\n")
for(k in seq_along(x$Libs)) {
cat("\n*** Library ", names(x$Libs)[k], "\n", sep = "")
print(x$Libs[[k]], ...)
}
cat("\n\nAvailable packages:\n")
cat( "-------------------\n")
cat("(each package appears only once)\n")
for(k in seq_along(x$Repos)){
cat("\n*** Repository ", names(x$Repos)[k], "\n", sep = "")
print(x$Repos[[k]], ...)
}
invisible(x)
}
print.packageStatus <- function(x, ...)
{
cat("Number of installed packages:\n")
print(table(x$inst$LibPath, x$inst$Status), ...)
cat("\nNumber of available packages (each package counted only once):\n")
print(table(x$avail$Repository, x$avail$Status), ...)
invisible(x)
}
update.packageStatus <-
function(object, lib.loc=levels(object$inst$LibPath),
repositories=levels(object$avail$Repository),
...)
{
packageStatus(lib.loc=lib.loc, repositories=repositories)
}
upgrade <- function(object, ...)
UseMethod("upgrade")
upgrade.packageStatus <- function(object, ask = TRUE, ...)
{
update <- NULL
old <- which(object$inst$Status == "upgrade")
if(length(old) == 0L) {
cat("Nothing to do!\n")
return(invisible())
}
askprint <- function(x)
write.table(x, row.names = FALSE, col.names = FALSE, quote = FALSE,
sep = " at ")
haveasked <- character()
if(ask) {
for(k in old) {
pkg <- object$inst[k, "Package"]
tmpstring <- paste(pkg, as.character(object$inst[k, "LibPath"]))
if(tmpstring %in% haveasked) next
haveasked <- c(haveasked, tmpstring)
cat("\n")
cat(pkg, ":\n")
askprint(object$inst[k,c("Version", "LibPath")])
askprint(object$avail[pkg, c("Version", "Repository")])
answer <- askYesNo("Update?")
if(is.na(answer)) {
cat("cancelled by user\n")
return(invisible())
}
if(isTRUE(answer))
update <-
rbind(update,
c(pkg, as.character(object$inst[k, "LibPath"]),
as.character(object$avail[pkg, "Repository"])))
}
} else {
pkgs <- object$inst[ ,"Package"]
update <- cbind(pkgs, as.character(object$inst[ , "LibPath"]),
as.character(object$avail[pkgs, "Repository"]))
update <- update[old, , drop = FALSE]
}
if(length(update)) {
for(repo in unique(update[,3])) {
ok <- update[, 3] == repo
install.packages(update[ok, 1], update[ok, 2], contriburl = repo,
...)
}
}
}