From ad97e2ebd68e0f152960ede2126539987b7fb319 Mon Sep 17 00:00:00 2001 From: gbaranski Date: Tue, 4 May 2021 12:07:39 +0200 Subject: [PATCH 1/4] feat: fetching from remote repository via HTTP URL --- Cargo.lock | 14 ++++++++++++++ Cargo.toml | 2 ++ src/main.rs | 29 +++++++++++++++++++++++++---- src/onefetch/cli.rs | 9 +++++++++ src/onefetch/info.rs | 3 +-- src/onefetch/repo.rs | 5 +++++ 6 files changed, 56 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a77dc9212..35ac10fe9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -643,6 +643,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "humansize" version = "1.1.0" @@ -823,6 +829,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + [[package]] name = "memchr" version = "2.3.4" @@ -968,9 +980,11 @@ dependencies = [ "colored", "error-chain", "git2", + "hex", "image", "json", "libc", + "md5", "more-asserts", "paste", "regex", diff --git a/Cargo.toml b/Cargo.toml index 3c508452d..0f662308e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,6 +41,8 @@ term_size = "0.3.2" tokei = "12.1.2" toml = "0.5.8" yaml-rust = "0.4" +md5 = "0.7" +hex = "0.4" [target.'cfg(windows)'.dependencies] ansi_term = "0.12" diff --git a/src/main.rs b/src/main.rs index d7bbfa9a5..754852980 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,28 @@ use std::{io, process}; mod onefetch; +fn get_repo(config: &Cli) -> Result { + let repo = if config.is_remote { + let temp_directory = std::env::temp_dir(); + let repo_digest = md5::compute(&config.repo_path); + let mut repo_directory = temp_directory; + repo_directory.push("onefetch/"); + repo_directory.push(hex::encode(repo_digest.0)); + if repo_directory.exists() { + git2::Repository::discover(repo_directory)? + } else { + repo::clone_remote(&config.repo_path, &repo_directory)? + } + + } else { + if !repo::is_valid(&config.repo_path)? { + return Err("please run onefetch inside of a non-bare git repository".into()); + } + git2::Repository::discover(&config.repo_path)? + }; + Ok(repo) +} + fn run() -> Result<()> { #[cfg(windows)] let _ = ansi_term::enable_ansi_support(); @@ -22,10 +44,9 @@ fn run() -> Result<()> { return cli_utils::print_supported_package_managers(); } - if !repo::is_valid(&config.repo_path)? { - return Err("please run onefetch inside of a non-bare git repository".into()); - } - let info = info::Info::new(config)?; + let repo = get_repo(&config)?; + + let info = info::Info::new(config, repo)?; let mut printer = Printer::new(io::BufWriter::new(io::stdout()), info); diff --git a/src/onefetch/cli.rs b/src/onefetch/cli.rs index 9cde0f92a..e51e3e22f 100644 --- a/src/onefetch/cli.rs +++ b/src/onefetch/cli.rs @@ -37,6 +37,7 @@ pub struct Cli { pub art_off: bool, pub text_colors: Vec, pub iso_time: bool, + pub is_remote: bool, } impl Cli { @@ -253,6 +254,11 @@ impl Cli { .takes_value(true) .help("Ignore all files & directories matching EXCLUDE."), ) + .arg( + Arg::with_name("remote") + .long("remote") + .help("Clone repository from remote"), + ) .get_matches(); let true_color = match matches.value_of("true-color") { @@ -349,6 +355,8 @@ impl Cli { Vec::new() }; + let is_remote = matches.is_present("remote"); + Ok(Cli { repo_path, ascii_input, @@ -370,6 +378,7 @@ impl Cli { text_colors, art_off, iso_time, + is_remote, }) } } diff --git a/src/onefetch/info.rs b/src/onefetch/info.rs index 8f3bef150..86d509781 100644 --- a/src/onefetch/info.rs +++ b/src/onefetch/info.rs @@ -208,9 +208,8 @@ impl std::fmt::Display for Info { } impl Info { - pub fn new(config: Cli) -> Result { + pub fn new(config: Cli, repo: Repository) -> Result { let git_version = cli_utils::get_git_version(); - let repo = Repository::discover(&config.repo_path)?; let internal_repo = Repo::new(&repo, config.no_merges)?; let (repo_name, repo_url) = internal_repo.get_name_and_url()?; let head_refs = internal_repo.get_head_refs()?; diff --git a/src/onefetch/repo.rs b/src/onefetch/repo.rs index f1176839c..b46886897 100644 --- a/src/onefetch/repo.rs +++ b/src/onefetch/repo.rs @@ -264,6 +264,11 @@ impl<'a> Repo<'a> { } } +pub fn clone_remote(url: &str, path: &std::path::PathBuf) -> Result { + let repository = Repository::clone(url, path)?; + Ok(repository) +} + pub fn is_valid(repo_path: &str) -> Result { let repo = Repository::open_ext(repo_path, RepositoryOpenFlags::empty(), Vec::<&Path>::new()); Ok(repo.is_ok() && !repo?.is_bare()) From bc868420c128542dcc46cf4d11ee7e6a11c382fa Mon Sep 17 00:00:00 2001 From: gbaranski Date: Tue, 4 May 2021 14:25:08 +0200 Subject: [PATCH 2/4] feat: progress bars when cloning git remote repo --- Cargo.lock | 50 ++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/onefetch/repo.rs | 37 ++++++++++++++++++++++++++++++-- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35ac10fe9..73569e203 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -286,6 +286,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "console" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "regex", + "terminal_size", + "unicode-width", + "winapi", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -414,6 +429,12 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.28" @@ -709,6 +730,18 @@ dependencies = [ "tiff", ] +[[package]] +name = "indicatif" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507cf157a0dab3c837bef6e2086466255d9de4a6b1af69e62b62c54cd52f6062" +dependencies = [ + "console", + "lazy_static", + "number_prefix", + "regex", +] + [[package]] name = "instant" version = "0.1.9" @@ -952,6 +985,12 @@ dependencies = [ "libc", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.23.0" @@ -982,6 +1021,7 @@ dependencies = [ "git2", "hex", "image", + "indicatif", "json", "libc", "md5", @@ -1470,6 +1510,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "textwrap" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index 0f662308e..6a6d5f75f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ toml = "0.5.8" yaml-rust = "0.4" md5 = "0.7" hex = "0.4" +indicatif = "0.16" [target.'cfg(windows)'.dependencies] ansi_term = "0.12" diff --git a/src/onefetch/repo.rs b/src/onefetch/repo.rs index b46886897..1950f2776 100644 --- a/src/onefetch/repo.rs +++ b/src/onefetch/repo.rs @@ -1,7 +1,10 @@ use crate::onefetch::{commit_info::CommitInfo, error::*, utils}; +use colored::*; use git2::{ - BranchType, Commit, Repository, RepositoryOpenFlags, Status, StatusOptions, StatusShow, + build::RepoBuilder, BranchType, Commit, FetchOptions, RemoteCallbacks, Repository, + RepositoryOpenFlags, Status, StatusOptions, StatusShow, }; +use indicatif::{ProgressBar, ProgressStyle}; use regex::Regex; use std::path::Path; @@ -265,7 +268,37 @@ impl<'a> Repo<'a> { } pub fn clone_remote(url: &str, path: &std::path::PathBuf) -> Result { - let repository = Repository::clone(url, path)?; + // I'm creating new scope for each option to avoid exposing mutable variables + + let progress_bar = ProgressBar::new(1); + let progress_bar_style = ProgressStyle::default_bar() + .template("{msg}\n{spinner:.green} [{elapsed}] [{wide_bar:.cyan/blue}] {pos}/{len}") + .progress_chars("#>-"); + + progress_bar.set_style(progress_bar_style); + progress_bar.set_message("- Cloning Git repository".bold().to_string()); + let remote_callbacks = { + let mut v = RemoteCallbacks::new(); + v.transfer_progress(|v| { + progress_bar.set_length(v.total_objects() as u64); + progress_bar.set_position(v.received_objects() as u64); + true + }); + v + }; + + let fetch_options = { + let mut v = FetchOptions::new(); + v.remote_callbacks(remote_callbacks); + v + }; + let mut builder = { + let mut v = RepoBuilder::new(); + v.fetch_options(fetch_options); + v + }; + let repository = builder.clone(url, path)?; + progress_bar.finish_and_clear(); Ok(repository) } From dfd047273faf246e42ec8b49e4ddd8a07cf5ae86 Mon Sep 17 00:00:00 2001 From: gbaranski Date: Tue, 4 May 2021 14:27:19 +0200 Subject: [PATCH 3/4] fix: remove '/' in path, windows doesnt understand --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 754852980..fcffe3d52 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ fn get_repo(config: &Cli) -> Result { let temp_directory = std::env::temp_dir(); let repo_digest = md5::compute(&config.repo_path); let mut repo_directory = temp_directory; - repo_directory.push("onefetch/"); + repo_directory.push("onefetch"); repo_directory.push(hex::encode(repo_digest.0)); if repo_directory.exists() { git2::Repository::discover(repo_directory)? From bd3abbf92a7898cfea81d51e8eed29298d6cedba Mon Sep 17 00:00:00 2001 From: o2sh Date: Wed, 5 May 2021 20:50:32 +0200 Subject: [PATCH 4/4] pull ssl/ssh features from git2 + code cleanup --- Cargo.lock | 37 +++++++++++++++++++++++++++++++++++++ Cargo.toml | 8 ++++---- src/main.rs | 28 ++-------------------------- src/onefetch/info.rs | 15 +++++++++++---- src/onefetch/repo.rs | 26 +++++++++++++++++++++++--- 5 files changed, 77 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73569e203..c4589d5b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -589,6 +589,8 @@ dependencies = [ "libc", "libgit2-sys", "log", + "openssl-probe", + "openssl-sys", "url", ] @@ -810,10 +812,26 @@ checksum = "f322155d574c8b9ebe991a04f6908bb49e68a79463338d24a43d6274cb6443e6" dependencies = [ "cc", "libc", + "libssh2-sys", "libz-sys", + "openssl-sys", "pkg-config", ] +[[package]] +name = "libssh2-sys" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0186af0d8f171ae6b9c4c90ec51898bad5d08a2d5e470903a50d9ad8959cbee" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + [[package]] name = "libz-sys" version = "1.1.2" @@ -1044,6 +1062,25 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52160d45fa2e7608d504b7c3a3355afed615e6d8b627a74458634ba21b69bd" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.11.1" diff --git a/Cargo.toml b/Cargo.toml index 6a6d5f75f..4e42cfe6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,9 +29,12 @@ clap = "2.33.3" color_quant = "1.1.0" colored = "2.0.0" error-chain = "0.12" -git2 = {version = "0.13.18", default-features = false} +git2 = "0.13.18" +hex = "0.4" image = "0.23.14" +indicatif = "0.16" json = "0.12.4" +md5 = "0.7" regex = "1.4.6" serde = "1.0.125" serde_json = "1.0.64" @@ -41,9 +44,6 @@ term_size = "0.3.2" tokei = "12.1.2" toml = "0.5.8" yaml-rust = "0.4" -md5 = "0.7" -hex = "0.4" -indicatif = "0.16" [target.'cfg(windows)'.dependencies] ansi_term = "0.12" diff --git a/src/main.rs b/src/main.rs index fcffe3d52..d45186fe8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,34 +2,12 @@ #![recursion_limit = "1024"] #![cfg_attr(feature = "fail-on-deprecated", deny(deprecated))] -use onefetch::{cli::Cli, cli_utils, error::*, info, printer::Printer, repo}; +use onefetch::{cli::Cli, cli_utils, error::*, info, printer::Printer}; use std::{io, process}; mod onefetch; -fn get_repo(config: &Cli) -> Result { - let repo = if config.is_remote { - let temp_directory = std::env::temp_dir(); - let repo_digest = md5::compute(&config.repo_path); - let mut repo_directory = temp_directory; - repo_directory.push("onefetch"); - repo_directory.push(hex::encode(repo_digest.0)); - if repo_directory.exists() { - git2::Repository::discover(repo_directory)? - } else { - repo::clone_remote(&config.repo_path, &repo_directory)? - } - - } else { - if !repo::is_valid(&config.repo_path)? { - return Err("please run onefetch inside of a non-bare git repository".into()); - } - git2::Repository::discover(&config.repo_path)? - }; - Ok(repo) -} - fn run() -> Result<()> { #[cfg(windows)] let _ = ansi_term::enable_ansi_support(); @@ -44,9 +22,7 @@ fn run() -> Result<()> { return cli_utils::print_supported_package_managers(); } - let repo = get_repo(&config)?; - - let info = info::Info::new(config, repo)?; + let info = info::Info::new(config)?; let mut printer = Printer::new(io::BufWriter::new(io::stdout()), info); diff --git a/src/onefetch/info.rs b/src/onefetch/info.rs index 86d509781..ef84024f1 100644 --- a/src/onefetch/info.rs +++ b/src/onefetch/info.rs @@ -1,10 +1,16 @@ use { crate::onefetch::{ - cli::Cli, cli_utils, commit_info::CommitInfo, error::*, language::Language, - license::Detector, package_managers::DependencyDetector, repo::Repo, text_color::TextColor, + cli::Cli, + cli_utils, + commit_info::CommitInfo, + error::*, + language::Language, + license::Detector, + package_managers::DependencyDetector, + repo::{get_repo, Repo}, + text_color::TextColor, }, colored::{Color, ColoredString, Colorize}, - git2::Repository, serde::ser::SerializeStruct, serde::Serialize, }; @@ -208,8 +214,9 @@ impl std::fmt::Display for Info { } impl Info { - pub fn new(config: Cli, repo: Repository) -> Result { + pub fn new(config: Cli) -> Result { let git_version = cli_utils::get_git_version(); + let repo = get_repo(config.is_remote, &config.repo_path)?; let internal_repo = Repo::new(&repo, config.no_merges)?; let (repo_name, repo_url) = internal_repo.get_name_and_url()?; let head_refs = internal_repo.get_head_refs()?; diff --git a/src/onefetch/repo.rs b/src/onefetch/repo.rs index 1950f2776..261cb12c8 100644 --- a/src/onefetch/repo.rs +++ b/src/onefetch/repo.rs @@ -267,9 +267,28 @@ impl<'a> Repo<'a> { } } -pub fn clone_remote(url: &str, path: &std::path::PathBuf) -> Result { - // I'm creating new scope for each option to avoid exposing mutable variables +pub fn get_repo(is_remote: bool, repo_path: &str) -> Result { + let repo = if is_remote { + let temp_directory = std::env::temp_dir(); + let repo_digest = md5::compute(repo_path); + let mut repo_directory = temp_directory; + repo_directory.push("onefetch"); + repo_directory.push(hex::encode(repo_digest.0)); + if repo_directory.exists() { + Repository::discover(repo_directory)? + } else { + clone_remote(repo_path, &repo_directory)? + } + } else { + if !is_valid(repo_path)? { + return Err("please run onefetch inside of a non-bare git repository".into()); + } + Repository::discover(repo_path)? + }; + Ok(repo) +} +fn clone_remote(url: &str, path: &std::path::PathBuf) -> Result { let progress_bar = ProgressBar::new(1); let progress_bar_style = ProgressStyle::default_bar() .template("{msg}\n{spinner:.green} [{elapsed}] [{wide_bar:.cyan/blue}] {pos}/{len}") @@ -284,6 +303,7 @@ pub fn clone_remote(url: &str, path: &std::path::PathBuf) -> Result progress_bar.set_position(v.received_objects() as u64); true }); + v }; @@ -302,7 +322,7 @@ pub fn clone_remote(url: &str, path: &std::path::PathBuf) -> Result Ok(repository) } -pub fn is_valid(repo_path: &str) -> Result { +fn is_valid(repo_path: &str) -> Result { let repo = Repository::open_ext(repo_path, RepositoryOpenFlags::empty(), Vec::<&Path>::new()); Ok(repo.is_ok() && !repo?.is_bare()) }