Skip to content

Commit

Permalink
Improvements to standalone header (#1903)
Browse files Browse the repository at this point in the history
* Add ref and host to standalone header

* Add code to generate the standalone

* Make some more changes

* Dogfood it

* Add NEWS bullet

* Use fs

* Update a snapshot

---------

Co-authored-by: Jenny Bryan <[email protected]>
  • Loading branch information
krlmlr and jennybc authored Jul 24, 2024
1 parent 2dab4c2 commit acac3f9
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 25 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# usethis (development version)

* `use_standalone()` inserts an improved header that includes the code needed to
update the standalone file (@krlmlr, #1903).

* `use_release_issue()` and `use_upkeep()` behave better when the user has a
fork. The user is asked just once to choose between `origin` and `upstream` as
the target repo (#2023).
Expand Down
29 changes: 22 additions & 7 deletions R/import-standalone-obj-type.R
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
# Standalone file: do not edit by hand
# Source: <https://github.com/r-lib/rlang/blob/main/R/standalone-obj-type.R>
# Source: https://github.com/r-lib/rlang/blob/HEAD/R/standalone-obj-type.R
# Generated by: usethis::use_standalone("r-lib/rlang", "obj-type")
# ----------------------------------------------------------------------
#
# ---
# repo: r-lib/rlang
# file: standalone-obj-type.R
# last-updated: 2022-10-04
# last-updated: 2024-02-14
# license: https://unlicense.org
# imports: rlang (>= 1.1.0)
# ---
#
# ## Changelog
#
# 2024-02-14:
# - `obj_type_friendly()` now works for S7 objects.
#
# 2023-05-01:
# - `obj_type_friendly()` now only displays the first class of S3 objects.
#
# 2023-03-30:
# - `stop_input_type()` now handles `I()` input literally in `arg`.
#
# 2022-10-04:
# - `obj_type_friendly(value = TRUE)` now shows numeric scalars
# literally.
Expand Down Expand Up @@ -65,7 +75,7 @@ obj_type_friendly <- function(x, value = TRUE) {
if (inherits(x, "quosure")) {
type <- "quosure"
} else {
type <- paste(class(x), collapse = "/")
type <- class(x)[[1L]]
}
return(sprintf("a <%s> object", type))
}
Expand Down Expand Up @@ -261,19 +271,19 @@ vec_type_friendly <- function(x, length = FALSE) {
#' Return OO type
#' @param x Any R object.
#' @return One of `"bare"` (for non-OO objects), `"S3"`, `"S4"`,
#' `"R6"`, or `"R7"`.
#' `"R6"`, or `"S7"`.
#' @noRd
obj_type_oo <- function(x) {
if (!is.object(x)) {
return("bare")
}

class <- inherits(x, c("R6", "R7_object"), which = TRUE)
class <- inherits(x, c("R6", "S7_object"), which = TRUE)

if (class[[1]]) {
"R6"
} else if (class[[2]]) {
"R7"
"S7"
} else if (isS4(x)) {
"S4"
} else {
Expand Down Expand Up @@ -315,10 +325,15 @@ stop_input_type <- function(x,
if (length(what)) {
what <- oxford_comma(what)
}
if (inherits(arg, "AsIs")) {
format_arg <- identity
} else {
format_arg <- cli$format_arg
}

message <- sprintf(
"%s must be %s, not %s.",
cli$format_arg(arg),
format_arg(arg),
what,
obj_type_friendly(x, value = show_value)
)
Expand Down
3 changes: 2 additions & 1 deletion R/import-standalone-types-check.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Standalone file: do not edit by hand
# Source: <https://github.com/r-lib/rlang/blob/main/R/standalone-types-check.R>
# Source: https://github.com/r-lib/rlang/blob/HEAD/R/standalone-types-check.R
# Generated by: usethis::use_standalone("r-lib/rlang", "types-check")
# ----------------------------------------------------------------------
#
# ---
Expand Down
18 changes: 15 additions & 3 deletions R/use_standalone.R
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ use_standalone <- function(repo_spec, file = NULL, ref = NULL, host = NULL) {
dest_path <- path("R", as_standalone_dest_file(file))

lines <- read_github_file(repo_spec, path = src_path, ref = ref, host = host)
lines <- c(standalone_header(repo_spec, src_path), lines)
lines <- c(standalone_header(repo_spec, src_path, ref, host), lines)
write_over(proj_path(dest_path), lines, overwrite = TRUE)

dependencies <- standalone_dependencies(lines, path)
Expand Down Expand Up @@ -156,10 +156,22 @@ as_standalone_dest_file <- function(file) {
gsub("standalone-", "import-standalone-", file)
}

standalone_header <- function(repo_spec, path) {
standalone_header <- function(repo_spec, path, ref = NULL, host = NULL) {
ref_string <- ref %||% "HEAD"
host_string <- host %||% "https://github.com"
source_comment <-
glue("# Source: {host_string}/{repo_spec}/blob/{ref_string}/{path}")

path_string <- path_ext_remove(sub("^standalone-", "", path_file(path)))
ref_string <- if (is.null(ref)) "" else glue(', ref = "{ref}"')
host_string <- if (is.null(host) || host == "https://github.com") "" else glue(', host = "{host}"')
code_hint <- glue('usethis::use_standalone("{repo_spec}", "{path_string}"{ref_string}{host_string})')
generated_comment <- glue('# Generated by: {code_hint}')

c(
"# Standalone file: do not edit by hand",
glue("# Source: <https://github.com/{repo_spec}/blob/main/{path}>"),
source_comment,
generated_comment,
paste0("# ", strrep("-", 72 - 2)),
"#"
)
Expand Down
76 changes: 66 additions & 10 deletions tests/testthat/_snaps/use_standalone.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,69 @@
# standalone_header() works with various inputs

Code
standalone_header("OWNER/REPO", "R/standalone-foo.R")
Output
[1] "# Standalone file: do not edit by hand"
[2] "# Source: https://github.com/OWNER/REPO/blob/HEAD/R/standalone-foo.R"
[3] "# Generated by: usethis::use_standalone(\"OWNER/REPO\", \"foo\")"
[4] "# ----------------------------------------------------------------------"
[5] "#"

---

Code
standalone_header("OWNER/REPO", "R/standalone-foo.R", ref = "blah")
Output
[1] "# Standalone file: do not edit by hand"
[2] "# Source: https://github.com/OWNER/REPO/blob/blah/R/standalone-foo.R"
[3] "# Generated by: usethis::use_standalone(\"OWNER/REPO\", \"foo\", ref = \"blah\")"
[4] "# ----------------------------------------------------------------------"
[5] "#"

---

Code
standalone_header("OWNER/REPO", "R/standalone-foo.R", host = "https://github.com")
Output
[1] "# Standalone file: do not edit by hand"
[2] "# Source: https://github.com/OWNER/REPO/blob/HEAD/R/standalone-foo.R"
[3] "# Generated by: usethis::use_standalone(\"OWNER/REPO\", \"foo\")"
[4] "# ----------------------------------------------------------------------"
[5] "#"

---

Code
standalone_header("OWNER/REPO", "R/standalone-foo.R", host = "https://github.acme.com")
Output
[1] "# Standalone file: do not edit by hand"
[2] "# Source: https://github.acme.com/OWNER/REPO/blob/HEAD/R/standalone-foo.R"
[3] "# Generated by: usethis::use_standalone(\"OWNER/REPO\", \"foo\", host = \"https://github.acme.com\")"
[4] "# ----------------------------------------------------------------------"
[5] "#"

---

Code
standalone_header("OWNER/REPO", "R/standalone-foo.R", ref = "blah", host = "https://github.com")
Output
[1] "# Standalone file: do not edit by hand"
[2] "# Source: https://github.com/OWNER/REPO/blob/blah/R/standalone-foo.R"
[3] "# Generated by: usethis::use_standalone(\"OWNER/REPO\", \"foo\", ref = \"blah\")"
[4] "# ----------------------------------------------------------------------"
[5] "#"

---

Code
standalone_header("OWNER/REPO", "R/standalone-foo.R", ref = "blah", host = "https://github.acme.com")
Output
[1] "# Standalone file: do not edit by hand"
[2] "# Source: https://github.acme.com/OWNER/REPO/blob/blah/R/standalone-foo.R"
[3] "# Generated by: usethis::use_standalone(\"OWNER/REPO\", \"foo\", ref = \"blah\", host = \"https://github.acme.com\")"
[4] "# ----------------------------------------------------------------------"
[5] "#"

# can offer choices

Code
Expand All @@ -12,16 +78,6 @@
! `file` is absent, but must be supplied.
i Possible options are cli, downstream-deps, lazyeval, lifecycle, linked-version, obj-type, purrr, rlang, s3-register, sizes, types-check, vctrs, or zeallot.

# header provides useful summary

Code
standalone_header("r-lib/usethis", "R/standalone-test.R")
Output
[1] "# Standalone file: do not edit by hand"
[2] "# Source: <https://github.com/r-lib/usethis/blob/main/R/standalone-test.R>"
[3] "# ----------------------------------------------------------------------"
[4] "#"

# can extract imports

Code
Expand Down
35 changes: 31 additions & 4 deletions tests/testthat/test-use_standalone.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
test_that("standalone_header() works with various inputs", {
expect_snapshot(
standalone_header("OWNER/REPO", "R/standalone-foo.R")
)
expect_snapshot(
standalone_header("OWNER/REPO", "R/standalone-foo.R", ref = "blah")
)
expect_snapshot(
standalone_header(
"OWNER/REPO", "R/standalone-foo.R", host = "https://github.com"
)
)
expect_snapshot(
standalone_header(
"OWNER/REPO", "R/standalone-foo.R", host = "https://github.acme.com"
)
)
expect_snapshot(
standalone_header(
"OWNER/REPO", "R/standalone-foo.R",
ref = "blah", host = "https://github.com"
)
)
expect_snapshot(
standalone_header(
"OWNER/REPO", "R/standalone-foo.R",
ref = "blah", host = "https://github.acme.com"
)
)
})

test_that("can import standalone file with dependencies", {
skip_if_offline("github.com")
create_local_package()
Expand Down Expand Up @@ -40,10 +71,6 @@ test_that("can offer choices", {
})
})

test_that("header provides useful summary", {
expect_snapshot(standalone_header("r-lib/usethis", "R/standalone-test.R"))
})

test_that("can extract dependencies", {
extract_deps <- function(deps) {
out <- standalone_dependencies(c("# ---", deps, "# ---"), "test.R")
Expand Down

0 comments on commit acac3f9

Please sign in to comment.