Skip to content

Commit 2cc63ca

Browse files
committed
refactor
- fmt - clippy
1 parent 030e040 commit 2cc63ca

File tree

7 files changed

+127
-142
lines changed

7 files changed

+127
-142
lines changed

gitoxide-core/src/repository/credential.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ pub fn function(repo: gix::Repository, action: gix::credentials::program::main::
1515
std::io::stdin(),
1616
std::io::stdout(),
1717
|action, context| -> Result<_, Error> {
18-
let url = context.url.clone().or_else(|| context.to_url()).ok_or_else(|| {
19-
Error::Protocol(gix::credentials::protocol::Error::UrlMissing)
20-
})?;
21-
let (mut cascade, _action, prompt_options) = repo.config_snapshot().credential_helpers(gix::url::parse(
22-
url.as_ref(),
23-
)?)?;
18+
let url = context
19+
.url
20+
.clone()
21+
.or_else(|| context.to_url())
22+
.ok_or(Error::Protocol(gix::credentials::protocol::Error::UrlMissing))?;
23+
let (mut cascade, _action, prompt_options) = repo
24+
.config_snapshot()
25+
.credential_helpers(gix::url::parse(url.as_ref())?)?;
2426
cascade
2527
.invoke(
2628
match action {

gix-credentials/src/program/main.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,16 @@ pub(crate) mod function {
9292
if ctx.url.is_none() && (ctx.protocol.is_none() || ctx.host.is_none()) {
9393
return Err(Error::UrlMissing);
9494
}
95-
let res = credentials(action, ctx).map_err(|err| Error::Helper { source: Box::new(err) })?;
95+
let res = credentials(action, ctx.clone()).map_err(|err| Error::Helper { source: Box::new(err) })?;
9696
match (action, res) {
9797
(Action::Get, None) => {
98-
let ctx_for_error = Context::from_bytes(&buf)?;
99-
let url = ctx_for_error.url.clone()
98+
let ctx_for_error = ctx;
99+
let url = ctx_for_error
100+
.url
101+
.clone()
100102
.or_else(|| ctx_for_error.to_url())
101-
.expect("URL is available either directly or via protocol+host");
102-
return Err(Error::CredentialsMissing { url })
103+
.expect("URL is available either directly or via protocol+host which we checked for");
104+
return Err(Error::CredentialsMissing { url });
103105
}
104106
(Action::Get, Some(ctx)) => ctx.write_to(stdout)?,
105107
(Action::Erase | Action::Store, None) => {}

gix-credentials/src/protocol/context/mod.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,9 @@ mod mutate {
9393
#[allow(clippy::result_large_err)]
9494
pub fn destructure_url_in_place(&mut self, use_http_path: bool) -> Result<&mut Self, protocol::Error> {
9595
if self.url.is_none() {
96-
// If URL is not present but protocol and host are, construct the URL
97-
if let Some(constructed_url) = self.to_url() {
98-
self.url = Some(constructed_url);
99-
} else {
100-
return Err(protocol::Error::UrlMissing);
101-
}
96+
self.url = Some(self.to_url().ok_or(protocol::Error::UrlMissing)?);
10297
}
103-
98+
10499
let url = gix_url::parse(self.url.as_ref().expect("URL is present after check above").as_ref())?;
105100
self.protocol = Some(url.scheme.as_str().into());
106101
self.username = url.user().map(ToOwned::to_owned);
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use gix_credentials::program::main;
2+
use std::io::Cursor;
3+
4+
#[derive(Debug, thiserror::Error)]
5+
#[error("Test error")]
6+
struct TestError;
7+
8+
#[test]
9+
fn protocol_and_host_without_url_is_valid() {
10+
let input = b"protocol=https\nhost=github.com\n";
11+
let mut output = Vec::new();
12+
13+
let mut called = false;
14+
let result = main(
15+
["get".into()],
16+
Cursor::new(input),
17+
&mut output,
18+
|_action, context| -> Result<Option<gix_credentials::protocol::Context>, TestError> {
19+
assert_eq!(context.protocol.as_deref(), Some("https"));
20+
assert_eq!(context.host.as_deref(), Some("github.com"));
21+
assert_eq!(context.url, None, "the URL isn't automatically populated");
22+
called = true;
23+
24+
Ok(None)
25+
},
26+
);
27+
28+
// This should fail because our mock helper returned None (no credentials found)
29+
// but it should NOT fail because of missing URL
30+
match result {
31+
Err(gix_credentials::program::main::Error::CredentialsMissing { .. }) => {
32+
assert!(
33+
called,
34+
"The helper gets called, but as nothing is provided in the function it ulimately fails"
35+
);
36+
}
37+
other => panic!("Expected CredentialsMissing error, got: {other:?}"),
38+
}
39+
}
40+
41+
#[test]
42+
fn missing_protocol_with_only_host_or_protocol_fails() {
43+
for input in ["host=github.com\n", "protocol=https\n"] {
44+
let mut output = Vec::new();
45+
46+
let mut called = false;
47+
let result = main(
48+
["get".into()],
49+
Cursor::new(input),
50+
&mut output,
51+
|_action, _context| -> Result<Option<gix_credentials::protocol::Context>, TestError> {
52+
called = true;
53+
Ok(None)
54+
},
55+
);
56+
57+
match result {
58+
Err(gix_credentials::program::main::Error::UrlMissing) => {
59+
assert!(!called, "the context is lacking, hence nothing gets called");
60+
}
61+
other => panic!("Expected UrlMissing error, got: {other:?}"),
62+
}
63+
}
64+
}
65+
66+
#[test]
67+
fn url_alone_is_valid() {
68+
let input = b"url=https://github.com\n";
69+
let mut output = Vec::new();
70+
71+
let mut called = false;
72+
let result = main(
73+
["get".into()],
74+
Cursor::new(input),
75+
&mut output,
76+
|_action, context| -> Result<Option<gix_credentials::protocol::Context>, TestError> {
77+
called = true;
78+
assert_eq!(context.url.unwrap(), "https://github.com");
79+
assert_eq!(context.host, None, "not auto-populated");
80+
assert_eq!(context.protocol, None, "not auto-populated");
81+
82+
Ok(None)
83+
},
84+
);
85+
86+
// This should fail because our mock helper returned None (no credentials found)
87+
// but it should NOT fail because of missing URL
88+
match result {
89+
Err(gix_credentials::program::main::Error::CredentialsMissing { .. }) => {
90+
assert!(called);
91+
}
92+
other => panic!("Expected CredentialsMissing error, got: {other:?}"),
93+
}
94+
}

gix-credentials/tests/program/main_validation.rs

Lines changed: 0 additions & 101 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
mod from_custom_definition;
2-
mod main_validation;
2+
mod main;

gix-credentials/tests/protocol/context.rs

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,38 +73,28 @@ mod destructure_url_in_place {
7373
);
7474
}
7575

76-
#[test]
77-
fn protocol_and_host_without_url_constructs_url_first() {
78-
let mut ctx = Context {
79-
protocol: Some("https".into()),
80-
host: Some("github.com".into()),
81-
..Default::default()
82-
};
83-
ctx.destructure_url_in_place(false).expect("should work with protocol and host");
84-
85-
// URL should be constructed from protocol and host
86-
assert_eq!(ctx.url.as_deref().map(|b| &**b), Some("https://github.com".as_bytes()));
87-
// Original fields should be preserved
88-
assert_eq!(ctx.protocol.as_deref(), Some("https"));
89-
assert_eq!(ctx.host.as_deref(), Some("github.com"));
90-
}
91-
9276
#[test]
9377
fn protocol_and_host_with_path_without_url_constructs_full_url() {
9478
let mut ctx = Context {
9579
protocol: Some("https".into()),
9680
host: Some("github.com".into()),
9781
path: Some("org/repo".into()),
82+
username: Some("user".into()),
83+
password: Some("pass-to-be-ignored".into()),
9884
..Default::default()
9985
};
100-
ctx.destructure_url_in_place(false).expect("should work with protocol, host and path");
101-
102-
// URL should be constructed from all provided fields
103-
assert_eq!(ctx.url.as_deref().map(|b| &**b), Some("https://github.com/org/repo".as_bytes()));
86+
ctx.destructure_url_in_place(false)
87+
.expect("should work with protocol, host and path");
88+
89+
assert_eq!(
90+
ctx.url.unwrap(),
91+
"https://[email protected]/org/repo",
92+
"URL should be constructed from all provided fields, except password"
93+
);
10494
// Original fields should be preserved
10595
assert_eq!(ctx.protocol.as_deref(), Some("https"));
10696
assert_eq!(ctx.host.as_deref(), Some("github.com"));
107-
assert_eq!(ctx.path.as_deref().map(|b| &**b), Some("org/repo".as_bytes()));
97+
assert_eq!(ctx.path.unwrap(), "org/repo");
10898
}
10999

110100
#[test]
@@ -113,7 +103,10 @@ mod destructure_url_in_place {
113103
host: Some("github.com".into()),
114104
..Default::default()
115105
};
116-
assert!(ctx_no_protocol.destructure_url_in_place(false).is_err());
106+
assert_eq!(
107+
ctx_no_protocol.destructure_url_in_place(false).unwrap_err().to_string(),
108+
"Either 'url' field or both 'protocol' and 'host' fields must be provided"
109+
);
117110

118111
let mut ctx_no_host = Context {
119112
protocol: Some("https".into()),

0 commit comments

Comments
 (0)