Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7061274
* add `renv_lock_pkgs()` function
RichardJActon Oct 11, 2024
803bfd7
factor out reading renv.lock
RichardJActon Oct 11, 2024
8387137
* add `renv_lock_r_ver()` function
RichardJActon Oct 11, 2024
701eafa
* add simple non-standard repo filtering to `renv_lock_pkgs()` function
RichardJActon Oct 11, 2024
2e74fcd
* add `renv2nix()` function
RichardJActon Oct 11, 2024
8e4e0a2
* add `return_rix_call` argument to `renv2nix()` function
RichardJActon Oct 11, 2024
926102f
* remove the now unnecessary `renv_lock_pkgs()` function
RichardJActon Oct 11, 2024
700e014
bugfix: renv2nix dots not properly epanded when constructing rix call
RichardJActon Oct 12, 2024
eed8e9a
* add `renv_remote_pkgs()` function, factors out generating `git_pkgs…
RichardJActon Oct 12, 2024
e4b86ef
* rename `renv_remote_pkgs()` to `renv_remote_pkg()` as it only handl…
RichardJActon Oct 12, 2024
be0ffa2
remove test for old `renv_lock_pkgs()` function
RichardJActon Oct 13, 2024
7c108be
add simple tests for `renv_read_lock()`
RichardJActon Oct 13, 2024
c34d908
add simple tests for `renv_remote_pkg()`
RichardJActon Oct 13, 2024
d75319d
add simple tests for `renv_lock_r_ver()`
RichardJActon Oct 13, 2024
bd52c7d
add simple tests for `renv2nix()`
RichardJActon Oct 13, 2024
72f930e
remove unnecessary asignment
RichardJActon Oct 13, 2024
de7dfb2
wrap overlong lines
RichardJActon Oct 13, 2024
730bad1
styler styling
RichardJActon Oct 13, 2024
e7a5d08
update `renv2nix()` documentation with the return type when `return_r…
RichardJActon Oct 14, 2024
ebb17b3
fix typo in `renv_lock_r_ver()` documentation
RichardJActon Oct 14, 2024
f717e9a
document `renv2nix()` `method` argument and list "accurate" the secon…
RichardJActon Oct 14, 2024
0f9de72
do not export `renv_lock_r_ver()`
RichardJActon Oct 15, 2024
68ebf8a
* add `renv_remote_pkgs()`
RichardJActon Oct 15, 2024
43137b9
add remote type checking and assertion
RichardJActon Oct 15, 2024
7bd3d50
skip unsupported remote types in `renv2nix()` with warning
RichardJActon Oct 16, 2024
d24730d
* remove `renv_remote_pkg()` refactoring into `renv_remote_pkgs()`, w…
RichardJActon Oct 16, 2024
753c30b
nest renv_helper tests to keep example inputs out of the global names…
RichardJActon Oct 23, 2024
1fa96f3
switch to building lists of remote and repo packages
RichardJActon Oct 23, 2024
c8d2cb5
test for skipping and warning about unsupported remote types
RichardJActon Oct 23, 2024
d54e044
add error for unsupported inferred remote types in `renv_remote_pkgs()`
RichardJActon Oct 23, 2024
dc168a1
styling fix
RichardJActon Oct 23, 2024
d953b4b
add tests `renv_remote_pkgs()` errors
RichardJActon Oct 23, 2024
3bda5ea
add test for `renv2nix(method="accurate")` error
RichardJActon Oct 23, 2024
4ef5f97
add test where an named `rix()` argument is passed via renv2nix()`
RichardJActon Oct 24, 2024
05cbf6b
use `expect_warning()` instead of `capture_warnings()`
RichardJActon Oct 24, 2024
ff69fe2
inherit dot params documentation from `rix()` in `renv2nix()`
RichardJActon Oct 24, 2024
9c1f539
more succinct inherit dot params
RichardJActon Oct 24, 2024
1fb1e48
add some example 'real world' renv.lock files for use in testing
RichardJActon Oct 29, 2024
adcb182
fix bug where bioconductor is the source
RichardJActon Oct 29, 2024
c0c7b3c
test sample renv.lock files can be read
RichardJActon Oct 29, 2024
41343f3
removing packages from renv example which appear to have build errors…
RichardJActon Oct 29, 2024
62d19ba
renv2nix docs
b-rodrigues Nov 1, 2024
078ac16
build documentation changes to `renv2nix()`
RichardJActon Nov 3, 2024
be98490
please linter (locally)
b-rodrigues Nov 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
export(available_r)
export(ga_cachix)
export(nix_build)
export(renv2nix)
export(rix)
export(rix_init)
export(tar_nix_ga)
Expand All @@ -14,6 +15,7 @@ importFrom(curl,handle_reset)
importFrom(curl,has_internet)
importFrom(curl,new_handle)
importFrom(jsonlite,fromJSON)
importFrom(jsonlite,read_json)
importFrom(stats,na.omit)
importFrom(tools,pskill)
importFrom(utils,data)
Expand Down
200 changes: 200 additions & 0 deletions R/renv_helpers.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#' read_renv_lock
#'
#' Reads renv.lock if it exists and can be parsed as json.
#'
#' @param renv_lock_path location of the renv.lock file, defaults to "renv.lock"
#'
#' @return the result of reading renv.lock with [jsonlite::read_json]
#'
#' @importFrom jsonlite read_json
read_renv_lock <- function(renv_lock_path = "renv.lock") {
if (!file.exists(renv_lock_path)) {
stop(renv_lock_path, " does not exist!")
}
tryCatch(
renv_lock <- jsonlite::read_json(renv_lock_path),
error = function(e) {
stop("Error reading renv.lock file\n", e)
}
)
renv_lock
}

#' renv_remote_pkgs
#'
#' Construct a list to be passed the git_pkgs argument of [rix]
#' The list returned contains the information necessary to have nix attempt to
#' build the packages from their external repositories.
#'
#' @param renv_lock_pkgs the list of package information from an renv.lock file.
#' @param type the type of remote package, defaults to NULL meaning the RemoteType of the
#' renv entry will be used.
#' currently supported types: 'github' 'gitlab'
#' see [remotes](https://remotes.r-lib.org/) for more.
#'
#' @return a list of lists with three elements named:
#' "package_name", "repo_url", "commit"
#'
#' @examples
#' \dontrun{
#' renv_remote_pkgs(read_renv_lock()$Packages)
#' }
renv_remote_pkgs <- function(
renv_lock_remote_pkgs, type = NULL) {
# , "bitbucket", "git", "local", "svn", "url", "version", "cran", "bioc"
supported_pkg_types <- c("github", "gitlab")
if (!(is.null(type) || (type %in% supported_pkg_types))) {
stop("Unsupported remote type: ", type)
}
initial_type_state <- type
git_pkgs <- vector(mode = "list", length = length(renv_lock_remote_pkgs))
names(git_pkgs) <- names(renv_lock_remote_pkgs)
for (i in seq_along(renv_lock_remote_pkgs)) {
renv_lock_pkg_info <- renv_lock_remote_pkgs[[i]]
if (is.null(type)) {
if (is.null(renv_lock_pkg_info$RemoteType)) {
stop(
"Not a package installed from a remote outside of the main package repositories\n",
"renv_remote_pkgs() only handles pkgs where remote type is specified"
)
} else if (renv_lock_pkg_info$RemoteType %in% supported_pkg_types) {
type <- renv_lock_pkg_info$RemoteType
} else {
stop(
renv_lock_pkg_info$Package, " has unsupported remote type: ",
renv_lock_pkg_info$RemoteType, "\nSupported types are: ",
paste0(supported_pkg_types, collapse = ", ")
)
}
} else {
if (type != renv_lock_pkg_info$RemoteType) {
stop(
"Remote type (", renv_lock_pkg_info$RemoteType, ") of ", renv_lock_pkg_info$Package,
" does not match the provided type (", type, ")"
)
}
}

pkg_info <- vector(mode = "list", length = 3)
names(pkg_info) <- c("package_name", "repo_url", "commit")
switch(type,
"github" = {
pkg_info[[1]] <- renv_lock_pkg_info$Package
pkg_info[[2]] <- paste0(
# RemoteHost is listed as api.github.com for some reason
"https://github.com/", renv_lock_pkg_info$RemoteUser, "/",
renv_lock_pkg_info$RemoteRepo
)
pkg_info[[3]] <- renv_lock_pkg_info$RemoteSha
},
"gitlab" = {
pkg_info[[1]] <- renv_lock_pkg_info$Package
pkg_info[[2]] <- paste0(
"https://", renv_lock_pkg_info$RemoteHost, "/",
renv_lock_pkg_info$RemoteUser, "/",
renv_lock_pkg_info$RemoteRepo
)
pkg_info[[3]] <- renv_lock_pkg_info$RemoteSha
}
)
type <- initial_type_state
git_pkgs[[i]] <- pkg_info
}
git_pkgs
}

#' renv2nix
#'
#' @param renv_lock_path Character, path of the renv.lock file, defaults to
#' "renv.lock"
#' @param return_rix_call Logical, return the generated rix function call
#' instead of evaluating it this is for debugging purposes, defaults to
#' `FALSE`
#' @param method Character, the method of generating a nix environment from an
#' renv.lock file. "fast" is an inexact conversion which simply extracts the R
#' version and a list of all the packages in an renv.lock file and adds them
#' to the `r_pkgs` argument of `rix()`. This will use a snapshot of `nixpkgs`
#' that should contain package versions that are not too different from the
#' ones defined in the `renv.lock` file. For packages installed from Github or
#' similar, an attempt is made to handle them and pass them to the `git_pkgs`
#' argument of `rix()`. Currently defaults to "fast", "accurate" is not yet
#' implemented.
#' @inheritDotParams rix system_pkgs local_r_pkgs:shell_hook
#'
#' @return Nothing, this function is called for its side effects only, unless
#' `return_rix_call = TRUE` in which case an unevaluated call to `rix()`
#' is returned
#' @export
#'
renv2nix <- function(
renv_lock_path = "renv.lock",
return_rix_call = FALSE,
method = c("fast", "accurate"),
...) {
method <- match.arg(method, c("fast", "accurate"))
renv_lock <- read_renv_lock(renv_lock_path = renv_lock_path)
if (method == "fast") {
repo_pkgs <- list()
remote_pkgs <- list()
# unsupported_pkgs <- list()
renv_lock_pkg_names <- names(renv_lock$Packages)
for (i in seq_along(renv_lock$Packages)) {
if (renv_lock$Packages[[i]]$Source %in% c("Repository", "Bioconductor")) {
repo_pkgs[[renv_lock_pkg_names[i]]] <- renv_lock$Packages[[i]]
} else if (renv_lock$Packages[[i]]$RemoteType %in% c("github", "gitlab")) {
remote_pkgs[[renv_lock_pkg_names[i]]] <- renv_lock$Packages[[i]]
} else {
# unsupported_pkgs[[renv_lock_pkg_names[i]]] <- renv_lock$Packages[[i]]
warning(
renv_lock$Packages[[i]]$Package, " has the unsupported remote type ",
renv_lock$Packages[[i]]$RemoteType, " and will not be included in the Nix expression.",
"\n Consider manually specifying the git remote or a local package install."
)
}
}
git_pkgs <- NULL
# as local_r_pkgs expects an archive not sure how to set type here..
# local_r_pkgs <- NULL
if (length(remote_pkgs) > 0) {
git_pkgs <- renv_remote_pkgs(remote_pkgs)
}
rix_call <- call("rix",
r_ver = renv_lock$R$Version,
r_pkgs = names(repo_pkgs),
git_pkgs = git_pkgs # ,
# local_r_pkgs = local_r_pkgs
)
dots <- list(...)
for (arg in names(dots)) {
rix_call[[arg]] <- dots[[arg]]
}

if (return_rix_call) {
# print(rix_call)
return(rix_call)
}
eval(rix_call)
} else {
stop(
"The 'accurate' method to generate Nix expressions with exact package versions",
"matching the ones in the `renv.lock` file is not yet implemented."
)
}
}

#' renv_lock_r_ver
#'
#' @param renv_lock_path location of the renv.lock file from which to get the
#' R version, defaults to "renv.lock"
#'
#' @return a length 1 character vector with the version of R recorded in
#' renv.lock
#'
#' @examples
#'
#' rix(r_ver = renv_lock_r_ver())
#'
renv_lock_r_ver <- function(renv_lock_path = "renv.lock") {
renv_lock <- read_renv_lock(renv_lock_path = renv_lock_path)
renv_lock$R$Version
}
17 changes: 17 additions & 0 deletions man/read_renv_lock.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

154 changes: 154 additions & 0 deletions man/renv2nix.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading