mirror of
https://git.proxmox.com/git/rustc
synced 2025-08-12 16:57:45 +00:00
133 lines
4.2 KiB
Rust
133 lines
4.2 KiB
Rust
/*
|
|
* libgit2 "fetch" example - shows how to fetch remote data
|
|
*
|
|
* 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::{AutotagOption, FetchOptions, RemoteCallbacks, RemoteUpdateFlags, Repository};
|
|
use std::io::{self, Write};
|
|
use std::str;
|
|
|
|
#[derive(Parser)]
|
|
struct Args {
|
|
#[structopt(name = "remote")]
|
|
arg_remote: Option<String>,
|
|
}
|
|
|
|
fn run(args: &Args) -> Result<(), git2::Error> {
|
|
let repo = Repository::open(".")?;
|
|
let remote = args.arg_remote.as_ref().map(|s| &s[..]).unwrap_or("origin");
|
|
|
|
// Figure out whether it's a named remote or a URL
|
|
println!("Fetching {} for repo", remote);
|
|
let mut cb = RemoteCallbacks::new();
|
|
let mut remote = repo
|
|
.find_remote(remote)
|
|
.or_else(|_| repo.remote_anonymous(remote))?;
|
|
cb.sideband_progress(|data| {
|
|
print!("remote: {}", str::from_utf8(data).unwrap());
|
|
io::stdout().flush().unwrap();
|
|
true
|
|
});
|
|
|
|
// This callback gets called for each remote-tracking branch that gets
|
|
// updated. The message we output depends on whether it's a new one or an
|
|
// update.
|
|
cb.update_tips(|refname, a, b| {
|
|
if a.is_zero() {
|
|
println!("[new] {:20} {}", b, refname);
|
|
} else {
|
|
println!("[updated] {:10}..{:10} {}", a, b, refname);
|
|
}
|
|
true
|
|
});
|
|
|
|
// Here we show processed and total objects in the pack and the amount of
|
|
// received data. Most frontends will probably want to show a percentage and
|
|
// the download rate.
|
|
cb.transfer_progress(|stats| {
|
|
if stats.received_objects() == stats.total_objects() {
|
|
print!(
|
|
"Resolving deltas {}/{}\r",
|
|
stats.indexed_deltas(),
|
|
stats.total_deltas()
|
|
);
|
|
} else if stats.total_objects() > 0 {
|
|
print!(
|
|
"Received {}/{} objects ({}) in {} bytes\r",
|
|
stats.received_objects(),
|
|
stats.total_objects(),
|
|
stats.indexed_objects(),
|
|
stats.received_bytes()
|
|
);
|
|
}
|
|
io::stdout().flush().unwrap();
|
|
true
|
|
});
|
|
|
|
// Download the packfile and index it. This function updates the amount of
|
|
// received data and the indexer stats which lets you inform the user about
|
|
// progress.
|
|
let mut fo = FetchOptions::new();
|
|
fo.remote_callbacks(cb);
|
|
remote.download(&[] as &[&str], Some(&mut fo))?;
|
|
|
|
{
|
|
// If there are local objects (we got a thin pack), then tell the user
|
|
// how many objects we saved from having to cross the network.
|
|
let stats = remote.stats();
|
|
if stats.local_objects() > 0 {
|
|
println!(
|
|
"\rReceived {}/{} objects in {} bytes (used {} local \
|
|
objects)",
|
|
stats.indexed_objects(),
|
|
stats.total_objects(),
|
|
stats.received_bytes(),
|
|
stats.local_objects()
|
|
);
|
|
} else {
|
|
println!(
|
|
"\rReceived {}/{} objects in {} bytes",
|
|
stats.indexed_objects(),
|
|
stats.total_objects(),
|
|
stats.received_bytes()
|
|
);
|
|
}
|
|
}
|
|
|
|
// Disconnect the underlying connection to prevent from idling.
|
|
remote.disconnect()?;
|
|
|
|
// Update the references in the remote's namespace to point to the right
|
|
// commits. This may be needed even if there was no packfile to download,
|
|
// which can happen e.g. when the branches have been changed but all the
|
|
// needed objects are available locally.
|
|
remote.update_tips(
|
|
None,
|
|
RemoteUpdateFlags::UPDATE_FETCHHEAD,
|
|
AutotagOption::Unspecified,
|
|
None,
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn main() {
|
|
let args = Args::parse();
|
|
match run(&args) {
|
|
Ok(()) => {}
|
|
Err(e) => println!("error: {}", e),
|
|
}
|
|
}
|