Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions src/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ use std::path::Path;

use clap::{App, Arg, SubCommand};
use colored::*;
use git2::{Error as GitError, FetchOptions, RemoteCallbacks};
use git2::build::RepoBuilder;
use git2::Error as GitError;
use serde::{Deserialize, Serialize};

use crate::conf;
use crate::git::GitAction;
use crate::input_args::InputArgs;

Expand Down Expand Up @@ -81,21 +82,41 @@ pub fn clone(args: InputArgs, mut clone_repos: Vec<GitRepo>) {
}

for remote in remotes_from_args {
let mut clone = GitClone { remote_url: remote.remote_url.as_str(), local_path: Path::new(remote.local_path.as_str()) };
let mut use_ssh = false;
if remote.remote_url.contains("git@") {
use_ssh = true;
}

let mut clone = GitClone {
remote_url: remote.remote_url.as_str(),
local_path: Path::new(remote.local_path.as_str()),
use_ssh: use_ssh,
};
clone.git_action().expect(format!("Failed to clone repo {}, ", remote.remote_url).as_str());
}
}

pub struct GitClone<'a> {
pub remote_url: &'a str,
pub local_path: &'a Path,
pub use_ssh: bool,
}

// Todo: Add spinner to show progress.
impl<'a> GitAction for GitClone<'a> {
fn git_action(&mut self) -> Result<(), GitError> {
RepoBuilder::new()
.clone(self.remote_url, self.local_path)?;
let mut builder = RepoBuilder::new();

if self.use_ssh {
let mut callback = RemoteCallbacks::new();
callback.credentials(conf::ssh_auth_callback);

let mut fetch_options = FetchOptions::new();
fetch_options.remote_callbacks(callback);

builder.fetch_options(fetch_options);
}

builder.clone(self.remote_url, self.local_path)?;
println!("{} - {} {} {:#?}", "Remote repo".green(), self.remote_url.blue(), "cloned locally at".green(),
self.local_path.as_os_str());

Expand Down
16 changes: 16 additions & 0 deletions src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::error::Error;
use std::fs;
use std::path::Path;

use git2::{Cred, CredentialType, Error as GitError};
use regex::Regex;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -67,3 +68,18 @@ fn create_filter_list(conf: &mut GGConf) -> Result<&mut GGConf, Box<dyn Error>>
conf.filter_list_regex = filter_list;
Ok(conf)
}

pub fn ssh_auth_callback(_user: &str, _user_from_url: Option<&str>, _cred: CredentialType)
-> Result<Cred, GitError> {
match std::env::var("HOME") {
Ok(home) => {
let path = format!("{}/.ssh/id_rsa", home);
let credentials_path = std::path::Path::new(&path);
match credentials_path.exists() {
true => Cred::ssh_key("git", None, credentials_path, None),
false => Err(GitError::from_str(&format!("unable to get key from {}", path))),
}
}
Err(_) => Err(GitError::from_str("unable to get env variable HOME")),
}
}
9 changes: 7 additions & 2 deletions src/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use clap::{App, Arg, SubCommand};
use colored::*;
use reqwest::{Client, RequestBuilder};

use crate::clone::GitClone;
use crate::git::GitAction;
use crate::input_args::InputArgs;
use crate::clone::GitClone;

pub fn sub_command<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("create")
Expand Down Expand Up @@ -50,7 +50,12 @@ pub fn create(args: InputArgs) {
process::exit(1);
});

let mut clone = GitClone { remote_url: remote_url.as_str(), local_path: root_path.as_path() };
let mut clone = GitClone {
remote_url: remote_url.as_str(),
local_path: root_path.as_path(),
use_ssh: false,
};

clone.git_action().expect(format!("Failed to clone repo {}, ", remote_url).as_str());
}

Expand Down
3 changes: 1 addition & 2 deletions src/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,11 @@ fn fetch_repo<'a>(repo: Repository) -> Result<(), Box<dyn Error>> {
let remote = "origin";
print!("{} {} {} {:#?} -> ", "\nFetching".blue(), remote.blue(), "for".blue(), path);

let mut cb = RemoteCallbacks::new();

let remote = repo
.find_remote(remote)
.or_else(|_| repo.remote_anonymous(remote))?;

let mut cb = RemoteCallbacks::new();
cb.credentials(git_credentials_callback);

let mut fo = FetchOptions::new();
Expand Down