Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: rix
Title: Reproducible Data Science Environments with 'Nix'
Version: 0.15.2
Version: 0.15.3
Authors@R: c(
person(given = "Bruno", family = "Rodrigues", email = "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-3211-3689")),
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ importFrom(jsonlite,read_json)
importFrom(stats,na.omit)
importFrom(tools,pskill)
importFrom(utils,data)
importFrom(utils,head)
importFrom(utils,read.csv)
importFrom(utils,tail)
importFrom(utils,untar)
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<!-- NEWS.md is maintained by https://cynkra.github.io/fledge, do not edit -->

# rix 0.15.3 (2025-02-28)

- `rix()`: cannot generate expressions that contain remote packages without Nix
being locally installed anymore. Previously, when Nix was not available, a remote
server was being used to compute the hash but this is now being decommissioned.

# rix 0.15.2 (2025-02-15)

- `rix()`: duplicate entries were not correctly being removed, this is now fixed.
Expand Down
62 changes: 37 additions & 25 deletions R/fetchers.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
repo_url <- git_pkg$repo_url
commit <- git_pkg$commit

output <- get_sri_hash_deps(repo_url, commit)
output <- nix_hash(repo_url, commit)
sri_hash <- output$sri_hash
# If package has no remote dependencies

Expand All @@ -32,18 +32,22 @@
# if no remote dependencies

