-
Notifications
You must be signed in to change notification settings - Fork 32
/
submodules.R
134 lines (124 loc) · 4.3 KB
/
submodules.R
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
#' Submodules
#'
#' Interact with submodules in the repository.
#'
#' @export
#' @rdname git_submodule
#' @inheritParams git_open
#' @useDynLib gert R_git_submodule_list
git_submodule_list <- function(repo = '.'){
repo <- git_open(repo)
.Call(R_git_submodule_list, repo)
}
#' @export
#' @rdname git_submodule
#' @useDynLib gert R_git_submodule_info
git_submodule_info <- function(submodule, repo = '.'){
repo <- git_open(repo)
submodule <- as.character(submodule)
.Call(R_git_submodule_info, repo, submodule)
}
#' @export
#' @rdname git_submodule
#' @useDynLib gert R_git_submodule_init
#' @param submodule name of the submodule
#' @param overwrite overwrite existing entries
git_submodule_init <- function(submodule, overwrite = FALSE, repo = '.'){
repo <- git_open(repo)
submodule <- as.character(submodule)
overwrite <- as.logical(overwrite)
.Call(R_git_submodule_init, repo, submodule, overwrite)
}
#' @export
#' @rdname git_submodule
#' @useDynLib gert R_git_submodule_set_to
#' @param ref branch or tag to point the submodule at. If checkout = FALSE, you
#' can pass a commit hash before downloading the submodule.
#' @param checkout actually switch the contents of the directory to this commit
git_submodule_set_to <- function(submodule, ref, checkout = TRUE, repo = '.'){
repo <- git_open(repo)
submodule <- as.character(submodule)
info <- git_submodule_info(submodule, repo = repo)
if(isTRUE(checkout)){
git_reset_hard(ref = ref, repo = I(info$path))
ref <- git_info(repo = I(info$path))$commit
} else if(!is_full_hash(ref)) {
ref <- git_commit_info(ref, repo = I(info$path))$id
}
if(!is_full_hash(ref))
stop("When checkout = FALSE, parameter ref must be a full hash")
.Call(R_git_submodule_set_to, repo, submodule, ref)
}
#' @export
#' @rdname git_submodule
#' @param url full git url of the submodule
#' @param path relative of the submodule
#' @param ref a branch or tag or hash with
#' @param ... extra arguments for [git_fetch] for authentication things
git_submodule_add <- function(url, path = basename(url), ref = 'HEAD', ..., repo = '.'){
if(!is_a_hash(ref)){
upstream_refs <- git_remote_ls(url, ..., repo = repo)
ref_match <- sub("refs/(heads|tags)/","", upstream_refs$ref) == ref
if(!any(ref_match)){
stop(sprintf("Upstream repo %s does not have a branch or tag named '%s'",
basename(url), ref))
}
ref <- upstream_refs$oid[ref_match]
}
submodule <- git_submodule_setup(url = url, path = path, repo = repo)
git_fetch('origin', ..., repo = submodule)
git_reset_hard(ref, repo = submodule)
git_submodule_save(path, repo = repo)
git_submodule_info(path, repo = repo)
}
#' @export
#' @rdname git_submodule
git_submodule_fetch <- function(submodule, ..., repo = '.'){
sm <- git_submodule_info(submodule = submodule, repo = repo)
subrepo = I(sm$path)
tryCatch({
git_fetch('origin', ..., repo = subrepo)
}, GIT_ENOTFOUND = function(e){
inform("Initial clone for submodule '%s'", submodule)
git_clone(sm$url, ..., path = subrepo)
})
if(length(sm$branch) && !is.na(sm$branch)){
git_reset_hard(sm$branch, repo = subrepo)
} else {
remote_head <- git_remote_info('origin', repo = subrepo)$head
if(!length(remote_head)){
git_remote_ls('origin', ..., repo = subrepo)
remote_head <- git_remote_info('origin', repo = subrepo)$head
}
git_reset_hard(remote_head, repo = I(sm$path))
}
git_commit_id(repo = subrepo)
}
#' @useDynLib gert R_git_submodule_setup
git_submodule_setup <- function(url, path, repo){
repo <- git_open(repo)
path <- as.character(path)
url <- as.character(url)
.Call(R_git_submodule_setup, repo, url, path)
}
#' @useDynLib gert R_git_submodule_save
git_submodule_save <- function(submodule, repo){
repo <- git_open(repo)
submodule <- as.character(submodule)
.Call(R_git_submodule_save, repo, submodule)
}
# I find this confusing, also doesn't support auth.
# Better use git_submodule_fetch()
#' @useDynLib gert R_git_submodule_update
git_submodule_update <- function(submodule, init = TRUE, repo = '.'){
repo <- git_open(repo)
submodule <- as.character(submodule)
init <- as.logical(init)
.Call(R_git_submodule_update, repo, submodule, init)
}
is_a_hash <- function(x){
grepl('^[a-f0-9]{7,}$', tolower(x))
}
is_full_hash <- function(x){
grepl('^[a-f0-9]{40}$', tolower(x))
}