Skip to content

Commit 917fabc

Browse files
committed
add drake-based revdepcheck from RSQLite
1 parent 407f9cd commit 917fabc

File tree

4 files changed

+312
-0
lines changed

4 files changed

+312
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.Rproj.user
22
.Rhistory
33
.RData
4+
/.drake

revdep/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/.cache.rds
2+
/libs
3+
/download

revdep/drake-base.R

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
library(drake)
2+
library(tidyverse)
3+
library(glue)
4+
5+
options(repos = revdepcheck:::get_repos(TRUE))
6+
7+
get_this_pkg <- function() {
8+
desc::desc_get("Package") %>% unname()
9+
}
10+
11+
get_base_pkgs <- function() {
12+
rownames(installed.packages(priority = "base"))
13+
}
14+
15+
flatten <- . %>% unname() %>% unlist() %>% unique()
16+
17+
retry <- function(code, N = 1) {
18+
quo <- rlang::enquo(code)
19+
20+
for (i in seq_len(N)) {
21+
ret <- tryCatch(rlang::eval_tidy(quo), error = identity)
22+
if (!inherits(ret, "error")) return(ret)
23+
Sys.sleep(runif(1) * 2)
24+
}
25+
26+
stop(ret)
27+
}
28+
29+
get_plan_deps <- function() {
30+
plan_deps <- drake_plan(
31+
available = available.packages(),
32+
this_pkg = get_this_pkg(),
33+
revdeps = tools::package_dependencies(this_pkg, available, 'most', reverse = TRUE) %>% flatten(),
34+
first_level_deps = tools::package_dependencies(revdeps, available, 'most'),
35+
all_level_deps = tools::package_dependencies(first_level_deps %>% flatten(), available, recursive = TRUE),
36+
base_pkgs = get_base_pkgs(),
37+
deps = c(revdeps, first_level_deps, all_level_deps) %>% flatten() %>% tools::package_dependencies(recursive = TRUE) %>% .[!(names(.) %in% base_pkgs)],
38+
strings_in_dots = "literals"
39+
)
40+
41+
plan_deps
42+
}

