# File src/library/tools/R/admin.R # Part of the R package, http://www.R-project.org # # 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 # http://www.r-project.org/Licenses/ ### * .install_package_description .install_package_description <- function(dir, outDir) { ## Function for taking the DESCRIPTION package meta-information, ## checking/validating it, and installing it with the 'Built:' ## field added. Note that from 1.7.0 on, packages without ## compiled code are not marked as being from any platform. ## Check first. Note that this also calls .read_description(), but ## .check_package_description() currently really needs to know the ## path to the DESCRIPTION file, and returns an object with check ## results and not the package metadata ... ok <- .check_package_description(file.path(dir, "DESCRIPTION")) if(any(as.integer(sapply(ok, length))) > 0) { stop(paste(gettext("Invalid DESCRIPTION file") , paste(.capture_output_from_print(ok), collapse = "\n"), sep = "\n\n"), domain = NA, call. = FALSE) } db <- .read_description(file.path(dir, "DESCRIPTION")) ## should not have a Built: field, so ignore it if it is there nm <- names(db) if("Built" %in% nm) { db <- db[-match("Built", nm)] warning(gettextf("*** someone has corrupted the Built field in package '%s' ***", db["Package"]), domain = NA, call. = FALSE) } OS <- Sys.getenv("R_OSTYPE") OStype <- if(nzchar(OS) && OS == "windows") "i386-pc-mingw32" else R.version$platform if (length(grep("-apple-darwin",R.version$platform)) > 0 && nzchar(Sys.getenv("R_ARCH"))) OStype <- sub(".*-apple-darwin", "universal-apple-darwin", OStype) Built <- paste("R ", paste(R.version[c("major", "minor")], collapse = "."), "; ", if(file_test("-d", file.path(dir, "src"))) OStype else "", "; ", ## Prefer date in ISO 8601 format. ## Could also use ## format(Sys.time(), "%a %b %d %X %Y") Sys.time(), "; ", .OStype(), sep = "") ## At some point of time, we had: ## We must not split the Built: field across lines. ## Not sure if this is still true. If not, the following could be ## simplified to ## db["Built"] <- Built ## write.dcf(rbind(db), file.path(outDir, "DESCRIPTION")) outConn <- file(file.path(outDir, "DESCRIPTION"), open = "w") write.dcf(rbind(db), outConn) writeLines(paste("Built", Built, sep = ": "), outConn) close(outConn) db["Built"] <- Built outMetaDir <- file.path(outDir, "Meta") if(!file_test("-d", outMetaDir) && !dir.create(outMetaDir)) stop(gettextf("cannot open directory '%s'", outMetaDir), domain = NA) saveInfo <- .split_description(db) .saveRDS(saveInfo, file.path(outMetaDir, "package.rds")) invisible() } ### * .split_description .split_description <- function(db, verbose = FALSE) { if(!is.na(Built <- db["Built"])) { Built <- as.list(strsplit(Built, "; ")[[1]]) if(length(Built) != 4) { warning(gettextf("*** someone has corrupted the Built field in package '%s' ***", db["Package"]), domain = NA, call. = FALSE) Built <- NULL } else { names(Built) <- c("R", "Platform", "Date", "OStype") Built[["R"]] <- R_system_version(sub("^R ([0-9.]+)", "\\1", Built[["R"]])) } } else Built <- NULL ## might perhaps have multiple entries Depends <- .split_dependencies(db[names(db) %in% "Depends"]) if("R" %in% names(Depends)) { if(verbose && sum("R" == names(Depends)) > 1) { entries <- Depends["R" == names(Depends)] entries <- lapply(entries, function(x) paste(lapply(x, as.character), collapse="") ) message("WARNING: 'Depends' entry has multiple dependencies: ", paste(unlist(entries), collapse=', '), "\n\tonly the first will be used") } Rdeps <- Depends[["R", exact = TRUE]] # the first one Depends <- Depends[names(Depends) != "R"] ## several packages have 'Depends: R', which is a noop. if(verbose && length(Rdeps) == 1) message("WARNING: omitting pointless dependence on 'R' without a version requirement") if(length(Rdeps) <= 1) Rdeps <- NULL } else Rdeps <- NULL Rdeps <- as.vector(Rdeps) Suggests <- .split_dependencies(db[names(db) %in% "Suggests"]) Imports <- .split_dependencies(db[names(db) %in% "Imports"]) structure(list(DESCRIPTION = db, Built = Built, Rdepends = Rdeps, Depends = Depends, Suggests = Suggests, Imports = Imports), class = "packageDescription2") } ### * .vinstall_package_descriptions_as_RDS .vinstall_package_descriptions_as_RDS <- function(dir, packages) { ## For the given packages installed in @file{dir}, install their ## DESCRIPTION package metadata as R metadata. ## Really only useful for base packages under Unix. ## See @file{src/library/Makefile.in}. for(p in unlist(strsplit(packages, "[[:space:]]+"))) { meta_dir <- file.path(dir, p, "Meta") if(!file_test("-d", meta_dir) && !dir.create(meta_dir)) stop(gettextf("cannot open directory '%s'", meta_dir)) package_info_dcf_file <- file.path(dir, p, "DESCRIPTION") package_info_rds_file <- file.path(meta_dir, "package.rds") if(file_test("-nt", package_info_rds_file, package_info_dcf_file)) next .saveRDS(.split_description(.read_description(package_info_dcf_file)), package_info_rds_file) } invisible() } ### * .update_package_rds .update_package_rds <- function(lib.loc = NULL) { ## rebuild the dumped package descriptions for all packages in lib.loc if (is.null(lib.loc)) lib.loc <- .libPaths() lib.loc <- lib.loc[file.exists(lib.loc)] for (lib in lib.loc) { a <- list.files(lib, all.files = FALSE, full.names = TRUE) for (nam in a) { dfile <- file.path(nam, "DESCRIPTION") if (file.exists(dfile)) { print(nam) .install_package_description(nam, nam) } } } } ### * .install_package_code_files .install_package_code_files <- function(dir, outDir) { if(!file_test("-d", dir)) stop(gettextf("directory '%s' does not exist", dir), domain = NA) dir <- file_path_as_absolute(dir) ## Attempt to set the LC_COLLATE locale to 'C' to turn off locale ## specific sorting. curLocale <- Sys.getlocale("LC_COLLATE") on.exit(Sys.setlocale("LC_COLLATE", curLocale), add = TRUE) ## (Guaranteed to work as per the Sys.setlocale() docs.) lccollate <- "C" if(Sys.setlocale("LC_COLLATE", lccollate) != lccollate) { ## ## I don't think we can give an error here. ## It may be the case that Sys.setlocale() fails because the "OS ## reports request cannot be honored" (src/main/platform.c), in ## which case we should still proceed ... warning("cannot turn off locale-specific sorting via LC_COLLATE") ## } ## We definitely need a valid DESCRIPTION file. db <- .read_description(file.path(dir, "DESCRIPTION")) codeDir <- file.path(dir, "R") if(!file_test("-d", codeDir)) return(invisible()) codeFiles <- list_files_with_type(codeDir, "code", full.names = FALSE) collationField <- c(paste("Collate", .OStype(), sep = "."), "Collate") if(any(i <- collationField %in% names(db))) { ## We have a Collate specification in the DESCRIPTION file: ## currently, file paths relative to codeDir, separated by ## white space, possibly quoted. Note that we could have ## newlines in DCF entries but do not allow them in file names, ## hence we gsub() them out. collationField <- collationField[i][1] con <- textConnection(gsub("\n", " ", db[collationField])) on.exit(close(con)) codeFilesInCspec <- scan(con, what = character(), strip.white = TRUE, quiet = TRUE) ## Duplicated entries in the collation spec? badFiles <- unique(codeFilesInCspec[duplicated(codeFilesInCspec)]) if(length(badFiles)) { out <- gettextf("\nduplicated files in '%s' field:", collationField) out <- paste(out, paste(" ", badFiles, collapse = "\n"), sep = "\n") stop(out, domain = NA) } ## See which files are listed in the collation spec but don't ## exist. badFiles <- codeFilesInCspec %w/o% codeFiles if(length(badFiles)) { out <- gettextf("\nfiles in '%s' field missing from '%s':", collationField, codeDir) out <- paste(out, paste(" ", badFiles, collapse = "\n"), sep = "\n") stop(out, domain = NA) } ## See which files exist but are missing from the collation ## spec. Note that we do not want the collation spec to use ## only a subset of the available code files. badFiles <- codeFiles %w/o% codeFilesInCspec if(length(badFiles)) { out <- gettextf("\nfiles in '%s' missing from '%s' field:", codeDir, collationField) out <- paste(out, paste(" ", badFiles, collapse = "\n"), sep = "\n") stop(out, domain = NA) } ## Everything's groovy ... codeFiles <- codeFilesInCspec } codeFiles <- file.path(codeDir, codeFiles) if(!file_test("-d", outDir) && !dir.create(outDir)) stop(gettextf("cannot open directory '%s'", outDir), domain = NA) outCodeDir <- file.path(outDir, "R") if(!file_test("-d", outCodeDir) && !dir.create(outCodeDir)) stop(gettextf("cannot open directory '%s'", outCodeDir), domain = NA) outFile <- file.path(outCodeDir, db["Package"]) if(!file.create(outFile)) stop(gettextf("unable to create '%s'", outFile), domain = NA) writeLines(paste(".packageName <- \"", db["Package"], "\"", sep=""), outFile) enc <- as.vector(db["Encoding"]) need_enc <- !is.na(enc) # Encoding was specified ## assume that if locale if 'C' we can used 8-bit encodings unchanged. if(need_enc && capabilities("iconv") && !(Sys.getlocale("LC_CTYPE") %in% c("C", "POSIX")) ) { con <- file(outFile, "a") on.exit(close(con)) # Windows does not like files left open for(f in codeFiles) { tmp <- iconv(readLines(f, warn = FALSE), from = enc, to = "") if(any(is.na(tmp))) stop(gettextf("unable to re-encode '%s'", basename(f)), domain = NA, call. = FALSE) writeLines(tmp, con) } } else { ## ## It may be safer to do ## writeLines(sapply(codeFiles, readLines), outFile) ## instead, but this would be much slower ... ## use fast version of file.append that ensures LF between files if(!all(.file_append_ensuring_LFs(outFile, codeFiles))) stop("unable to write code files") ## } invisible() } ### * .install_package_indices .install_package_indices <- function(dir, outDir) { options(warn = 1) # to ensure warnings get seen if(!file_test("-d", dir)) stop(gettextf("directory '%s' does not exist", dir), domain = NA) if(!file_test("-d", outDir)) stop(gettextf("directory '%s' does not exist", outDir), domain = NA) ## If there is an @file{INDEX} file in the package sources, we ## install this, and do not build it. if(file_test("-f", file.path(dir, "INDEX"))) if(!file.copy(file.path(dir, "INDEX"), file.path(outDir, "INDEX"), overwrite = TRUE)) stop(gettextf("unable to copy INDEX to '%s'", file.path(outDir, "INDEX")), domain = NA) outMetaDir <- file.path(outDir, "Meta") if(!file_test("-d", outMetaDir) && !dir.create(outMetaDir)) stop(gettextf("cannot open directory '%s'", outMetaDir), domain = NA) .install_package_Rd_indices(dir, outDir) .install_package_vignette_index(dir, outDir) .install_package_demo_index(dir, outDir) invisible() } ### * .install_package_Rd_indices .install_package_Rd_indices <- function(dir, outDir) { dir <- file_path_as_absolute(dir) docsDir <- file.path(dir, "man") dataDir <- file.path(outDir, "data") outDir <- file_path_as_absolute(outDir) ## allow for a data dir but no man pages if(!file_test("-d", docsDir)) { if(file_test("-d", dataDir)) .saveRDS(.build_data_index(dataDir, NULL), file.path(outDir, "Meta", "data.rds")) return(invisible()) } ## ## Not clear whether we should use the basename of the directory we ## install to, or the package name as obtained from the DESCRIPTION ## file in the directory we install from (different for versioned ## installs). We definitely do not want the basename of the dir we ## install from. packageName <- basename(outDir) ## indices <- c(file.path("Meta", "Rd.rds"), file.path("Meta", "hsearch.rds"), "CONTENTS", "INDEX") upToDate <- file_test("-nt", file.path(outDir, indices), docsDir) if(file_test("-d", dataDir)) { ## Note that the data index is computed from both the package's ## Rd files and the data sets actually available. upToDate <- c(upToDate, file_test("-nt", file.path(outDir, "Meta", "data.rds"), c(dataDir, docsDir))) } if(all(upToDate)) return(invisible()) contents <- Rdcontents(list_files_with_type(docsDir, "docs")) .write_contents_as_RDS(contents, file.path(outDir, "Meta", "Rd.rds")) .saveRDS(.build_hsearch_index(contents, packageName), file.path(outDir, "Meta", "hsearch.rds")) .write_contents_as_DCF(contents, packageName, file.path(outDir, "CONTENTS")) ## If there is no @file{INDEX} file in the package sources, we ## build one. ## ## We currently do not also save this in RDS format, as we can ## always do ## .build_Rd_index(.readRDS(file.path(outDir, "Meta", "Rd.rds")) if(!file_test("-f", file.path(dir, "INDEX"))) writeLines(formatDL(.build_Rd_index(contents)), file.path(outDir, "INDEX")) ## if(file_test("-d", dataDir)) .saveRDS(.build_data_index(dataDir, contents), file.path(outDir, "Meta", "data.rds")) invisible() } ### * .install_package_vignette_index .install_package_vignette_index <- function(dir, outDir) { dir <- file_path_as_absolute(dir) vignetteDir <- file.path(dir, "inst", "doc") ## Create a vignette index only if the vignette dir exists. if(!file_test("-d", vignetteDir)) return(invisible()) outDir <- file_path_as_absolute(outDir) ## ## Not clear whether we should use the basename of the directory we ## install to, or the package name as obtained from the DESCRIPTION ## file in the directory we install from (different for versioned ## installs). We definitely do not want the basename of the dir we ## install from. packageName <- basename(outDir) ## outVignetteDir <- file.path(outDir, "doc") if(!file_test("-d", outVignetteDir) && !dir.create(outVignetteDir)) stop(gettextf("cannot open directory '%s'", outVignetteDir), domain = NA) ## If there is an HTML index in the @file{inst/doc} subdirectory of ## the package source directory (@code{dir}), we do not overwrite it ## (similar to top-level @file{INDEX} files). Installation already ## copies/d this over. hasHtmlIndex <- file_test("-f", file.path(vignetteDir, "index.html")) htmlIndex <- file.path(outDir, "doc", "index.html") ## Write dummy HTML index if no vignettes are found and exit. if(!length(list_files_with_type(vignetteDir, "vignette"))) { ## we don't want to write an index if the directory is in fact empty files <- list.files(vignetteDir, all.files = TRUE) # includes . and .. if((length(files) > 2) && !hasHtmlIndex) .writeVignetteHtmlIndex(packageName, htmlIndex) return(invisible()) } vignetteIndex <- .build_vignette_index(vignetteDir) ## For base package vignettes there is no PDF in @file{vignetteDir} ## but there might/should be one in @file{outVignetteDir}. if(NROW(vignetteIndex) > 0) { vignettePDFs <- sub("$", ".pdf", basename(file_path_sans_ext(vignetteIndex$File))) ind <- file_test("-f", file.path(outVignetteDir, vignettePDFs)) vignetteIndex$PDF[ind] <- vignettePDFs[ind] } if(!hasHtmlIndex) .writeVignetteHtmlIndex(packageName, htmlIndex, vignetteIndex) .saveRDS(vignetteIndex, file = file.path(outDir, "Meta", "vignette.rds")) invisible() } ### * .install_package_demo_index .install_package_demo_index <- function(dir, outDir) { demoDir <- file.path(dir, "demo") if(!file_test("-d", demoDir)) return(invisible()) demoIndex <- .build_demo_index(demoDir) .saveRDS(demoIndex, file = file.path(outDir, "Meta", "demo.rds")) invisible() } ### * .vinstall_package_indices .vinstall_package_indices <- function(src_dir, out_dir, packages) { ## For the given packages with sources rooted at @file{src_dir} and ## installations rooted at @file{out_dir}, install the package ## indices. ## Really only useful for base packages under Unix. ## See @file{src/library/Makefile.in}. for(p in unlist(strsplit(packages, "[[:space:]]+"))) .install_package_indices(file.path(src_dir, p), file.path(out_dir, p)) unix.packages.html(.Library) invisible() } ### * .install_package_vignettes ## this is only used when building R, to build the 'grid' vignettes. .install_package_vignettes <- function(dir, outDir, keep.source = FALSE) { dir <- file_path_as_absolute(dir) vignetteDir <- file.path(dir, "inst", "doc") if(!file_test("-d", vignetteDir)) return(invisible()) vignetteFiles <- list_files_with_type(vignetteDir, "vignette") if(!length(vignetteFiles)) return(invisible()) outDir <- file_path_as_absolute(outDir) outVignetteDir <- file.path(outDir, "doc") if(!file_test("-d", outVignetteDir) && !dir.create(outVignetteDir)) stop(gettextf("cannot open directory '%s'", outVignetteDir), domain = NA) ## For the time being, assume that no PDFs are available in ## vignetteDir. vignettePDFs <- file.path(outVignetteDir, sub("$", ".pdf", basename(file_path_sans_ext(vignetteFiles)))) upToDate <- file_test("-nt", vignettePDFs, vignetteFiles) if(all(upToDate)) return(invisible()) ## For the time being, the primary use of this function is to ## install (and build) vignettes in base packages. Hence, we build ## in a subdir of the current directory rather than a temp dir: this ## allows inspection of problems and automatic cleanup via Make. cwd <- getwd() buildDir <- file.path(cwd, ".vignettes") if(!file_test("-d", buildDir) && !dir.create(buildDir)) stop(gettextf("cannot create directory '%s'", buildDir), domain = NA) on.exit(setwd(cwd)) setwd(buildDir) ## Argh. We need to ensure that vignetteDir is in TEXINPUTS and ## BIBINPUTS. Note that this does not work with MiKTeX. envSep <- if(.Platform$OS.type == "windows") ";" else ":" ## (Yes, it would be nice to have envPath() similar to file.path().) texinputs <- Sys.getenv("TEXINPUTS") bibinputs <- Sys.getenv("BIBINPUTS") on.exit(Sys.setenv(TEXINPUTS = texinputs, BIBINPUTS = bibinputs), add = TRUE) Sys.setenv(TEXINPUTS = paste(vignetteDir, Sys.getenv("TEXINPUTS"), sep = envSep), BIBINPUTS = paste(vignetteDir, Sys.getenv("BIBINPUTS"), sep = envSep)) for(srcfile in vignetteFiles[!upToDate]) { base <- basename(file_path_sans_ext(srcfile)) message("processing '", basename(srcfile), "'") texfile <- paste(base, ".tex", sep = "") yy <- try(utils::Sweave(srcfile, pdf = TRUE, eps = FALSE, quiet = TRUE, keep.source = keep.source)) if(inherits(yy, "try-error")) stop(yy) ## In case of an error, do not clean up: should we point to ## buildDir for possible inspection of results/problems? texi2dvi(texfile, pdf = TRUE, quiet = TRUE) pdffile <- paste(basename(file_path_sans_ext(srcfile)), ".pdf", sep = "") if(!file.exists(pdffile)) stop(gettextf("file '%s' was not created", pdffile), domain = NA) if(!file.copy(pdffile, outVignetteDir, overwrite = TRUE)) stop(gettextf("cannot copy '%s' to '%s'", pdffile, outVignetteDir), domain = NA) } ## Need to change out of this dir before we delete it, ## at least on Windows. setwd(cwd) unlink(buildDir, recursive = TRUE) ## Now you need to update the HTML index! .install_package_vignette_index(dir, outDir) invisible() } ### * .install_package_namespace_info .install_package_namespace_info <- function(dir, outDir) { dir <- file_path_as_absolute(dir) nsFile <- file.path(dir, "NAMESPACE") if(!file_test("-f", nsFile)) return(invisible()) nsInfoFilePath <- file.path(outDir, "Meta", "nsInfo.rds") if(file_test("-nt", nsInfoFilePath, nsFile)) return(invisible()) nsInfo <- parseNamespaceFile(basename(dir), dirname(dir)) outMetaDir <- file.path(outDir, "Meta") if(!file_test("-d", outMetaDir) && !dir.create(outMetaDir)) stop(gettextf("cannot open directory '%s'", outMetaDir), domain = NA) .saveRDS(nsInfo, nsInfoFilePath) invisible() } ### * .vinstall_package_namespaces_as_RDS .vinstall_package_namespaces_as_RDS <- function(dir, packages) { ## For the given packages installed in @file{dir} which have a ## NAMESPACE file, install the namespace info as R metadata. ## Really only useful for base packages under Unix. ## See @file{src/library/Makefile.in}. for(p in unlist(strsplit(packages, "[[:space:]]+"))) .install_package_namespace_info(file.path(dir, p), file.path(dir, p)) invisible() } ### * .convert_examples .convert_examples <- function(infile, outfile, encoding) { ## convert infile from encoding to current, if possible if(capabilities("iconv") && l10n_info()[["MBCS"]]) { text <- iconv(readLines(infile), encoding, "") if(any(is.na(text))) stop("invalid input", domain = NA) writeLines(text, outfile) } else file.copy(infile, outfile, TRUE) } ### * .install_package_man_sources .install_package_man_sources <- function(dir, outDir) { mandir <- file.path(dir, "man") if(!file_test("-d", mandir)) return() manfiles <- list_files_with_type(mandir, "docs") if(!length(manfiles)) return() manOutDir <- file.path(outDir, "man") if(!file_test("-d", manOutDir)) dir.create(manOutDir) pkgname <- sub("_.*$", "", basename(outDir)) # allow for versioned installs filepath <- file.path(manOutDir, paste(pkgname, ".Rd.gz", sep = "")) con <- gzfile(filepath, "wb") for(file in manfiles) { fn <- sub(".*/man/", "", file) cat(file=con, "% --- Source file: ", fn, " ---\n", sep="") writeLines(readLines(file, warn = FALSE), con) # will ensure final \n ## previous format had (sometimes) blank line before \eof, but ## this is not needed. cat(file=con, "\\eof\n") } close(con) } ### * .install_package_demos .install_package_demos <- function(dir, outDir) { ## NB: we no longer install 00Index demodir <- file.path(dir, "demo") if(!file_test("-d", demodir)) return() demofiles <- list_files_with_type(demodir, "demo", full.names = FALSE) if(!length(demofiles)) return() demoOutDir <- file.path(outDir, "demo") if(!file_test("-d", demoOutDir)) dir.create(demoOutDir) file.copy(file.path(demodir, demofiles), demoOutDir) } ### * .find_cinclude_paths .find_cinclude_paths <- function(pkgs, lib.loc = NULL, file = NULL) { ## given a character string of comma-separated package names, ## find where the packages are installed and generate ## -I"/path/to/package/include" ... if(!is.null(file)) { tmp <- read.dcf(file, "LinkingTo")[1,1] if(is.na(tmp)) return(invisible()) pkgs <- tmp } pkgs <- strsplit(pkgs[1], ",[:blank]*")[[1]] paths <- .find.package(pkgs, lib.loc, quiet=TRUE) if(length(paths)) cat(paste(paste('-I"', paths, '/include"', sep=""), collapse=" ")) return(invisible()) } ### * .vcreate_bundle_package_descriptions .vcreate_bundle_package_descriptions <- function(dir, packages) { .canonicalize_metadata <- function(m) { ## Drop entries which are NA or empty. m[!is.na(m) & (regexpr("^[[:space:]]*$", m) < 0)] } dir <- file_path_as_absolute(dir) ## Bundle level metadata. meta <- .read_description(file.path(dir, "DESCRIPTION")) meta <- .canonicalize_metadata(meta) if(missing(packages)) packages <- meta[["Contains"]] for(p in unlist(strsplit(.strip_whitespace(packages), "[[:space:]]+"))) { bmeta <- meta ## Package metadata. this <- file.path(dir, p, "DESCRIPTION.in") if(file_test("-f", this)) { pmeta <- .read_description(this) pmeta <- .canonicalize_metadata(pmeta) ## Need to merge dependency fields in *both* metadata. fields_to_merge <- c("Depends", "Imports", "Suggests", "Enhances") fields <- intersect(intersect(names(bmeta), fields_to_merge), intersect(names(pmeta), fields_to_merge)) if(length(fields)) { bmeta[fields] <- paste(bmeta[fields], pmeta[fields], sep = ", ") pmeta <- pmeta[!(names(pmeta) %in% fields)] } } else { warning(gettextf("missing 'DESCRIPTION.in' for package '%s'", p), domain = NA) d <- sprintf("Package '%s' from bundle '%s'", p, meta[["Bundle"]]) pmeta <- c(p, d, d) names(pmeta) <- c("Package", "Description", "Title") } write.dcf(rbind(c(bmeta, pmeta)), file.path(dir, p, "DESCRIPTION")) } invisible() } ### * .test_package_depends_R_version .test_package_depends_R_version <- function(dir) { if(missing(dir)) dir <- "." meta <- .read_description(file.path(dir, "DESCRIPTION")) depends <- .split_description(meta, verbose = TRUE)$Rdepends status <- 0 ## .split_description will have ensured that this is NULL or ## of length 3. if(length(depends) > 1) { ## .check_package_description will insist on these operators if(!depends$op %in% c("<=", ">=")) message("WARNING: malformed 'Depends' field in 'DESCRIPTION'") else status <- !do.call(depends$op, list(getRversion(), depends$version)) if(status != 0) { package <- Sys.getenv("R_PACKAGE_NAME") if(!nzchar(package)) package <- meta["Package"] if(nzchar(package)) msg <- gettextf("ERROR: this R is version %s, package '%s' requires R %s %s", getRversion(), package, depends$op, depends$version) else if (nzchar(bundle <- meta["Bundle"]) && !is.na(bundle)) msg <- gettextf("ERROR: this R is version %s, bundle '%s' requires R %s %s", getRversion(), bundle, depends$op, depends$version) else msg <- gettextf("ERROR: this R is version %s, required is R %s %s", getRversion(), depends$op, depends$version) message(strwrap(msg, exdent = 2)) } } q(status = status) } ### Local variables: *** ### mode: outline-minor *** ### outline-regexp: "### [*]+" *** ### End: ***