Showing 1 of 4 files from the diff.

@@ -131,15 +131,17 @@
Loading
131 131
#'   `repo` part will be the name of the new local folder, which is also
132 132
#'   a project and Git repo.
133 133
#' @inheritParams use_course
134 -
#' @param fork If `TRUE`, we create and clone a fork. If `FALSE`, we clone
135 -
#'   `repo_spec` itself. If `NA` (the default), we check your permissions on the
136 -
#'   target repo. If you can push, we clone `repo_spec` (so, `fork = FALSE`).
137 -
#'   If you can't push, we do fork-and-clone and other setup:
138 -
#'   * The source repo is configured as the `upstream` remote, using the
139 -
#'     indicated `protocol`.
134 +
#' @param fork If `FALSE`, we clone `repo_spec`. If `TRUE`, we fork
135 +
#'   `repo_spec`, clone that fork, and do additional set up favorable for
136 +
#'   future pull requests:
137 +
#'   * The source repo, `repo_spec`, is configured as the `upstream` remote,
138 +
#'   using the indicated `protocol`.
140 139
#'   * The local `DEFAULT` branch is set to track `upstream/DEFAULT`, where
141 -
#'     `DEFAULT` is typically `master` or `main`. It is also immediately
142 -
#'     pulled, to cover the case of a pre-existing, out-of-date fork.
140 +
#'   `DEFAULT` is typically `master` or `main`. It is also immediately pulled,
141 +
#'   to cover the case of a pre-existing, out-of-date fork.
142 +
#'
143 +
#'   If `fork = NA` (the default), we check your permissions on `repo_spec`. If
144 +
#'   you can push, we set `fork = FALSE`, If you cannot, we set `fork = TRUE`.
143 145
#' @param rstudio Initiate an [RStudio
144 146
#'   Project](https://support.rstudio.com/hc/en-us/articles/200526207-Using-Projects)?
145 147
#'   Defaults to `TRUE` if in an RStudio session and project has no
@@ -169,70 +171,66 @@
Loading
169 171
    deprecate_warn_credentials("create_from_github")
170 172
  }
171 173
172 -
  host_url <- gh:::get_hosturl(host)
173 -
  api_url <- gh:::get_apiurl(host)
174 -
  auth_token <- gh::gh_token(host_url)
174 +
  whoami <- suppressMessages(gh::gh_whoami(.api_url = host))
175 +
  no_auth <- is.null(whoami)
176 +
  user <- if (no_auth) NULL else whoami$login
177 +
  if (is.null(host)) {
178 +
    code_hint <- "gh_token_help()"
179 +
  } else {
180 +
    code_hint <- glue('gh_token_help("{host}")')
181 +
  }
175 182
176 -
  # TODO: revisit if usethis or gh gains a better "sitrep" helper for PATs
