77 if (is.null(a )) b else a
88}
99
10+ # Borrowed from pkgload:::dev_meta, with some modifications.
11+ devtools_loaded <- function (pkg ) {
12+ ns <- .getNamespace(pkg )
13+ if (is.null(ns ) || is.null(ns $ .__DEVTOOLS__ )) {
14+ return (FALSE )
15+ }
16+ TRUE
17+ }
18+
19+ # Since I/O can be expensive, only utils::packageVersion() if the package isn't already loaded
1020get_package_version <- function (pkg ) {
1121 ns <- .getNamespace(pkg )
1222 if (is.null(ns )) {
@@ -17,7 +27,7 @@ get_package_version <- function(pkg) {
1727}
1828
1929is_installed <- function (pkg , version = NULL ) {
20- installed <- isNamespaceLoaded(pkg ) || nzchar(system.file (package = pkg ))
30+ installed <- isNamespaceLoaded(pkg ) || nzchar(system_file_cached (package = pkg ))
2131 if (is.null(version )) {
2232 return (installed )
2333 }
@@ -75,3 +85,70 @@ register_upgrade_message <- function(pkg, version, error = FALSE) {
7585 }
7686 )
7787}
88+
89+ # Borrowed from pkgload::shim_system.file, with some modifications.
90+ # Most notably, if the package isn't loaded via devtools, the package directory
91+ # lookup is cached. Also, to keep the implementation simple, it doesn't support
92+ # specification of lib.loc or mustWork
93+ system_file <- function (... , package = " base" ) {
94+ if (! devtools_loaded(package )) {
95+ return (system_file_cached(... , package = package ))
96+ }
97+
98+ if (! is.null(names(list (... )))) {
99+ stop(" All arguments other than `package` must be unnamed." )
100+ }
101+
102+ # If package was loaded with devtools (the package loaded with load_all),
103+ # also search for files under inst/, and don't cache the results (it seems
104+ # more likely that the package path will change during the development
105+ # process)
106+ pkg_path <- find.package(package )
107+
108+ # First look in inst/
109+ files_inst <- file.path(pkg_path , " inst" , ... )
110+ present_inst <- file.exists(files_inst )
111+
112+ # For any files that weren't present in inst/, look in the base path
113+ files_top <- file.path(pkg_path , ... )
114+ present_top <- file.exists(files_top )
115+
116+ # Merge them together. Here are the different possible conditions, and the
117+ # desired result. NULL means to drop that element from the result.
118+ #
119+ # files_inst: /inst/A /inst/B /inst/C /inst/D
120+ # present_inst: T T F F
121+ # files_top: /A /B /C /D
122+ # present_top: T F T F
123+ # result: /inst/A /inst/B /C NULL
124+ #
125+ files <- files_top
126+ files [present_inst ] <- files_inst [present_inst ]
127+ # Drop cases where not present in either location
128+ files <- files [present_inst | present_top ]
129+ if (length(files ) == 0 ) {
130+ return (" " )
131+ }
132+ # Make sure backslashes are replaced with slashes on Windows
133+ normalizePath(files , winslash = " /" )
134+ }
135+
136+ system_file_cached <- local({
137+ pkg_dir_cache <- character ()
138+
139+ function (... , package = " base" ) {
140+ if (! is.null(names(list (... )))) {
141+ stop(" All arguments other than `package` must be unnamed." )
142+ }
143+
144+ not_cached <- is.na(match(package , names(pkg_dir_cache )))
145+ if (not_cached ) {
146+ pkg_dir <- system.file(package = package )
147+ pkg_dir_cache [[package ]] <<- pkg_dir
148+ } else {
149+ pkg_dir <- pkg_dir_cache [[package ]]
150+ }
151+
152+ file.path(pkg_dir , ... )
153+ }
154+ })
0 commit comments