mirror of
https://git.proxmox.com/git/rustc
synced 2025-08-12 12:20:19 +00:00
127 lines
3.3 KiB
Rust
127 lines
3.3 KiB
Rust
/*
|
|
* libgit2 "clone" example
|
|
*
|
|
* Written by the libgit2 contributors
|
|
*
|
|
* To the extent possible under law, the author(s) have dedicated all copyright
|
|
* and related and neighboring rights to this software to the public domain
|
|
* worldwide. This software is distributed without any warranty.
|
|
*
|
|
* You should have received a copy of the CC0 Public Domain Dedication along
|
|
* with this software. If not, see
|
|
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
*/
|
|
|
|
#![deny(warnings)]
|
|
|
|
use clap::Parser;
|
|
use git2::build::{CheckoutBuilder, RepoBuilder};
|
|
use git2::{FetchOptions, Progress, RemoteCallbacks};
|
|
use std::cell::RefCell;
|
|
use std::io::{self, Write};
|
|
use std::path::{Path, PathBuf};
|
|
|
|
#[derive(Parser)]
|
|
struct Args {
|
|
#[structopt(name = "url")]
|
|
arg_url: String,
|
|
#[structopt(name = "path")]
|
|
arg_path: String,
|
|
}
|
|
|
|
struct State {
|
|
progress: Option<Progress<'static>>,
|
|
total: usize,
|
|
current: usize,
|
|
path: Option<PathBuf>,
|
|
newline: bool,
|
|
}
|
|
|
|
fn print(state: &mut State) {
|
|
let stats = state.progress.as_ref().unwrap();
|
|
let network_pct = (100 * stats.received_objects()) / stats.total_objects();
|
|
let index_pct = (100 * stats.indexed_objects()) / stats.total_objects();
|
|
let co_pct = if state.total > 0 {
|
|
(100 * state.current) / state.total
|
|
} else {
|
|
0
|
|
};
|
|
let kbytes = stats.received_bytes() / 1024;
|
|
if stats.received_objects() == stats.total_objects() {
|
|
if !state.newline {
|
|
println!();
|
|
state.newline = true;
|
|
}
|
|
print!(
|
|
"Resolving deltas {}/{}\r",
|
|
stats.indexed_deltas(),
|
|
stats.total_deltas()
|
|
);
|
|
} else {
|
|
print!(
|
|
"net {:3}% ({:4} kb, {:5}/{:5}) / idx {:3}% ({:5}/{:5}) \
|
|
/ chk {:3}% ({:4}/{:4}) {}\r",
|
|
network_pct,
|
|
kbytes,
|
|
stats.received_objects(),
|
|
stats.total_objects(),
|
|
index_pct,
|
|
stats.indexed_objects(),
|
|
stats.total_objects(),
|
|
co_pct,
|
|
state.current,
|
|
state.total,
|
|
state
|
|
.path
|
|
.as_ref()
|
|
.map(|s| s.to_string_lossy().into_owned())
|
|
.unwrap_or_default()
|
|
)
|
|
}
|
|
io::stdout().flush().unwrap();
|
|
}
|
|
|
|
fn run(args: &Args) -> Result<(), git2::Error> {
|
|
let state = RefCell::new(State {
|
|
progress: None,
|
|
total: 0,
|
|
current: 0,
|
|
path: None,
|
|
newline: false,
|
|
});
|
|
let mut cb = RemoteCallbacks::new();
|
|
cb.transfer_progress(|stats| {
|
|
let mut state = state.borrow_mut();
|
|
state.progress = Some(stats.to_owned());
|
|
print(&mut *state);
|
|
true
|
|
});
|
|
|
|
let mut co = CheckoutBuilder::new();
|
|
co.progress(|path, cur, total| {
|
|
let mut state = state.borrow_mut();
|
|
state.path = path.map(|p| p.to_path_buf());
|
|
state.current = cur;
|
|
state.total = total;
|
|
print(&mut *state);
|
|
});
|
|
|
|
let mut fo = FetchOptions::new();
|
|
fo.remote_callbacks(cb);
|
|
RepoBuilder::new()
|
|
.fetch_options(fo)
|
|
.with_checkout(co)
|
|
.clone(&args.arg_url, Path::new(&args.arg_path))?;
|
|
println!();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn main() {
|
|
let args = Args::parse();
|
|
match run(&args) {
|
|
Ok(()) => {}
|
|
Err(e) => println!("error: {}", e),
|
|
}
|
|
}
|