Skip to content

Commit 171071d

Browse files
authored
Add useHttpPath support in CredentialHelper (#663)
1 parent 53fd0fb commit 171071d

File tree

1 file changed

+40
-3
lines changed

1 file changed

+40
-3
lines changed

src/cred.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct CredentialHelper {
2222
pub username: Option<String>,
2323
protocol: Option<String>,
2424
host: Option<String>,
25+
path: Option<String>,
2526
url: String,
2627
commands: Vec<String>,
2728
}
@@ -198,6 +199,7 @@ impl CredentialHelper {
198199
let mut ret = CredentialHelper {
199200
protocol: None,
200201
host: None,
202+
path: None,
201203
username: None,
202204
url: url.to_string(),
203205
commands: Vec::new(),
@@ -208,7 +210,7 @@ impl CredentialHelper {
208210
if let Some(url::Host::Domain(s)) = url.host() {
209211
ret.host = Some(s.to_string());
210212
}
211-
ret.protocol = Some(url.scheme().to_string())
213+
ret.protocol = Some(url.scheme().to_string());
212214
}
213215
ret
214216
}
@@ -227,12 +229,11 @@ impl CredentialHelper {
227229
// Figure out the configured username/helper program.
228230
//
229231
// see http://git-scm.com/docs/gitcredentials.html#_configuration_options
230-
//
231-
// TODO: implement useHttpPath
232232
if self.username.is_none() {
233233
self.config_username(config);
234234
}
235235
self.config_helper(config);
236+
self.config_use_http_path(config);
236237
self
237238
}
238239

@@ -261,6 +262,29 @@ impl CredentialHelper {
261262
self.add_command(global.as_ref().ok().map(|s| &s[..]));
262263
}
263264

265+
// Discover `useHttpPath` from `config`
266+
fn config_use_http_path(&mut self, config: &Config) {
267+
let mut use_http_path = false;
268+
if let Some(value) = config.get_bool(&self.exact_key("useHttpPath")).ok() {
269+
use_http_path = value;
270+
} else if let Some(value) = self
271+
.url_key("useHttpPath")
272+
.and_then(|key| config.get_bool(&key).ok())
273+
{
274+
use_http_path = value;
275+
} else if let Some(value) = config.get_bool("credential.useHttpPath").ok() {
276+
use_http_path = value;
277+
}
278+
279+
if use_http_path {
280+
if let Ok(url) = url::Url::parse(&self.url) {
281+
let path = url.path();
282+
// Url::parse always includes a leading slash for rooted URLs, while git does not.
283+
self.path = Some(path.strip_prefix('/').unwrap_or(path).to_string());
284+
}
285+
}
286+
}
287+
264288
// Add a `helper` configured command to the list of commands to execute.
265289
//
266290
// see https://www.kernel.org/pub/software/scm/git/docs/technical
@@ -386,6 +410,9 @@ impl CredentialHelper {
386410
if let Some(ref p) = self.host {
387411
let _ = writeln!(stdin, "host={}", p);
388412
}
413+
if let Some(ref p) = self.path {
414+
let _ = writeln!(stdin, "path={}", p);
415+
}
389416
if let Some(ref p) = *username {
390417
let _ = writeln!(stdin, "username={}", p);
391418
}
@@ -602,6 +629,16 @@ echo password=$2
602629
assert_eq!(p, "b");
603630
}
604631

632+
#[test]
633+
fn credential_helper8() {
634+
let cfg = test_cfg! {
635+
"credential.useHttpPath" => "true"
636+
};
637+
let mut helper = CredentialHelper::new("https://example.com/foo/bar");
638+
helper.config(&cfg);
639+
assert_eq!(helper.path.as_deref(), Some("foo/bar"));
640+
}
641+
605642
#[test]
606643
#[cfg(feature = "ssh")]
607644
fn ssh_key_from_memory() {

0 commit comments

Comments
 (0)