Visualizes Quality Control(QC) Results of the Metabolomics for Quartet Project.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

654 行
17KB

  1. local({
  2. # the requested version of renv
  3. version <- "0.13.0"
  4. # the project directory
  5. project <- getwd()
  6. # avoid recursion
  7. if (!is.na(Sys.getenv("RENV_R_INITIALIZING", unset = NA)))
  8. return(invisible(TRUE))
  9. # signal that we're loading renv during R startup
  10. Sys.setenv("RENV_R_INITIALIZING" = "true")
  11. on.exit(Sys.unsetenv("RENV_R_INITIALIZING"), add = TRUE)
  12. # signal that we've consented to use renv
  13. options(renv.consent = TRUE)
  14. # load the 'utils' package eagerly -- this ensures that renv shims, which
  15. # mask 'utils' packages, will come first on the search path
  16. library(utils, lib.loc = .Library)
  17. # check to see if renv has already been loaded
  18. if ("renv" %in% loadedNamespaces()) {
  19. # if renv has already been loaded, and it's the requested version of renv,
  20. # nothing to do
  21. spec <- .getNamespaceInfo(.getNamespace("renv"), "spec")
  22. if (identical(spec[["version"]], version))
  23. return(invisible(TRUE))
  24. # otherwise, unload and attempt to load the correct version of renv
  25. unloadNamespace("renv")
  26. }
  27. # load bootstrap tools
  28. bootstrap <- function(version, library) {
  29. # attempt to download renv
  30. tarball <- tryCatch(renv_bootstrap_download(version), error = identity)
  31. if (inherits(tarball, "error"))
  32. stop("failed to download renv ", version)
  33. # now attempt to install
  34. status <- tryCatch(renv_bootstrap_install(version, tarball, library), error = identity)
  35. if (inherits(status, "error"))
  36. stop("failed to install renv ", version)
  37. }
  38. renv_bootstrap_tests_running <- function() {
  39. getOption("renv.tests.running", default = FALSE)
  40. }
  41. renv_bootstrap_repos <- function() {
  42. # check for repos override
  43. repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA)
  44. if (!is.na(repos))
  45. return(repos)
  46. # if we're testing, re-use the test repositories
  47. if (renv_bootstrap_tests_running())
  48. return(getOption("renv.tests.repos"))
  49. # retrieve current repos
  50. repos <- getOption("repos")
  51. # ensure @CRAN@ entries are resolved
  52. repos[repos == "@CRAN@"] <- "https://cloud.r-project.org"
  53. # add in renv.bootstrap.repos if set
  54. default <- c(FALLBACK = "https://cloud.r-project.org")
  55. extra <- getOption("renv.bootstrap.repos", default = default)
  56. repos <- c(repos, extra)
  57. # remove duplicates that might've snuck in
  58. dupes <- duplicated(repos) | duplicated(names(repos))
  59. repos[!dupes]
  60. }
  61. renv_bootstrap_download <- function(version) {
  62. # if the renv version number has 4 components, assume it must
  63. # be retrieved via github
  64. nv <- numeric_version(version)
  65. components <- unclass(nv)[[1]]
  66. methods <- if (length(components) == 4L) {
  67. list(
  68. renv_bootstrap_download_github
  69. )
  70. } else {
  71. list(
  72. renv_bootstrap_download_cran_latest,
  73. renv_bootstrap_download_cran_archive
  74. )
  75. }
  76. for (method in methods) {
  77. path <- tryCatch(method(version), error = identity)
  78. if (is.character(path) && file.exists(path))
  79. return(path)
  80. }
  81. stop("failed to download renv ", version)
  82. }
  83. renv_bootstrap_download_impl <- function(url, destfile) {
  84. mode <- "wb"
  85. # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715
  86. fixup <-
  87. Sys.info()[["sysname"]] == "Windows" &&
  88. substring(url, 1L, 5L) == "file:"
  89. if (fixup)
  90. mode <- "w+b"
  91. utils::download.file(
  92. url = url,
  93. destfile = destfile,
  94. mode = mode,
  95. quiet = TRUE
  96. )
  97. }
  98. renv_bootstrap_download_cran_latest <- function(version) {
  99. repos <- renv_bootstrap_download_cran_latest_find(version)
  100. message("* Downloading renv ", version, " ... ", appendLF = FALSE)
  101. downloader <- function(type) {
  102. tryCatch(
  103. utils::download.packages(
  104. pkgs = "renv",
  105. destdir = tempdir(),
  106. repos = repos,
  107. type = type,
  108. quiet = TRUE
  109. ),
  110. condition = identity
  111. )
  112. }
  113. # first, try downloading a binary on Windows + macOS if appropriate
  114. binary <-
  115. !identical(.Platform$pkgType, "source") &&
  116. !identical(getOption("pkgType"), "source") &&
  117. Sys.info()[["sysname"]] %in% c("Darwin", "Windows")
  118. if (binary) {
  119. info <- downloader(type = "binary")
  120. if (!inherits(info, "condition")) {
  121. message("OK (downloaded binary)")
  122. return(info[1, 2])
  123. }
  124. }
  125. # otherwise, try downloading a source tarball
  126. info <- downloader(type = "source")
  127. if (inherits(info, "condition")) {
  128. message("FAILED")
  129. return(FALSE)
  130. }
  131. # report success and return
  132. message("OK (downloaded source)")
  133. info[1, 2]
  134. }
  135. renv_bootstrap_download_cran_latest_find <- function(version) {
  136. all <- renv_bootstrap_repos()
  137. for (repos in all) {
  138. db <- tryCatch(
  139. as.data.frame(
  140. x = utils::available.packages(repos = repos),
  141. stringsAsFactors = FALSE
  142. ),
  143. error = identity
  144. )
  145. if (inherits(db, "error"))
  146. next
  147. entry <- db[db$Package %in% "renv" & db$Version %in% version, ]
  148. if (nrow(entry) == 0)
  149. next
  150. return(repos)
  151. }
  152. fmt <- "renv %s is not available from your declared package repositories"
  153. stop(sprintf(fmt, version))
  154. }
  155. renv_bootstrap_download_cran_archive <- function(version) {
  156. name <- sprintf("renv_%s.tar.gz", version)
  157. repos <- renv_bootstrap_repos()
  158. urls <- file.path(repos, "src/contrib/Archive/renv", name)
  159. destfile <- file.path(tempdir(), name)
  160. message("* Downloading renv ", version, " ... ", appendLF = FALSE)
  161. for (url in urls) {
  162. status <- tryCatch(
  163. renv_bootstrap_download_impl(url, destfile),
  164. condition = identity
  165. )
  166. if (identical(status, 0L)) {
  167. message("OK")
  168. return(destfile)
  169. }
  170. }
  171. message("FAILED")
  172. return(FALSE)
  173. }
  174. renv_bootstrap_download_github <- function(version) {
  175. enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE")
  176. if (!identical(enabled, "TRUE"))
  177. return(FALSE)
  178. # prepare download options
  179. pat <- Sys.getenv("GITHUB_PAT")
  180. if (nzchar(Sys.which("curl")) && nzchar(pat)) {
  181. fmt <- "--location --fail --header \"Authorization: token %s\""
  182. extra <- sprintf(fmt, pat)
  183. saved <- options("download.file.method", "download.file.extra")
  184. options(download.file.method = "curl", download.file.extra = extra)
  185. on.exit(do.call(base::options, saved), add = TRUE)
  186. } else if (nzchar(Sys.which("wget")) && nzchar(pat)) {
  187. fmt <- "--header=\"Authorization: token %s\""
  188. extra <- sprintf(fmt, pat)
  189. saved <- options("download.file.method", "download.file.extra")
  190. options(download.file.method = "wget", download.file.extra = extra)
  191. on.exit(do.call(base::options, saved), add = TRUE)
  192. }
  193. message("* Downloading renv ", version, " from GitHub ... ", appendLF = FALSE)
  194. url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version)
  195. name <- sprintf("renv_%s.tar.gz", version)
  196. destfile <- file.path(tempdir(), name)
  197. status <- tryCatch(
  198. renv_bootstrap_download_impl(url, destfile),
  199. condition = identity
  200. )
  201. if (!identical(status, 0L)) {
  202. message("FAILED")
  203. return(FALSE)
  204. }
  205. message("OK")
  206. return(destfile)
  207. }
  208. renv_bootstrap_install <- function(version, tarball, library) {
  209. # attempt to install it into project library
  210. message("* Installing renv ", version, " ... ", appendLF = FALSE)
  211. dir.create(library, showWarnings = FALSE, recursive = TRUE)
  212. # invoke using system2 so we can capture and report output
  213. bin <- R.home("bin")
  214. exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R"
  215. r <- file.path(bin, exe)
  216. args <- c("--vanilla", "CMD", "INSTALL", "-l", shQuote(library), shQuote(tarball))
  217. output <- system2(r, args, stdout = TRUE, stderr = TRUE)
  218. message("Done!")
  219. # check for successful install
  220. status <- attr(output, "status")
  221. if (is.numeric(status) && !identical(status, 0L)) {
  222. header <- "Error installing renv:"
  223. lines <- paste(rep.int("=", nchar(header)), collapse = "")
  224. text <- c(header, lines, output)
  225. writeLines(text, con = stderr())
  226. }
  227. status
  228. }
  229. renv_bootstrap_platform_prefix <- function() {
  230. # construct version prefix
  231. version <- paste(R.version$major, R.version$minor, sep = ".")
  232. prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-")
  233. # include SVN revision for development versions of R
  234. # (to avoid sharing platform-specific artefacts with released versions of R)
  235. devel <-
  236. identical(R.version[["status"]], "Under development (unstable)") ||
  237. identical(R.version[["nickname"]], "Unsuffered Consequences")
  238. if (devel)
  239. prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r")
  240. # build list of path components
  241. components <- c(prefix, R.version$platform)
  242. # include prefix if provided by user
  243. prefix <- renv_bootstrap_platform_prefix_impl()
  244. if (!is.na(prefix) && nzchar(prefix))
  245. components <- c(prefix, components)
  246. # build prefix
  247. paste(components, collapse = "/")
  248. }
  249. renv_bootstrap_platform_prefix_impl <- function() {
  250. # if an explicit prefix has been supplied, use it
  251. prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA)
  252. if (!is.na(prefix))
  253. return(prefix)
  254. # if the user has requested an automatic prefix, generate it
  255. auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA)
  256. if (auto %in% c("TRUE", "True", "true", "1"))
  257. return(renv_bootstrap_platform_prefix_auto())
  258. # empty string on failure
  259. ""
  260. }
  261. renv_bootstrap_platform_prefix_auto <- function() {
  262. prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity)
  263. if (inherits(prefix, "error") || prefix %in% "unknown") {
  264. msg <- paste(
  265. "failed to infer current operating system",
  266. "please file a bug report at https://github.com/rstudio/renv/issues",
  267. sep = "; "
  268. )
  269. warning(msg)
  270. }
  271. prefix
  272. }
  273. renv_bootstrap_platform_os <- function() {
  274. sysinfo <- Sys.info()
  275. sysname <- sysinfo[["sysname"]]
  276. # handle Windows + macOS up front
  277. if (sysname == "Windows")
  278. return("windows")
  279. else if (sysname == "Darwin")
  280. return("macos")
  281. # check for os-release files
  282. for (file in c("/etc/os-release", "/usr/lib/os-release"))
  283. if (file.exists(file))
  284. return(renv_bootstrap_platform_os_via_os_release(file, sysinfo))
  285. # check for redhat-release files
  286. if (file.exists("/etc/redhat-release"))
  287. return(renv_bootstrap_platform_os_via_redhat_release())
  288. "unknown"
  289. }
  290. renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) {
  291. # read /etc/os-release
  292. release <- utils::read.table(
  293. file = file,
  294. sep = "=",
  295. quote = c("\"", "'"),
  296. col.names = c("Key", "Value"),
  297. comment.char = "#",
  298. stringsAsFactors = FALSE
  299. )
  300. vars <- as.list(release$Value)
  301. names(vars) <- release$Key
  302. # get os name
  303. os <- tolower(sysinfo[["sysname"]])
  304. # read id
  305. id <- "unknown"
  306. for (field in c("ID", "ID_LIKE")) {
  307. if (field %in% names(vars) && nzchar(vars[[field]])) {
  308. id <- vars[[field]]
  309. break
  310. }
  311. }
  312. # read version
  313. version <- "unknown"
  314. for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) {
  315. if (field %in% names(vars) && nzchar(vars[[field]])) {
  316. version <- vars[[field]]
  317. break
  318. }
  319. }
  320. # join together
  321. paste(c(os, id, version), collapse = "-")
  322. }
  323. renv_bootstrap_platform_os_via_redhat_release <- function() {
  324. # read /etc/redhat-release
  325. contents <- readLines("/etc/redhat-release", warn = FALSE)
  326. # infer id
  327. id <- if (grepl("centos", contents, ignore.case = TRUE))
  328. "centos"
  329. else if (grepl("redhat", contents, ignore.case = TRUE))
  330. "redhat"
  331. else
  332. "unknown"
  333. # try to find a version component (very hacky)
  334. version <- "unknown"
  335. parts <- strsplit(contents, "[[:space:]]")[[1L]]
  336. for (part in parts) {
  337. nv <- tryCatch(numeric_version(part), error = identity)
  338. if (inherits(nv, "error"))
  339. next
  340. version <- nv[1, 1]
  341. break
  342. }
  343. paste(c("linux", id, version), collapse = "-")
  344. }
  345. renv_bootstrap_library_root_name <- function(project) {
  346. # use project name as-is if requested
  347. asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE")
  348. if (asis)
  349. return(basename(project))
  350. # otherwise, disambiguate based on project's path
  351. id <- substring(renv_bootstrap_hash_text(project), 1L, 8L)
  352. paste(basename(project), id, sep = "-")
  353. }
  354. renv_bootstrap_library_root <- function(project) {
  355. path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA)
  356. if (!is.na(path))
  357. return(path)
  358. path <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA)
  359. if (!is.na(path)) {
  360. name <- renv_bootstrap_library_root_name(project)
  361. return(file.path(path, name))
  362. }
  363. prefix <- renv_bootstrap_profile_prefix()
  364. paste(c(project, prefix, "renv/library"), collapse = "/")
  365. }
  366. renv_bootstrap_validate_version <- function(version) {
  367. loadedversion <- utils::packageDescription("renv", fields = "Version")
  368. if (version == loadedversion)
  369. return(TRUE)
  370. # assume four-component versions are from GitHub; three-component
  371. # versions are from CRAN
  372. components <- strsplit(loadedversion, "[.-]")[[1]]
  373. remote <- if (length(components) == 4L)
  374. paste("rstudio/renv", loadedversion, sep = "@")
  375. else
  376. paste("renv", loadedversion, sep = "@")
  377. fmt <- paste(
  378. "renv %1$s was loaded from project library, but this project is configured to use renv %2$s.",
  379. "Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile.",
  380. "Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.",
  381. sep = "\n"
  382. )
  383. msg <- sprintf(fmt, loadedversion, version, remote)
  384. warning(msg, call. = FALSE)
  385. FALSE
  386. }
  387. renv_bootstrap_hash_text <- function(text) {
  388. hashfile <- tempfile("renv-hash-")
  389. on.exit(unlink(hashfile), add = TRUE)
  390. writeLines(text, con = hashfile)
  391. tools::md5sum(hashfile)
  392. }
  393. renv_bootstrap_load <- function(project, libpath, version) {
  394. # try to load renv from the project library
  395. if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE))
  396. return(FALSE)
  397. # warn if the version of renv loaded does not match
  398. renv_bootstrap_validate_version(version)
  399. # load the project
  400. renv::load(project)
  401. TRUE
  402. }
  403. renv_bootstrap_profile_load <- function(project) {
  404. # if RENV_PROFILE is already set, just use that
  405. profile <- Sys.getenv("RENV_PROFILE", unset = NA)
  406. if (!is.na(profile) && nzchar(profile))
  407. return(profile)
  408. # check for a profile file (nothing to do if it doesn't exist)
  409. path <- file.path(project, "renv/local/profile")
  410. if (!file.exists(path))
  411. return(NULL)
  412. # read the profile, and set it if it exists
  413. contents <- readLines(path, warn = FALSE)
  414. if (length(contents) == 0L)
  415. return(NULL)
  416. # set RENV_PROFILE
  417. profile <- contents[[1L]]
  418. if (nzchar(profile))
  419. Sys.setenv(RENV_PROFILE = profile)
  420. profile
  421. }
  422. renv_bootstrap_profile_prefix <- function() {
  423. profile <- renv_bootstrap_profile_get()
  424. if (!is.null(profile))
  425. return(file.path("renv/profiles", profile))
  426. }
  427. renv_bootstrap_profile_get <- function() {
  428. profile <- Sys.getenv("RENV_PROFILE", unset = "")
  429. renv_bootstrap_profile_normalize(profile)
  430. }
  431. renv_bootstrap_profile_set <- function(profile) {
  432. profile <- renv_bootstrap_profile_normalize(profile)
  433. if (is.null(profile))
  434. Sys.unsetenv("RENV_PROFILE")
  435. else
  436. Sys.setenv(RENV_PROFILE = profile)
  437. }
  438. renv_bootstrap_profile_normalize <- function(profile) {
  439. if (is.null(profile) || profile %in% c("", "default"))
  440. return(NULL)
  441. profile
  442. }
  443. # load the renv profile, if any
  444. renv_bootstrap_profile_load(project)
  445. # construct path to library root
  446. root <- renv_bootstrap_library_root(project)
  447. # construct library prefix for platform
  448. prefix <- renv_bootstrap_platform_prefix()
  449. # construct full libpath
  450. libpath <- file.path(root, prefix)
  451. # attempt to load
  452. if (renv_bootstrap_load(project, libpath, version))
  453. return(TRUE)
  454. # load failed; inform user we're about to bootstrap
  455. prefix <- paste("# Bootstrapping renv", version)
  456. postfix <- paste(rep.int("-", 77L - nchar(prefix)), collapse = "")
  457. header <- paste(prefix, postfix)
  458. message(header)
  459. # perform bootstrap
  460. bootstrap(version, libpath)
  461. # exit early if we're just testing bootstrap
  462. if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA)))
  463. return(TRUE)
  464. # try again to load
  465. if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) {
  466. message("* Successfully installed and loaded renv ", version, ".")
  467. return(renv::load())
  468. }
  469. # failed to download or load renv; warn the user
  470. msg <- c(
  471. "Failed to find an renv installation: the project will not be loaded.",
  472. "Use `renv::activate()` to re-initialize the project."
  473. )
  474. warning(paste(msg, collapse = "\n"), call. = FALSE)
  475. })