Skip to content
Merged
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
69 changes: 69 additions & 0 deletions crates/ark/src/modules/positron/packages_pane.R
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,75 @@
as.list(version)
}

# Return detail fields for a single installed package by name.
#' @export
.ps.rpc.pkg_detail <- function(name) {
if (!nzchar(name)) {
return(NULL)
}
fields <- c(
"Title",
"Author",
"Maintainer",
"License",
"Repository",
"Date/Publication"
)
# Read straight from the package's DESCRIPTION. packageDescription() returns
# a length-1 NA (and warns) when the package isn't installed, which is far
# cheaper than installed.packages() -- that parses every installed package's
# DESCRIPTION just to answer an existence check.
d <- suppressWarnings(utils::packageDescription(name, fields = fields))
if (!inherits(d, "packageDescription")) {
return(NULL)
}

# Collapse DCF whitespace; return NULL for missing (NA) fields.
clean <- function(x) {
if (is.null(x) || is.na(x)) {
return(NULL)
}
trimws(gsub("\\s+", " ", x, perl = TRUE))
}

# Reduce an R License field to its primary license: the first alternative
# (before "|"), without the "+ file LICENSE" clause.
primary_license <- function(x) {
if (is.null(x)) {
return(NULL)
}
first <- trimws(strsplit(x, "\\|")[[1]][1])
first <- trimws(sub(
"\\s*\\+\\s*file\\s+.*$",
"",
first,
ignore.case = TRUE
))
if (!nzchar(first)) {
return(NULL)
}
first
}

# Prefer Maintainer for author display; fall back to Author.
author <- clean(d$Maintainer)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW a CRAN package absolutely must have a Maintainer. But I suppose this pane could populate from a non-CRAN source? Just thought I'd mention.

if (is.null(author)) {
author <- clean(d$Author)
}

# Drop absent (NULL) fields so the other side only sees populated keys.
out <- list(
name = name,
title = clean(d$Title),
author = author,
license = primary_license(clean(d$License)),
sourceRepository = clean(d$Repository),
publishedDate = clean(d[["Date/Publication"]])
)
Filter(Negate(is.null), out)
}


# Return the list of outdated packages with their latest available versions.
#
# `utils::old.packages()` queries the user's configured repositories, so
Expand Down
Loading