Initial commit
This commit is contained in:
parent
785fe10e0c
commit
a98638b947
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
**/*.rs.bk
|
|
@ -0,0 +1,23 @@
|
||||||
|
[[package]]
|
||||||
|
name = "colored"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gclone"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e9a455e156a4271e12fd0246238c380b1e223e3736663c7a18ed8b6362028a9"
|
||||||
|
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
|
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "gclone"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Thomas Forgione <thomas@forgione.fr>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
colored = "1.7.0"
|
5
LICENSE
5
LICENSE
|
@ -581,9 +581,10 @@ them to the start of each source file to most effectively state the exclusion
|
||||||
of warranty; and each file should have at least the "copyright" line and a
|
of warranty; and each file should have at least the "copyright" line and a
|
||||||
pointer to where the full notice is found.
|
pointer to where the full notice is found.
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
gclone: a program that clones a git repository and automatically puts it in the
|
||||||
|
right place
|
||||||
|
|
||||||
Copyright (C) <year> <name of author>
|
Copyright (C) 2019 Thomas Forgione <thomas@forgione.fr>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify it under
|
This program is free software: you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
|
|
@ -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!");
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue