r-lib / usethis

Compare 5fcf05d ... +2 ... 7f47181


@@ -161,20 +161,16 @@
Loading
161 161
  # don't absolutely require PAT success, because we could be offline
162 162
  # or in another salvageable situation, e.g. need to configure PAT
163 163
  cfg <- github_remote_config(github_get = NA)
164 -
  good_configs <- c("ours", "fork")
165 -
  maybe_good_configs <- c("maybe_ours_or_theirs", "maybe_fork")
166 -
  if (!cfg$type %in% c(good_configs, maybe_good_configs)) {
167 -
    stop_unsupported_pr_config(cfg)
168 -
  }
164 +
  check_for_bad_config(cfg)
169 165
  tr <- target_repo(cfg, ask = FALSE)
170 166
167 +
  maybe_good_configs <- c("maybe_ours_or_theirs", "maybe_fork")
171 168
  if (cfg$type %in% maybe_good_configs) {
172 -
    # TODO: revisit when I have somewhere better to send people
173 169
    ui_line('
174 170
      Unable to confirm the GitHub remote configuration is "pull request ready"
175 171
      You probably need to configure a personal access token for \\
176 172
      {ui_value(tr$host)}
177 -
      See {ui_code("?create_github_token")} for help
173 +
      See {ui_code("gh_token_help()")} for help
178 174
      (Or maybe we\'re just offline?)')
179 175
    if (ui_github_remote_config_wat(cfg)) {
180 176
      ui_stop("Aborting")
@@ -745,14 +741,6 @@
Loading
745 741
  pr_data_tidy(raw)
746 742
}
747 743
748 -
check_ours_or_fork <- function(cfg = NULL) {
749 -
  cfg <- cfg %||% github_remote_config(github_get = TRUE)
750 -
  if (cfg$type %in% c("ours", "fork")) {
751 -
    return(invisible(cfg))
752 -
  }
753 -
  stop_unsupported_pr_config(cfg)
754 -
}
755 -
756 744
check_pr_branch <- function() {
757 745
  default_branch <- git_branch_default()
758 746
  if (git_branch() != default_branch) {

@@ -9,9 +9,8 @@
Loading
9 9
#'   - No pre-existing `origin` remote
10 10
#' * Creates an associated repo on GitHub
11 11
#' * Adds that GitHub repo to your local repo as the `origin` remote
12 -
#' * Offers to commit changes, e.g. the addition of GitHub links to the
13 -
#'   URL and BugReports fields of DESCRIPTION
14 12
#' * Makes an initial push to GitHub
13 +
#' * Calls [use_github_links()], if the project is an R package
15 14
#' * Configures `origin/DEFAULT` to be the upstream branch of the local
16 15
#'   `DEFAULT` branch, e.g. `master` or `main`
17 16
#'
@@ -71,36 +70,22 @@
Loading
71 70
    deprecate_warn_credentials("use_github")
72 71
  }
73 72
74 -
  host_url <- gh:::get_hosturl(host)
75 -
  api_url <- gh:::get_apiurl(host)
76 -
  # TODO: do I even need to proactively get the token here? what if I just go
77 -
  # straight to a tryCatch'd gh::gh_whoami()? if it fails due to invalid token
78 -
  # refer people to a yet-to-be written humane function in gh (or one I put in
79 -
  # usethis)
80 -
  auth_token <- gh::gh_token(host_url)
81 -
  if (auth_token == "") {
82 -
    # TODO: revisit when I have better advice (if I continue to proactively get
83 -
    # a token)
84 -
    get_code <- glue("gitcreds::gitcreds_get(\"{host_url}\")")
85 -
    set_code <- glue("gitcreds::gitcreds_set(\"{host_url}\")")
73 +
  whoami <- suppressMessages(gh::gh_whoami(.api_url = host))
74 +
  if (is.null(whoami)) {
86 75
    ui_stop("
87 -
      Unable to discover a token for {ui_value(host_url)}
88 -
        Call {ui_code(get_code)} to experience this first-hand
89 -
        Call {ui_code(set_code)} to store a token")
76 +
      Unable to discover a GitHub personal access token
77 +
      A token is required in order to create and push to a new repo
78 +
79 +
      Call {ui_code('gh_token_help()')} for help configuring a token")
80 +
  }
81 +
  empirical_host <- parse_github_remotes(glue("{whoami$html_url}/REPO"))$host
82 +
  if (empirical_host != "github.com") {
83 +
    ui_info("Targeting the GitHub host {ui_value(empirical_host)}")
90 84
  }
91 -
  who <- tryCatch(
92 -
    gh::gh_whoami(.token = auth_token, .api_url = api_url),
93 -
    http_error_401 = function(e) ui_stop("Token is invalid."),
94 -
    error = function(e) {
95 -
      ui_oops("
96 -
        Can't get login associated with this token. Is the network reachable?")
97 -
    }
98 -
  )
99 -
  login <- who$login
100 85
101 -
  owner <- organisation %||% login
86 +
  owner <- organisation %||%  whoami$login
102 87
  repo_name <- project_name()
103 -
  check_no_github_repo(owner, repo_name, api_url, auth_token)
88 +
  check_no_github_repo(owner, repo_name, host)
104 89
105 90
  repo_desc <- project_data()$Title %||% ""
106 91
  repo_desc <- gsub("\n", " ", repo_desc)
@@ -114,7 +99,7 @@
Loading
114 99
      name = repo_name,
115 100
      description = repo_desc,
116 101
      private = private,
117 -
      .api_url = api_url, .token = auth_token
102 +
      .api_url = host
118 103
    )
119 104
  } else {
120 105
    create <- gh::gh(
@@ -123,7 +108,7 @@
Loading
123 108
      name = repo_name,
124 109
      description = repo_desc,
125 110
      private = private,
126 -
      .api_url = api_url, .token = auth_token
111 +
      .api_url = host
127 112
    )
128 113
  }
129 114
@@ -160,16 +145,15 @@
Loading
160 145
    verbose = FALSE
161 146
  )
162 147
163 -
  gbl <- gert::git_branch_list(repo = repo)
164 -
  gbl <- gbl[gbl$local, ]
148 +
  gbl <- gert::git_branch_list(local = TRUE, repo = repo)
165 149
  if (nrow(gbl) > 1) {
166 150
    ui_done("
167 151
      Setting {ui_value(default_branch)} as default branch on GitHub")
168 152
    gh::gh(
169 153
      "PATCH /repos/{owner}/{repo}",
170 154
      owner = owner, repo = repo_name,
171 155
      default_branch = default_branch,
172 -
      .api_url = api_url, .token = auth_token
156 +
      .api_url = host
173 157
    )
174 158
  }
175 159
@@ -235,13 +219,6 @@
Loading
235 219
  invisible()
236 220
}
237 221
238 -
origin_is_on_github <- function() {
239 -
  if (!uses_git()) {
240 -
    return(FALSE)
241 -
  }
242 -
  nrow(github_remote_list("origin")) > 0
243 -
}
244 -
245 222
check_no_origin <- function() {
246 223
  remotes <- git_remotes()
247 224
  if ("origin" %in% names(remotes)) {
@@ -254,13 +231,13 @@
Loading
254 231
  invisible()
255 232
}
256 233
257 -
check_no_github_repo <- function(owner, repo, .api_url, .token) {
234 +
check_no_github_repo <- function(owner, repo, host) {
258 235
  repo_found <- tryCatch(
259 236
    {
260 -
      gh::gh(
237 +
      repo_info <- gh::gh(
261 238
        "/repos/:owner/:repo",
262 239
        owner = owner, repo = repo,
263 -
        .api_url = .api_url, .token = .token
240 +
        .api_url = host
264 241
      )
265 242
      TRUE
266 243
    },
@@ -270,6 +247,6 @@
Loading
270 247
    return(invisible())
271 248
  }
272 249
  spec <- glue("{owner}/{repo}")
273 -
  host_url <- gh:::get_hosturl(.api_url)
274 -
  ui_stop("Repo {ui_value(spec)} already exists on {ui_value(host_url)}.")
250 +
  empirical_host <- parse_github_remotes(repo_info$html_url)$host
251 +
  ui_stop("Repo {ui_value(spec)} already exists on {ui_value(empirical_host)}")
275 252
}

@@ -115,6 +115,13 @@
Loading
115 115
  )]
116 116
}
117 117
118 +
origin_is_on_github <- function() {
119 +
  if (!uses_git()) {
120 +
    return(FALSE)
121 +
  }
122 +
  nrow(github_remote_list("origin")) > 0
123 +
}
124 +
118 125
#' Gather LOCAL and (maybe) REMOTE data on GitHub-associated remotes
119 126
#'
120 127
#' Creates a data frame where each row represents a GitHub-associated remote,
@@ -439,9 +446,8 @@
Loading
439 446
440 447
  check_for_bad_config(cfg)
441 448
442 -
  if (isTRUE(github_get) && (!cfg$type %in% c("ours", "fork"))) {
443 -
    # TODO: this doesn't offer any helpful advice, such as configuring a PAT
444 -
    stop_bad_github_remote_config(cfg)
449 +
  if (isTRUE(github_get)) {
450 +
    check_ours_or_fork(cfg)
445 451
  }
446 452
447 453
  # upstream only
@@ -558,11 +564,14 @@
Loading
558 564
  )
559 565
}
560 566
561 -
stop_unsupported_pr_config <- function(cfg) {
567 +
stop_maybe_github_remote_config <- function(cfg) {
562 568
  msg <- github_remote_config_wat(cfg)
563 569
  msg$type <- glue("
564 570
    Pull request functions can't work with GitHub remote configuration: \\
565 -
    {ui_value(cfg$type)}")
571 +
    {ui_value(cfg$type)}
572 +
    The most likely problem is that we aren't discovering your GitHub \\
573 +
    personal access token
574 +
    Call {ui_code('gh_token_help()')} for help")
566 575
  abort(
567 576
    message = unname(msg),
568 577
    class = c("usethis_error_invalid_pr_config", "usethis_error"),
@@ -583,6 +592,29 @@
Loading
583 592
  invisible()
584 593
}
585 594
595 +
check_for_maybe_config <- function(cfg,
596 +
                                   maybe_configs = c(
597 +
                                     "maybe_ours_or_theirs",
598 +
                                     "maybe_fork"
599 +
                                   )) {
600 +
  if (cfg$type %in% maybe_configs) {
601 +
    stop_maybe_github_remote_config(cfg)
602 +
  }
603 +
  invisible()
604 +
}
605 +
606 +
check_ours_or_fork <- function(cfg = NULL) {
607 +
  cfg <- cfg %||% github_remote_config(github_get = TRUE)
608 +
  stopifnot(inherits(cfg, "github_remote_config"))
609 +
  if (cfg$type %in% c("ours", "fork")) {
610 +
    return(invisible(cfg))
611 +
  }
612 +
  check_for_bad_config()
613 +
  check_for_maybe_config()
614 +
  ui_stop("
615 +
    Internal error: Unexpected GitHub remote configuration: {ui_value(cfg$type)}")
616 +
}
617 +
586 618
# github remote configurations -------------------------------------------------
587 619
cfg_no_github <- function(cfg) {
588 620
  utils::modifyList(

@@ -87,16 +87,21 @@
Loading
87 87
88 88
  paths <- sort(paths)
89 89
  ui_paths <- map_chr(paths, ui_path)
90 -
  if (n > 20) {
91 -
    ui_paths <- c(ui_paths[1:20], "...")
90 +
  if (n > 10) {
91 +
    ui_paths <- c(ui_paths[1:10], "...")
92 92
  }
93 93
94 +
  if (n == 1) {
95 +
    file_hint <- "There is 1 uncommitted file:"
96 +
  } else {
97 +
    file_hint <- "There are {n} uncommitted files:"
98 +
  }
94 99
  ui_line(c(
95 -
    "There are {n} uncommitted files:",
100 +
    file_hint,
96 101
    paste0("* ", ui_paths)
97 102
  ))
98 103
99 -
  if (ui_yeah("Is it ok to commit them?")) {
104 +
  if (ui_yeah("Is it ok to commit {if (n == 1) 'it' else 'them'}?")) {
100 105
    git_commit(paths, message)
101 106
  }
102 107
  invisible()

Everything is accounted for!

No changes detected that need to be reviewed.
What changes does Codecov check for?
Lines, not adjusted in diff, that have changed coverage data.
Files that introduced coverage data that had none before.
Files that have missing coverage data that once were tracked.
Files Coverage
R -0.03% 51.75%
Project Totals (64 files) 51.75%
Loading