Skip to content

Commit e52ef7f

Browse files
committed
implement push, fetch, clone
1 parent 095a6a2 commit e52ef7f

File tree

12 files changed

+138
-12
lines changed

12 files changed

+138
-12
lines changed

R/fetch.R

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
##' see examples. Pass NULL to use the
2828
##' \code{remote.<repository>.fetch} variable. Default is
2929
##' \code{NULL}.
30+
##' @param proxy Either \code{NULL} (the default) to disable proxy usage,
31+
##' \code{TRUE} for automatic proxy detection, or a character string
32+
##' with a proxy URL (for example, \code{"http://proxy.example.org:3128"}).
3033
##' @return invisible list of class \code{git_transfer_progress}
3134
##' with statistics from the fetch operation:
3235
##' \describe{
@@ -96,9 +99,9 @@
9699
##' summary(repo)
97100
##' }
98101
fetch <- function(repo = ".", name = NULL, credentials = NULL,
99-
verbose = TRUE, refspec = NULL) {
102+
verbose = TRUE, refspec = NULL, proxy = NULL) {
100103
invisible(.Call(git2r_remote_fetch, lookup_repository(repo),
101-
name, credentials, "fetch", verbose, refspec))
104+
name, credentials, "fetch", verbose, refspec, proxy))
102105
}
103106

104107
##' Get updated heads during the last fetch.

