From 99cb213b7459ee45923ce1d655c707cbb60d94d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20Salmon?= Date: Mon, 23 Mar 2026 14:26:40 +0100 Subject: [PATCH] feat: `git_clone()` creates `path` more similarly to `git clone` --- NEWS.md | 2 ++ R/fetch.R | 12 ++++++++++-- man/git_fetch.Rd | 5 ++++- tests/testthat/test-clone.R | 12 ++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 55e606b..e3ded08 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # gert (development version) +- `git_clone()` without a `path` argument now clones into a directory named after the +"humanish" part of the URL, so "git@github.com:francisbarton/myrepo.git" gets cloned into `myrepo` (@francisbardon, #192). - `git_remote_set_pushurl()` gains an `add` argument to append push URLs instead of replacing them. (@robitalec, #128) - Fix `git_info()` for the case when no upstream is configured (@mpage, #263) - `git_branch_create()`: `force` now also applies to the checkout step, allowing branch creation even when local changes would be overwritten (@MichaelChirico, #177). diff --git a/R/fetch.R b/R/fetch.R index 47210e3..aa12c2a 100644 --- a/R/fetch.R +++ b/R/fetch.R @@ -174,6 +174,9 @@ git_push <- function( #' repositories, and `https://yourname@github.com/` or `git@github.com/` for #' private repos. You will be prompted for a password or pat when needed. #' @param path Directory of the Git repository to create. +#' By default, the "humanish" part of the URL. +#' For instance, "git@github.com:someone/myrepo.git" will be cloned to +#' `myrepo/`. #' @param ssh_key path or object containing your ssh private key. By default we #' look for keys in `ssh-agent` and [credentials::ssh_key_info()]. #' @param branch name of branch to check out locally @@ -220,8 +223,13 @@ git_clone <- function( verbose = interactive() ) { stopifnot(is.character(url)) + # "humanish" part of the URL + # https://github.com/git/git/blob/6e8d538aab8fe4dd07ba9fb87b5c7edcfa5706ad/dir.h#L494 if (!length(path)) { - path <- file.path(getwd(), basename(url)) + path <- file.path( + getwd(), + sub("\\.git$", "", sub("/.git$", "", basename(url))) + ) } stopifnot(is.character(path)) stopifnot(is.null(branch) || is.character(branch)) @@ -249,7 +257,7 @@ git_clone <- function( #' @param rebase if TRUE we try to rebase instead of merge local changes. This #' is not possible in case of conflicts (you will get an error). #' @param ... arguments passed to `git_fetch()` -git_pull <- function(remote = NULL, rebase = FALSE, ..., repo = '.'){ +git_pull <- function(remote = NULL, rebase = FALSE, ..., repo = '.') { repo <- git_open(repo) info <- git_info(repo) branch <- info$shorthand diff --git a/man/git_fetch.Rd b/man/git_fetch.Rd index ca87243..448b18c 100644 --- a/man/git_fetch.Rd +++ b/man/git_fetch.Rd @@ -89,7 +89,10 @@ successful and if the branch does not have an upstream set yet.} repositories, and \verb{https://yourname@github.com/} or \verb{git@github.com/} for private repos. You will be prompted for a password or pat when needed.} -\item{path}{Directory of the Git repository to create.} +\item{path}{Directory of the Git repository to create. +By default, the "humanish" part of the URL. +For instance, "git@github.com:someone/myrepo.git" will be cloned to +\verb{myrepo/}.} \item{branch}{name of branch to check out locally} diff --git a/tests/testthat/test-clone.R b/tests/testthat/test-clone.R index 972da85..1d99f7a 100644 --- a/tests/testthat/test-clone.R +++ b/tests/testthat/test-clone.R @@ -33,3 +33,15 @@ test_that("cloning repositories works", { expect_equal(zip::zip_list('gert.zip')$filename, git_ls(repo = repo)$path) unlink('gert.zip') }) + +test_that("cloning repositories works, no path", { + skip_if_offline('github.com') + path <- file.path(tempdir(), 'gert-test') + dir.create(path) + on.exit(unlink(path, recursive = TRUE)) + oldwd <- getwd() + on.exit(setwd(oldwd), add = TRUE) + setwd(path) + repo <- git_clone('https://github.com/r-lib/gert.git') + expect_true(file.exists(file.path(path, "gert", 'DESCRIPTION'))) +})