Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

removed add_dependencies_to_description() #105

Closed
wants to merge 1 commit into from
Closed
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
151 changes: 14 additions & 137 deletions R/core_manage_dependencies.R
Original file line number Diff line number Diff line change
@@ -1,137 +1,14 @@
#' Searches for external packages and adds them to the Imports field in the description
#'
#' Scans script files (.R, .Rmd, .Rnw, .Rpres, etc.) for external package dependencies indicated by
#' \code{library()}, \code{require()} or \code{::} and adds those packages to the Imports field in
#' the package DESCRIPTION.
#'
#' @param path location of individual file or directory where to search for scripts.
#' @param description_file location of description file to be updated.
#' @param just_packages just give back a character vector of the found packages.
#'
#' @export
add_dependencies_to_description <- function(
path = getwd(),
description_file = "DESCRIPTION",
just_packages = FALSE
) {

# check if directory or single file
if (utils::file_test("-d", path)) {
# if directory, search for all possible R or Rmd files
pattern <- "\\.[rR]$|\\.[rR]md$|\\.[rR]nw$|\\.[rR]pres$"
R_files <- list.files(
path,
pattern = pattern,
ignore.case = TRUE,
recursive = TRUE,
full.names = TRUE
)
} else if (utils::file_test("-f", path)) {
# if file, just copy it into the files list
R_files <- path
} else {
# stop if path doesn't exist at all
stop("File or directory doesn't exist.")
}

# loop over every file
pkgs <- lapply(
R_files,
function(y) {
# read files libe by line
current_file <- readLines(y)
# get libraries explicitly called via library()
library_lines <- grep(pattern = "library", x = current_file, value = TRUE)
l_libs <- strsplit(library_lines, split = "library\\(")
l_libs <- lapply(l_libs, function(x){strsplit(x[2], split = "\\)")})
l_libs <- unlist(l_libs)
# get libraries explicitly called via require()
require_lines <- grep(pattern = "require", x = current_file, value = TRUE)
r_libs <- strsplit(require_lines, split = "require\\(")
r_libs <- lapply(r_libs, function(x){strsplit(x[2], split = "\\)")})
r_libs <- unlist(r_libs)
# get libraries implicitly called via ::
point_lines <- grep(pattern = "::", x = current_file, value = TRUE)
# search for all collections of alphanumeric signs in between the
# line start/a non-alphanumeric sign and ::
p_libs <- regmatches(
point_lines,
gregexpr("(?<=^|[^a-zA-Z0-9])[a-zA-Z0-9]*?(?=::)", point_lines, perl = TRUE)
)
p_libs <- unlist(p_libs)
# merge results for current file
res <- c(l_libs, r_libs, p_libs)
return(unique(res))
}
)

# merge results of every file
pkgs <- unique(unlist(pkgs))
# remove NA and empty string
pkgs <- pkgs[pkgs != "" & !is.na(pkgs)]
# order alphabetically
pkgs <- sort(pkgs)

# remove packages that are not on CRAN
# TODO: keep an eye on that one: https://github.com/ropenscilabs/available
if (curl::has_internet()==TRUE & RCurl::url.exists("https://cran.r-project.org") ==TRUE ) {
pkgs <- pkgs[pkgs %in% utils::available.packages(repos = "https://cran.r-project.org")[,1]==TRUE]
}

# if the just_packages option is selected, just give back the list of packages
if (just_packages) {
return(pkgs)
}

# read DESCRIPTION file
tmp <- readLines(description_file)
# check, if Imports fields is available
if (length(grep("Imports", tmp)) == 0) {
# if no: add it
tmp[length(tmp)+1] <- "Imports:"
}
# get line where Imports starts
i_begin <- grep("Imports", tmp)
# get line where Imports ends (determination via search for next ":")
# if Imports is the last tag, set i_end to the last line
if((i_begin + 1) >= length(tmp)) {
i_end <- length(tmp)
} else {
i_end <- i_begin + grep(":", tmp[(i_begin + 1):length(tmp)])[1] - 1
if(is.na(i_end)) {
i_end <- length(tmp)
}
}
# check which packages are already present in DESCRIPTION
present <- unlist(lapply(
pkgs,
function(x) {
doublespace <- paste0(" ", x, " ")
space <- any(grep(doublespace, tmp))
spacecomma <- paste0(" ", x, ",")
comma <- any(grep(spacecomma, tmp))
spacelinebreak <- paste0(" ", x, "$")
linebreak <- any(grep(spacelinebreak, tmp))
return(space | comma | linebreak)
}
))
# stop if all packages already in DESCRIPTION
if(all(present)) {
stop("All used packages are already in the DESCRIPTION somewhere (Imports, Suggests, Depends).")
}
# create string with missing packages and their version number in correct layout
to_add_version <- unlist(lapply(
pkgs[!present],
function(x) {
# check if package is installed
if(x %in% rownames(installed.packages())) {
paste0(x, " (>= ", utils::packageDescription(x)$Version, ")")
} else {x}
}
))
to_add_final <- paste0("\n ", paste0(to_add_version, collapse = ",\n "))
# add newly created package string to last line of Imports
tmp[i_end] <- paste0(tmp[i_end], ",", to_add_final)
# write result back into DESCRIPTION file
writeLines(text = tmp, con = description_file)
}
#' add_dependencies_to_description() is deprecated
#'
#' Please use \code{attachment::att_to_description()} from https://cran.r-project.org/package=attachment.
#'
#' @param ... nothing
#'
#' @export
add_dependencies_to_description <- function(
...
) {

message("This function is deprecated. Please use attachment::att_to_description().")

}
2 changes: 1 addition & 1 deletion README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ analysis/
- the `references.bib` file has just one item to demonstrate the format. It is ready to insert more reference details.
- you can replace the supplied `csl` file with a different citation style from <https://github.com/citation-style-language/>
- we recommend using the [citr addin](https://github.com/crsh/citr) and [Zotero](https://www.zotero.org/) to efficiently insert citations while writing in an Rmd file
- remember that the `Imports:` field in the `DESCRIPTION` file must include the names of all packages used in analysis documents (e.g. `paper.Rmd`). We have a helper function `rrtools::add_dependencies_to_description()` that will scan the Rmd file, identify libraries used in there, and add them to the `DESCRIPTION` file.
- remember that the `Imports:` field in the `DESCRIPTION` file must include the names of all packages used in analysis documents (e.g. `paper.Rmd`). The [attachment](https://github.com/Thinkr-open/attachment) package provides some useful functions that scan R and Rmd files, identify libraries used in there, and add them to the `DESCRIPTION` file.
- this function has an `data_in_git =` argument, which is `TRUE` by default. If set to `FALSE` you will exclude files in the `data/` directory from being tracked by git and prevent them from appearing on GitHub. You should set `data_in_git = FALSE` if your data files are large (>100 mb is the limit for GitHub) or you do not want to make the data files publicly accessible on GitHub.
- To load your custom code in the `paper.Rmd`, you have a few options. You can write all your R code in chunks in the Rmd, that's the simplest method. Or you can write R code in script files in `/R`, and include `devtools::load_all(".")` at the top of your `paper.Rmd`. Or you can write functions in `/R` and use `library(pkgname)` at the top of your `paper.Rmd`, or omit `library` and preface each function call with `pkgname::`. Up to you to choose whatever seems most natural to you.

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,10 @@ your project: they are meant to be once-off setup functions.
citations while writing in an Rmd file
- remember that the `Imports:` field in the `DESCRIPTION` file must
include the names of all packages used in analysis documents
(e.g. `paper.Rmd`). We have a helper function
`rrtools::add_dependencies_to_description()` that will scan the Rmd
file, identify libraries used in there, and add them to the
`DESCRIPTION` file.
(e.g. `paper.Rmd`). The
[attachment](https://github.com/Thinkr-open/attachment) package
provides some useful functions that scan R and Rmd files, identify
libraries used in there, and add them to the `DESCRIPTION` file.
- this function has an `data_in_git =` argument, which is `TRUE` by
default. If set to `FALSE` you will exclude files in the `data/`
directory from being tracked by git and prevent them from appearing
Expand Down
15 changes: 4 additions & 11 deletions man/add_dependencies_to_description.Rd

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

63 changes: 0 additions & 63 deletions tests/testthat/test_add_dependencies_to_description.R

This file was deleted.