Advertisement
Guest User

Untitled

a guest
May 7th, 2022
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 9.40 KB | None | 0 0
  1. use crate::{CROSS, TICK, YELLOW_TICK};
  2. use anyhow::{bail, Result};
  3. use colored::Colorize;
  4. use ferinth::Ferinth;
  5. use fs_extra::file::{move_file, CopyOptions};
  6. use furse::Furse;
  7. use itertools::Itertools;
  8. use libium::config;
  9. use libium::upgrade;
  10. use octocrab::Octocrab;
  11. use std::{fs::read_dir, sync::Mutex};
  12. use tokio::fs::copy;
  13. use tokio::spawn;
  14.  
  15. struct Downloadable {
  16.     filename: String,
  17.     download_url: String,
  18. }
  19. impl From<furse::structures::file_structs::File> for Downloadable {
  20.     fn from(file: furse::structures::file_structs::File) -> Self {
  21.         Self {
  22.             filename: file.file_name,
  23.             download_url: file.download_url,
  24.         }
  25.     }
  26. }
  27. impl From<ferinth::structures::version_structs::Version> for Downloadable {
  28.     #[allow(clippy::redundant_else)] // The `else` makes it more readable
  29.     fn from(version: ferinth::structures::version_structs::Version) -> Self {
  30.         let mut files = Vec::new();
  31.         for file in version.files {
  32.             if file.primary {
  33.                 return Self {
  34.                     filename: file.filename,
  35.                     download_url: file.url,
  36.                 };
  37.             } else {
  38.                 files.push(file);
  39.             }
  40.         }
  41.         let file = files.remove(0);
  42.         Self {
  43.             filename: file.filename,
  44.             download_url: file.url,
  45.         }
  46.     }
  47. }
  48. impl From<octocrab::models::repos::Asset> for Downloadable {
  49.     fn from(asset: octocrab::models::repos::Asset) -> Self {
  50.         Self {
  51.             filename: asset.name,
  52.             download_url: asset.browser_download_url.into(),
  53.         }
  54.     }
  55. }
  56.  
  57. pub async fn upgrade(
  58.     modrinth: &Ferinth,
  59.     curseforge: &Furse,
  60.     github: &Octocrab,
  61.     profile: &config::structs::Profile,
  62. ) -> Result<()> {
  63.     let to_download = Mutex::new(Vec::new());
  64.     let backwards_compat_msg = Mutex::new(false);
  65.     let error = Mutex::new(false);
  66.  
  67.     println!("{}\n", "Determining the Latest Compatible Versions".bold());
  68.     for mod_ in &profile.mods {
  69.         let modrinth = modrinth.clone();
  70.         let curseforge = curseforge.clone();
  71.         let github = github.clone();
  72.         let profile = profile.clone();
  73.         spawn(async move {
  74.             use libium::config::structs::ModIdentifier;
  75.             let (result, backwards_compat): (Result<Downloadable, _>, bool) = match &mod_.identifier
  76.             {
  77.                 ModIdentifier::CurseForgeProject(project_id) => {
  78.                     let result = upgrade::curseforge(
  79.                         &curseforge,
  80.                         *project_id,
  81.                         &profile.game_version,
  82.                         &profile.mod_loader,
  83.                         mod_.check_game_version,
  84.                         mod_.check_mod_loader,
  85.                     )
  86.                     .await;
  87.                     if matches!(result, Err(upgrade::Error::NoCompatibleFile))
  88.                         && profile.mod_loader == config::structs::ModLoader::Quilt
  89.                     {
  90.                         (
  91.                             upgrade::curseforge(
  92.                                 &curseforge,
  93.                                 *project_id,
  94.                                 &profile.game_version,
  95.                                 &config::structs::ModLoader::Fabric,
  96.                                 mod_.check_game_version,
  97.                                 mod_.check_mod_loader,
  98.                             )
  99.                             .await
  100.                             .map(Into::into),
  101.                             true,
  102.                         )
  103.                     } else {
  104.                         (result.map(Into::into), false)
  105.                     }
  106.                 },
  107.                 ModIdentifier::ModrinthProject(project_id) => {
  108.                     let result = upgrade::modrinth(
  109.                         &modrinth,
  110.                         project_id,
  111.                         &profile.game_version,
  112.                         &profile.mod_loader,
  113.                         mod_.check_game_version,
  114.                         mod_.check_mod_loader,
  115.                     )
  116.                     .await;
  117.                     if matches!(result, Err(upgrade::Error::NoCompatibleFile))
  118.                         && profile.mod_loader == config::structs::ModLoader::Quilt
  119.                     {
  120.                         (
  121.                             upgrade::modrinth(
  122.                                 &modrinth,
  123.                                 project_id,
  124.                                 &profile.game_version,
  125.                                 &config::structs::ModLoader::Fabric,
  126.                                 mod_.check_game_version,
  127.                                 mod_.check_mod_loader,
  128.                             )
  129.                             .await
  130.                             .map(Into::into),
  131.                             true,
  132.                         )
  133.                     } else {
  134.                         (result.map(Into::into), false)
  135.                     }
  136.                 },
  137.                 ModIdentifier::GitHubRepository(full_name) => {
  138.                     let result = upgrade::github(
  139.                         &github.repos(&full_name.0, &full_name.1),
  140.                         &profile.game_version,
  141.                         &profile.mod_loader,
  142.                         mod_.check_game_version,
  143.                         mod_.check_mod_loader,
  144.                     )
  145.                     .await;
  146.                     if matches!(result, Err(upgrade::Error::NoCompatibleFile))
  147.                         && profile.mod_loader == config::structs::ModLoader::Quilt
  148.                     {
  149.                         (
  150.                             upgrade::github(
  151.                                 &github.repos(&full_name.0, &full_name.1),
  152.                                 &profile.game_version,
  153.                                 &config::structs::ModLoader::Fabric,
  154.                                 mod_.check_game_version,
  155.                                 mod_.check_mod_loader,
  156.                             )
  157.                             .await
  158.                             .map(Into::into),
  159.                             true,
  160.                         )
  161.                     } else {
  162.                         (result.map(Into::into), false)
  163.                     }
  164.                 },
  165.             };
  166.  
  167.             match result {
  168.                 Ok(result) => {
  169.                     println!(
  170.                         "{} {:40}{}",
  171.                         if backwards_compat {
  172.                             *backwards_compat_msg.lock().expect("PoisonError!") = true;
  173.                             YELLOW_TICK.clone()
  174.                         } else {
  175.                             TICK.clone()
  176.                         },
  177.                         mod_.name,
  178.                         format!("({})", result.filename).dimmed()
  179.                     );
  180.                     to_download.lock().expect("PoisonError!").push(result);
  181.                 },
  182.                 Err(err) => {
  183.                     eprintln!("{}", format!("{} {:40}{}", CROSS, mod_.name, err).red());
  184.                     *error.lock().expect("PoisonError!") = true;
  185.                 },
  186.             }
  187.         })
  188.         .await;
  189.     }
  190.     let to_download = to_download.into_inner()?;
  191.     if backwards_compat_msg.into_inner()? {
  192.         println!(
  193.             "{}",
  194.             "Fabric mod using Quilt backwards compatibility".yellow()
  195.         );
  196.     }
  197.  
  198.     let mut to_install = Vec::new();
  199.     if profile.output_dir.join("user").exists() {
  200.         for file in read_dir(&profile.output_dir.join("user"))? {
  201.             let file = file?;
  202.             let path = file.path();
  203.             if path.is_file() {
  204.                 to_install.push((file.file_name(), path));
  205.             }
  206.         }
  207.     }
  208.  
  209.     println!("\n{}\n", "Downloading Mod Files".bold());
  210.  
  211.     for file in read_dir(&profile.output_dir)? {
  212.         let file = file?;
  213.         if file.file_type()?.is_file() {
  214.             let filename = file.file_name();
  215.             let filename = filename.to_str().unwrap();
  216.             if let Some((index, _)) = to_download
  217.                 .iter()
  218.                 .find_position(|thing| filename == thing.filename)
  219.             {
  220.                 to_download.swap_remove(index);
  221.             } else if let Some((index, _)) =
  222.                 to_install.iter().find_position(|thing| filename == thing.0)
  223.             {
  224.                 to_install.swap_remove(index);
  225.             } else {
  226.                 let _ = move_file(
  227.                     file.path(),
  228.                     profile.output_dir.join(".old").join(filename),
  229.                     &CopyOptions::new(),
  230.                 );
  231.             }
  232.         }
  233.     }
  234.  
  235.     for downloadable in to_download.iter() {
  236.         eprint!("Downloading {}... ", downloadable.filename.dimmed());
  237.         let contents = reqwest::get(downloadable.download_url)
  238.             .await?
  239.             .bytes()
  240.             .await?;
  241.         upgrade::write_mod_file(profile, contents, &downloadable.filename).await?;
  242.         println!("{}", &*TICK);
  243.     }
  244.     for installable in to_install {
  245.         eprint!(
  246.             "Installing  {}... ",
  247.             installable.0.to_string_lossy().dimmed()
  248.         );
  249.         copy(installable.1, profile.output_dir.join(installable.0)).await?;
  250.         println!("{}", &*TICK);
  251.     }
  252.  
  253.     if error.into_inner()? {
  254.         bail!("\nCould not get the latest compatible version of some mods")
  255.     }
  256.  
  257.     Ok(())
  258. }
  259.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement