Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I11a2103f3530f07409177404577b90136a6a6964
151 lines
4 KiB
Rust
151 lines
4 KiB
Rust
use std::{
|
|
fs,
|
|
path::{Path, PathBuf},
|
|
};
|
|
|
|
use crate::{
|
|
cli::RemoteArgs,
|
|
error::{PakkerError, Result},
|
|
fetch::Fetcher,
|
|
git,
|
|
model::{config::Config, lockfile::LockFile},
|
|
};
|
|
|
|
const REMOTE_DIR: &str = ".pakku-remote";
|
|
|
|
pub async fn execute(args: RemoteArgs) -> Result<()> {
|
|
let remote_path = PathBuf::from(REMOTE_DIR);
|
|
|
|
// Handle --remove flag
|
|
if args.remove {
|
|
if remote_path.exists() {
|
|
fs::remove_dir_all(&remote_path)?;
|
|
log::info!("Removed remote from modpack");
|
|
} else {
|
|
log::warn!("No remote configured");
|
|
}
|
|
return Ok(());
|
|
}
|
|
|
|
// If no URL provided, show status
|
|
if args.url.is_none() {
|
|
show_remote_status(&remote_path);
|
|
return Ok(());
|
|
}
|
|
|
|
let url = args
|
|
.url
|
|
.ok_or_else(|| PakkerError::InvalidInput("URL is required".to_string()))?;
|
|
log::info!("Installing modpack from: {url}");
|
|
|
|
// Clone or update repository
|
|
if remote_path.exists() {
|
|
log::info!("Remote directory exists, updating...");
|
|
let remote_name = "origin";
|
|
let ref_name = args.branch.as_deref().unwrap_or("HEAD");
|
|
|
|
git::fetch_updates(&remote_path, remote_name, ref_name, None)?;
|
|
git::reset_to_ref(&remote_path, remote_name, ref_name)?;
|
|
} else {
|
|
log::info!("Cloning repository...");
|
|
let ref_name = args.branch.as_deref().unwrap_or("HEAD");
|
|
git::clone_repository(&url, &remote_path, ref_name, None)?;
|
|
}
|
|
|
|
// Load lockfile and config from remote
|
|
let remote_lockfile_path = remote_path.join("pakku-lock.json");
|
|
if !remote_lockfile_path.exists() {
|
|
return Err(PakkerError::ConfigError(
|
|
"Remote repository does not contain pakku-lock.json".to_string(),
|
|
));
|
|
}
|
|
|
|
let remote_lockfile = LockFile::load(&remote_path)?;
|
|
let remote_config = Config::load(&remote_path).ok();
|
|
|
|
// Copy lockfile to current directory
|
|
let current_lockfile_path = PathBuf::from("pakku-lock.json");
|
|
fs::copy(&remote_lockfile_path, ¤t_lockfile_path)?;
|
|
log::info!("Copied lockfile from remote");
|
|
|
|
// Copy config if exists
|
|
if remote_config.is_some() {
|
|
let remote_config_path = remote_path.join("pakku.json");
|
|
let current_config_path = PathBuf::from("pakku.json");
|
|
if remote_config_path.exists() {
|
|
fs::copy(&remote_config_path, ¤t_config_path)?;
|
|
log::info!("Copied config from remote");
|
|
}
|
|
}
|
|
|
|
// Fetch project files
|
|
log::info!("Fetching project files...");
|
|
let fetcher = Fetcher::new(&remote_path);
|
|
fetcher
|
|
.fetch_all(&remote_lockfile, &remote_config.unwrap_or_default())
|
|
.await?;
|
|
|
|
// Sync overrides
|
|
sync_overrides(&remote_path, args.server_pack)?;
|
|
|
|
log::info!("Successfully installed modpack from remote");
|
|
Ok(())
|
|
}
|
|
|
|
fn show_remote_status(remote_path: &Path) {
|
|
if !remote_path.exists() {
|
|
println!("No remote configured");
|
|
return;
|
|
}
|
|
|
|
println!("Remote status:");
|
|
println!(" Directory: {}", remote_path.display());
|
|
|
|
if git::is_git_repository(remote_path) {
|
|
if let Ok(url) = git::get_remote_url(remote_path, "origin") {
|
|
println!(" URL: {url}");
|
|
}
|
|
if let Ok(sha) = git::get_current_commit_sha(remote_path, None) {
|
|
println!(" Commit: {}", &sha[..8]);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn sync_overrides(remote_path: &Path, server_pack: bool) -> Result<()> {
|
|
let override_dirs = if server_pack {
|
|
vec!["overrides", "server_overrides"]
|
|
} else {
|
|
vec!["overrides", "client_overrides"]
|
|
};
|
|
|
|
for dir_name in override_dirs {
|
|
let src_dir = remote_path.join(dir_name);
|
|
if src_dir.exists() && src_dir.is_dir() {
|
|
log::info!("Syncing {dir_name} directory...");
|
|
copy_dir_recursive(&src_dir, Path::new("."))?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<()> {
|
|
if !dst.exists() {
|
|
fs::create_dir_all(dst)?;
|
|
}
|
|
|
|
for entry in fs::read_dir(src)? {
|
|
let entry = entry?;
|
|
let src_path = entry.path();
|
|
let file_name = entry.file_name();
|
|
let dst_path = dst.join(file_name);
|
|
|
|
if src_path.is_dir() {
|
|
copy_dir_recursive(&src_path, &dst_path)?;
|
|
} else {
|
|
fs::copy(&src_path, &dst_path)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|