output <- main_package_expression
} else { # if there are remote dependencies, start over
} else {
# if there are remote dependencies, start over
# don't include remote dependencies twice
# this can happen if a remote dependency of a remote dependency
# is already present as a remote dependency
remotes_remotes <- unique(unlist(lapply(remotes, get_remote)))
remotes <- remotes[!sapply(remotes, function(pkg) {
pkg$package_name %in% remotes_remotes
})]
remotes <- remotes[
!sapply(remotes, function(pkg) {
pkg$package_name %in% remotes_remotes
})
]

remote_packages_expressions <- fetchgits(remotes)

output <- paste0(remote_packages_expressions,
output <- paste0(
remote_packages_expressions,
main_package_expression,
collapse = "\n"
)
Expand All @@ -62,12 +66,14 @@
#' @return A character. Part of the Nix definition to download and build the R package
#' from the CRAN archives.
#' @noRd
generate_git_nix_expression <- function(package_name,
repo_url,
commit,
sri_hash,
imports,
remotes = NULL) {
generate_git_nix_expression <- function(
package_name,
repo_url,
commit,
sri_hash,
imports,
remotes = NULL
) {
# If there are remote dependencies, pass this string
flag_remote_deps <- if (is.list(remotes) && length(remotes) == 0) {
""
Expand Down Expand Up @@ -112,7 +118,8 @@

cran_archive_link <- paste0(
"https://cran.r-project.org/src/contrib/Archive/",
pkgs[1], "/",
pkgs[1],
"/",
paste0(pkgs[1], "_", pkgs[2]),
".tar.gz"
)
Expand All @@ -121,7 +128,7 @@
repo_url <- cran_archive_link

if (is.null(sri_hash)) {
output <- get_sri_hash_deps(repo_url, commit = NULL)
output <- nix_hash(repo_url, commit = NULL)
sri_hash <- output$sri_hash
imports <- output$deps$imports
imports <- paste(c("", imports), collapse = "\n ")
Expand Down Expand Up @@ -199,7 +206,9 @@
} else if (grepl("DESCRIPTION", path)) {
desc_path <- path
} else {
stop("Path is neither a .tar.gz archive, nor pointing to a DESCRIPTION file directly.")
stop(
"Path is neither a .tar.gz archive, nor pointing to a DESCRIPTION file directly."
)
}

columns_of_interest <- c("Depends", "Imports", "LinkingTo")
Expand Down Expand Up @@ -228,7 +237,7 @@
# Keep only if it looks like a SHA (7-40 hex chars)
if (grepl("^[0-9a-f]{7,40}$", ref)) {
return(x)
}

Check warning on line 240 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=240,col=7,[return_linter] Use implicit return behavior; explicit return() is not needed.
return(parts[1])
}))
# Get user names
Expand All @@ -247,7 +256,8 @@

urls <- paste0(
"https://github.com/",
remote_pkgs_usernames, "/",
remote_pkgs_usernames,
"/",
remote_pkgs_names
)

Expand Down Expand Up @@ -282,7 +292,11 @@

if (length(namespace_imports) > 0) {
# Get package names from `importFrom` statements
namespace_imports_pkgs <- gsub("importFrom\\(([^,]+).*", "\\1", namespace_imports)
namespace_imports_pkgs <- gsub(
"importFrom\\(([^,]+).*",
"\\1",
namespace_imports
)
# Remove quotes, which is sometimes necessary
# example: https://github.com/cran/AER/blob/master/NAMESPACE
namespace_imports_pkgs <- gsub("[\"']", "", namespace_imports_pkgs)
Expand Down Expand Up @@ -367,7 +381,6 @@
}



#' fetchgits Downloads and installs packages hosted on Git. Wraps `fetchgit()`
#' to handle multiple packages
#' @param git_pkgs A list of three elements: "package_name", the name of the
Expand Down Expand Up @@ -427,9 +440,11 @@
# Only include git packages that aren't already remote dependencies
if (all(sapply(git_pkgs, is.list))) {
all_remotes <- unique(unlist(lapply(git_pkgs, get_remote)))
git_pkgs <- git_pkgs[!sapply(git_pkgs, function(pkg) {
pkg$package_name %in% all_remotes
})]
git_pkgs <- git_pkgs[
!sapply(git_pkgs, function(pkg) {
pkg$package_name %in% all_remotes
})
]
}

# Combine git and archive package definitions
Expand All @@ -449,9 +464,9 @@
get_remote <- function(git_pkg) {
repo_url <- git_pkg$repo_url
commit <- git_pkg$commit
output <- get_sri_hash_deps(repo_url, commit)
output <- nix_hash(repo_url, commit)
remotes <- output$deps$remotes
remote_package_names <- sapply(remotes, `[[`, "package_name")

Check warning on line 469 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=469,col=3,[return_linter] Use implicit return behavior; explicit return() is not needed.
return(remote_package_names)
}

Expand All @@ -475,7 +490,7 @@
message(
paste0(
"When fetching the commit date from GitHub from <<< ",
repo,

Check warning on line 493 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=493,col=101,[line_length_linter] Lines should not be more than 100 characters. This line is 146 characters.
" >>>, no GitHub Personal Access Token found.\nPlease set GITHUB_PAT in your environment.\nFalling back to unauthenticated API request.\n"
)
)
Expand Down Expand Up @@ -504,7 +519,7 @@
Sys.Date(),
" >>>.\n"
)
)

Check warning on line 522 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=522,col=7,[return_linter] Use implicit return behavior; explicit return() is not needed.
return(Sys.Date())
}
)
Expand All @@ -530,7 +545,7 @@
message(
paste0(
"When downloading commits from <<< ",
repo,

Check warning on line 548 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=548,col=101,[line_length_linter] Lines should not be more than 100 characters. This line is 146 characters.
" >>>, no GitHub Personal Access Token found.\nPlease set GITHUB_PAT in your environment.\nFalling back to unauthenticated API request.\n"
)
)
Expand Down Expand Up @@ -564,7 +579,6 @@
n_commits <- length(commits$sha)
if (n_commits == 0) break


idx <- (commit_count + 1):(commit_count + n_commits)
all_commits$sha[idx] <- commits$sha
all_commits$date[idx] <- as.POSIXct(
Expand Down Expand Up @@ -605,20 +619,20 @@
}

# Find the closest commit by selecting the maximum date
closest_commit <- filtered_commits[which.max(filtered_commits$date), ]

