diff --git a/DESCRIPTION b/DESCRIPTION index edadb31..0401a17 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -9,12 +9,12 @@ Maintainer: Bob Rudis Description: SourceHut () provides support for collaborative development of anything that can can be managed by Git or Mecurial version control systems. Tools are provided to query and ochestrate a wide variety of SourceHut servies. -URL: https://gitlab.com/hrbrmstr/sourcehut -BugReports: https://gitlab.com/hrbrmstr/sourcehut/issues +URL: https://git.sr.ht/~hrbrmstr/sourcehut +BugReports: https://todo.sr.ht/~hrbrmstr/sourcehut Encoding: UTF-8 License: MIT + file LICENSE Suggests: covr, tinytest Depends: R (>= 3.2.0) -Imports: httr, jsonlite, usethis, crayon, desc, rprojroot +Imports: httr, jsonlite, usethis, crayon, desc, rprojroot, glue Roxygen: list(markdown = TRUE) RoxygenNote: 6.1.1 diff --git a/NAMESPACE b/NAMESPACE index 02dfa9b..3679961 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,9 +1,17 @@ # Generated by roxygen2: do not edit by hand +export(git_repos) +export(git_user) +export(meta_audit) +export(meta_pgp_keys) +export(meta_profile) +export(meta_ssh_keys) +export(sourcehut_pat) export(sourcehut_user) export(use_builds) import(crayon) import(desc) +import(glue) import(httr) import(rprojroot) import(usethis) diff --git a/R/aaa.R b/R/aaa.R new file mode 100644 index 0000000..81f5dbf --- /dev/null +++ b/R/aaa.R @@ -0,0 +1,7 @@ +httr::user_agent( + sprintf( + "sourcehut package v%s: (<%s>)", + utils::packageVersion("sourcehut"), + utils::packageDescription("sourcehut")[["URL"]] + ) +) -> .SOURCEHUT_UA \ No newline at end of file diff --git a/R/authorize.R b/R/authorize.R new file mode 100644 index 0000000..9833b5e --- /dev/null +++ b/R/authorize.R @@ -0,0 +1,3 @@ +sh_authorize <- function(pat = sourcehut_pat()) { + httr::add_headers(`Authorization` = glue::glue("token {pat}")) +} \ No newline at end of file diff --git a/R/git.R b/R/git.R new file mode 100644 index 0000000..11b6a7d --- /dev/null +++ b/R/git.R @@ -0,0 +1,37 @@ +#' Retrieve metadata about yourself or another SourceHut user +#' +#' @param username if not `NULL` then a valid SourceHut username +#' @param pat see [sourcehut_pat()] +#' @references +#' @export +git_user <- function(username = NULL, pat = sourcehut_pat()) { + + username <- if (!is.null(username)) glue::glue("/{make_canonical(username)}") else "" + + route_url <- glue::glue("https://git.sr.ht/api/user{username}") + + res <- make_get_request(route_url = route_url, pat = pat) + process_response(res) + +} + +#' Retrieve metadata about repositories +#' +#' @param username if not `NULL` then a valid SourceHut username +#' @param next_id if there is a `next` field in the API response and you wish +#' to paginate through the results, feed the value of `next` to +#' the `next_id` parameter. +#' @param pat see [sourcehut_pat()] +#' @references +#' @export +git_repos <- function(username = NULL, next_id = 1, pat = sourcehut_pat()) { + + username <- if (!is.null(username)) glue::glue("/{make_canonical(username)}") else "" + + route_url <- glue::glue("https://git.sr.ht/api{username}/repos") + + res <- make_get_request(route_url = route_url, next_id = next_id, pat = pat) + process_response(res) + +} + diff --git a/R/make-canonical.R b/R/make-canonical.R new file mode 100644 index 0000000..e857885 --- /dev/null +++ b/R/make-canonical.R @@ -0,0 +1,3 @@ +make_canonical <- function(username) { + if (!startsWith(username, "~")) glue::glue("~{username}") else username +} \ No newline at end of file diff --git a/R/make-get-request.R b/R/make-get-request.R new file mode 100644 index 0000000..3cd0689 --- /dev/null +++ b/R/make-get-request.R @@ -0,0 +1,17 @@ +make_get_request <- function(route_url, next_id = NULL, query = list(), ..., pat = sourcehut_pat()) { + + if (!is.null(next_id)) { + if (next_id > 1) { + query[["start"]] = next_id + } + } + + httr::GET( + url = route_url, + sh_authorize(pat), + .SOURCEHUT_UA, + query = query, + ... + ) + +} \ No newline at end of file diff --git a/R/meta.R b/R/meta.R new file mode 100644 index 0000000..d0fff17 --- /dev/null +++ b/R/meta.R @@ -0,0 +1,66 @@ +#' Retrieve metadata about yourself +#' +#' @param pat see [sourcehut_pat()] +#' @references +#' @export +meta_profile <- function(pat = sourcehut_pat()) { + + route_url <- "https://meta.sr.ht/api/user/profile" + + res <- make_get_request(route_url = route_url, pat = pat) + process_response(res) + +} + +#' Retrieve your audit log +#' +#' @inheritParams meta_profile +#' @export +meta_audit <- function(pat = sourcehut_pat()) { + + route_url <- "https://meta.sr.ht/api/user/audit-log" + + res <- make_get_request(route_url = route_url, pat = pat) + process_response(res) + +} + +#' Retrieve your SSH keys +#' +#' @inheritParams meta_profile +#' @param id if not `NULL` then a valid key ID +#' @param next_id if there is a `next` field in the API response and you wish +#' to paginate through the results, feed the value of `next` to +#' the `next_id` parameter. +#' @export +meta_ssh_keys <- function(id = NULL, next_id = 1, pat = sourcehut_pat()) { + + id <- if (!is.null(id)) glue::glue("/{id}") else "" + + route_url <- glue::glue("https://meta.sr.ht/api/user/ssh-keys{id}") + + res <- make_get_request(route_url = route_url, next_id = next_id, pat = pat) + process_response(res) + +} + +#' Retrieve your PGP keys +#' +#' @inheritParams meta_profile +#' @inheritParams meta_ssh_keys +#' @rdname meta_profile +#' @export +meta_pgp_keys <- function(id = NULL, next_id = 1, pat = sourcehut_pat()) { + + id <- if (!is.null(id)) glue::glue("/{id}") else "" + + route_url <- glue::glue("https://meta.sr.ht/api/user/pgp-keys{id}") + + res <- make_get_request(route_url = route_url, next_id = next_id, pat = pat) + process_response(res) + +} + + + + diff --git a/R/process-reponse.R b/R/process-reponse.R new file mode 100644 index 0000000..5190372 --- /dev/null +++ b/R/process-reponse.R @@ -0,0 +1,10 @@ +process_response <- function(res) { + + httr::stop_for_status(res) + + out <- httr::content(res, as = "text", encoding = "UTF-8") + out <- jsonlite::fromJSON(out) + + out + +} \ No newline at end of file diff --git a/R/sourcehut-package.R b/R/sourcehut-package.R index 8b7b622..af75be9 100644 --- a/R/sourcehut-package.R +++ b/R/sourcehut-package.R @@ -8,6 +8,6 @@ #' @name sourcehut #' @keywords internal #' @author Bob Rudis (bob@@rud.is) -#' @import httr usethis crayon desc rprojroot +#' @import httr usethis crayon desc rprojroot glue #' @importFrom jsonlite fromJSON "_PACKAGE" diff --git a/R/sourcehut-pat.R b/R/sourcehut-pat.R new file mode 100644 index 0000000..fe82ebf --- /dev/null +++ b/R/sourcehut-pat.R @@ -0,0 +1,32 @@ +#' Get or set SourceHut Personal Access Token +#' +#' @param force force setting a new SourceHut Personal Access Token +#' @return atomic character vector containing the SourceHut Personal Access Token +#' @references +#' @export +sourcehut_pat <- function(force = FALSE) { + + pat <- Sys.getenv('SOURCEHUT_PAT') + if (!identical(pat, "") && !force) { + return(pat) + } + + if (!interactive()) { + stop("Please set env var SOURCEHUT_PAT to your SourceHut Personal Access Token", + call. = FALSE) + } + + message("Couldn't find env var SOURCEHUT_PAT See ?sourcehut_pat for more details.") + message("Please enter your SourceHut personal access token and press enter:") + pat <- readline(": ") + + if (identical(pat, "")) { + stop("SourceHut personal access token entry failed", call. = FALSE) + } + + message("Updating SOURCEHUT_PAT env var") + Sys.setenv(SOURCEHUT_PAT = pat) + + pat + +} \ No newline at end of file diff --git a/R/sourcehut-user.R b/R/sourcehut-user.R index efc40d9..eb3b11b 100644 --- a/R/sourcehut-user.R +++ b/R/sourcehut-user.R @@ -7,8 +7,7 @@ sourcehut_user <- function(force = FALSE) { user <- Sys.getenv('SOURCEHUT_USERNAME') if (!identical(user, "") && !force) { - if (!startsWith(user, "~")) user <- sprintf("~%s", user) - return(user) + return(make_canonical(user)) } if (!interactive()) { @@ -24,10 +23,8 @@ sourcehut_user <- function(force = FALSE) { stop("SourceHut username entry failed", call. = FALSE) } - if (!startsWith(user, "~")) user <- sprintf("~%s", user) - message("Updating SOURCEHUT_USERNAME env var") - Sys.setenv(SOURCEHUT_USERNAME = user) + Sys.setenv(SOURCEHUT_USERNAME = make_canonical(user)) user diff --git a/README.Rmd b/README.Rmd index 5215a8b..cfe3544 100644 --- a/README.Rmd +++ b/README.Rmd @@ -8,7 +8,7 @@ hrbrpkghelpr::global_opts() ``` ```{r badges, results='asis', echo=FALSE, cache=FALSE} -hrbrpkghelpr::stinking_badges() +hrbrpkghelpr::stinking_badges(repo_status = "WIP") ``` ```{r description, results='asis', echo=FALSE, cache=FALSE} diff --git a/README.md b/README.md index a903f8e..a67eda1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -[![Project Status: Active – The project has reached a stable, usable -state and is being actively -developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) +[![Project Status: WIP – Initial development is in progress, but there +has not yet been a stable, usable release suitable for the +public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip) [![Signed by](https://img.shields.io/badge/Keybase-Verified-brightgreen.svg)](https://keybase.io/hrbrmstr) ![Signed commit @@ -12,7 +12,7 @@ Status](https://travis-ci.org/hrbrmstr/sourcehut.svg?branch=master)](https://tra status](https://builds.sr.ht/~hrbrmstr/sourcehut.svg)](https://builds.sr.ht/~hrbrmstr/sourcehut?) ![Minimal R Version](https://img.shields.io/badge/R%3E%3D-3.2.0-blue.svg) -![License](https://img.shields.io/badge/License-AGPL-blue.svg) +![License](https://img.shields.io/badge/License-MIT-blue.svg) # sourcehut @@ -29,6 +29,13 @@ wide variety of SourceHut servies. The following functions are implemented: + - `git_repos`: Retrieve metadata about repositories + - `git_user`: Retrieve metadata about yourself or another SourceHut + user + - `meta_audit`: Retrieve your audit log + - `meta_profile`: Retrieve metadata about yourself + - `meta_ssh_keys`: Retrieve your SSH keys + - `sourcehut_pat`: Get or set SourceHut Personal Access Token - `sourcehut_user`: Get or set SourceHut username value - `use_builds`: Setup .build.yml for SourceHut builds @@ -61,10 +68,10 @@ packageVersion("sourcehut") ## sourcehut Metrics -| Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | -| :--- | -------: | ---: | --: | --: | ----------: | ---: | -------: | --: | -| R | 5 | 0.83 | 71 | 0.9 | 23 | 0.61 | 28 | 0.5 | -| Rmd | 1 | 0.17 | 8 | 0.1 | 15 | 0.39 | 28 | 0.5 | +| Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | +| :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: | +| R | 13 | 0.93 | 155 | 0.95 | 67 | 0.82 | 72 | 0.72 | +| Rmd | 1 | 0.07 | 8 | 0.05 | 15 | 0.18 | 28 | 0.28 | ## Code of Conduct diff --git a/man/git_repos.Rd b/man/git_repos.Rd new file mode 100644 index 0000000..4d631a7 --- /dev/null +++ b/man/git_repos.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/git.R +\name{git_repos} +\alias{git_repos} +\title{Retrieve metadata about repositories} +\usage{ +git_repos(username = NULL, next_id = 1, pat = sourcehut_pat()) +} +\arguments{ +\item{username}{if not \code{NULL} then a valid SourceHut username} + +\item{next_id}{if there is a \code{next} field in the API response and you wish +to paginate through the results, feed the value of \code{next} to +the \code{next_id} parameter.} + +\item{pat}{see \code{\link[=sourcehut_pat]{sourcehut_pat()}}} +} +\description{ +Retrieve metadata about repositories +} +\references{ +\url{https://man.sr.ht/git.sr.ht/api.md} +} diff --git a/man/git_user.Rd b/man/git_user.Rd new file mode 100644 index 0000000..208f0d1 --- /dev/null +++ b/man/git_user.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/git.R +\name{git_user} +\alias{git_user} +\title{Retrieve metadata about yourself or another SourceHut user} +\usage{ +git_user(username = NULL, pat = sourcehut_pat()) +} +\arguments{ +\item{username}{if not \code{NULL} then a valid SourceHut username} + +\item{pat}{see \code{\link[=sourcehut_pat]{sourcehut_pat()}}} +} +\description{ +Retrieve metadata about yourself or another SourceHut user +} +\references{ +\url{https://man.sr.ht/git.sr.ht/api.md} +} diff --git a/man/meta_audit.Rd b/man/meta_audit.Rd new file mode 100644 index 0000000..accfa4b --- /dev/null +++ b/man/meta_audit.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/meta.R +\name{meta_audit} +\alias{meta_audit} +\title{Retrieve your audit log} +\usage{ +meta_audit(pat = sourcehut_pat()) +} +\arguments{ +\item{pat}{see \code{\link[=sourcehut_pat]{sourcehut_pat()}}} +} +\description{ +Retrieve your audit log +} diff --git a/man/meta_profile.Rd b/man/meta_profile.Rd new file mode 100644 index 0000000..4c60293 --- /dev/null +++ b/man/meta_profile.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/meta.R +\name{meta_profile} +\alias{meta_profile} +\alias{meta_pgp_keys} +\title{Retrieve metadata about yourself} +\usage{ +meta_profile(pat = sourcehut_pat()) + +meta_pgp_keys(id = NULL, next_id = 1, pat = sourcehut_pat()) +} +\arguments{ +\item{pat}{see \code{\link[=sourcehut_pat]{sourcehut_pat()}}} + +\item{id}{if not \code{NULL} then a valid key ID} + +\item{next_id}{if there is a \code{next} field in the API response and you wish +to paginate through the results, feed the value of \code{next} to +the \code{next_id} parameter.} +} +\description{ +Retrieve metadata about yourself + +Retrieve your PGP keys +} +\references{ +\url{https://man.sr.ht/meta.sr.ht/user-api.md} +} diff --git a/man/meta_ssh_keys.Rd b/man/meta_ssh_keys.Rd new file mode 100644 index 0000000..9039fce --- /dev/null +++ b/man/meta_ssh_keys.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/meta.R +\name{meta_ssh_keys} +\alias{meta_ssh_keys} +\title{Retrieve your SSH keys} +\usage{ +meta_ssh_keys(id = NULL, next_id = 1, pat = sourcehut_pat()) +} +\arguments{ +\item{id}{if not \code{NULL} then a valid key ID} + +\item{next_id}{if there is a \code{next} field in the API response and you wish +to paginate through the results, feed the value of \code{next} to +the \code{next_id} parameter.} + +\item{pat}{see \code{\link[=sourcehut_pat]{sourcehut_pat()}}} +} +\description{ +Retrieve your SSH keys +} diff --git a/man/sourcehut.Rd b/man/sourcehut.Rd index 58e932a..4058749 100644 --- a/man/sourcehut.Rd +++ b/man/sourcehut.Rd @@ -13,8 +13,8 @@ systems. Tools are provided to query and ochestrate a wide variety of SourceHut \seealso{ Useful links: \itemize{ - \item \url{https://gitlab.com/hrbrmstr/sourcehut} - \item Report bugs at \url{https://gitlab.com/hrbrmstr/sourcehut/issues} + \item \url{https://git.sr.ht/~hrbrmstr/sourcehut} + \item Report bugs at \url{https://todo.sr.ht/~hrbrmstr/sourcehut} } } diff --git a/man/sourcehut_pat.Rd b/man/sourcehut_pat.Rd new file mode 100644 index 0000000..f600947 --- /dev/null +++ b/man/sourcehut_pat.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sourcehut-pat.R +\name{sourcehut_pat} +\alias{sourcehut_pat} +\title{Get or set SourceHut Personal Access Token} +\usage{ +sourcehut_pat(force = FALSE) +} +\arguments{ +\item{force}{force setting a new SourceHut Personal Access Token} +} +\value{ +atomic character vector containing the SourceHut Personal Access Token +} +\description{ +Get or set SourceHut Personal Access Token +} +\references{ +\url{https://meta.sr.ht/oauth/personal-token} +}