-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor cargo-processx functions (#397)
* refactor cargo-processx functions * set display color option * make --no-deps optional in read_cargo_metadata * fix lintr issues * use updated read_cargo_metadata * replace missing values in license note * remove error tests for write_license_note * exclude current package from license note * update license note snapshot * fix lintr issue * devtools::document * fix roxygen typo * add replace_na utility * add run_cargo utility * use run_cargo * use run_cargo * pass root to clean_dll * replace glue with paste, update snapshot to reflect new unicode license * devtools::document() * appease codecov. modify docs. and refactor run_cargo * lintr --------- Co-authored-by: Josiah Parry <[email protected]>
- Loading branch information
1 parent
d8689d9
commit 3ee8ae3
Showing
18 changed files
with
401 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,97 +1,140 @@ | ||
#' 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 | ||
#' @return No return value, called for side effects. | ||
#' LICENSE.note generated by this function contains information about all | ||
#' recursive dependencies in Rust crate. | ||
#' | ||
#' @param path character scalar, the R package directory | ||
#' @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 text printed to LICENSE.note (invisibly). | ||
#' | ||
#' @export | ||
write_license_note <- function(path = ".", quiet = FALSE, force = TRUE) { | ||
if (!cargo_command_available(c("license", "--help"))) { | ||
#' | ||
#' @examples | ||
#' \dontrun{ | ||
#' write_license_note() | ||
#' } | ||
write_license_note <- function( | ||
path = ".", | ||
quiet = FALSE, | ||
force = TRUE) { | ||
check_string(path, class = "rextendr_error") | ||
check_bool(quiet, class = "rextendr_error") | ||
check_bool(force, class = "rextendr_error") | ||
|
||
outfile <- rprojroot::find_package_root_file( | ||
"LICENSE.note", | ||
path = path | ||
) | ||
|
||
args <- c( | ||
"metadata", | ||
"--format-version=1" | ||
) | ||
|
||
metadata <- run_cargo( | ||
args, | ||
wd = find_extendr_crate(path = path), | ||
echo = FALSE, | ||
parse_json = TRUE | ||
) | ||
|
||
packages <- metadata[["packages"]] | ||
|
||
# did we actually get the recursive dependency metadata we need? | ||
required_variables <- c("name", "repository", "authors", "license", "id") | ||
|
||
packages_exist <- is.data.frame(packages) && | ||
!is.null(packages) && | ||
nrow(packages) > 0 && | ||
all(required_variables %in% names(packages)) | ||
|
||
if (!packages_exist) { | ||
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.", | ||
i = "Run {.code cargo install cargo-license} from your terminal." | ||
), | ||
"Unable to write LICENSE.note.", | ||
"Metadata for recursive dependencies not found.", | ||
call = rlang::caller_call(), | ||
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) | ||
# exclude current package from LICENSE.note | ||
current_package <- metadata[["resolve"]][["root"]] | ||
|
||
current_package_exists <- length(current_package) == 1 && | ||
is.character(current_package) && | ||
!is.null(current_package) | ||
|
||
if (!isTRUE(force) && file.exists(outfile)) { | ||
if (!current_package_exists) { | ||
cli::cli_abort( | ||
c( | ||
"LICENSE.note already exists.", | ||
"If you want to regenerate LICENSE.note, set `force = TRUE` to {.fun write_license_note}." | ||
), | ||
"Unable to write LICENSE.note.", | ||
"Failed to identify current Rust crate.", | ||
call = rlang::caller_call(), | ||
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") | ||
|
||
.prep_authors <- function(authors, package) { | ||
ifelse(!is.null(authors), authors, paste0(package, " authors")) %>% | ||
stringi::stri_replace_all_regex(r"(\ <.+?>)", "") %>% | ||
stringi::stri_replace_all_regex(r"(\|)", ", ") | ||
} | ||
packages <- packages[packages[["id"]] != current_package, ] | ||
|
||
# replace missing values | ||
packages[["respository"]] <- replace_na( | ||
packages[["repository"]], | ||
"unknown" | ||
) | ||
|
||
packages[["licenses"]] <- replace_na( | ||
packages[["repository"]], | ||
"not provided" | ||
) | ||
|
||
# remove email addresses and special characters and combine all authors | ||
# of a crate into a single character scalar | ||
packages[["authors"]] <- unlist(Map( | ||
prep_authors, | ||
packages[["authors"]], | ||
packages[["name"]] | ||
)) | ||
|
||
separator <- "-------------------------------------------------------------" | ||
|
||
note_header <- paste0( | ||
"The binary compiled from the source code of this package contains the following Rust crates:\n", | ||
"The binary compiled from the source code of this package ", | ||
"contains the following Rust crates:\n", | ||
"\n", | ||
"\n", | ||
separator | ||
) | ||
|
||
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 <- paste0( | ||
"\n", | ||
"Name: ", packages[["name"]], "\n", | ||
"Repository: ", packages[["repository"]], "\n", | ||
"Authors: ", packages[["authors"]], "\n", | ||
"License: ", packages[["license"]], "\n", | ||
"\n", | ||
separator | ||
) | ||
|
||
write_file( | ||
text = c(note_header, note_body), | ||
path = outfile, | ||
search_root_from = path, | ||
quiet = quiet | ||
quiet = quiet, | ||
overwrite = force | ||
) | ||
} | ||
|
||
prep_authors <- function(authors, package) { | ||
authors <- ifelse( | ||
is.na(authors), | ||
paste0(package, " authors"), | ||
authors | ||
) | ||
|
||
authors <- stringi::stri_replace_all_regex(authors, r"(\ <.+?>)", "") | ||
|
||
paste0(authors, collapse = ", ") | ||
} |
Oops, something went wrong.