revdep/drake.R

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
source("revdep/drake-base.R")
2+
3+
subset_available <- function(available, pkg) {
4+
if (pkg %in% rownames(available)) {
5+
available[pkg, , drop = FALSE]
6+
} else {
7+
available[integer(), , drop = FALSE]
8+
}
9+
}
10+
11+
download <- function(pkg, available, ...) {
12+
dir <- fs::dir_create("revdep/download")
13+
dir <- fs::path_real(dir)
14+
15+
withr::with_options(
16+
list(warn = 2),
17+
download.packages(pkg, dir, available = available)[, 2]
18+
)
19+
}
20+
21+
get_i_lib <- function() {
22+
path <- "revdep/libs/cran"
23+
fs::dir_create(path)
24+
fs::path_real(path)
25+
}
26+
27+
install <- function(pkg, path, ...) {
28+
dep_packages <- list(...)
29+
dep_paths <- map_chr(dep_packages, attr, "path")
30+
stopifnot(all(fs::dir_exists(dep_paths)))
31+
32+
deps <- c(pkg, sort(as.character(unique(unlist(map(dep_packages, attr, "deps"))))))
33+
34+
lib <- get_i_lib()
35+
36+
# Avoid flaky check for compiler availability on mclapply()
37+
pkgbuild:::cache_set("has_compiler", TRUE)
38+
39+
withr::with_libpaths(
40+
lib, action = "replace",
41+
# Suppress warnings about loaded packages
42+
retry(suppressWarnings(pkginstall::install_source(path, vignettes = FALSE)))
43+
)
44+
45+
structure(
46+
pkg,
47+
path = file.path(lib, pkg),
48+
version = utils::packageVersion(pkg, lib),
49+
deps = deps
50+
)
51+
}
52+
53+
get_old_lib <- function() {
54+
path <- "revdep/libs/old"
55+
fs::dir_create(path)
56+
fs::path_real(path)
57+
}
58+
59+
get_new_lib <- function() {
60+
path <- "revdep/libs/new"
61+
fs::dir_create(path)
62+
fs::path_real(path)
63+
}
64+
65+
create_lib <- function(pkg, lib) {
66+
fs::dir_create(lib)
67+
68+
target <- fs::path(lib, pkg)
69+
fs::link_delete(target[fs::link_exists(target)])
70+
fs::link_create(fs::path(get_i_lib(), pkg), target)
71+
lib
72+
}
73+
74+
create_new_lib <- function(old_lib, new_lib) {
75+
lib <- c(new_lib, old_lib)
76+
withr::with_libpaths(lib, action = "replace", {
77+
remotes::install_local(".")
78+
})
79+
80+
lib
81+
}
82+
83+
get_pkg_and_deps <- function(i_pkg) {
84+
get_deps(i_pkg)
85+
}
86+
87+
get_deps <- function(i_pkg) {
88+
attr(i_pkg, "deps")
89+
}
90+
91+
check <- function(tarball, lib, ...) {
92+
pkgs <- c(...)
93+
check_lib <- fs::file_temp("checklib")
94+
create_lib(pkgs, check_lib)
95+
withr::with_libpaths(c(lib, check_lib), rcmdcheck::rcmdcheck(tarball, quiet = TRUE, timeout = ignore(600)))
96+
}
97+
98+
compare <- function(old, new) {
99+
rcmdcheck::compare_checks(old, new)
100+
}
101+
102+
get_plan <- function() {
103+
104+
plan_deps <- get_plan_deps()
105+
config_deps <- drake_config(plan_deps)
106+
if (length(outdated(config_deps, make_imports = FALSE)) > 0) {
107+
warning("Making dependencies first, rerun.", call. = FALSE)
108+
return(plan_deps)
109+
}
110+
111+
112+
# Avoid expensive and flaky check for build tools from pkgbuild
113+
# Leads to errors, need to check!
114+
#options(buildtools.check = identity)
115+
116+
deps <- readd(deps)
117+
118+
make_subset_available <- function(pkg) {
119+
expr(subset_available(available, !!pkg))
120+
}
121+
122+
plan_available <-
123+
deps %>%
124+
enframe() %>%
125+
transmute(
126+
target = glue("av_{name}"),
127+
call = map(name, make_subset_available)
128+
) %>%
129+
deframe() %>%
130+
drake_plan(list = .)
131+
132+
make_download <- function(pkg, my_pkgs) {
133+
av_pkg <- sym(glue("av_{pkg}"))
134+
deps <- list()
135+
if (!(pkg %in% my_pkgs)) {
136+
deps <- c(deps, expr(old_lib))
137+
}
138+
139+
expr(download(!!pkg, available = !!av_pkg, !!!deps))
140+
}
141+
142+
plan_download <-
143+
deps %>%
144+
enframe() %>%
145+
transmute(
146+
target = glue("d_{name}"),
147+
call = map(name, make_download, c(get_this_pkg(), deps[[get_this_pkg()]]))
148+
) %>%
149+
deframe() %>%
150+
drake_plan(list = .)
151+
152+
make_install <- function(pkg, dep_list) {
153+
d_pkg <- sym(glue("d_{pkg}"))
154+
expr(install(!!pkg, path = !!d_pkg, !!! dep_list))
155+
}
156+
157+
create_dep_list <- function(deps, base_pkgs) {
158+
valid_deps <- setdiff(deps, base_pkgs)
159+
syms(glue("i_{valid_deps}"))
160+
}
161+
162+
plan_install <-
163+
deps %>%
164+
enframe() %>%
165+
mutate(target = glue("i_{name}")) %>%
166+
mutate(
167+
dep_list = map(value, create_dep_list, readd(base_pkgs)),
168+
call = map2(name, dep_list, make_install)
169+
) %>%
170+
select(target, call) %>%
171+
deframe() %>%
172+
drake_plan(list = .)
173+
174+
plan_base_libs <- drake_plan(
175+
old_lib = create_lib(get_pkg_and_deps(!!sym(glue("i_{get_this_pkg()}"))), get_old_lib()),
176+
new_lib = create_new_lib(old_lib, get_new_lib())
177+
)
178+
179+
make_check <- function(pkg, lib, deps, first_level_deps, base_pkgs) {
180+
lib <- enexpr(lib)
181+
182+
req_pkgs <- first_level_deps[[pkg]]
183+
req_pkgs_deps <- deps[c(pkg, req_pkgs)] %>% unname() %>% unlist() %>% unique()
184+
all_deps <- c(req_pkgs, req_pkgs_deps) %>% unique()
185+
186+
i_deps <- create_dep_list(all_deps, base_pkgs)
187+
d_dep <- sym(glue("d_{pkg}"))
188+
189+
expr(check(!!d_dep, !!lib, !!! i_deps))
190+
}
191+
192+
plan_check <-
193+
readd(revdeps) %>%
194+
enframe() %>%
195+
mutate(
196+
old = map(value, make_check, old_lib, readd(deps), readd(first_level_deps), readd(base_pkgs)),
197+
new = map(value, make_check, new_lib, readd(deps), readd(first_level_deps), readd(base_pkgs))
198+
) %>%
199+
gather(kind, call, old, new) %>%
200+
transmute(
201+
target = glue("c_{value}_{kind}"),
202+
call
203+
) %>%
204+
deframe() %>%
205+
drake_plan(list = .)
206+
207+
make_compare <- function(pkg) {
208+
old_result <- sym(glue("c_{pkg}_old"))
209+
new_result <- sym(glue("c_{pkg}_new"))
210+
expr(compare(!!old_result, !!new_result))
211+
}
212+
213+
plan_compare <-
214+
readd(revdeps) %>%
215+
enframe() %>%
216+
transmute(
217+
target = glue("c_{value}"),
218+
call = map(value, make_compare)
219+
) %>%
220+
deframe() %>%
221+
drake_plan(list = .)
222+
223+
make_compare_all <- function(pkg) {
224+
check_targets <- set_names(syms(glue("c_{pkg}")), pkg)
225+
expr(list(!!! check_targets))
226+
}
227+
228+
plan_compare_all <-
229+
readd(revdeps) %>%
230+
enframe() %>%
231+
summarize(
232+
target = "compare_all",
233+
call = list(make_compare_all(value))
234+
) %>%
235+
deframe() %>%
236+
drake_plan(list = .)
237+
238+
#future::plan(future.callr::callr)
239+
240+
plan <-
241+
bind_rows(
242+
# Put first to give higher priority
243+
plan_check,
244+
plan_compare,
245+
plan_compare_all,
246+
plan_install,
247+
plan_base_libs,
248+
plan_download,
249+
plan_available,
250+
plan_deps
251+
)
252+
253+
plan
254+
}
255+
256+
plan <- get_plan()
257+
258+
#trace(conditionCall.condition, recover)
259+
make(
260+
plan,
261+
#"compare_all",
262+
keep_going = TRUE,
263+
#parallelism = "future"
264+
, verbose = 3
265+
, jobs = parallel::detectCores() - 2
266+
)

0 commit comments

Comments
 (0)