Modernize upload command

This commit is contained in:
Lucien Greathouse
2021-06-08 21:53:56 -04:00
parent 561a3e3256
commit d0482a004e
2 changed files with 75 additions and 106 deletions

View File

@@ -1,46 +1,87 @@
use std::path::PathBuf;
use std::str::FromStr;
use anyhow::{bail, format_err, Context};
use memofs::Vfs;
use reqwest::{
header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT},
StatusCode,
};
use thiserror::Error;
use structopt::StructOpt;
use crate::{auth_cookie::get_auth_cookie, cli::UploadCommand, serve_session::ServeSession};
use crate::{auth_cookie::get_auth_cookie, serve_session::ServeSession};
#[derive(Debug, Error)]
enum Error {
#[error("Rojo could not find your Roblox auth cookie. Please pass one via --cookie.")]
NeedAuthCookie,
use super::resolve_path;
#[error("The Roblox API returned an unexpected error: {body}")]
RobloxApi { body: String },
/// Builds the project and uploads it to Roblox.
#[derive(Debug, StructOpt)]
pub struct UploadCommand {
/// Path to the project to upload. Defaults to the current directory.
#[structopt(default_value = "")]
pub project: PathBuf,
/// Authenication cookie to use. If not specified, Rojo will attempt to find one from the system automatically.
#[structopt(long)]
pub cookie: Option<String>,
/// Asset ID to upload to.
#[structopt(long = "asset_id")]
pub asset_id: u64,
}
pub fn upload(options: UploadCommand) -> Result<(), anyhow::Error> {
let cookie = options
.cookie
.clone()
.or_else(get_auth_cookie)
.ok_or(Error::NeedAuthCookie)?;
impl UploadCommand {
pub fn run(self) -> Result<(), anyhow::Error> {
let project_path = resolve_path(&self.project);
let vfs = Vfs::new_default();
let cookie = self.cookie.or_else(get_auth_cookie).context(
"Rojo could not find your Roblox auth cookie. Please pass one via --cookie.",
)?;
let session = ServeSession::new(vfs, &options.absolute_project())?;
let vfs = Vfs::new_default();
let tree = session.tree();
let inner_tree = tree.inner();
let root = inner_tree.root();
let session = ServeSession::new(vfs, project_path)?;
let encode_ids = match root.class.as_str() {
"DataModel" => root.children().to_vec(),
_ => vec![root.referent()],
};
let tree = session.tree();
let inner_tree = tree.inner();
let root = inner_tree.root();
let mut buffer = Vec::new();
let encode_ids = match root.class.as_str() {
"DataModel" => root.children().to_vec(),
_ => vec![root.referent()],
};
log::trace!("Encoding binary model");
rbx_binary::to_writer_default(&mut buffer, tree.inner(), &encode_ids)?;
do_upload(buffer, options.asset_id, &cookie)
let mut buffer = Vec::new();
log::trace!("Encoding binary model");
rbx_binary::to_writer_default(&mut buffer, tree.inner(), &encode_ids)?;
do_upload(buffer, self.asset_id, &cookie)
}
}
/// The kind of asset to upload to the website. Affects what endpoints Rojo uses
/// and changes how the asset is built.
#[derive(Debug, Clone, Copy)]
enum UploadKind {
/// Upload to a place.
Place,
/// Upload to a model-like asset, like a Model, Plugin, or Package.
Model,
}
impl FromStr for UploadKind {
type Err = anyhow::Error;
fn from_str(source: &str) -> Result<Self, Self::Err> {
match source {
"place" => Ok(UploadKind::Place),
"model" => Ok(UploadKind::Model),
attempted => Err(format_err!(
"Invalid upload kind '{}'. Valid kinds are: place, model",
attempted
)),
}
}
}
fn do_upload(buffer: Vec<u8>, asset_id: u64, cookie: &str) -> anyhow::Result<()> {
@@ -76,10 +117,10 @@ fn do_upload(buffer: Vec<u8>, asset_id: u64, cookie: &str) -> anyhow::Result<()>
let status = response.status();
if !status.is_success() {
return Err(Error::RobloxApi {
body: response.text()?,
}
.into());
bail!(
"The Roblox API returned an unexpected error: {}",
response.text()?
);
}
Ok(())