From 17eaab095845d5bd1e05b5d21a92c99a35fd0788 Mon Sep 17 00:00:00 2001 From: wheatfox Date: Fri, 20 Dec 2024 22:43:24 +0800 Subject: [PATCH] Rewrite get_os_distro(), get_os() and OS enum struct --- compiler-cli/src/beam_compiler.rs | 5 ++- compiler-cli/src/fs.rs | 55 +++++++++++++++++-------------- compiler-core/src/error.rs | 49 +++++++++++++-------------- compiler-core/src/error/tests.rs | 36 ++++++++------------ 4 files changed, 68 insertions(+), 77 deletions(-) diff --git a/compiler-cli/src/beam_compiler.rs b/compiler-cli/src/beam_compiler.rs index 94ef8a6a53a..974a2a314ea 100644 --- a/compiler-cli/src/beam_compiler.rs +++ b/compiler-cli/src/beam_compiler.rs @@ -4,6 +4,8 @@ use gleam_core::{ paths, Result, }; +use crate::fs::get_os; + use std::{ collections::HashSet, io::{self, BufRead, BufReader, Write}, @@ -13,8 +15,6 @@ use std::{ use camino::{Utf8Path, Utf8PathBuf}; use itertools::Itertools; -use crate::fs::{get_os, get_os_distro}; - #[derive(Debug)] struct BeamCompilerInner { process: Child, @@ -114,7 +114,6 @@ impl BeamCompiler { io::ErrorKind::NotFound => Error::ShellProgramNotFound { program: "escript".into(), os: get_os(), - distro: get_os_distro(), }, other => Error::ShellCommand { program: "escript".into(), diff --git a/compiler-cli/src/fs.rs b/compiler-cli/src/fs.rs index f8836a3cb39..59bfa607a9d 100644 --- a/compiler-cli/src/fs.rs +++ b/compiler-cli/src/fs.rs @@ -1,6 +1,6 @@ use gleam_core::{ build::{NullTelemetry, Target}, - error::{Distro, Error, FileIoAction, FileKind, OS}, + error::{parse_linux_distribution, Distro, Error, FileIoAction, FileKind, OS}, io::{ BeamCompiler, CommandExecutor, Content, DirEntry, FileSystemReader, FileSystemWriter, OutputFile, ReadDir, Stdio, WrappedReader, @@ -54,32 +54,38 @@ pub fn get_project_root(path: Utf8PathBuf) -> Result { }) } -#[inline] pub fn get_os() -> OS { - OS::from(std::env::consts::OS) -} - -// Return the distro enum if /etc/os-release exists, otherwise return Other -pub fn get_os_distro() -> Distro { - if let OS::Linux = get_os() { - let os_release = std::fs::read_to_string("/etc/os-release"); - match os_release { - Ok(release) => { - let mut distro = Distro::Other; - for line in release.lines() { - if line.starts_with("ID=") { - let distro_id = line.split('=').nth(1).unwrap_or("other"); - distro = Distro::from(distro_id); - break; - } - } - distro - } - Err(_) => Distro::Other, + match std::env::consts::OS { + "macos" => OS::MacOS, + "windows" => OS::Windows, + "linux" => { + let distro = get_linux_distribution(); + OS::Linux(distro) } - } else { - Distro::Other + _ => OS::Other, + } +} + +pub fn get_linux_distribution() -> Distro { + let path = Utf8Path::new("/etc/os-release"); + if std::env::consts::OS != "linux" || !path.exists() { + return Distro::Other; + } + let os_release = read(path); + if os_release.is_err() { + return Distro::Other; + } + let os_release = os_release.unwrap_or_default(); + let distro = os_release.lines().find(|line| line.starts_with("ID=")); + if let Some(distro) = distro { + let id = distro + .split('=') + .nth(1) + .unwrap_or("other") + .replace("\"", ""); + return parse_linux_distribution(&id); } + Distro::Other } /// A `FileWriter` implementation that writes to the file system. @@ -212,7 +218,6 @@ impl CommandExecutor for ProjectIO { io::ErrorKind::NotFound => Error::ShellProgramNotFound { program: program.to_string(), os: get_os(), - distro: get_os_distro(), }, other => Error::ShellCommand { diff --git a/compiler-core/src/error.rs b/compiler-core/src/error.rs index 65d192cf440..1ee5c8c380c 100644 --- a/compiler-core/src/error.rs +++ b/compiler-core/src/error.rs @@ -151,11 +151,7 @@ pub enum Error { Gzip(String), #[error("shell program `{program}` not found")] - ShellProgramNotFound { - program: String, - os: OS, - distro: Distro, - }, + ShellProgramNotFound { program: String, os: OS }, #[error("shell program `{program}` failed")] ShellCommand { @@ -350,26 +346,14 @@ impl SmallVersion { } } } - #[derive(Debug, Clone, Eq, PartialEq, Copy)] pub enum OS { - Linux, + Linux(Distro), MacOS, Windows, Other, } -impl From<&str> for OS { - fn from(env_os: &str) -> Self { - match env_os { - "linux" => OS::Linux, - "macos" => OS::MacOS, - "windows" => OS::Windows, - _ => OS::Other, - } - } -} - #[derive(Debug, Clone, Eq, PartialEq, Copy)] pub enum Distro { Ubuntu, @@ -377,13 +361,24 @@ pub enum Distro { Other, } -impl From<&str> for Distro { - fn from(distro_id: &str) -> Self { - match distro_id { - "ubuntu" => Distro::Ubuntu, - "debian" => Distro::Debian, - _ => Distro::Other, - } +pub fn parse_os(os: &str, distro: &str) -> OS { + match os { + "macos" => OS::MacOS, + "windows" => OS::Windows, + "linux" => match distro { + "ubuntu" => OS::Linux(Distro::Ubuntu), + "debian" => OS::Linux(Distro::Debian), + _ => OS::Linux(Distro::Other), + }, + _ => OS::Other, + } +} + +pub fn parse_linux_distribution(distribution: &str) -> Distro { + match distribution { + "ubuntu" => Distro::Ubuntu, + "debian" => Distro::Debian, + _ => Distro::Other, } } @@ -1060,7 +1055,7 @@ your app.src file \"{app_ver}\"." }] } - Error::ShellProgramNotFound { program , os, distro } => { + Error::ShellProgramNotFound { program , os } => { let mut text = format!("The program `{program}` was not found. Is it installed?\n"); match program.as_str() { @@ -1117,7 +1112,7 @@ https://git-scm.com/book/en/v2/Getting-Started-Installing-Git", _ => (), } } - OS::Linux => { + OS::Linux(distro) => { fn apt_install(program: &str) -> String { format!("\nYou can install {} via apt: sudo apt install {}", program, program) } diff --git a/compiler-core/src/error/tests.rs b/compiler-core/src/error/tests.rs index 3900c7f1e0a..1c15349a5cf 100644 --- a/compiler-core/src/error/tests.rs +++ b/compiler-core/src/error/tests.rs @@ -9,36 +9,28 @@ fn test_shell_program_not_found_error() { for cmd in &cmds { for os in &oses { - let os_enum = OS::from(*os); - match os_enum { - OS::MacOS | OS::Windows => { + if os != &"linux" { + let err = Error::ShellProgramNotFound { + program: cmd.to_string(), + os: parse_os(os, "other"), + } + .to_diagnostics(); + assert_snapshot!( + format!("shell_program_not_found_{cmd}_{os}_other"), + err[0].text + ); + } else { + for distro in &distros { let err = Error::ShellProgramNotFound { program: cmd.to_string(), - os: os_enum, - distro: Distro::Other, + os: parse_os(os, distro), } .to_diagnostics(); assert_snapshot!( - format!("shell_program_not_found_{cmd}_{os}_other"), + format!("shell_program_not_found_{cmd}_{os}_{distro}"), err[0].text ); } - OS::Linux => { - for distro in &distros { - let distro_enum = Distro::from(*distro); - let err = Error::ShellProgramNotFound { - program: cmd.to_string(), - os: os_enum, - distro: distro_enum, - } - .to_diagnostics(); - assert_snapshot!( - format!("shell_program_not_found_{cmd}_{os}_{distro}"), - err[0].text - ); - } - } - _ => (), } } }