Initial commit

This commit is contained in:
Thomas Forgione 2019-02-11 17:33:37 +01:00
parent 785fe10e0c
commit a98638b947
No known key found for this signature in database
GPG Key ID: 203DAEA747F48F41
5 changed files with 183 additions and 2 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
**/*.rs.bk

23
Cargo.lock generated Normal file
View File

@ -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"

8
Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "gclone"
version = "0.1.0"
authors = ["Thomas Forgione <thomas@forgione.fr>"]
edition = "2018"
[dependencies]
colored = "1.7.0"

View File

@ -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

147
src/main.rs Normal file
View 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!");
}