mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-06-22 04:11:32 +10:00
80 lines
2.4 KiB
Rust
80 lines
2.4 KiB
Rust
use std::path::Path;
|
|
|
|
use crate::{
|
|
cli::UploadInfo,
|
|
commands::connect::{config::Config, config_option::ConfigOption},
|
|
manifest::{ClosureFactory, CompressionOption, DepotManifest, generate_v2_manifest},
|
|
operator_builder::OperatorBuilder,
|
|
};
|
|
use futures::AsyncWriteExt;
|
|
use log::info;
|
|
use opendal::{FuturesAsyncWriter, Operator};
|
|
use tokio_util::compat::{Compat, FuturesAsyncWriteCompatExt};
|
|
|
|
pub async fn upload(
|
|
upload_info: &UploadInfo,
|
|
config: Config,
|
|
name: &Option<String>,
|
|
) -> anyhow::Result<()> {
|
|
let game_id = upload_info.game_id.clone();
|
|
let path = upload_info.path.clone();
|
|
let version_id = upload_info.version_id.clone();
|
|
|
|
let operator = get_operator(config, name)?;
|
|
|
|
let mut existing_depot_manifest = get_depot_manifest(&operator).await?;
|
|
|
|
info!("Uploading chunks");
|
|
|
|
let v2_manifest = generate_v2_manifest(
|
|
Path::new(&path),
|
|
ClosureFactory::new(
|
|
async move |id: String| {
|
|
info!("Uploading chunk id {id}");
|
|
let writer = operator
|
|
.writer(&format!("{game_id}/{version_id}/{id}"))
|
|
.await
|
|
.unwrap()
|
|
.into_futures_async_write()
|
|
.compat_write();
|
|
writer
|
|
},
|
|
|writer: Compat<FuturesAsyncWriter>| async {
|
|
writer.into_inner().close().await.unwrap();
|
|
},
|
|
),
|
|
)
|
|
.await?;
|
|
|
|
info!("Finished uploading chunks");
|
|
|
|
existing_depot_manifest.append(
|
|
upload_info.game_id.to_string(),
|
|
upload_info.version_id.to_string(),
|
|
CompressionOption::None,
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
async fn get_depot_manifest(operator: &Operator) -> Result<DepotManifest, anyhow::Error> {
|
|
let existing_depot_manifest = operator.read("manifest.json").await?.to_bytes();
|
|
let existing_depot_manifest: DepotManifest =
|
|
serde_json::from_slice(existing_depot_manifest.as_ref())?;
|
|
Ok(existing_depot_manifest)
|
|
}
|
|
|
|
fn get_operator(config: Config, name: &Option<String>) -> anyhow::Result<Operator> {
|
|
let operator = match if let Some(name) = name {
|
|
config
|
|
.get(name)
|
|
.ok_or(anyhow::anyhow!("Name does not exist"))?
|
|
} else {
|
|
config.get_active().ok_or(anyhow::anyhow!(
|
|
"No active connection set. Please specify with --name"
|
|
))?
|
|
} {
|
|
ConfigOption::S3(s3_config) => s3_config.build()?,
|
|
};
|
|
Ok(operator)
|
|
}
|