R/push.R

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ get_upstream_name <- function(object) {
3838
##' ssh key credentials, let this parameter be NULL (the default).
3939
##' @param set_upstream Set the current local branch to track the
4040
##' remote branch. Default is FALSE.
41+
##' @param proxy Either \code{NULL} (the default) to disable proxy usage,
42+
##' \code{TRUE} for automatic proxy detection, or a character string
43+
##' with a proxy URL (for example, \code{"http://proxy.example.org:3128"}).
4144
##' @return invisible(NULL)
4245
##' @seealso \code{\link{cred_user_pass}}, \code{\link{cred_ssh_key}}
4346
##' @export
@@ -98,7 +101,8 @@ push <- function(object = ".",
98101
refspec = NULL,
99102
force = FALSE,
100103
credentials = NULL,
101-
set_upstream = FALSE) {
104+
set_upstream = FALSE,
105+
proxy = NULL) {
102106
if (is_branch(object)) {
103107
name <- get_upstream_name(object)
104108

@@ -126,7 +130,7 @@ push <- function(object = ".",
126130
refspec <- tmp$refspec
127131
}
128132

129-
.Call(git2r_push, object, name, refspec, credentials)
133+
.Call(git2r_push, object, name, refspec, credentials, proxy)
130134

131135
if (isTRUE(set_upstream)) {
132136
b <- repository_head(object)

R/repository.R

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ init <- function(path = ".", bare = FALSE, branch = NULL) {
219219
##' access. Default is NULL. To use and query an ssh-agent for the
220220
##' ssh key credentials, let this parameter be NULL (the default).
221221
##' @param progress Show progress. Default is TRUE.
222+
##' @param proxy Either \code{NULL} (the default) to disable proxy usage,
223+
##' \code{TRUE} for automatic proxy detection, or a character string
224+
##' with a proxy URL (for example, \code{"http://proxy.example.org:3128"}).
222225
##' @return A \code{git_repository} object.
223226
##' @seealso \link{repository}, \code{\link{cred_user_pass}},
224227
##' \code{\link{cred_ssh_key}}
@@ -273,9 +276,10 @@ clone <- function(url,
273276
branch = NULL,
274277
checkout = TRUE,
275278
credentials = NULL,
276-
progress = TRUE) {
279+
progress = TRUE,
280+
proxy = NULL) {
277281
.Call(git2r_clone, url, local_path, bare,
278-
branch, checkout, credentials, progress)
282+
branch, checkout, credentials, progress, proxy)
279283
repository(local_path)
280284
}
281285

src/git2r.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ static const R_CallMethodDef callMethods[] =
109109
CALLDEF(git2r_odb_hash, 1),
110110
CALLDEF(git2r_odb_hashfile, 1),
111111
CALLDEF(git2r_odb_objects, 1),
112-
CALLDEF(git2r_push, 4),
112+
CALLDEF(git2r_push, 5),
113113
CALLDEF(git2r_reference_dwim, 2),
114114
CALLDEF(git2r_reference_list, 1),
115115
CALLDEF(git2r_reflog_list, 2),
116116
CALLDEF(git2r_remote_add, 3),
117-
CALLDEF(git2r_remote_fetch, 6),
117+
CALLDEF(git2r_remote_fetch, 7),
118118
CALLDEF(git2r_remote_list, 1),
119119
CALLDEF(git2r_remote_remove, 2),
120120
CALLDEF(git2r_remote_rename, 3),

src/git2r_error.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ extern const char git2r_err_revparse_single[];
4040
extern const char git2r_err_ssl_cert_locations[];
4141
extern const char git2r_err_unexpected_config_level[];
4242
extern const char git2r_err_unable_to_authenticate[];
43+
extern const char git2r_err_unable_to_set_proxy_options[];
4344

4445
/**
4546
* Error messages specific to argument checking
@@ -49,6 +50,7 @@ extern const char git2r_err_branch_arg[];
4950
extern const char git2r_err_commit_arg[];
5051
extern const char git2r_err_commit_stash_arg[];
5152
extern const char git2r_err_credentials_arg[];
53+
extern const char git2r_err_proxy_arg[];
5254
extern const char git2r_err_diff_arg[];
5355
extern const char git2r_err_fetch_heads_arg[];
5456
extern const char git2r_err_filename_arg[];

src/git2r_push.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,28 +59,33 @@ git2r_nothing_to_push(
5959
* @param name The remote to push to
6060
* @param refspec The string vector of refspec to push
6161
* @param credentials The credentials for remote repository access.
62+
* @param proxy_val The proxy settings
6263
* @return R_NilValue
6364
*/
6465
SEXP attribute_hidden
6566
git2r_push(
6667
SEXP repo,
6768
SEXP name,
6869
SEXP refspec,
69-
SEXP credentials)
70+
SEXP credentials,
71+
SEXP proxy_val)
7072
{
7173
int error;
7274
git_remote *remote = NULL;
7375
git_repository *repository = NULL;
7476
git_strarray c_refspecs = {0};
7577
git_push_options opts = GIT_PUSH_OPTIONS_INIT;
7678
git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT;
79+
git_proxy_options proxy_opts = GIT_PROXY_OPTIONS_INIT;
7780

7881
if (git2r_arg_check_string(name))
7982
git2r_error(__func__, NULL, "'name'", git2r_err_string_arg);
8083
if (git2r_arg_check_string_vec(refspec))
8184
git2r_error(__func__, NULL, "'refspec'", git2r_err_string_vec_arg);
8285
if (git2r_arg_check_credentials(credentials))
8386
git2r_error(__func__, NULL, "'credentials'", git2r_err_credentials_arg);
87+
if (git2r_arg_check_proxy(proxy_val))
88+
git2r_error(__func__, NULL, "'proxy_val'", git2r_err_proxy_arg);
8489

8590
if (git2r_nothing_to_push(refspec))
8691
return R_NilValue;
@@ -93,6 +98,16 @@ git2r_push(
9398
if (error)
9499
goto cleanup;
95100

101+
/* Initialize proxy options */
102+
error = git2r_set_proxy_options(&proxy_opts, proxy_val);
103+
if (error)
104+
git2r_error(
105+
__func__,
106+
git_error_last(),
107+
git2r_err_unable_to_set_proxy_options,
108+
NULL);
109+
opts.proxy_opts = proxy_opts;
110+
96111
payload.credentials = credentials;
97112
opts.callbacks.payload = &payload;
98113
opts.callbacks.credentials = &git2r_cred_acquire_cb;

src/git2r_push.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@
2222
#include <R.h>
2323
#include <Rinternals.h>
2424

25-
SEXP git2r_push(SEXP repo, SEXP name, SEXP refspec, SEXP credentials);
25+
SEXP git2r_push(SEXP repo, SEXP name, SEXP refspec, SEXP credentials, SEXP proxy_val);
2626

2727
#endif

src/git2r_remote.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ git2r_update_tips_cb(
123123
* @param verbose Print information each time a reference is updated locally.
124124
* @param refspecs The refspecs to use for this fetch. Pass R_NilValue
125125
* to use the base refspecs.
126+
* @param proxy_val The proxy settings
126127
* @return R_NilValue
127128
*/
128129
SEXP attribute_hidden
@@ -132,7 +133,8 @@ git2r_remote_fetch(
132133
SEXP credentials,
133134
SEXP msg,
134135
SEXP verbose,
135-
SEXP refspecs)
136+
SEXP refspecs,
137+
SEXP proxy_val)
136138
{
137139
int error, nprotect = 0;
138140
SEXP result = R_NilValue;
@@ -142,6 +144,7 @@ git2r_remote_fetch(
142144
git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
143145
git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT;
144146
git_strarray refs = {0};
147+
git_proxy_options proxy_opts = GIT_PROXY_OPTIONS_INIT;
145148

146149
if (git2r_arg_check_string(name))
147150
git2r_error(__func__, NULL, "'name'", git2r_err_string_arg);
@@ -153,6 +156,19 @@ git2r_remote_fetch(
153156
git2r_error(__func__, NULL, "'verbose'", git2r_err_logical_arg);
154157
if ((!Rf_isNull(refspecs)) && git2r_arg_check_string_vec(refspecs))
155158
git2r_error(__func__, NULL, "'refspecs'", git2r_err_string_vec_arg);
159+
if (git2r_arg_check_proxy(proxy_val))
160+
git2r_error(__func__, NULL, "'proxy_val'", git2r_err_proxy_arg);
161+
162+
/* Initialize proxy options */
163+
error = git2r_set_proxy_options(&proxy_opts, proxy_val);
164+
if (error)
165+
git2r_error(
166+
__func__,
167+
git_error_last(),
168+
git2r_err_unable_to_set_proxy_options,
169+
NULL);
170+
171+
fetch_opts.proxy_opts = proxy_opts;
156172

157173
repository = git2r_repository_open(repo);
158174
if (!repository)

src/git2r_remote.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ SEXP git2r_remote_fetch(
2929
SEXP credentials,
3030
SEXP msg,
3131
SEXP verbose,
32-
SEXP refspecs);
32+
SEXP refspecs,
33+
SEXP proxy_val);
3334
SEXP git2r_remote_list(SEXP repo);
3435
SEXP git2r_remote_remove(SEXP repo, SEXP remote);
3536
SEXP git2r_remote_rename(SEXP repo, SEXP oldname, SEXP newname);

tests/clone_bare.R

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,23 @@ stopifnot(identical(commit_1$summary, bare_commit_1$summary))
6060
stopifnot(identical(commit_1$message, bare_commit_1$message))
6161
stopifnot(!identical(commit_1$repo, bare_commit_1$repo))
6262

63+
if (identical(Sys.getenv("NOT_CRAN"), "true")) {
64+
## Minimal check: test that calling `clone` with `proxy=TRUE` doesn't crash
65+
test_path_proxy <- tempfile(pattern = "git2r-clone-proxy-")
66+
dir.create(test_path_proxy)
67+
68+
message("Testing clone() with proxy=TRUE (auto-detect)")
69+
tryCatch({
70+
proxy_repo <- clone(path_repo, test_path_proxy, proxy = TRUE)
71+
# If we get here without error, the parameter was accepted;
72+
# further checks might be minimal if there's no real proxy in use.
73+
stopifnot(identical(is_bare(proxy_repo), FALSE))
74+
stopifnot(length(commits(proxy_repo)) == 1L)
75+
}, error = function(e) {
76+
message("clone() with proxy=TRUE failed as expected if no actual proxy is set: ", e$message)
77+
})
78+
}
79+
6380
## Cleanup
6481
unlink(path_bare, recursive = TRUE)
6582
unlink(path_repo, recursive = TRUE)

0 commit comments

Comments
 (0)