use anyhow::{bail, Result};
use clap::*;
use reqwest::blocking::Client;
use std::{env, fs::File, path::PathBuf, process::Command};
use utils::env::MOVE_HOME;
use utils::movey_credential;
#[derive(serde::Serialize, Default)]
pub struct MoveyUploadRequest {
github_repo_url: String,
total_files: usize,
token: String,
subdir: String,
}
#[derive(Parser)]
#[clap(name = "upload")]
pub struct MoveyUpload;
impl MoveyUpload {
pub fn execute(path: Option<PathBuf>) -> Result<()> {
if let Some(path) = path {
if path.exists() && path.is_dir() {
let _ = env::set_current_dir(&path);
} else {
bail!("invalid directory")
}
}
let move_toml = File::open("Move.toml");
if move_toml.is_err() {
bail!("Move.toml not found")
}
let metadata = move_toml.unwrap().metadata()?;
if metadata.len() == 0 {
bail!("Move.toml not found")
}
let mut movey_upload_request: MoveyUploadRequest = Default::default();
let mut output = Command::new("git")
.current_dir(".")
.args(["remote", "-v"])
.output()
.unwrap();
if !output.status.success() || output.stdout.is_empty() {
bail!("invalid git repository")
}
let lines = String::from_utf8_lossy(output.stdout.as_slice());
let lines = lines.split('\n');
for line in lines {
if line.contains("github.com") {
let tokens: Vec<&str> = line.split(&['\t', ' '][..]).collect();
if tokens.len() != 3 {
bail!("invalid remote url")
}
let https_url = if tokens[1].starts_with("git@github.com") {
let author_slash_repo = tokens[1].split(':').last().unwrap();
format!("https://github.com/{author_slash_repo}")
} else {
String::from(tokens[1])
};
movey_upload_request.github_repo_url = if https_url.ends_with(".git") {
https_url[..https_url.len() - 4].to_string()
} else {
https_url
};
}
}
output = Command::new("git")
.current_dir(".")
.args(["rev-parse", "--show-prefix"])
.output()
.unwrap();
let subdir = String::from_utf8_lossy(output.stdout.as_slice());
movey_upload_request.subdir = String::from(subdir);
output = Command::new("git")
.current_dir(".")
.args(["ls-files"])
.output()
.unwrap();
let tracked_files = String::from_utf8_lossy(output.stdout.as_slice());
let tracked_files: Vec<&str> = tracked_files.split('\n').collect();
let mut total_files = tracked_files.len();
for file_path in tracked_files {
if file_path.is_empty() {
total_files -= 1;
continue;
}
}
movey_upload_request.total_files = total_files;
movey_upload_request.token = movey_credential::get_registry_api_token(&MOVE_HOME)?;
let movey_url = movey_credential::get_movey_url(&MOVE_HOME);
match movey_url {
Ok(url) => {
let client = Client::new();
let response = client
.post(&format!("{}/api/v1/packages/upload", &url))
.json(&movey_upload_request)
.send();
match response {
Ok(response) => {
if response.status().is_success() {
println!(
"Your package has been successfully uploaded to Movey at {}/packages/{}.",
url,
response.text()?
);
} else if response.status().is_client_error() {
bail!("{}", response.text()?)
} else if response.status().is_server_error() {
bail!("An unexpected error occurred. Please try again later");
}
}
Err(_) => {
bail!("An unexpected error occurred. Please try again later");
}
}
}
Err(_) => bail!("An unexpected error occurred. Please try again later"),
}
Ok(())
}
}