Check warning on line 622 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=622,col=3,[return_linter] Use implicit return behavior; explicit return() is not needed.
return(closest_commit)
}

#' resolve_package_commit Resolves the commit SHA for a package based on a date
#' @param remote_pkg_name_and_ref A list containing the package name and optionally a ref
#' @param date The target date to find the closest commit
#' @param remotess A character vector of remotes

Check warning on line 629 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=629,col=101,[line_length_linter] Lines should not be more than 100 characters. This line is 102 characters.
#' @return A character. The commit SHA of the closest commit to the target date or "HEAD" if API fails
#' @noRd
resolve_package_commit <- function(remote_pkg_name_and_ref, date, remotes) {
# Check if remote is a list with a package name and a ref
if (length(remote_pkg_name_and_ref) == 2) {
# Keep existing ref if present

Check warning on line 635 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=635,col=5,[return_linter] Use implicit return behavior; explicit return() is not needed.
return(remote_pkg_name_and_ref[[2]])
} else if (length(remote_pkg_name_and_ref) == 1) {
# For packages without ref, try to find closest one by date
Expand All @@ -639,14 +653,12 @@
e$message,
".\nFalling back to <<< HEAD >>>\n"
)
)

Check warning on line 656 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=656,col=9,[return_linter] Use implicit return behavior; explicit return() is not needed.
return("HEAD")
}
)

Check warning on line 659 in R/fetchers.R

View workflow job for this annotation

GitHub Actions / style_pkg

file=R/fetchers.R,line=659,col=5,[return_linter] Use implicit return behavior; explicit return() is not needed.
return(result)
} else {
stop("remote_pkg_name_and_ref must be a list of length 1 or 2")
}
}


34 changes: 22 additions & 12 deletions R/nix_build.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
#' \dontrun{
#' nix_build()
#' }
nix_build <- function(project_path = getwd(),
message_type = c("simple", "quiet", "verbose")) {
message_type <- match.arg(message_type,
nix_build <- function(
project_path = getwd(),
message_type = c("simple", "quiet", "verbose")
) {
message_type <- match.arg(
message_type,
choices = c("simple", "quiet", "verbose")
)
# if nix store is not PATH variable; e.g. on macOS (system's) RStudio
Expand Down Expand Up @@ -66,19 +69,24 @@ nix_build <- function(project_path = getwd(),

# nolint start: line_length_linter
stopifnot(
"`project_path` must be character of length 1." =
is.character(project_path) && length(project_path) == 1L,
"`project_path` has no `default.nix` file. Use one that contains `default.nix`" =
file.exists(nix_file),
"`nix-build` not available. To install, we suggest you follow https://zero-to-nix.com/start/install ." =
isTRUE(has_nix_build)
"`project_path` must be character of length 1." = is.character(
project_path
) &&
length(project_path) == 1L,
"`project_path` has no `default.nix` file. Use one that contains `default.nix`" = file.exists(
nix_file
),
"`nix-build` not available. To install, we suggest you follow the 'Setting up and using Nix' vignette for your operating system." = isTRUE(
has_nix_build
)
)
# nolint end

max_jobs <- getOption("rix.nix_build_max_jobs", default = 1L)
stopifnot(
"option `rix.nix_build_max_jobs` is not integerish" =
is_integerish(max_jobs)
"option `rix.nix_build_max_jobs` is not integerish" = is_integerish(
max_jobs
)
)
max_jobs <- as.integer(max_jobs)

Expand All @@ -92,7 +100,9 @@ nix_build <- function(project_path = getwd(),

if (identical(Sys.getenv("TESTTHAT"), "false")) {
cat(paste0(
"Running `", paste0(cmd, " ", args, collapse = " "), "`",
"Running `",
paste0(cmd, " ", args, collapse = " "),
"`",
" ...\n"
))
}
Expand Down
Loading
Loading