Browse Source

Initial commit

master
Thomas Forgione 5 months ago
parent
commit
a98638b947
Signed by: Thomas Forgione <thomas@forgione.fr> GPG Key ID: 203DAEA747F48F41
5 changed files with 183 additions and 2 deletions
  1. 2
    0
      .gitignore
  2. 23
    0
      Cargo.lock
  3. 8
    0
      Cargo.toml
  4. 3
    2
      LICENSE
  5. 147
    0
      src/main.rs

+ 2
- 0
.gitignore View File

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

+ 23
- 0
Cargo.lock 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
- 0
Cargo.toml 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"

+ 3
- 2
LICENSE 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
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
the terms of the GNU General Public License as published by the Free Software

+ 147
- 0
src/main.rs 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!");

}

Loading…
Cancel
Save