mirror of
https://codeberg.org/Cyborus/forgejo-cli.git
synced 2024-11-10 12:09:33 +01:00
add repo clone
This commit is contained in:
parent
b168dcef7e
commit
b262d31b01
2 changed files with 104 additions and 0 deletions
12
src/main.rs
12
src/main.rs
|
@ -190,6 +190,10 @@ struct SpecialRender {
|
||||||
light_grey: &'static str,
|
light_grey: &'static str,
|
||||||
white: &'static str,
|
white: &'static str,
|
||||||
reset: &'static str,
|
reset: &'static str,
|
||||||
|
|
||||||
|
hide_cursor: &'static str,
|
||||||
|
show_cursor: &'static str,
|
||||||
|
clear_line: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecialRender {
|
impl SpecialRender {
|
||||||
|
@ -227,6 +231,10 @@ impl SpecialRender {
|
||||||
light_grey: "\x1b[37m",
|
light_grey: "\x1b[37m",
|
||||||
white: "\x1b[97m",
|
white: "\x1b[97m",
|
||||||
reset: "\x1b[0m",
|
reset: "\x1b[0m",
|
||||||
|
|
||||||
|
hide_cursor: "\x1b[?25l",
|
||||||
|
show_cursor: "\x1b[?25h",
|
||||||
|
clear_line: "\x1b[2K",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +263,10 @@ impl SpecialRender {
|
||||||
light_grey: "",
|
light_grey: "",
|
||||||
white: "",
|
white: "",
|
||||||
reset: "",
|
reset: "",
|
||||||
|
|
||||||
|
hide_cursor: "",
|
||||||
|
show_cursor: "",
|
||||||
|
clear_line: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
92
src/repo.rs
92
src/repo.rs
|
@ -1,3 +1,5 @@
|
||||||
|
use std::{io::Write, path::PathBuf};
|
||||||
|
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
use eyre::{eyre, OptionExt};
|
use eyre::{eyre, OptionExt};
|
||||||
use forgejo_api::structs::CreateRepoOption;
|
use forgejo_api::structs::CreateRepoOption;
|
||||||
|
@ -248,6 +250,10 @@ pub enum RepoCommand {
|
||||||
#[clap(long, short = 'R')]
|
#[clap(long, short = 'R')]
|
||||||
remote: Option<String>,
|
remote: Option<String>,
|
||||||
},
|
},
|
||||||
|
Clone {
|
||||||
|
repo: String,
|
||||||
|
path: Option<PathBuf>,
|
||||||
|
},
|
||||||
Star {
|
Star {
|
||||||
repo: String,
|
repo: String,
|
||||||
},
|
},
|
||||||
|
@ -446,6 +452,92 @@ impl RepoCommand {
|
||||||
println!("View online at {html_url}");
|
println!("View online at {html_url}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RepoCommand::Clone { repo, path } => {
|
||||||
|
let repo = RepoInfo::get_current(host_name, Some(&repo), None)?;
|
||||||
|
let api = keys.get_api(&repo.host_url())?;
|
||||||
|
let name = repo.name().unwrap();
|
||||||
|
|
||||||
|
let repo_data = api.repo_get(name.owner(), name.name()).await?;
|
||||||
|
let clone_url = repo_data
|
||||||
|
.clone_url
|
||||||
|
.as_ref()
|
||||||
|
.ok_or_eyre("repo does not have clone url")?;
|
||||||
|
|
||||||
|
let repo_name = repo_data
|
||||||
|
.name
|
||||||
|
.as_deref()
|
||||||
|
.ok_or_eyre("repo does not have name")?;
|
||||||
|
let repo_full_name = repo_data
|
||||||
|
.full_name
|
||||||
|
.as_deref()
|
||||||
|
.ok_or_eyre("repo does not have full name")?;
|
||||||
|
|
||||||
|
let path = path.unwrap_or_else(|| PathBuf::from(format!("./{repo_name}")));
|
||||||
|
|
||||||
|
let SpecialRender {
|
||||||
|
colors, // actually using it to indicate fanciness FIXME
|
||||||
|
hide_cursor,
|
||||||
|
show_cursor,
|
||||||
|
clear_line,
|
||||||
|
..
|
||||||
|
} = *crate::special_render();
|
||||||
|
|
||||||
|
let mut options = git2::FetchOptions::new();
|
||||||
|
|
||||||
|
if colors {
|
||||||
|
print!("{hide_cursor}");
|
||||||
|
print!(" Preparing...");
|
||||||
|
let _ = std::io::stdout().flush();
|
||||||
|
|
||||||
|
let mut callbacks = git2::RemoteCallbacks::new();
|
||||||
|
callbacks.transfer_progress(|progress| {
|
||||||
|
print!("{clear_line}\r");
|
||||||
|
if progress.received_objects() == progress.total_objects() {
|
||||||
|
if progress.indexed_deltas() == progress.total_deltas() {
|
||||||
|
print!("Finishing up...");
|
||||||
|
} else {
|
||||||
|
let percent = 100.0 * (progress.indexed_deltas() as f64)
|
||||||
|
/ (progress.total_deltas() as f64);
|
||||||
|
print!(" Resolving... {percent:.01}%");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let bytes = progress.received_bytes();
|
||||||
|
let percent = 100.0 * (progress.received_objects() as f64)
|
||||||
|
/ (progress.total_objects() as f64);
|
||||||
|
print!(" Downloading... {percent:.01}%");
|
||||||
|
match bytes {
|
||||||
|
0..=1023 => print!(" ({}b)", bytes),
|
||||||
|
1024..=1048575 => print!(" ({:.01}kb)", (bytes as f64) / 1024.0),
|
||||||
|
1048576..=1073741823 => {
|
||||||
|
print!(" ({:.01}mb)", (bytes as f64) / 1048576.0)
|
||||||
|
}
|
||||||
|
1073741824.. => {
|
||||||
|
print!(" ({:.01}gb)", (bytes as f64) / 1073741824.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = std::io::stdout().flush();
|
||||||
|
true
|
||||||
|
});
|
||||||
|
options.remote_callbacks(callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
let local_repo = git2::build::RepoBuilder::new()
|
||||||
|
.fetch_options(options)
|
||||||
|
.clone(clone_url.as_str(), &path)?;
|
||||||
|
if colors {
|
||||||
|
print!("{clear_line}{show_cursor}\r");
|
||||||
|
}
|
||||||
|
println!("Cloned {} into {}", repo_full_name, path.display());
|
||||||
|
|
||||||
|
if let Some(parent) = repo_data.parent.as_deref() {
|
||||||
|
let parent_clone_url = parent
|
||||||
|
.clone_url
|
||||||
|
.as_ref()
|
||||||
|
.ok_or_eyre("parent repo does not have clone url")?;
|
||||||
|
local_repo.remote("upstream", parent_clone_url.as_str())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
RepoCommand::Star { repo } => {
|
RepoCommand::Star { repo } => {
|
||||||
let repo = RepoInfo::get_current(host_name, Some(&repo), None)?;
|
let repo = RepoInfo::get_current(host_name, Some(&repo), None)?;
|
||||||
let api = keys.get_api(&repo.host_url())?;
|
let api = keys.get_api(&repo.host_url())?;
|
||||||
|
|
Loading…
Reference in a new issue