use std::{
io::{Read, Seek},
path::Path,
};
use tempfile::NamedTempFile;
use zip::ZipArchive;
const CFX_ARTIFACTS_FILE_API_URL: &str =
"https://runtime.fivem.net/artifacts/fivem/{platform}/master/{version}-{commit}/{archive}";
#[derive(Clone, Copy)]
pub enum ArtifactsPlatform {
Windows,
Linux,
}
impl Default for ArtifactsPlatform {
fn default() -> Self {
#[cfg(windows)]
return Self::Windows;
#[cfg(unix)]
return Self::Linux;
}
}
impl ArtifactsPlatform {
pub fn changelogs_name(&self) -> &str {
match self {
Self::Windows => "win32",
Self::Linux => "linux",
}
}
pub fn runtime_name(&self) -> &str {
match self {
Self::Windows => "build_server_windows",
Self::Linux => "build_proot_linux",
}
}
pub fn archive_name(&self) -> &str {
match self {
Self::Windows => "server.zip",
Self::Linux => "fx.tar.xz",
}
}
pub fn exe_name(&self) -> &str {
match self {
Self::Windows => "FXServer.exe",
Self::Linux => "run.sh",
}
}
pub fn runtime_url<S, C>(&self, version: S, commit_sha: C) -> String
where
S: AsRef<str>,
C: AsRef<str>,
{
let version = version.as_ref();
let commit_sha = commit_sha.as_ref();
CFX_ARTIFACTS_FILE_API_URL
.replace("{platform}", self.runtime_name())
.replace("{version}", version)
.replace("{commit}", commit_sha)
.replace("{archive}", self.archive_name())
}
pub fn decompress<R, P>(&self, reader: R, dir: P) -> std::io::Result<()>
where
R: Read + Seek,
P: AsRef<Path>,
{
match self {
ArtifactsPlatform::Windows => {
ZipArchive::new(reader)?.extract(dir)?;
}
ArtifactsPlatform::Linux => {
let mut file = NamedTempFile::with_prefix("dxmfx")?;
let mut decoder = xz2::read::XzDecoder::new(reader);
std::io::copy(&mut decoder, file.as_file_mut())?;
tar::Archive::new(file.reopen()?).unpack(dir)?;
}
};
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn returns_runtime_url() {
assert_eq!(
ArtifactsPlatform::Windows.runtime_url("1234", "abcd"),
"https://runtime.fivem.net/artifacts/fivem/build_server_windows/master/1234-abcd/server.zip"
);
}
}