177 -
  if (auth_token == "" && is.na(fork)) {
178 -
    # TODO: revisit when there's better troubleshooting advice
179 -
    create_code <- "usethis::create_github_token()"
180 -
    set_code <- glue("gitcreds::gitcreds_set(\"{host_url}\")")
183 +
  if (no_auth && is.na(fork)) {
181 184
    ui_stop("
182 -
      Unable to discover a token for {ui_value(host_url)}
185 +
      Unable to discover a GitHub personal access token
183 186
      Therefore, can't determine your permissions on {ui_value(repo_spec)}
187 +
      Therefore, can't decide if `fork` should be `TRUE` or `FALSE`
184 188
185 189
      You have two choices:
186 190
      1. Make your token available (if in doubt, DO THIS):
187 -
         - If you don't have a token yet, use {ui_code(create_code)}
188 -
         - Store your token with {ui_code(set_code)}
191 +
         - Call {ui_code(code_hint)} for directions
189 192
      2. Call {ui_code('create_from_github()')} again, but with \\
190 193
      {ui_code('fork = FALSE')}
191 194
         - Only do this if you are absolutely sure you don't want to fork
192 -
         - Note you will NOT be in a position to make a pull request.")
195 +
         - Note you will NOT be in a position to make a pull request")
193 196
  }
194 197
195 -
  if (auth_token == "" && isTRUE(fork)) {
196 -
    # TODO: revisit when there's better troubleshooting advice
197 -
    create_code <- "usethis::create_github_token()"
198 -
    set_code <- glue("gitcreds::gitcreds_set(\"{host_url}\")")
198 +
  if (no_auth && isTRUE(fork)) {
199 199
    ui_stop("
200 -
      Unable to discover a token for {ui_value(host_url)}
200 +
      Unable to discover a GitHub personal access token
201 201
      A token is required in order to fork {ui_value(repo_spec)}
202 202
203 -
      How to make a token available:
204 -
        - If you don't have a token yet, use {ui_code(create_code)}
205 -
        - Store your token with {ui_code(set_code)}")
203 +
      Call {ui_code(code_hint)} for help configuring a token")
206 204
  }
207 205
  # one of these is true:
208 -
  # - we have what appears to be a real auth_token
209 -
  # - we do NOT have an auth_token AND `fork = FALSE`
210 -
211 -
  gh <- function(endpoint, ...) {
212 -
    gh::gh(endpoint, ..., .token = auth_token, .api_url = api_url)
213 -
  }
206 +
  # - gh is discovering a token for `host`
207 +
  # - gh is NOT discovering a token, but `fork = FALSE`, so that's OK
214 208
215 209
  source_owner <- spec_owner(repo_spec)
216 210
  repo_name <- spec_repo(repo_spec)
217 211
218 -
  repo_info <- gh(
212 +
  repo_info <- gh::gh(
219 213
    "GET /repos/:owner/:repo",
220 -
    owner = source_owner, repo = repo_name
214 +
    owner = source_owner, repo = repo_name,
215 +
    .api_url = host
221 216
  )
217 +
  # 2020-10-14 GitHub has had some bugs lately around default branch
218 +
  # today, the POST payload, if I create a fork, mis-reports the default branch
219 +
  # it reports 'main', even though actual default branch is 'master'
220 +
  # therefore, we're consulting the source repo for this info
221 +
  default_branch <- repo_info$default_branch
222 222
223 -
  if (auth_token != "" && is.na(fork)) {
223 +
  if (is.na(fork)) {
224 224
    fork <- !isTRUE(repo_info$permissions$push)
225 +
    fork_status <- glue("fork = {fork}")
226 +
    ui_done("Setting {ui_code(fork_status)}")
225 227
  }
226 228
  # fork is either TRUE or FALSE
227 229
228 -
  if (fork) {
229 -
    out <- gh::gh_whoami(.token = auth_token, .api_url = api_url)
230 -
    user <- out$login
231 -
    if (identical(user, repo_info$owner$login)) {
232 -
      ui_stop("
233 -
        Repo {ui_value(repo_info$full_name)} is owned by user \\
234 -
        {ui_value(user)}. Can't fork.")
235 -
    }
230 +
  if (fork && identical(user, repo_info$owner$login)) {
231 +
    ui_stop("
232 +
      Can't fork, because the authenticated user {ui_value(user)} \\
233 +
      already owns the source repo {ui_value(repo_info$full_name)}")
236 234
  }
237 235
238 236
  destdir <- user_path_prep(destdir %||% conspicuous_place())
@@ -250,9 +248,10 @@
Loading
250 248
      https = repo_info$clone_url,
251 249
      ssh = repo_info$ssh_url
252 250
    )
253 -
    repo_info <- gh(
251 +
    repo_info <- gh::gh(
254 252
      "POST /repos/:owner/:repo/forks",
255 -
      owner = source_owner, repo = repo_name
253 +
      owner = source_owner, repo = repo_name,
254 +
      .api_url = host
256 255
    )
257 256
  }
258 257
@@ -266,7 +265,9 @@
Loading
266 265
  gert::git_clone(origin_url, repo_path, verbose = FALSE)
267 266
  local_project(repo_path, force = TRUE) # schedule restoration of project
268 267
269 -
  default_branch <- repo_info$default_branch
268 +
  # 2020-10-14 due to a GitHub bug, we are consulting the source repo for this
269 +
  # previously (and more naturally) we consulted the fork itself
270 +
  # default_branch <- repo_info$default_branch
270 271
  ui_info("Default branch is {ui_value(default_branch)}")
271 272
272 273
  if (fork) {
Files Coverage
R 51.78%
Project Totals (64 files) 51.78%
1
comment: false
2

3
coverage:
4
  status:
5
    project:
6
      default:
7
        target: auto
8
        threshold: 1%
9
        informational: true
10
    patch:
11
      default:
12
        target: auto
13
        threshold: 1%
14
        informational: true
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading