require("tools", quiet = TRUE)
check_log_URL <- "http://www.R-project.org/nosvn/R.check/"
r_patched_is_prelease <- FALSE
r_p_o_p <- if(r_patched_is_prelease) "r-prerelease" else "r-patched"
## Adjust as needed, in particular for prerelease stages.
R_flavors_db <- local({
## modified BEGIN
db <- c("Flavor|OS_type|CPU_type|OS_kind|CPU_info",
paste("R-2.5-macosx",
"R 2.5 branch", "Mac OS X", "universal",
"Mac OS X 10.4.10",
"Mac Pro",
sep = "|"),
paste("R-2.6-macosx",
"R 2.6 branch", "Mac OS X", "universal",
"Mac OS X 10.4.10",
"Mac Pro",
sep = "|")
)
## modified END
con <- textConnection(db)
db <- read.table(con, header = TRUE, sep = "|")
close(con)
db
})
check_summarize_flavor <-
function(dir = file.path("~", "tmp", "R.check"), flavor = "r-devel",
check_dirs_root = file.path(dir, flavor, "PKGS"))
{
if(!file_test("-d", check_dirs_root)) return()
get_description_fields_as_utf8 <-
function(dfile, fields = c("Version", "Priority", "Maintainer"))
{
lc_ctype <- Sys.getlocale("LC_CTYPE")
Sys.setlocale("LC_CTYPE", "en_US.utf8")
on.exit(Sys.setlocale("LC_CTYPE", lc_ctype))
meta <- if(file.exists(dfile))
try(read.dcf(dfile,
fields = unique(c(fields, "Encoding")))[1, ],
silent = TRUE)
else
NULL
## What if this fails? Grr ...
if(inherits(meta, "try-error") || is.null(meta))
return(rep.int("", length(fields)))
else if(any(i <- !is.na(meta) & is.na(nchar(meta, "c")))) {
## Try converting to UTF-8.
from <- meta["Encoding"]
if(is.na(from)) from <- "latin1"
meta[i] <- iconv(meta[i], from, "utf8")
}
meta[fields]
}
check_dirs <- list.files(path = check_dirs_root,
pattern = "\\.Rcheck", full = TRUE)
results <- matrix(character(), nr = 0, nc = 5)
fields <- c("Version", "Priority", "Maintainer")
## (Want Package, Version, Priority, Maintainer, Status.)
for(check_dir in check_dirs) {
dfile <- file.path(check_dir, "00package.dcf")
##
", paste("Last updated on", format(Sys.time())), "
", "Results for installing and checking packages", "using the three current flavors of R", "on systems running Debian GNU/Linux testing", "(r-devel ix86: AMD Athlon(tm) XP 2400+ (2GHz),", "r-devel x86_64: Dual Core AMD Opteron(tm) Processor 280,", sprintf("%s/r-release:", r_p_o_p), "Intel(R) Pentium(R) 4 CPU 2.66GHz),", "MacOS X 10.4.7 (iMac, Intel Core Duo 1.83GHz),", "and Windows Server 2003 SP1 (AMD Athlon64 X2 5000+).", "
"), out) print(xtable(tab, align = c("r", rep("l", 3), rep("r", 4)), digits = rep(0, NCOL(tab) + 1)), type = "html", file = out, append = TRUE) writeLines("
Results per package:", out) ## Older versions of package xtable needed post-processing as ## suggested by Uwe Ligges, reducing checkSummary.html from 370 kB ## to 120 kB ... ## lines <- capture.output(print(xtable(summary), type = "html"), ## file = NULL) ## lines <- gsub(" *", " ", lines) ## lines <- gsub(" align=\"left\"", "", lines) ## writeLines(lines, out) ## (Oh no, why does print.xtable() want to write to a *file*?) ## Seems that this is no longer necessary in 1.2.995 or better, so ## let's revert to the original code. print(xtable(summary), type = "html", file = out, append = TRUE) writeLines(c("",
"Results with [*] or [**] were obtained by checking",
"with ",
paste("Last updated on", format(Sys.time())),
" ",
paste("Timings for installing and checking packages",
"using the current development version of R",
"on an AMD Athlon(tm) XP 2400+ (2GHz) system",
"running Debian GNU/Linux testing."),
" ",
paste("Total CPU seconds: ", sum(db$Total),
" (", round(sum(db$Total) / 3600, 2),
" hours)", sep = ""),
" "),
out)
print(xtable(db), type = "html", file = out, append = TRUE)
writeLines(c("", ""), out)
close(out)
}
check_timings_summary <-
function(dir = file.path("~", "tmp", "R.check"))
{
## Overall timings for all flavors.
R_flavors <- row.names(R_flavors_db)
timings <- vector("list", length = length(R_flavors))
names(timings) <- R_flavors
for(flavor in R_flavors)
timings[[flavor]] <- check_timings(dir, flavor)
timings <- timings[sapply(timings, NROW) > 0]
if(!length(timings)) return(NULL)
out <- sapply(timings,
function(x) colSums(x[, c("Check", "Install")],
na.rm = TRUE))
out <- rbind(out, Total = colSums(out))
t(out)
}
write_check_log_as_HTML <-
function(log, out = "")
{
if(out == "")
out <- stdout()
else if(is.character(out)) {
out <- file(out, "wt")
on.exit(close(out))
}
if(!inherits(out, "connection"))
stop("'out' must be a character string or connection")
lines <- readLines(log)[-1]
## The first line says
## using log directory '/var/www/R.check/......"
## which is really useless ...
## HTML escapes:
lines <- gsub("&", "&", lines)
lines <- gsub("<", "<", lines)
lines <- gsub(">", ">", lines)
## Fancy stuff:
ind <- grep("^\\*\\*? ", lines)
lines[ind] <- sub("\\.\\.\\. (WARNING|ERROR)",
"... \\1",
lines[ind])
## ind <- grep("^\\*\\*? (.*)\\.\\.\\. OK$", lines)
## lines[ind] <- sub("^(\\*\\*?) (.*)",
## "\\1 \\2",
## lines[ind])
## Convert pointers to install.log:
ind <- grep("^See 'http://.*' for details.$", lines)
if(length(ind))
lines[ind] <- sub("^See '(.*)' for details.$",
"See \\1 for details.",
lines[ind])
ind <- regexpr("^\\*\\*? ", lines) > -1
pos <- c((which(ind) - 1)[-1], length(lines))
lines[pos] <- sprintf("%s", lines[pos])
pos <- which(!ind) - 1
if(any(pos))
lines[pos] <- sprintf("%s--install=fake
",
"and --install=no
, respectively.",
"",
""),
out)
close(out)
}
check_summary_table <-
function(summary)
{
## Create an executive summary of the summaries.
pos <- grep("^r-", names(summary))
out <- matrix(0, length(pos), 4)
for(i in seq_along(pos)) {
status <- summary[[pos[i]]]
totals <- c(length(grep("OK( \\[\\*{1,2}\\])?$", status)),
length(grep("WARN( \\[\\*{1,2}\\])?$", status)),
length(grep("ERROR( \\[\\*{1,2}\\])?$", status)))
out[i, ] <- c(totals, sum(totals))
}
dimnames(out) <- list(names(summary)[pos],
c("OK", "WARN", "ERROR", "Total"))
out
}
get_timings_from_timings_files <-
function(tfile)
{
timings_files <- c(tfile, paste(tfile, "prev", sep = "."))
timings_files <- timings_files[file.exists(timings_files)]
if(!length(timings_files)) return()
x <- paste(readLines(timings_files[1]), collapse = "\n")
## Safeguard against possibly incomplete entries.
x <- sub("(.*swaps(\n|$))*.*", "\\1", x)
x <- paste(unlist(strsplit(x, "swaps(\n|$)")), "swaps", sep = "")
## Eliminate 'Command exited with non-zero ...'
bad <- rep("OK", length(x))
bad[grep(": Command exited[^\n]*\n", x)] <- "ERROR"
x <- sub(": Command exited[^\n]*\n", ": ", x)
x <- sub("([0-9])system .*", "\\1", x)
x <- sub("([0-9])user ", "\\1 ", x)
x <- sub(": ", " ", x)
x <- read.table(textConnection(c("User System", x)))
x <- cbind(Total = rowSums(x), x, Status = bad)
x <- x[order(x$Total, decreasing = TRUE), ]
x
}
check_timings <-
function(dir = file.path("~", "tmp", "R.check"),
flavor = "r-devel-linux-ix86")
{
t_c <- get_timings_from_timings_files(file.path(dir, flavor,
"time_c.out"))
t_i <- get_timings_from_timings_files(file.path(dir, flavor,
"time_i.out"))
if(is.null(t_i) || is.null(t_c)) return()
db <- merge(t_c[c("Total", "Status")], t_i["Total"],
by = 0, all = TRUE)
db$Total <- rowSums(db[, c("Total.x", "Total.y")], na.rm = TRUE)
out <- db[, c("Total", "Total.x", "Total.y", "Status")]
names(out) <- c("Total", "Check", "Install", "Status")
rownames(out) <- db$Row.names
## Add information on check mode. If possible, use the summary.
summary_files <- file.path(dir, flavor,
c("summary.rds", "summary.rds.prev"))
summary_files <- summary_files[file.exists(summary_files)]
if(length(summary_files)) {
s <- .readRDS(summary_files[1])
s <- as.data.frame(s[, -1], row.names = s[, 1])
## CRAN Daily Package Check Timings
",
"
", lines[pos])
## Handle list items.
count <- rep(0, length(lines))
count[grep("^\\* ", lines)] <- 1
count[grep("^\\*\\* ", lines)] <- 2
pos <- which(count > 0)
## Need to start a new where diff(count[pos]) > 0, and to close
## it where diff(count[pos]) < 0. Substitute the
")
## Make things look nicer: ensure gray bullets as well.
## Maybe we could also do the first substitution later and
## match for
## "^")
ind <- diff(count[pos]) < 0
lines[pos[ind]] <- paste(lines[pos[ind]], "\n
")
if(sum(diff(count[pos])) > 0)
lines <- c(lines, ""),
out)
## Body.
cat(lines, sep = "\n", file = out)
## Footer.
writeLines(c("",
""),
out)
}
check_results_diff_db <-
function(dir)
{
## Assume that we know that both check.csv.prev and check.csv exist
## in dir.
x <- read.csv(file.path(dir, "check.csv.prev"),
colClasses = "character")
x <- x[names(x) != "Maintainer"]
y <- read.csv(file.path(dir, "check.csv"),
colClasses = "character")
y <- y[names(y) != "Maintainer"]
z <- merge(x, y, by = 1, all = TRUE)
row.names(z) <- z$Package
z
}
check_results_diffs <-
function(dir) {
db <- check_results_diff_db(dir)
db <- db[, c("Version.x", "Status.x", "Version.y", "Status.y")]
## Show packages with one status missing (removed or added) as
## status change only.
is_na_x <- is.na(db$Status.x)
is_na_y <- is.na(db$Status.y)
isc <- (is_na_x | is_na_y | (db$Status.x != db$Status.y))
# Status change.
ivc <- (!is_na_x & !is_na_y & (db$Version.x != db$Version.y))
# Version change.
names(db) <- c("V_Old", "S_Old", "V_New", "S_New")
db <- cbind("S" = ifelse(isc, "*", ""),
"V" = ifelse(ivc, "*", ""),
db)
db[c(which(isc & !ivc), which(isc & ivc), which(!isc & ivc)),
c("S", "V", "S_Old", "S_New", "V_Old", "V_New")]
}