rtpm 0.0.1

The official tool to simplify the management of plugins for Rtop.
Documentation
// Code based on the git2-rs example available on the URL: https://github.com/rust-lang/git2-rs/blob/master/examples/clone.rs.

use crate::util::utils::convert_to_readable_unity;
use colored::Colorize;
use git2::build::{CheckoutBuilder, RepoBuilder};
use git2::{FetchOptions, Progress, RemoteCallbacks};
use std::cell::{RefCell, RefMut};
use std::io::{self, Write};
use std::path::Path;

struct State {
    progress: Option<Progress<'static>>,
    total: usize,
    current: usize,
    newline: bool,
}

fn print(state: &mut State) {
    let stats: &Progress = state.progress.as_ref().unwrap();
    let network_pct: usize = (100 * stats.received_objects()) / stats.total_objects();
    if stats.received_objects() == stats.total_objects() {
        if !state.newline {
            print!("{}\r", " ".repeat(50));
            println!(":: {}", "Download terminated!".green());
            state.newline = true;
        }

        if state.total != 0 && state.current == state.total {
            println!(":: {}", "Checkout terminated!".green());
        } else {
            print!(
                ":: {}",
                format!("Checkout {}/{}...\r", state.current, state.total).green(),
            );
        }
    } else {
        print!(
            ":: {}",
            format!(
                "Download {}% - speed: {} - objects: {}/{}...\r",
                network_pct,
                convert_to_readable_unity(stats.received_bytes() as f64),
                stats.received_objects(),
                stats.total_objects()
            )
            .green(),
        );
    }
    io::stdout().flush().unwrap();
}

pub fn clone(url: &str, path: &Path) {
    let state: RefCell<State> = RefCell::new(State {
        progress: None,
        total: 0,
        current: 0,
        newline: false,
    });
    let mut cb: RemoteCallbacks = RemoteCallbacks::new();
    cb.transfer_progress(|stats| {
        let mut state_borrowed = state.borrow_mut();
        state_borrowed.progress = Some(stats.to_owned());
        print(&mut state_borrowed);
        true
    });

    let mut co: CheckoutBuilder = CheckoutBuilder::new();
    co.progress(|_, cur, total| {
        let mut state_borrowed: RefMut<State> = state.borrow_mut();
        state_borrowed.current = cur;
        state_borrowed.total = total;
        print(&mut state_borrowed);
    });

    let mut fo = FetchOptions::new();
    fo.remote_callbacks(cb);
    RepoBuilder::new()
        .fetch_options(fo)
        .with_checkout(co)
        .clone(url, path)
        .unwrap();
}