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

Version manifest #9

Merged
merged 8 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
4 changes: 3 additions & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
^LICENSE\.md$
^.*~$
^.*\.json$
^.*\.Rproj$
^\.Rproj\.user$
^LICENSE\.md$
^main$
^pull_request$
^packages\.json$
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*~
*.json
.Rproj.user
.Rhistory
.RData
Expand Down
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: r.releases.utils
Title: Utilities for An R Universe of Package Releases
Description: Utilities for an R universe of package releases.
Version: 0.0.7.9000
Version: 0.0.8
License: MIT + file LICENSE
URL:
https://r-releases.github.io/r.releases.utils/,
Expand Down Expand Up @@ -33,6 +33,7 @@ Imports:
jsonlite,
nanonext,
pkgsearch,
utils,
vctrs
Encoding: UTF-8
Language: en-US
Expand Down
5 changes: 5 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ export(assert_cran_url)
export(assert_package)
export(assert_release_exists)
export(build_universe)
export(get_current_versions)
export(record_versions)
export(review_pull_request)
export(review_pull_requests)
export(try_message)
importFrom(gh,gh)
importFrom(jsonlite,parse_json)
importFrom(jsonlite,read_json)
importFrom(jsonlite,write_json)
importFrom(nanonext,ncurl)
importFrom(nanonext,parse_url)
importFrom(nanonext,status_code)
importFrom(pkgsearch,cran_package)
importFrom(utils,available.packages)
importFrom(utils,compareVersion)
importFrom(vctrs,vec_rbind)
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# r.releases.utils 0.0.7.9000 (development)
# r.releases.utils 0.0.8

* Use R-releases and not `r-releases` to refer to the project.
* Edit bot messages.
* Add `record_versions()`.

# r.releases.utils 0.0.7

Expand Down
3 changes: 2 additions & 1 deletion R/package.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
#' @name r.releases.utils-package
#' @family help
#' @importFrom gh gh
#' @importFrom jsonlite parse_json read_json
#' @importFrom jsonlite parse_json read_json write_json
#' @importFrom nanonext ncurl parse_url status_code
#' @importFrom pkgsearch cran_package
#' @importFrom utils available.packages compareVersion
#' @importFrom vctrs vec_rbind
NULL
102 changes: 102 additions & 0 deletions R/record_versions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#' @title Record the manifest of package versions.
#' @export
#' @description Record the manifest of versions of packages
#' and their hashes.
#' @details This function tracks a manifest containing the current version,
#' the current hash, the highest version ever released, and
#' the hash of the highest version ever released. It uses this information
#' to determine whether the package complies with best
#' practices for version numbers.
#' @return `NULL` (invisibly). Writes a package version manifest
#' and a manifest of version issues as JSON files.
#' @param manifest Character of length 1, file path to the JSON manifest.
#' @param issues Character of length 1, file path to a JSON file
#' which records packages with version issues.
#' @param repos Character string of package repositories to track.
#' @param current A data frame of current versions and hashes of packages
#' in `repos`. This argument is exposed for testing only.
#' @param check_hash Logical of length 1, check hashes when judging package
#' version compliance. This allows [record_versions()] to flag packages
#' that create new releases but keep the same version number.
record_versions <- function(
manifest = "versions.json",
issues = "version_issues.json",
repos = "https://r-releases.r-universe.dev",
current = r.releases.utils::get_current_versions(repos = repos),
shikokuchuo marked this conversation as resolved.
Show resolved Hide resolved
check_hash = TRUE
) {
if (!file.exists(manifest)) {
jsonlite::write_json(x = current, path = manifest, pretty = TRUE)
return(invisible())
}
previous <- read_versions_previous(manifest = manifest)
new <- update_version_manifest(current = current, previous = previous)
jsonlite::write_json(x = new, path = manifest, pretty = TRUE)
aligned <- versions_aligned(manifest = new, check_hash = check_hash)
new_issues <- new[!aligned,, drop = FALSE] # nolint
jsonlite::write_json(x = new_issues, path = issues, pretty = TRUE)
invisible()
}

#' @title Get the current versions of packages
#' @export
#' @keywords internal
#' @description Get the current versions of packages in the repos.
#' @return A data frame of packages with their current versions and hashes.
#' @inheritParams record_versions
get_current_versions <- function(
repos = "https://r-releases.r-universe.dev"
) {
out <- utils::available.packages(repos = repos)
out <- as.data.frame(out)
out <- out[, c("Package", "Version", "MD5sum")]
shikokuchuo marked this conversation as resolved.
Show resolved Hide resolved
colnames(out) <- c("package", "version_current", "hash_current")
rownames(out) <- NULL
out
}

read_versions_previous <- function(manifest) {
out <- jsonlite::read_json(path = manifest)
out <- do.call(what = vctrs::vec_rbind, args = out)
for (field in colnames(out)) {
out[[field]] <- as.character(out[[field]])
}
shikokuchuo marked this conversation as resolved.
Show resolved Hide resolved
if (is.null(out$version_highest)) {
out$version_highest <- out$version_current
}
if (is.null(out$hash_highest)) {
out$hash_highest <- out$hash_current
}
out$version_current <- NULL
out$hash_current <- NULL
out
}

update_version_manifest <- function(current, previous) {
new <- merge(x = current, y = previous, all = TRUE)
incremented <- manifest_compare_versions(manifest = new) > 0.5
shikokuchuo marked this conversation as resolved.
Show resolved Hide resolved
new$version_highest[incremented] <- new$version_current[incremented]
new$hash_highest[incremented] <- new$hash_current[incremented]
new
}

manifest_compare_versions <- function(manifest) {
apply(
X = manifest,
MARGIN = 1L,
FUN = function(row) {
utils::compareVersion(
a = .subset2(row, "version_current"),
b = .subset2(row, "version_highest")
)
}
)
}

versions_aligned <- function(manifest, check_hash) {
aligned <- manifest$version_current == manifest$version_highest
if (check_hash) {
aligned <- aligned & (manifest$hash_current == manifest$hash_highest)
}
aligned
}
18 changes: 18 additions & 0 deletions man/get_current_versions.Rd

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

44 changes: 44 additions & 0 deletions man/record_versions.Rd

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

Loading