mirror of
https://codeberg.org/Cyborus/forgejo-cli.git
synced 2024-11-27 12:03:49 +01:00
feat: wiki clone
This commit is contained in:
parent
de144f29e6
commit
13b7bf5305
2 changed files with 109 additions and 61 deletions
127
src/repo.rs
127
src/repo.rs
|
@ -600,65 +600,7 @@ impl RepoCommand {
|
|||
|
||||
let path = path.unwrap_or_else(|| PathBuf::from(format!("./{repo_name}")));
|
||||
|
||||
let SpecialRender {
|
||||
fancy,
|
||||
hide_cursor,
|
||||
show_cursor,
|
||||
clear_line,
|
||||
..
|
||||
} = *crate::special_render();
|
||||
|
||||
let auth = auth_git2::GitAuthenticator::new();
|
||||
let git_config = git2::Config::open_default()?;
|
||||
|
||||
let mut options = git2::FetchOptions::new();
|
||||
let mut callbacks = git2::RemoteCallbacks::new();
|
||||
callbacks.credentials(auth.credentials(&git_config));
|
||||
|
||||
if fancy {
|
||||
print!("{hide_cursor}");
|
||||
print!(" Preparing...");
|
||||
let _ = std::io::stdout().flush();
|
||||
|
||||
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 fancy {
|
||||
print!("{clear_line}{show_cursor}\r");
|
||||
}
|
||||
println!("Cloned {} into {}", repo_full_name, path.display());
|
||||
let local_repo = clone_repo(&repo_full_name, &clone_url, &path)?;
|
||||
|
||||
if let Some(parent) = repo_data.parent.as_deref() {
|
||||
let parent_clone_url = parent
|
||||
|
@ -717,3 +659,70 @@ impl RepoCommand {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_repo(
|
||||
repo_name: &str,
|
||||
url: &url::Url,
|
||||
path: &std::path::Path,
|
||||
) -> eyre::Result<git2::Repository> {
|
||||
let SpecialRender {
|
||||
fancy,
|
||||
hide_cursor,
|
||||
show_cursor,
|
||||
clear_line,
|
||||
..
|
||||
} = *crate::special_render();
|
||||
|
||||
let auth = auth_git2::GitAuthenticator::new();
|
||||
let git_config = git2::Config::open_default()?;
|
||||
|
||||
let mut options = git2::FetchOptions::new();
|
||||
let mut callbacks = git2::RemoteCallbacks::new();
|
||||
callbacks.credentials(auth.credentials(&git_config));
|
||||
|
||||
if fancy {
|
||||
print!("{hide_cursor}");
|
||||
print!(" Preparing...");
|
||||
let _ = std::io::stdout().flush();
|
||||
|
||||
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(url.as_str(), &path)?;
|
||||
if fancy {
|
||||
print!("{clear_line}{show_cursor}\r");
|
||||
}
|
||||
println!("Cloned {} into {}", repo_name, path.display());
|
||||
Ok(local_repo)
|
||||
}
|
||||
|
|
43
src/wiki.rs
43
src/wiki.rs
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use base64ct::Encoding;
|
||||
use clap::{Args, Subcommand};
|
||||
use eyre::{Context, OptionExt};
|
||||
|
@ -27,6 +29,11 @@ pub enum WikiSubcommand {
|
|||
repo: Option<RepoArg>,
|
||||
page: String,
|
||||
},
|
||||
Clone {
|
||||
repo: Option<RepoArg>,
|
||||
#[clap(long, short)]
|
||||
path: Option<PathBuf>,
|
||||
},
|
||||
Browse {
|
||||
#[clap(long, short)]
|
||||
repo: Option<RepoArg>,
|
||||
|
@ -45,6 +52,7 @@ impl WikiCommand {
|
|||
match self.command {
|
||||
Contents { repo: _ } => wiki_contents(&repo, &api).await?,
|
||||
View { repo: _, page } => view_wiki_page(&repo, &api, &*page).await?,
|
||||
Clone { repo: _, path } => clone_wiki(&repo, &api, path).await?,
|
||||
Browse { repo: _, page } => browse_wiki_page(&repo, &api, &*page).await?,
|
||||
}
|
||||
Ok(())
|
||||
|
@ -53,14 +61,16 @@ impl WikiCommand {
|
|||
fn repo(&self) -> Option<&RepoArg> {
|
||||
use WikiSubcommand::*;
|
||||
match &self.command {
|
||||
Contents { repo } | View { repo, .. } | Browse { repo, .. } => repo.as_ref(),
|
||||
Contents { repo } | View { repo, .. } | Clone { repo, .. } | Browse { repo, .. } => {
|
||||
repo.as_ref()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn no_repo_error(&self) -> eyre::Error {
|
||||
use WikiSubcommand::*;
|
||||
match &self.command {
|
||||
Contents { repo: _ } | View { .. } | Browse { .. } => {
|
||||
Contents { repo: _ } | View { .. } | Clone { .. } | Browse { .. } => {
|
||||
eyre::eyre!("couldn't guess repo")
|
||||
}
|
||||
}
|
||||
|
@ -124,3 +134,32 @@ async fn browse_wiki_page(repo: &RepoName, api: &Forgejo, page: &str) -> eyre::R
|
|||
open::that(html_url.as_str())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn clone_wiki(repo: &RepoName, api: &Forgejo, path: Option<PathBuf>) -> eyre::Result<()> {
|
||||
let repo_data = api.repo_get(repo.owner(), repo.name()).await?;
|
||||
let clone_url = repo_data
|
||||
.clone_url
|
||||
.as_ref()
|
||||
.ok_or_eyre("repo does not have clone url")?;
|
||||
let git_stripped = clone_url
|
||||
.as_str()
|
||||
.strip_suffix(".git")
|
||||
.unwrap_or(clone_url.as_str());
|
||||
let clone_url = url::Url::parse(&format!("{}.wiki.git", git_stripped))?;
|
||||
|
||||
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 name = format!("{}'s wiki", repo_full_name);
|
||||
|
||||
let path = path.unwrap_or_else(|| PathBuf::from(format!("./{repo_name}-wiki")));
|
||||
|
||||
crate::repo::clone_repo(&name, &clone_url, &path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue