Initial commit
This commit is contained in:
147
src/main.rs
Normal file
147
src/main.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
use std::env;
|
||||
use std::process::{Command, exit};
|
||||
use std::fs::{create_dir_all, remove_dir_all};
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use colored::*;
|
||||
|
||||
macro_rules! unwrap {
|
||||
($e: expr) => {
|
||||
match $e {
|
||||
Some(e) => e,
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_http_url(input: &str) -> Option<(String, String, String)> {
|
||||
let split = input.split("/").collect::<Vec<_>>();
|
||||
if split.len() < 3 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let repo = String::from(split[split.len() - 1]);
|
||||
let owner = String::from(split[split.len() - 2]);
|
||||
let server = split[2 .. split.len() - 2].join("/");
|
||||
|
||||
Some((server, owner, repo))
|
||||
}
|
||||
|
||||
fn parse_ssh_url(input: &str) -> Option<(String, String, String)> {
|
||||
let url = unwrap!(input.split("@").nth(1));
|
||||
let mut split = url.split(":");
|
||||
let server = String::from(unwrap!(split.next()));
|
||||
let rest = unwrap!(split.next());
|
||||
|
||||
let mut resplit = rest.split("/");
|
||||
let owner = String::from(unwrap!(resplit.next()));
|
||||
let repo = String::from(unwrap!(resplit.next()));
|
||||
|
||||
Some((server, owner, repo))
|
||||
}
|
||||
|
||||
fn parse_url(input: &str) -> Option<(String, String, String)> {
|
||||
if input.starts_with("http") {
|
||||
parse_http_url(input)
|
||||
} else {
|
||||
parse_ssh_url(input)
|
||||
}
|
||||
}
|
||||
|
||||
fn help() {
|
||||
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let git_dir = match env::var("GCLONE_PATH") {
|
||||
Ok(path) => path,
|
||||
Err(e) => {
|
||||
eprintln!("{} {} {}",
|
||||
"error:".bold().red(),
|
||||
"environment variable GCLONE_PATH must be set:".bold(),
|
||||
e.description());
|
||||
|
||||
exit(1);
|
||||
},
|
||||
};
|
||||
|
||||
// Parse args
|
||||
let url = match env::args().nth(1) {
|
||||
Some(arg) => arg,
|
||||
None => {
|
||||
eprintln!("{} {}",
|
||||
"error:".bold().red(),
|
||||
"gclone expects an argument".bold());
|
||||
|
||||
exit(1);
|
||||
},
|
||||
};
|
||||
|
||||
if url == "-h" || url == "--help" {
|
||||
return help();
|
||||
}
|
||||
|
||||
let (server, owner, repo) = match parse_url(&url) {
|
||||
Some(parsed) => parsed,
|
||||
None => {
|
||||
eprintln!("{} {}",
|
||||
"error:".bold().red(),
|
||||
"couldn't guess server, owner and repo names from url".bold());
|
||||
|
||||
exit(1);
|
||||
},
|
||||
};
|
||||
|
||||
// Build path
|
||||
let mut path = PathBuf::from(git_dir);
|
||||
path.push(&server);
|
||||
path.push(&owner);
|
||||
path.push(&repo);
|
||||
|
||||
if path.exists() {
|
||||
eprintln!("{} {}",
|
||||
"error:".red().bold(),
|
||||
"the corresponding directory already exists".bold());
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
match create_dir_all(&path) {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
eprintln!("{} {} {}",
|
||||
"error:".red().bold(),
|
||||
"couldn't create the corresponding directory:".bold(),
|
||||
e.description());
|
||||
|
||||
remove_dir_all(&path).ok();
|
||||
|
||||
exit(1);
|
||||
},
|
||||
}
|
||||
|
||||
eprintln!("{} {} {}{}", "info:".bold(), "cloning", url, "...");
|
||||
|
||||
let command = Command::new("git")
|
||||
.args(&["clone", &url, &path.display().to_string()])
|
||||
.output();
|
||||
|
||||
match command {
|
||||
Ok(repo) => repo,
|
||||
Err(e) => {
|
||||
eprintln!("{} {} {}",
|
||||
"error:".bold().red(),
|
||||
"couldn't clone repository:".bold(),
|
||||
e.description());
|
||||
|
||||
remove_dir_all(&path).ok();
|
||||
|
||||
exit(1);
|
||||
},
|
||||
};
|
||||
|
||||
eprintln!("{} {}", "info:".bold(), "done!");
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user