Skip to content

Commit 8df2375

Browse files
committed
fix: url handling
1 parent 1c2c6e6 commit 8df2375

10 files changed

Lines changed: 84 additions & 45 deletions

File tree

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ serde = { version = "1.0.126", features = ["derive"] }
3030
fs_extra = "1.2.0"
3131
url-builder = "0.1.1"
3232
log = "0.4.22"
33+
pretty_env_logger = "0.5.0"

src/cli/src/cli.rs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,26 @@ impl Cli {
187187

188188
fn clone(args: Vec<String>, workspace: Option<String>) -> Result<(), Error> {
189189
let mut url = URLBuilder::new();
190+
url.set_protocol("https");
190191
let mut clone = if args.is_empty() {
191192
clone_setup()?
193+
} else if Settings::current().is_some() && args.len() == 1 {
194+
let Some(options) = Settings::current() else {
195+
return devmode::error("");
196+
};
197+
198+
url.set_host(Host::from(&options.host).url())
199+
.add_route(&options.owner);
200+
if let Some(repo) = args.get(0) {
201+
url.add_route(repo);
202+
}
203+
204+
CloneAction::new(&url.build())
192205
} else if args.len() == 1 {
193206
if let Some(url) = args.get(0) {
194207
CloneAction::new(url)
195208
} else {
196-
return devmode::generic("No URL provided");
209+
return devmode::error("No URL provided");
197210
}
198211
} else if args.len() == 3 {
199212
if let Some(host) = args.get(0) {
@@ -207,27 +220,23 @@ impl Cli {
207220
}
208221
CloneAction::new(&url.build())
209222
} else {
210-
let options = Settings::current().ok_or(Error::Generic("Failed to load settings"))?;
211-
url.set_host(Host::from(&options.host).url())
212-
.add_route(&options.owner);
213-
if let Some(repo) = args.get(2) {
214-
url.add_route(repo);
215-
}
216-
217-
CloneAction::new(&url.build())
223+
return devmode::error("The command was invalid");
218224
};
219225
if let Some(workspace) = workspace {
220226
clone.set_workspace(workspace);
221227
}
222228

223-
if let Err(Error::Git(error)) = clone.run() {
224-
match error.code() {
225-
git2::ErrorCode::Exists => {
226-
if overwrite(clone.get_local_path()?)? {
227-
clone.run()?;
229+
if let Err(error) = clone.run() {
230+
match error {
231+
Error::Git(error) => match error.code() {
232+
git2::ErrorCode::Exists => {
233+
if overwrite(clone.get_local_path()?)? {
234+
clone.run()?;
235+
}
228236
}
229-
}
230-
_ => log::error!("{error}"),
237+
_ => log::error!("{error}"),
238+
},
239+
error => log::error!("{error}"),
231240
}
232241
};
233242

@@ -238,7 +247,7 @@ impl Cli {
238247
let reader = create_paths_reader()?;
239248
let paths = find_paths(reader, project)?;
240249
if paths.is_empty() {
241-
return devmode::generic(NO_PROJECT_FOUND);
250+
return devmode::error(NO_PROJECT_FOUND);
242251
} else if paths.len() > 1 {
243252
let paths: Vec<&str> = paths.iter().map(|s| s as &str).collect();
244253
let path = select_repo(paths)?.to_string();
@@ -251,7 +260,7 @@ impl Cli {
251260
let reader = create_paths_reader()?;
252261
let paths = find_paths(reader, project)?;
253262
if paths.is_empty() {
254-
return devmode::generic(NO_PROJECT_FOUND);
263+
return devmode::error(NO_PROJECT_FOUND);
255264
} else if paths.len() > 1 {
256265
eprintln!("{}", MORE_PROJECTS_FOUND); // TODO: Let user decide which
257266
let paths: Vec<&str> = paths.iter().map(|s| s as &str).collect();
@@ -406,7 +415,7 @@ impl Cli {
406415
.filter(|path| !path.contains(name.as_str()))
407416
.collect();
408417
let path = if paths.is_empty() {
409-
return devmode::generic("Could not locate the {add} repository.");
418+
return devmode::error("Could not locate the {add} repository.");
410419
} else if paths.len() > 1 {
411420
eprintln!("{}", MORE_PROJECTS_FOUND);
412421
let paths: Vec<&str> = paths.iter().map(|s| s as &str).collect();
@@ -438,7 +447,7 @@ impl Cli {
438447
.filter(|path| path.contains(name.as_str()))
439448
.collect();
440449
let path = if paths.is_empty() {
441-
return devmode::generic(
450+
return devmode::error(
442451
"Could not locate the {remove} repository inside {name}",
443452
);
444453
} else if paths.len() > 1 {
@@ -469,7 +478,7 @@ impl Cli {
469478
println!("Workspace `{name}` found.");
470479
}
471480
} else if delete || rename.is_some() {
472-
return devmode::generic("Couldn't find a workspace that matches {name}.");
481+
return devmode::error("Couldn't find a workspace that matches {name}.");
473482
} else {
474483
settings.workspaces.names.push(name.clone());
475484
settings.write(true)?;

src/cli/src/input.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pub fn config_owner() -> Result<Settings, Error> {
9393
let answer = ask("owner", "Git username:", "Please enter a Git username.")?;
9494
let owner = match answer {
9595
Answer::String(owner) => owner,
96-
_ => return devmode::generic("Owner is required."),
96+
_ => return devmode::error("Owner is required."),
9797
};
9898
let current = Settings::current();
9999
let settings = match current {
@@ -113,7 +113,7 @@ pub fn config_host() -> Result<Settings, Error> {
113113
let answer = pick("host", "Choose your Git host:", vec!["GitHub", "GitLab"])?;
114114
let host = match answer {
115115
Answer::ListItem(item) => Host::from(&item.text).to_string(),
116-
_ => return devmode::generic("Host is required."),
116+
_ => return devmode::error("Host is required."),
117117
};
118118
let current = Settings::current();
119119
let settings = match current {
@@ -146,13 +146,13 @@ pub fn config_editor() -> Result<Settings, Error> {
146146
if let Answer::String(name) = answer {
147147
Editor::custom(name)
148148
} else {
149-
return devmode::generic("Editor name is required.");
149+
return devmode::error("Editor name is required.");
150150
}
151151
} else {
152152
Editor::new(Application::from(&*item.text))
153153
}
154154
}
155-
_ => return devmode::generic("Editor must be picked."),
155+
_ => return devmode::error("Editor must be picked."),
156156
};
157157
let current = Settings::current();
158158
let settings = match current {
@@ -172,7 +172,7 @@ pub fn select_repo(paths: Vec<&str>) -> Result<String, Error> {
172172
let answer = pick("repo", "Select the repository you want to open:", paths)?;
173173
let repo = match answer {
174174
Answer::ListItem(item) => item.text,
175-
_ => return devmode::generic("Repository must be picked."),
175+
_ => return devmode::error("Repository must be picked."),
176176
};
177177
Ok(repo)
178178
}

src/cli/src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@ mod cli;
77
mod input;
88

99
fn main() -> Result<(), Error> {
10+
start_logger();
1011
let cli = Cli::parse();
1112
if let Err(e) = cli.run() {
1213
log::error!("{}", e);
1314
}
1415
Ok(())
1516
}
17+
18+
pub fn start_logger() {
19+
std::env::set_var("RUST_LOG", "dm=info");
20+
pretty_env_logger::init();
21+
}

src/clone.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::{error, git_pull, Error};
1818
#[setters(strip_option)]
1919
pub struct CloneAction {
2020
#[setters(skip)]
21-
pub url: GitUrl,
21+
pub url: Option<GitUrl>,
2222
pub workspace: Option<String>,
2323
}
2424

@@ -31,23 +31,32 @@ impl Action for CloneAction {
3131
impl CloneAction {
3232
pub fn new(url: &str) -> Self {
3333
Self {
34-
url: GitUrl::parse(url).unwrap(),
34+
url: GitUrl::parse(url).ok(),
3535
workspace: None,
3636
}
3737
}
3838

3939
pub fn clone_repo(&self) -> Result<(), Error> {
40+
let Some(url) = &self.url else {
41+
return error::error("Url is not in the correct format.");
42+
};
4043
let path = self.get_local_path()?;
41-
4244
let clone = git2::build::RepoBuilder::new()
4345
.fetch_options(CloneAction::get_fetch_options()?)
44-
.clone(&self.url.to_string(), &path);
46+
.clone(&url.to_string(), &path);
4547

4648
if let Err(err) = clone {
47-
if let ErrorCode::NotFound = err.code() {
48-
remove_dir_all(&path)?
49+
match err.code() {
50+
ErrorCode::GenericError => {
51+
if let Some(parent) = path.parent() {
52+
let children: Vec<_> = std::fs::read_dir(parent)?.collect();
53+
if children.is_empty() {
54+
remove_dir_all(&parent)?;
55+
}
56+
}
57+
}
58+
_ => return Err(Error::Git(err)),
4959
}
50-
return Err(Error::Git(err));
5160
}
5261

5362
git_pull::status_short(path.to_str().unwrap().to_string())?;
@@ -56,15 +65,18 @@ impl CloneAction {
5665
}
5766

5867
pub fn get_local_path(&self) -> Result<PathBuf, Error> {
59-
if self.url.host.is_none() || self.url.owner.is_none() {
60-
return error::generic("Url is not in the correct format.");
68+
let Some(url) = &self.url else {
69+
return error::error("Url is not in the correct format.");
70+
};
71+
if url.host.is_none() || url.owner.is_none() {
72+
return error::error("Url is not in the correct format.");
6173
}
6274
let path = home()
6375
.join("Developer")
64-
.join(Host::from(self.url.host.as_ref().unwrap()).to_string())
65-
.join(self.url.owner.as_ref().unwrap())
76+
.join(Host::from(url.host.as_ref().unwrap()).to_string())
77+
.join(url.owner.as_ref().unwrap())
6678
.join(self.workspace.as_ref().unwrap_or(&String::default()))
67-
.join(self.url.name.clone());
79+
.join(url.name.clone());
6880

6981
Ok(path)
7082
}

src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ pub enum Error {
2626
String(String),
2727
}
2828

29-
pub fn generic<T>(msg: &'static str) -> Result<T, Error> {
29+
pub fn error<T>(msg: &'static str) -> Result<T, Error> {
3030
Err(Error::Generic(msg))
3131
}

src/fork.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,16 @@ impl ForkAction {
4747
}
4848
pub fn run(&self) -> Result<(), Error> {
4949
return if let Host::None = self.host {
50-
error::generic(
50+
error::error(
5151
"You can't do this unless you set your configuration with ` dm config -a`\n\
5252
In the meantime, you can clone by specifying <host> <owner> <repo>",
5353
)
5454
} else if self.owner.is_empty() {
55-
error::generic("Missing arguments: <owner> <repo>")
55+
error::error("Missing arguments: <owner> <repo>")
5656
} else if self.repo.is_empty() {
57-
error::generic("Missing arguments: <repo>")
57+
error::error("Missing arguments: <repo>")
5858
} else if self.upstream.is_empty() {
59-
error::generic(
59+
error::error(
6060
"Missing arguments: <upstream>. \
6161
For example ... -u https://github.com/user/upstream",
6262
)

src/git_pull.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ fn get_branch(repo: &Repository) -> Result<String, Error> {
124124
let head = head.as_ref().and_then(|h| h.shorthand());
125125
match head {
126126
Some(branch) => Ok(String::from(branch)),
127-
None => error::generic(FAILED_TO_GET_BRANCH),
127+
None => error::error(FAILED_TO_GET_BRANCH),
128128
}
129129
}
130130

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub mod clone;
44
pub mod constants;
55
pub mod editor;
66
mod error;
7-
pub use error::{generic, Error};
7+
pub use error::{error, Error};
88
pub mod fork;
99
pub mod git_pull;
1010
pub mod host;

0 commit comments

Comments
 (0)