Skip to content

Commit 4a353ce

Browse files
authored
Refactor to avoid non-api call (#230)
1 parent 12ee30a commit 4a353ce

File tree

4 files changed

+38
-32
lines changed

4 files changed

+38
-32
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: gert
33
Title: Simple Git Client for R
4-
Version: 2.0.2
4+
Version: 2.1.0
55
Authors@R: c(
66
person("Jeroen", "Ooms", role = c("aut", "cre"), email = "jeroen@berkeley.edu",
77
comment = c(ORCID = "0000-0002-4035-0289")),

NEWS

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
2.0.2
1+
2.1.0
22
- Workaround for accidental API change in libgit2 1.8.0
3-
- Disable a non-api call in R >= 4.5.0 for now
3+
- Refactor authentication callbacks to work around new "non-api"
4+
calls in R >= 4.5.0. Hopefully no breakage.
45

56
2.0.1
67
- Fix a printf warning for cran

R/credentials.R

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,30 @@
33
#' @importFrom askpass askpass
44
make_key_cb <- function(ssh_key = NULL, host = NULL, password = askpass){
55
function(){
6-
if(is.null(ssh_key)){
7-
ssh_key <- try(ssh_key_info(host = host, auto_keygen = FALSE)$key)
8-
if(inherits(ssh_key, "try-error"))
9-
return(NULL)
10-
}
11-
key <- tryCatch(ssh_read_key(ssh_key, password = password), error = function(e){
12-
stop(sprintf("Unable to load key: %s", ssh_key), call. = FALSE)
13-
})
14-
# NB: need to add ID for buggy libssh2: https://github.com/libgit2/libgit2/issues/5162
15-
writeLines(paste(write_ssh(key$pubkey), "git@localhost"), tmp_pub <- tempfile())
6+
try({
7+
if(is.null(ssh_key)){
8+
ssh_key <- try(ssh_key_info(host = host, auto_keygen = FALSE)$key)
9+
if(inherits(ssh_key, "try-error"))
10+
return(NULL)
11+
}
12+
key <- tryCatch(ssh_read_key(ssh_key, password = password), error = function(e){
13+
stop(sprintf("Unable to load key: %s", ssh_key), call. = FALSE)
14+
})
15+
# NB: need to add ID for buggy libssh2: https://github.com/libgit2/libgit2/issues/5162
16+
writeLines(paste(write_ssh(key$pubkey), "git@localhost"), tmp_pub <- tempfile())
1617

17-
# NB: pkcs1 is the only format that works on all libssh2 configurations
18-
tmp_key <- if(inherits(key, c("rsa", "dsa", "ecdsa"))){
19-
write_pkcs1(key, tempfile())
20-
} else {
21-
write_openssh_pem(key, tempfile())
22-
}
23-
if(.Platform$OS.type == "unix"){
24-
Sys.chmod(tmp_pub, '0644')
25-
Sys.chmod(tmp_key, '0400')
26-
}
27-
c(tmp_pub, tmp_key, "")
18+
# NB: pkcs1 is the only format that works on all libssh2 configurations
19+
tmp_key <- if(inherits(key, c("rsa", "dsa", "ecdsa"))){
20+
write_pkcs1(key, tempfile())
21+
} else {
22+
write_openssh_pem(key, tempfile())
23+
}
24+
if(.Platform$OS.type == "unix"){
25+
Sys.chmod(tmp_pub, '0644')
26+
Sys.chmod(tmp_key, '0400')
27+
}
28+
c(tmp_pub, tmp_key, "")
29+
})
2830
}
2931
}
3032

src/clone.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,19 @@ static char* get_password(SEXP cb, const char *url, const char **username, int r
8181
static int get_key_files(SEXP cb, auth_key_data *out, int verbose){
8282
if(!Rf_isFunction(cb))
8383
Rf_error("cb must be a function");
84-
int err;
84+
int err = 0;
8585
SEXP call = PROTECT(Rf_lcons(cb, R_NilValue));
8686
SEXP res = PROTECT(verbose ? R_tryEval(call, R_GlobalEnv, &err) :
8787
R_tryEvalSilent(call, R_GlobalEnv, &err));
88+
if(res && Rf_inherits(res, "try-error")){
89+
static char custom_callback_error[1000] = {0};
90+
snprintf(custom_callback_error, 999, "SSH authentication failure: %s", CHAR(STRING_ELT(res, 0)));
91+
giterr_set_str(GIT_ERROR_CALLBACK, custom_callback_error);
92+
UNPROTECT(2);
93+
return -1;
94+
}
8895
if(err || !Rf_isString(res)){
96+
giterr_set_str(GIT_ERROR_CALLBACK, "Failed to read local SSH key from callback function");
8997
UNPROTECT(2);
9098
return -1;
9199
}
@@ -171,7 +179,7 @@ static int auth_callback(git_cred **cred, const char *url, const char *username,
171179
auth_callback_data_t *cb_data = payload;
172180
const char * ssh_user = username ? username : "git";
173181
int verbose = cb_data->verbose;
174-
char custom_callback_error[1000] = "Authentication failure";
182+
git_error_clear();
175183

176184
#if AT_LEAST_LIBGIT2(0, 20)
177185

@@ -200,11 +208,6 @@ static int auth_callback(git_cred **cred, const char *url, const char *username,
200208
key_data.key_path, key_data.pass_phrase)){
201209
print_if_verbose("Trying to authenticate '%s' using provided ssh-key...\n", ssh_user);
202210
return 0;
203-
#if R_VERSION < 263424
204-
//TODO: better fallback for this non-API call in R 4.5....
205-
} else if(R_curErrorBuf()){
206-
snprintf(custom_callback_error, 999, "SSH authentication failure: %s", R_curErrorBuf());
207-
#endif
208211
}
209212
}
210213

@@ -230,6 +233,7 @@ static int auth_callback(git_cred **cred, const char *url, const char *username,
230233
char *pass = get_password(cb_data->getcred, url, &username, cb_data->retries);
231234
if(!username || !pass){
232235
print_if_verbose("Credential lookup failed\n");
236+
giterr_set_str(GIT_ERROR_CALLBACK, "HTTPS Authentication failure");
233237
goto failure;
234238
} else {
235239
return git_cred_userpass_plaintext_new(cred, username, pass);
@@ -238,7 +242,6 @@ static int auth_callback(git_cred **cred, const char *url, const char *username,
238242
}
239243
print_if_verbose("All authentication methods failed\n");
240244
failure:
241-
giterr_set_str(GIT_ERROR_CALLBACK, custom_callback_error);
242245
return GIT_EAUTH;
243246
}
244247

0 commit comments

Comments
 (0)