1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
#' Increment package version
#'
#' @description
#'
#' usethis supports semantic versioning, which is described in more detail in
#' the [version
#' section](https://r-pkgs.org/lifecycle.html#sec-lifecycle-version-number) of [R
#' Packages](https://r-pkgs.org). A version number breaks down like so:
#'
#' ```
#' <major>.<minor>.<patch> (released version)
#' <major>.<minor>.<patch>.<dev> (dev version)
#' ```
#' `use_version()` increments the "Version" field in `DESCRIPTION`, adds a new
#' heading to `NEWS.md` (if it exists), commits those changes (if package uses
#' Git), and optionally pushes (if safe to do so). It makes the same update to a
#' line like `PKG_version = "x.y.z";` in `src/version.c` (if it exists).
#'
#' `use_dev_version()` increments to a development version, e.g. from 1.0.0 to
#' 1.0.0.9000. If the existing version is already a development version with
#' four components, it does nothing. Thin wrapper around `use_version()`.
#'
#' @param which A string specifying which level to increment, one of: "major",
#' "minor", "patch", "dev". If `NULL`, user can choose interactively.
#'
#' @seealso The [version
#' section](https://r-pkgs.org/lifecycle.html#sec-lifecycle-version-number) of [R
#' Packages](https://r-pkgs.org).
#'
#' @examples
#' \dontrun{
#' ## for interactive selection, do this:
#' use_version()
#'
#' ## request a specific type of increment
#' use_version("minor")
#' use_dev_version()
#' }
#'
#' @name use_version
NULL
#' @rdname use_version
#' @param push If `TRUE`, also attempts to push the commits to the remote
#' branch.
#' @export
use_version <- function(which = NULL, push = FALSE) {
if (is.null(which) && !is_interactive()) {
return(invisible(FALSE))
}
check_is_package("use_version()")
challenge_uncommitted_changes(
msg = "There are uncommitted changes and you're about to bump version"
)
new_ver <- choose_version("What should the new version be?", which)
if (is.null(new_ver)) {
return(invisible(FALSE))
}
proj_desc_field_update("Version", new_ver, overwrite = TRUE)
if (names(new_ver) == "dev") {
use_news_heading("(development version)")
} else {
use_news_heading(new_ver)
}
use_c_version(new_ver)
git_ask_commit(
glue("Increment version number to {new_ver}"),
untracked = TRUE,
push = push,
paths = c("DESCRIPTION", "NEWS.md", path("src", "version.c"))
)
invisible(TRUE)
}
#' @rdname use_version
#' @export
use_dev_version <- function(push = FALSE) {
check_is_package("use_dev_version()")
if (is_dev_version()) {
return(invisible())
}
use_version(which = "dev", push = push)
}
choose_version <- function(message, which = NULL) {
versions <- bump_version()
rtypes <- names(versions)
which <- which %||% rtypes
which <- arg_match(which, values = rtypes, multiple = TRUE)
versions <- versions[which]
if (length(versions) == 1) {
return(versions)
}
choice <- utils::menu(
choices = glue(
"{format(names(versions), justify = 'right')} --> {versions}"
),
title = glue(
"Current version is {proj_version()}.\n",
"{message} (0 to exit)"
)
)
if (choice == 0) {
invisible()
} else {
# Not using `[[` even though there is only 1 `choice`,
# because that removes the names from `versions`
versions[choice]
}
}
bump_version <- function(ver = proj_version()) {
bumps <- c("major", "minor", "patch", "dev")
vapply(bumps, bump_, character(1), ver = ver)
}
bump_ <- function(x, ver) {
d <- desc::desc(text = paste0("Version: ", ver))
suppressMessages(d$bump_version(x)$get("Version")[[1]])
}
use_c_version <- function(ver) {
version_path <- proj_path("src", "version.c")
if (!file_exists(version_path)) {
return()
}
hint <- glue("{project_name()}_version")
ui_bullets(c(
"v" = "Setting {.field {hint}} to {.val {ver}} {.path {pth(version_path)}}."
))
lines <- read_utf8(version_path)
re <- glue("(^.*{project_name()}_version = \")([0-9.]+)(\";$)")
lines <- gsub(re, glue("\\1{ver}\\3"), lines)
write_utf8(version_path, lines)
}
is_dev_version <- function(version = proj_version()) {
ver <- package_version(version)
length(unlist(ver)) > 3
}
|