1#' Submodules 2#' 3#' Interact with submodules in the repository. 4#' 5#' @export 6#' @rdname git_submodule 7#' @inheritParams git_open 8#' @useDynLib gert R_git_submodule_list 9git_submodule_list <- function(repo = '.'){ 10 repo <- git_open(repo) 11 .Call(R_git_submodule_list, repo) 12} 13 14#' @export 15#' @rdname git_submodule 16#' @useDynLib gert R_git_submodule_info 17git_submodule_info <- function(submodule, repo = '.'){ 18 repo <- git_open(repo) 19 submodule <- as.character(submodule) 20 .Call(R_git_submodule_info, repo, submodule) 21} 22 23#' @export 24#' @rdname git_submodule 25#' @useDynLib gert R_git_submodule_init 26#' @param submodule name of the submodule 27#' @param overwrite overwrite existing entries 28git_submodule_init <- function(submodule, overwrite = FALSE, repo = '.'){ 29 repo <- git_open(repo) 30 submodule <- as.character(submodule) 31 overwrite <- as.logical(overwrite) 32 .Call(R_git_submodule_init, repo, submodule, overwrite) 33} 34 35#' @export 36#' @rdname git_submodule 37#' @useDynLib gert R_git_submodule_set_to 38#' @param ref branch or tag to point the submodule at. If checkout = FALSE, you 39#' can pass a commit hash before downloading the submodule. 40#' @param checkout actually switch the contents of the directory to this commit 41git_submodule_set_to <- function(submodule, ref, checkout = TRUE, repo = '.'){ 42 repo <- git_open(repo) 43 submodule <- as.character(submodule) 44 info <- git_submodule_info(submodule, repo = repo) 45 if(isTRUE(checkout)){ 46 git_reset_hard(ref = ref, repo = I(info$path)) 47 ref <- git_info(repo = I(info$path))$commit 48 } else if(!is_full_hash(ref)) { 49 ref <- git_commit_info(ref, repo = I(info$path))$id 50 } 51 if(!is_full_hash(ref)) 52 stop("When checkout = FALSE, parameter ref must be a full hash") 53 .Call(R_git_submodule_set_to, repo, submodule, ref) 54} 55 56#' @export 57#' @rdname git_submodule 58#' @param url full git url of the submodule 59#' @param path relative of the submodule 60#' @param ref a branch or tag or hash with 61#' @param ... extra arguments for [git_fetch] for authentication things 62git_submodule_add <- function(url, path = basename(url), ref = 'HEAD', ..., repo = '.'){ 63 if(!is_a_hash(ref)){ 64 upstream_refs <- git_remote_ls(url, ..., repo = repo) 65 ref_match <- sub("refs/(heads|tags)/","", upstream_refs$ref) == ref 66 if(!any(ref_match)){ 67 stop(sprintf("Upstream repo %s does not have a branch or tag named '%s'", 68 basename(url), ref)) 69 } 70 ref <- upstream_refs$oid[ref_match] 71 } 72 submodule <- git_submodule_setup(url = url, path = path, repo = repo) 73 git_fetch('origin', ..., repo = submodule) 74 git_reset_hard(ref, repo = submodule) 75 git_submodule_save(path, repo = repo) 76 git_submodule_info(path, repo = repo) 77} 78 79#' @export 80#' @rdname git_submodule 81git_submodule_fetch <- function(submodule, ..., repo = '.'){ 82 sm <- git_submodule_info(submodule = submodule, repo = repo) 83 subrepo = I(sm$path) 84 tryCatch({ 85 git_fetch('origin', ..., repo = subrepo) 86 }, GIT_ENOTFOUND = function(e){ 87 inform("Initial clone for submodule '%s'", submodule) 88 git_clone(sm$url, ..., path = subrepo) 89 }) 90 if(length(sm$branch) && !is.na(sm$branch)){ 91 git_reset_hard(sm$branch, repo = subrepo) 92 } else { 93 remote_head <- git_remote_info('origin', repo = subrepo)$head 94 if(!length(remote_head)){ 95 git_remote_ls('origin', ..., repo = subrepo) 96 remote_head <- git_remote_info('origin', repo = subrepo)$head 97 } 98 git_reset_hard(remote_head, repo = I(sm$path)) 99 } 100 git_commit_id(repo = subrepo) 101} 102 103#' @useDynLib gert R_git_submodule_setup 104git_submodule_setup <- function(url, path, repo){ 105 repo <- git_open(repo) 106 path <- as.character(path) 107 url <- as.character(url) 108 .Call(R_git_submodule_setup, repo, url, path) 109} 110 111#' @useDynLib gert R_git_submodule_save 112git_submodule_save <- function(submodule, repo){ 113 repo <- git_open(repo) 114 submodule <- as.character(submodule) 115 .Call(R_git_submodule_save, repo, submodule) 116} 117 118# I find this confusing, also doesn't support auth. 119# Better use git_submodule_fetch() 120#' @useDynLib gert R_git_submodule_update 121git_submodule_update <- function(submodule, init = TRUE, repo = '.'){ 122 repo <- git_open(repo) 123 submodule <- as.character(submodule) 124 init <- as.logical(init) 125 .Call(R_git_submodule_update, repo, submodule, init) 126} 127 128is_a_hash <- function(x){ 129 grepl('^[a-f0-9]{7,}$', tolower(x)) 130} 131 132is_full_hash <- function(x){ 133 grepl('^[a-f0-9]{40}$', tolower(x)) 134} 135