1
0
Fork 0
This commit is contained in:
Florian RICHER (MrDev023) 2021-07-24 13:37:14 +02:00
commit 687ce0f7bb
14 changed files with 2120 additions and 0 deletions

3
src/common/mod.rs Normal file
View file

@ -0,0 +1,3 @@
pub static TEMP_FOLDER: &str = "temp";
pub mod utils;

View file

@ -0,0 +1,17 @@
use std::{fs, path::PathBuf};
fn create_download_folder() -> Option<()> {
fs::create_dir_all(super::super::TEMP_FOLDER).ok()
}
pub fn download_file(url : &String, filename: &str) -> Option<PathBuf> {
create_download_folder()?;
let mut response = reqwest::blocking::get(url).ok()?;
let fname = std::path::Path::new(super::super::TEMP_FOLDER).join(filename);
let mut dest = fs::File::create(fname.clone()).ok()?;
response.copy_to(&mut dest).ok()?;
Some(fname)
}

View file

@ -0,0 +1,55 @@
use crate::common;
use std::{fs::{
File,
create_dir_all
}, io, path::{self, PathBuf}};
pub fn extract_file(path: &PathBuf, outdir: &str) -> Option<()> {
let file = File::open(&path).unwrap();
let mut archive = match zip::ZipArchive::new(file) {
Ok(archive) => archive,
Err(err) => {
println!("[ERROR][EXTRACTOR] {}", err);
return None
}
};
let path = path::Path::new(common::TEMP_FOLDER).join(outdir);
for i in 0..archive.len() {
let mut file = archive.by_index(i).ok()?;
let file_path = file.enclosed_name()?;
let output_path = path.join(file_path);
if (&*file.name()).ends_with('/') {
println!("File {} extracted to \"{}\"", i, output_path.display());
create_dir_all(&output_path).unwrap();
} else {
println!(
"File {} extracted to \"{}\" ({} bytes)",
i,
output_path.display(),
file.size()
);
if let Some(p) = output_path.parent() {
if !p.exists() {
create_dir_all(&p).unwrap();
}
}
let mut outfile = File::create(&output_path).unwrap();
io::copy(&mut file, &mut outfile).unwrap();
}
// Get and Set permissions
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
if let Some(mode) = file.unix_mode() {
fs::set_permissions(&outpath, fs::Permissions::from_mode(mode)).unwrap();
}
}
}
Some(())
}

39
src/common/utils/git.rs Normal file
View file

@ -0,0 +1,39 @@
use serde_derive::{Serialize, Deserialize};
use reqwest::header;
#[derive(Serialize, Deserialize, Debug)]
pub struct Asset {
pub browser_download_url: String,
pub name: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GitResponse {
pub assets: Vec<Asset>
}
pub fn get_git_release_by_version(repo: &str, version: &str) -> Option<GitResponse> {
let url = format!("https://api.github.com/repos/{}/releases/{}", repo, version);
let mut headers = header::HeaderMap::new();
headers.append(header::USER_AGENT, header::HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Edg/92.0.902.55"));
let data = reqwest::blocking::Client::builder()
.default_headers(headers)
.build()
.ok()?
.get(url)
.send()
.ok()?
.text()
.ok()?;
let git_response : GitResponse = serde_json::from_str(&data)
.ok()?;
Some(git_response)
}
pub fn get_git_latest_release(repo: &str) -> Option<GitResponse> {
Some(get_git_release_by_version(repo, "latest")?)
}

3
src/common/utils/mod.rs Normal file
View file

@ -0,0 +1,3 @@
pub mod downloader;
pub mod extractor;
pub mod git;

6
src/main.rs Normal file
View file

@ -0,0 +1,6 @@
mod windows;
pub mod common;
fn main() {
windows::start();
}

26
src/windows/fvm/git.rs Normal file
View file

@ -0,0 +1,26 @@
use crate::common::utils::git;
fn get_prefix_from_arch() -> Option<String> {
if std::env::consts::ARCH == "x86_64" {
Some(format!("x64"))
} else if std::env::consts::ARCH == "x86" {
Some(format!("ia32"))
} else {
None
}
}
pub fn get_file_url() -> Result<String, String> {
let git_response = git::get_git_latest_release("leoafarias/fvm")
.ok_or(format!("Failed to get git release"))?;
let arch_prefix = get_prefix_from_arch().ok_or(format!("Arch not supported"))?;
for asset in git_response.assets {
if asset.name.contains(std::env::consts::OS) && asset.name.contains(arch_prefix.as_str()) {
return Ok(asset.browser_download_url);
}
}
Err(format!("OS not supported"))
}

33
src/windows/fvm/mod.rs Normal file
View file

@ -0,0 +1,33 @@
mod git;
use crate::common::utils::downloader;
use crate::common::utils::extractor;
// use std::process::Command;
pub fn install() -> Result<(), String> {
println!("Install FVM");
let url = git::get_file_url()?;
let filename = url.split('/').last()
.ok_or(format!("Failed to download file"))?;
let file = downloader::download_file(&url, &filename)
.ok_or(format!("Failed to download file"))?;
extractor::extract_file(&file, "fvm")
.ok_or(format!("Failed to extract file"))?;
println!("{}", url);
// let output = Command::new("winget")
// .args(&[""])
// .output()
// .map_err(|_| format!("Permision refused ! Please run as administrator."))?;
// println!("{}", std::str::from_utf8(&output.stdout).map_err(|_| format!("Internal error"))?);
Ok(())
}

36
src/windows/mod.rs Normal file
View file

@ -0,0 +1,36 @@
mod fvm;
use structopt::{
StructOpt,
clap::{
arg_enum
}
};
arg_enum! {
#[derive(Debug)]
enum Tool {
Fvm
}
}
#[derive(Debug, StructOpt)]
#[structopt(name = "autoconfig", about = "Auto install local config.")]
struct Opt {
#[structopt(short = "i", long = "install", help = "Available values : fvm (Flutter version manager)")]
tools: Vec<Tool>,
}
pub fn start() {
let opt = Opt::from_args();
for tool in &opt.tools {
let result = match tool {
Tool::Fvm => fvm::install()
};
if let Err(err) = result {
eprintln!("[ERROR] {}", err);
}
}
}