Skip to content

Commit

Permalink
refactor cargo-processx functions
Browse files Browse the repository at this point in the history
  • Loading branch information
kbvernon committed Nov 18, 2024
1 parent 4aefce1 commit 4d1f41b
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 122 deletions.
55 changes: 24 additions & 31 deletions R/clean.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,19 @@
#' (found by default at `pkg_root/src/rust/target/`).
#' Useful when Rust code should be recompiled from scratch.
#' @param path \[ string \] Path to the package root.
#' @param echo logical scalar, should cargo command and outputs be printed to
#' console (default is TRUE)
#'
#' @export
clean <- function(path = ".") {
#'
#' @examples
#' \dontrun{
#' clean()
#' }
clean <- function(path = ".", echo = TRUE) {
check_string(path, class = "rextendr_error")
check_bool(echo, class = "rextendr_error")

root <- rprojroot::find_package_root_file(path = path)

rust_folder <- normalizePath(
Expand All @@ -15,7 +26,7 @@ clean <- function(path = ".") {
mustWork = FALSE
)

toml_path <- normalizePath(
manifest_path <- normalizePath(
file.path(rust_folder, "Cargo.toml"),
winslash = "/",
mustWork = FALSE
Expand All @@ -28,52 +39,34 @@ clean <- function(path = ".") {
mustWork = FALSE
)

if (!file.exists(toml_path)) {
if (!file.exists(manifest_path)) {
cli::cli_abort(c(
"Unable to clean binaries.",
"!" = "{.file Cargo.toml} not found in {.path {rust_folder}}.",
class = "rextendr_error"
))
}

cargo_envvars <- get_cargo_envvars()

args <- c(
"clean",
glue("--manifest-path={toml_path}"),
glue("--target-dir={target_dir}"),
glue::glue("--manifest-path={manifest_path}"),
glue::glue("--target-dir={target_dir}"),
if (tty_has_colors()) {
"--color=always"
} else {
"--color=never"
},
"--quiet"
}
)
exec_result <- processx::run(

out <- processx::run(

Check warning on line 61 in R/clean.R

View workflow job for this annotation

GitHub Actions / lint

file=R/clean.R,line=61,col=3,[object_usage_linter] local variable 'out' assigned but may not be used
command = "cargo",
args = args,
echo_cmd = FALSE,
windows_verbatim_args = FALSE,
stderr = "|",
stdout = "|",
error_on_status = FALSE,
env = cargo_envvars
error_on_status = TRUE,
wd = rust_folder,
echo_cmd = echo,
echo = echo,
env = get_cargo_envvars()
)

if (!isTRUE(exec_result$status == 0)) {
if (!tty_has_colors()) {
err_msg <- cli::ansi_strip(exec_result$stderr)
} else {
err_msg <- exec_result$stderr
}
cli::cli_abort(
c(
"Unable to execute {.code cargo clean}.",
"x" = paste(err_msg, collapse = "\n")
),
call = caller_env(),
class = "rextendr_error"
)
}
pkgbuild::clean_dll(path = root)
}
167 changes: 108 additions & 59 deletions R/license_note.R
Original file line number Diff line number Diff line change
@@ -1,92 +1,141 @@
#' Generate LICENSE.note file.
#'
#' LICENSE.note generated by this function contains information about Rust crate dependencies.
#' To use this function, the [cargo-license](https://crates.io/crates/cargo-license) command must be installed.
#' @param force Logical indicating whether to regenerate LICENSE.note if LICENSE.note already exists.
#' @inheritParams register_extendr
#' LICENSE.note generated by this function contains information about Rust crate
#' dependencies. To use this function, the
#' [cargo-license](https://crates.io/crates/cargo-license) command must be
#' installed.
#'
#' @param path character scalar, the R package directory
#' @param echo logical scalar, whether to print cargo command and outputs to the
#' console (default is `TRUE`)
#' @param quiet logical scalar, whether to signal successful writing of
#' LICENSE.note (default is `FALSE`)
#' @param force logical scalar, whether to regenerate LICENSE.note if
#' LICENSE.note already exists (default is `TRUE`)
#'
#' @return No return value, called for side effects.
#'
#' @export
write_license_note <- function(path = ".", quiet = FALSE, force = TRUE) {
#'
#' @examples
#' \dontrun{
#' write_license_note()
#' }
write_license_note <- function(
path = ".",
echo = TRUE,
quiet = FALSE,
force = TRUE) {
check_string(path, class = "rextendr_error")
check_bool(echo, class = "rextendr_error")
check_bool(force, class = "rextendr_error")

Check warning on line 31 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L29-L31

Added lines #L29 - L31 were not covered by tests

if (!cargo_command_available(c("license", "--help"))) {
cli::cli_abort(
c(
"The {.code cargo license} command is required to run the {.fun write_license_note} function.",
"*" = "Please install cargo-license ({.url https://crates.io/crates/cargo-license}) first.",
"The {.code cargo license} command is required \\
to run the {.fun write_license_note} function.",
"*" = "Please install cargo-license \\
({.url https://crates.io/crates/cargo-license}) first.",

Check warning on line 39 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L36-L39

Added lines #L36 - L39 were not covered by tests
i = "Run {.code cargo install cargo-license} from your terminal."
),
class = "rextendr_error"
)
}

manifest_file <- rprojroot::find_package_root_file("src", "rust", "Cargo.toml", path = path)
outfile <- rprojroot::find_package_root_file("LICENSE.note", path = path)
rust_folder <- rprojroot::find_package_root_file(
"src", "rust",
path = path
)

Check warning on line 49 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L46-L49

Added lines #L46 - L49 were not covered by tests

manifest_path <- normalizePath(
file.path(rust_folder, "Cargo.toml"),
winslash = "/",
mustWork = FALSE
)

Check warning on line 55 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L51-L55

Added lines #L51 - L55 were not covered by tests

if (!isTRUE(force) && file.exists(outfile)) {
outfile <- rprojroot::find_package_root_file(
"LICENSE.note",
path = path
)

Check warning on line 60 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L57-L60

Added lines #L57 - L60 were not covered by tests

if (isFALSE(force) && file.exists(outfile)) {

Check warning on line 62 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L62

Added line #L62 was not covered by tests
cli::cli_abort(
c(
"LICENSE.note already exists.",
"If you want to regenerate LICENSE.note, set `force = TRUE` to {.fun write_license_note}."
"If you want to regenerate LICENSE.note, \\
set `force = TRUE` to {.fun write_license_note}."

Check warning on line 67 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L66-L67

Added lines #L66 - L67 were not covered by tests
),
class = "rextendr_error"
)
}

list_license <- processx::run(
"cargo",
c(
"license",
"--authors",
"--json",
"--avoid-build-deps",
"--avoid-dev-deps",
"--manifest-path", manifest_file
)
)$stdout %>%
jsonlite::parse_json()

package_names <- processx::run(
"cargo",
c(
"metadata",
"--no-deps",
"--format-version", "1",
"--manifest-path", manifest_file
)
)$stdout %>%
jsonlite::parse_json() %>%
purrr::pluck("packages") %>%
purrr::map_chr("name")
args <- c(
"license",
"--authors",
"--json",
"--avoid-build-deps",
"--avoid-dev-deps",
"--manifest-path", manifest_path
)

Check warning on line 80 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L73-L80

Added lines #L73 - L80 were not covered by tests

out <- processx::run(
command = "cargo",
args = args,
error_on_status = TRUE,
wd = rust_folder,
echo_cmd = echo,
echo = echo,
env = get_cargo_envvars()
)

Check warning on line 90 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L82-L90

Added lines #L82 - L90 were not covered by tests

licenses <- jsonlite::parse_json(
out[["stdout"]],
simplifyDataFrame = TRUE
)

Check warning on line 95 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L92-L95

Added lines #L92 - L95 were not covered by tests

metadata <- read_cargo_metadata(path = path)

Check warning on line 97 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L97

Added line #L97 was not covered by tests

package_names <- metadata[["packages"]][["dependencies"]][[1]][["name"]]

Check warning on line 99 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L99

Added line #L99 was not covered by tests

licenses <- licenses[licenses[["name"]] %in% package_names, ]

Check warning on line 101 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L101

Added line #L101 was not covered by tests

.prep_authors <- function(authors, package) {

Check warning on line 103 in R/license_note.R

View workflow job for this annotation

GitHub Actions / lint

file=R/license_note.R,line=103,col=3,[object_usage_linter] local variable '.prep_authors' assigned but may not be used
ifelse(!is.null(authors), authors, paste0(package, " authors")) %>%
stringi::stri_replace_all_regex(r"(\ <.+?>)", "") %>%
stringi::stri_replace_all_regex(r"(\|)", ", ")
authors <- ifelse(
is.na(authors),
paste0(package, " authors"),
authors
)

Check warning on line 108 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L104-L108

Added lines #L104 - L108 were not covered by tests

authors <- stringi::stri_replace_all_regex(authors, r"(\ <.+?>)", "")

Check warning on line 110 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L110

Added line #L110 was not covered by tests

stringi::stri_replace_all_regex(authors, r"(\|)", ", ")

Check warning on line 112 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L112

Added line #L112 was not covered by tests
}

separator <- "-------------------------------------------------------------"

note_header <- paste0(
"The binary compiled from the source code of this package contains the following Rust crates:\n",
"\n",
"\n",
separator
note_header <- glue::glue(
"
The binary compiled from the source code of this package \\
contains the following Rust crates:

Check warning on line 120 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L117-L120

Added lines #L117 - L120 were not covered by tests
{separator}
"

Check warning on line 124 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L123-L124

Added lines #L123 - L124 were not covered by tests
)

note_body <- list_license %>%
purrr::discard(function(x) x$name %in% package_names) %>%
purrr::map_chr(
function(x) {
paste0(
"\n",
"Name: ", x$name, "\n",
"Repository: ", x$repository, "\n",
"Authors: ", .prep_authors(x$authors, x$name), "\n",
"License: ", x$license, "\n",
"\n",
separator
)
}
)
note_body <- glue::glue_data(
licenses,
"

Check warning on line 129 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L127-L129

Added lines #L127 - L129 were not covered by tests
Name: {name}
Repository: {repository}
Authors: {.prep_authors(authors, name)}
License: {license}

Check warning on line 134 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L131-L134

Added lines #L131 - L134 were not covered by tests
{separator}
"
)

Check warning on line 138 in R/license_note.R

View check run for this annotation

Codecov / codecov/patch

R/license_note.R#L136-L138

Added lines #L136 - L138 were not covered by tests

write_file(
text = c(note_header, note_body),
Expand Down
31 changes: 20 additions & 11 deletions R/read_cargo_metadata.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#' Retrieve metadata for packages and workspaces
#'
#' @param path character scalar, the R package directory
#' @param echo logical scalar, should cargo command and outputs be printed to
#' console (default is TRUE)
#'
#' @details
#' For more details, see
Expand All @@ -25,22 +27,29 @@
#' read_cargo_metadata()
#' }
#'
read_cargo_metadata <- function(path = ".") {
read_cargo_metadata <- function(path = ".", echo = TRUE) {
check_string(path, class = "rextendr_error")
check_bool(echo, class = "rextendr_error")

root <- rprojroot::find_package_root_file(path = path)

rust_folder <- normalizePath(
file.path(root, "src", "rust"),
winslash = "/",
mustWork = FALSE
rust_folder <- rprojroot::find_package_root_file(
"src", "rust",
path = path
)

args <- c("metadata", "--format-version=1", "--no-deps")

out <- processx::run(
"cargo",
args = c("metadata", "--format-version=1", "--no-deps"),
wd = rust_folder
command = "cargo",
args = args,
error_on_status = TRUE,
wd = rust_folder,
echo_cmd = echo,
echo = echo,
env = get_cargo_envvars()
)

jsonlite::fromJSON(out[["stdout"]])
jsonlite::parse_json(
out[["stdout"]],
simplifyDataFrame = TRUE
)
}
Loading

0 comments on commit 4d1f41b

Please sign in to comment.