Skip to content

Commit

Permalink
new devel version with news funs
Browse files Browse the repository at this point in the history
  • Loading branch information
Polkas committed Sep 8, 2024
1 parent 0112ced commit bdeeef8
Show file tree
Hide file tree
Showing 20 changed files with 461 additions and 74 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: pacs
Title: Supplementary Tools for R Packages Developers
Version: 0.4.10
Version: 0.4.10.9000
Authors@R:
person(given = "Maciej",
family = "Nasinski",
Expand All @@ -24,7 +24,7 @@ BugReports: https://github.com/Polkas/pacs/issues
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.1
RoxygenNote: 7.2.2
Depends: R (>= 3.5.0)
Imports:
curl,
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export(match_flavors)
export(pac_checkpage)
export(pac_checkred)
export(pac_compare_namespace)
export(pac_compare_news)
export(pac_compare_versions)
export(pac_deps)
export(pac_deps_dev)
Expand All @@ -28,6 +29,7 @@ export(pac_islast)
export(pac_last)
export(pac_lifeduration)
export(pac_namespace)
export(pac_news)
export(pac_size)
export(pac_timemachine)
export(pac_true_size)
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# pacs 0.4.10.9000

* add NEWS file related functions, pac_news and pac_compare_news.
* improve code base.

# pacs 0.4.10

* remove the not needed testthat log file.
Expand Down
85 changes: 75 additions & 10 deletions R/comapre.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@ pac_compare_versions <- function(pac,
lib.loc = .libPaths(),
repos = "https://cran.rstudio.com/") {
fields <- expand_dependency(fields)
stopifnot((length(pac) == 1) && is.character(pac))
stopifnot(is.null(old) || (length(old) == 1) && is.character(old))
stopifnot(is.null(new) || (length(new) == 1) && is.character(new))
stopifnot(is.character(repos))
stopifnot(is.null(lib.loc) || (all(lib.loc %in% .libPaths()) && (length(list.files(lib.loc)) > 0)))
validate_compare_input(pac, old, new, lib.loc, repos)
stopifnot(is_online())


if (isFALSE(pac_isin(pac, repos))) {
return(NA)
}
Expand Down Expand Up @@ -94,13 +91,10 @@ pac_compare_namespace <- function(pac,
new = NULL,
lib.loc = .libPaths(),
repos = "https://cran.rstudio.com/") {
stopifnot((length(pac) == 1) && is.character(pac))
stopifnot(is.null(old) || (length(old) == 1) && is.character(old))
stopifnot(is.null(new) || (length(new) == 1) && is.character(new))
stopifnot(is.character(repos))
stopifnot(is.null(lib.loc) || (all(lib.loc %in% .libPaths()) && (length(list.files(lib.loc)) > 0)))
validate_compare_input(pac, old, new, lib.loc, repos)
stopifnot(is_online())


if (isFALSE(pac_isin(pac, repos))) {
return(NA)
}
Expand Down Expand Up @@ -148,3 +142,74 @@ pac_compare_namespace <- function(pac,

structure(result, package = pac, old = old, new = new)
}

#' Compare NEWS files between specific CRAN packages versions
#' @description using the remote github CRAN mirror to compare NEWS files between specific packages versions.
#' @inheritParams standard_args
#' @param repos `character` vector repositories URLs to use. Used only for the validation. Default `https://cran.rstudio.com/`
#' @return `character` with NEWS content between specific versions.
#' @export
#' @examples
#' \dontrun{
#' pacs::pac_compare_news("shiny", "1.0.0", "1.6.0")
#' # local version to newest one
#' pacs::pac_compare_news("shiny")
#' }
pac_compare_news <- function(pac,
old = NULL,
new = NULL,
lib.loc = .libPaths(),
repos = "https://cran.rstudio.com/") {


validate_compare_input(pac, old, new, lib.loc, repos)
stopifnot(is_online())

if (isFALSE(pac_isin(pac, repos))) {
return(NA)
}

if (is.null(old)) {
stopifnot(pac %in% rownames(installed_packages(lib.loc = lib.loc)))
old <- pac_description(pac, local = TRUE)$Version
}

if (is.null(new)) {
new <- pac_last(pac)
}

stopifnot(utils::compareVersion(new, old) >= 0)

version_pattern <- function(version) {
paste0("#.*", version)
}

last_version <- pac_last(pac, repos = repos)
pac_news <- pac_news(pac, last_version, lib.loc = lib.loc, repos = repos)


old_version_reg <- regexpr(version_pattern(old), pac_news)
which_matched_old <- which(old_version_reg > 0)[1]
old_version_pos <- if (which_matched_old > 0) {
which_matched_old
} else {
NA
}

new_version_reg <- regexpr(version_pattern(new), pac_news)
which_matched_new <- which(new_version_reg > 0)[1]
new_version_pos <- if (which_matched_new > 0) {
which_matched_new
} else {
NA
}

if (is.na(old_version_pos) || is.na(new_version_pos)) {
return(NA)
}

result <- pac_news[new_version_pos:(old_version_pos - 1)]
result
}


10 changes: 2 additions & 8 deletions R/description.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ pac_description <- function(pac,
local = FALSE,
lib.loc = .libPaths(),
repos = "https://cran.rstudio.com/") {
stopifnot((isFALSE(local)) ||
(isTRUE(local) && (is.null(version) || isTRUE(utils::packageDescription(pac, lib.loc = lib.loc)$Version == version))))
stopifnot(all(c(is.null(version), is.null(at))) || xor(!is.null(version), !is.null(at)))
stopifnot(is.null(at) || inherits(at, "Date"))
stopifnot(length(pac) == 1 && is.character(pac))
stopifnot(is.null(lib.loc) || (all(lib.loc %in% .libPaths()) && (length(list.files(lib.loc)) > 0)))
stopifnot(is.null(version) || (length(version) == 1 && is.character(version)))
validate_pac_input(pac, version, at, local, lib.loc, repos)

is_installed <- isTRUE(pac %in% rownames(installed_packages(lib.loc = lib.loc)))
if ((!is_installed && local) || (!local && !is_online())) {
Expand Down Expand Up @@ -83,7 +77,7 @@ pac_description_dcf_raw <- function(pac, version, repos = "https://cran.rstudio.
silent = TRUE
)
if (inherits(tt, "try-error")) {
result <- cran_archive_file(pac, version, repos, "DESCRIPTION")
result <- cran_archive_file(pac, version, "DESCRIPTION", repos)
} else {
result <- as.list(read.dcf(ee)[1, ])
}
Expand Down
10 changes: 2 additions & 8 deletions R/namespace.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,7 @@
#' pacs::pac_namespace("memoise", local = TRUE)
#' }
pac_namespace <- function(pac, version = NULL, at = NULL, local = FALSE, lib.loc = .libPaths(), repos = "https://cran.rstudio.com/") {
stopifnot((isFALSE(local)) ||
(isTRUE(local) && (is.null(version) || isTRUE(utils::packageDescription(pac, lib.loc = lib.loc)$Version == version))))
stopifnot(all(c(is.null(version), is.null(at))) || xor(!is.null(version), !is.null(at)))
stopifnot(is.null(at) || inherits(at, "Date"))
stopifnot(length(pac) == 1 && is.character(pac))
stopifnot(is.null(lib.loc) || (all(lib.loc %in% .libPaths()) && (length(list.files(lib.loc)) > 0)))
stopifnot(is.null(version) || (length(version) == 1 && is.character(version)))
validate_pac_input(pac, version, at, local, lib.loc, repos)

is_installed <- isTRUE(pac %in% rownames(installed_packages(lib.loc = lib.loc)))
if ((!is_installed && local) || (!local && !is_online())) {
Expand Down Expand Up @@ -85,7 +79,7 @@ pac_readnamespace_raw <- function(pac, version, repos = "https://cran.rstudio.co
silent = TRUE
)
if (inherits(tt, "try-error")) {
result <- cran_archive_file(pac, version, repos, "NAMESPACE")
result <- cran_archive_file(pac, version, "NAMESPACE", repos)
} else {
result <- readLines(ee, warn = FALSE)
unlink(ee)
Expand Down
93 changes: 93 additions & 0 deletions R/news.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#' Get NEWS for a package
#' @description Get NEWS for a package from CRAN or local
#' @inheritParams standard_args
#' @param repos `character` vector repositories URLs to use. Used only for the validation. Default `https://cran.rstudio.com/`
#' @return `character` with NEWS content.
#' @note Results are cached for 30 minutes with `memoise` package.
#' @export
#' @examples
#' \dontrun{
#' pacs::pac_news("dplyr", version = "0.8.0")
#' pacs::pac_news("dplyr", at = as.Date("2019-02-01"))
#' }
pac_news <- function(
pac,
version = NULL,
at = NULL,
local = FALSE,
lib.loc = .libPaths(),
repos = "https://cran.rstudio.com/"
) {

validate_pac_input(pac, version, at, local, lib.loc, repos)

is_installed <- isTRUE(pac %in% rownames(installed_packages(lib.loc = lib.loc)))
if ((!is_installed && local) || (!local && !is_online())) {
return(NA)
}

version_installed <- if (is_installed) {
utils::packageDescription(pac)$Version
} else {
NA
}
version_null <- is.null(version)

if (local && is_installed && is.null(at) && (version_null || isTRUE(utils::compareVersion(version, version_installed) == 0))) {
news_name <- intersect(list.files(system.file(package = pac)), c("NEWS.md", "NEWS", "NEWS.Rmd"))
if (length(news_name) == 0) {
return(NA)
}
return(readLines(system.file(package = pac, news_name[1]), warn = FALSE))
} else if (isTRUE(is_isin(pac, "https://cran.rstudio.com/"))) {
last_version <- pac_last(pac, repos = repos)
version <- if (!version_null) {
version
} else if (!is.null(at)) {
vv <- utils::tail(pac_timemachine(pac, at = at)$Version, 1)
if (isNA(vv) || is.null(vv)) {
return(NA)
}
vv
} else {
last_version
}
news_lines <- pac_readnews(pac, version, repos)
if (isTRUE(is.na(news_lines))) {
return(NA)
} else if (length(news_lines) == 0) {
return(NA)
} else {
return(news_lines)
}
} else {
return(NA)
}
}


pac_readnews_raw <- function(pac, version, repos = "https://cran.rstudio.com/") {
ee <- tempfile()
d_url <- sprintf(
"https://raw.githubusercontent.com/cran/%s/%s/NEWS",
pac,
version
)
tt <- try(
{
suppressWarnings(utils::download.file(d_url,
destfile = ee,
quiet = TRUE
))
},
silent = TRUE
)
if (inherits(tt, "try-error")) {
result <- cran_archive_file(pac, version, "NEWS", repos)
} else {
res <- readLines(ee)
unlink(ee)
}
}

pac_readnews <- memoise::memoise(pac_readnews_raw, cache = cachem::cache_mem(max_age = 30 * 60))
59 changes: 59 additions & 0 deletions R/read_file_cran.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#' Read a file from CRAN
#' @description Read a file from CRAN package source.
#' @param pac `character` package name.
#' @param version `character` package version.
#' @param repos `character` vector repositories URLs to use. Used only for the validation. Default `https://cran.rstudio.com/`
#' @param file `character` file name to read. Possible values are `DESCRIPTION` and `NAMESPACE`.
#' @keywords internal
cran_archive_file <- function(pac, version, file, repos = "https://cran.rstudio.com/") {
last_version <- pac_last(pac, repos)

if (isTRUE(!is.null(version) && version != last_version)) {
base_url <- sprintf("https://cran.r-project.org/src/contrib/Archive/%s", pac)
} else {
base_url <- "https://cran.r-project.org/src/contrib"
version <- last_version
}

d_url <- sprintf(
"%s/%s_%s.tar.gz",
base_url,
pac,
version
)

temp_tar <- tempfile(fileext = ".tar.gz")

download <- try(
expr = {
suppressWarnings(utils::download.file(d_url,
destfile = temp_tar,
quiet = TRUE
))
},
silent = TRUE
)

if (inherits(download, "try-error")) {
result <- structure(list(), package = pac, version = version)
} else {
temp_dir <- tempdir()
utils::untar(temp_tar, exdir = temp_dir)
if (file == "DESCRIPTION") {
result <- as.list(read.dcf(file.path(temp_dir, pac, "DESCRIPTION"))[1, ])
} else if (file == "NAMESPACE") {
result <- readLines(file.path(temp_dir, pac, "NAMESPACE"), warn = FALSE)
} else if (file == "NEWS") {
news_name <- intersect(list.files(file.path(temp_dir, pac)), c("NEWS.md", "NEWS", "NEWS.Rmd"))
if (length(news_name) == 0) {
warning("NEWS file not found")
return(NA)
}
result <- readLines(file.path(temp_dir, pac, news_name[1]), warn = FALSE)
} else {
stop("Invalid file name")
}
}
unlink(temp_tar)
result
}
32 changes: 32 additions & 0 deletions R/read_file_github.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#' Read a file from a GitHub CRAN repository
#' @description Read a file from a GitHub CRAN repository.
#' @param pac `character` package name.
#' @param version `character` package version.
#' @param file `character` file name to read. Possible values are `DESCRIPTION` and `NAMESPACE`.
#' @param repos `character` vector repositories URLs to use. Used only for the validation. Default `https://cran.rstudio.com/`
#' @note if the file is not found in the GitHub repository, it will try to find it in the CRAN archive.
#' @keywords internal
read_github_file <- function(pac, version, file, repos = "https://cran.rstudio.com/") {
ee <- tempfile()
d_url <- sprintf(
"https://raw.githubusercontent.com/cran/%s/%s/%s",
pac,
version,
file
)
tt <- try(
expr = {
suppressWarnings(utils::download.file(d_url,
destfile = ee,
quiet = TRUE
))
},
silent = TRUE
)
if (inherits(tt, "try-error")) {
result <- cran_archive_file(pac, version, repos, file)
} else {
res <- readLines(ee)
unlink(ee)
}
}
Loading

0 comments on commit bdeeef8

Please sign in to comment.