Browse Source

Initial commit

master
Thomas Forgione 3 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 @@
1
+/target
2
+**/*.rs.bk

+ 23
- 0
Cargo.lock View File

@@ -0,0 +1,23 @@
1
+[[package]]
2
+name = "colored"
3
+version = "1.7.0"
4
+source = "registry+https://github.com/rust-lang/crates.io-index"
5
+dependencies = [
6
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
7
+]
8
+
9
+[[package]]
10
+name = "gclone"
11
+version = "0.1.0"
12
+dependencies = [
13
+ "colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
14
+]
15
+
16
+[[package]]
17
+name = "lazy_static"
18
+version = "1.2.0"
19
+source = "registry+https://github.com/rust-lang/crates.io-index"
20
+
21
+[metadata]
22
+"checksum colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e9a455e156a4271e12fd0246238c380b1e223e3736663c7a18ed8b6362028a9"
23
+"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 @@
1
+[package]
2
+name = "gclone"
3
+version = "0.1.0"
4
+authors = ["Thomas Forgione <thomas@forgione.fr>"]
5
+edition = "2018"
6
+
7
+[dependencies]
8
+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
581 581
 of warranty; and each file should have at least the "copyright" line and a
582 582
 pointer to where the full notice is found.
583 583
 
584
-<one line to give the program's name and a brief idea of what it does.>
584
+gclone: a program that clones a git repository and automatically puts it in the
585
+right place
585 586
 
586
-Copyright (C) <year> <name of author>
587
+Copyright (C) 2019 Thomas Forgione <thomas@forgione.fr>
587 588
 
588 589
 This program is free software: you can redistribute it and/or modify it under
589 590
 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 @@
1
+use std::env;
2
+use std::process::{Command, exit};
3
+use std::fs::{create_dir_all, remove_dir_all};
4
+use std::error::Error;
5
+use std::path::PathBuf;
6
+
7
+use colored::*;
8
+
9
+macro_rules! unwrap {
10
+    ($e: expr) => {
11
+        match $e {
12
+            Some(e) => e,
13
+            None => return None,
14
+        }
15
+    }
16
+}
17
+
18
+fn parse_http_url(input: &str) -> Option<(String, String, String)> {
19
+    let split = input.split("/").collect::<Vec<_>>();
20
+    if split.len() < 3 {
21
+        return None;
22
+    }
23
+
24
+    let repo = String::from(split[split.len() - 1]);
25
+    let owner = String::from(split[split.len() - 2]);
26
+    let server = split[2 .. split.len() - 2].join("/");
27
+
28
+    Some((server, owner, repo))
29
+}
30
+
31
+fn parse_ssh_url(input: &str) -> Option<(String, String, String)> {
32
+    let url = unwrap!(input.split("@").nth(1));
33
+    let mut split = url.split(":");
34
+    let server = String::from(unwrap!(split.next()));
35
+    let rest = unwrap!(split.next());
36
+
37
+    let mut resplit = rest.split("/");
38
+    let owner = String::from(unwrap!(resplit.next()));
39
+    let repo = String::from(unwrap!(resplit.next()));
40
+
41
+    Some((server, owner, repo))
42
+}
43
+
44
+fn parse_url(input: &str) -> Option<(String, String, String)> {
45
+    if input.starts_with("http") {
46
+        parse_http_url(input)
47
+    } else {
48
+        parse_ssh_url(input)
49
+    }
50
+}
51
+
52
+fn help() {
53
+
54
+}
55
+
56
+fn main() {
57
+
58
+    let git_dir = match env::var("GCLONE_PATH") {
59
+        Ok(path) => path,
60
+        Err(e) => {
61
+            eprintln!("{} {} {}",
62
+                "error:".bold().red(),
63
+                "environment variable GCLONE_PATH must be set:".bold(),
64
+                e.description());
65
+
66
+            exit(1);
67
+        },
68
+    };
69
+
70
+    // Parse args
71
+    let url = match env::args().nth(1) {
72
+        Some(arg) => arg,
73
+        None => {
74
+            eprintln!("{} {}",
75
+                "error:".bold().red(),
76
+                "gclone expects an argument".bold());
77
+
78
+            exit(1);
79
+        },
80
+    };
81
+
82
+    if url == "-h" || url == "--help" {
83
+        return help();
84
+    }
85
+
86
+    let (server, owner, repo) = match parse_url(&url) {
87
+        Some(parsed) => parsed,
88
+        None => {
89
+            eprintln!("{} {}",
90
+                "error:".bold().red(),
91
+                "couldn't guess server, owner and repo names from url".bold());
92
+
93
+            exit(1);
94
+        },
95
+    };
96
+
97
+    // Build path
98
+    let mut path = PathBuf::from(git_dir);
99
+    path.push(&server);
100
+    path.push(&owner);
101
+    path.push(&repo);
102
+
103
+    if path.exists() {
104
+        eprintln!("{} {}",
105
+            "error:".red().bold(),
106
+            "the corresponding directory already exists".bold());
107
+
108
+        exit(1);
109
+    }
110
+
111
+    match create_dir_all(&path) {
112
+        Ok(_) => (),
113
+        Err(e) => {
114
+            eprintln!("{} {} {}",
115
+                "error:".red().bold(),
116
+                "couldn't create the corresponding directory:".bold(),
117
+                e.description());
118
+
119
+            remove_dir_all(&path).ok();
120
+
121
+            exit(1);
122
+        },
123
+    }
124
+
125
+    eprintln!("{} {} {}{}", "info:".bold(), "cloning", url, "...");
126
+
127
+    let command = Command::new("git")
128
+        .args(&["clone", &url, &path.display().to_string()])
129
+        .output();
130
+
131
+    match command {
132
+        Ok(repo) => repo,
133
+        Err(e) => {
134
+            eprintln!("{} {} {}",
135
+                "error:".bold().red(),
136
+                "couldn't clone repository:".bold(),
137
+                e.description());
138
+
139
+            remove_dir_all(&path).ok();
140
+
141
+            exit(1);
142
+        },
143
+    };
144
+
145
+    eprintln!("{} {}", "info:".bold(), "done!");
146
+
147
+}

Loading…
Cancel
Save