Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement OS Family feature #313

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
5 changes: 3 additions & 2 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ fn main() {
}

println!(
"OS information:\nType: {}\nVersion: {}\nBitness: {}",
"OS information:\nType: {}\nVersion: {}\nBitness: {}\nFamily: {}",
info.os_type(),
info.version(),
info.bitness()
info.bitness(),
info.family(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it is useful to show the family here? I'm a little afraid for the output to become too verbose. Additionally it can be a little weird in some cases. For example, currently it will be "OS Windows, Family: Unknown".

Copy link
Contributor Author

@martintc martintc Jun 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can remove that out. Probably not so useful on output, but I also assumed the output here was probably mostly for eyes on validation since os_info's biggest use case is probably as a library to gather the data needed and the caller would just grab the info and the fields it needs.

For Windows, the family should appear as DOS.

OS information:
Type: Windows
Version: 10.0.22000
Bitness: 64-bit
Family: DOS

Mhmm, that is odd. I got that output from my work machine which is Windows 11, but shows the version as Windows 10.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mhmm, that is odd. I got that output from my work machine which is Windows 11, but shows the version as Windows 10.

According to this information it is correct, but I agree that it can be confusing. Ideally, it should be something like "Windows 11 (10.0.22000)".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, yea that is confusing. You would think you see "10" as a major number for versioning, it specifically would reference Windows 10 since they changed from their random naming scheme of XP, Vista, Millennium to 7, 8, 10, 11.

);
} else {
if options.type_ {
Expand Down
3 changes: 3 additions & 0 deletions cspell-dictionary.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
aarch64
berkely
bitness
centos
clippy
concat
distro
earmv
emscripten
endeavouros
family
freebsd
hardenedbsd
hbsd
Expand Down
3 changes: 2 additions & 1 deletion os_info/src/android/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use log::trace;

use crate::{Bitness, Info, Type};
use crate::{Bitness, Family, Info, Type};

pub fn current_platform() -> Info {
trace!("android::current_platform is called");

let info = Info::with_type(Type::Android);
info.family = Family::Linux;
trace!("Returning {:?}", info);
info
}
Expand Down
3 changes: 2 additions & 1 deletion os_info/src/dragonfly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::process::Command;

use log::trace;

use crate::{bitness, uname::uname, Bitness, Info, Type, Version};
use crate::{bitness, uname::uname, Bitness, Family, Info, Type, Version};

pub fn current_platform() -> Info {
trace!("dragonfly::current_platform is called");
Expand All @@ -15,6 +15,7 @@ pub fn current_platform() -> Info {
os_type: Type::DragonFly,
version,
bitness: bitness::get(),
family: Family::BSD,
..Default::default()
};

Expand Down
47 changes: 47 additions & 0 deletions os_info/src/family.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use std::fmt::{self, Display, Formatter};

/// A general category for operating system to place them into 'families'
/// Example of use case is when program logic needs to perform an operation
/// on linux, but does not care which distro it is.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[non_exhaustive]
pub enum Family {
/// Berkely Standard Distributions
/// https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
BSD,
/// Linux Operating systems of all type
/// https://en.wikipedia.org/wiki/Linux
Linux,
/// Apple's MacOS
/// https://en.wikipedia.org/wiki/Macintosh_operating_systems
MacOS,
/// NT based operatings system
/// https://en.wikipedia.org/wiki/Windows_NT
WindowsNT,
/// SunOS and OSs derived from SunOS such as Illumos
/// https://en.wikipedia.org/wiki/SunOS
SunOS,
/// Operating systems whose family is unknown
Unknown,
}

impl Default for Family {
fn default() -> Self {
Family::Unknown
}
}

impl Display for Family {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match *self {
Family::BSD => write!(f, "BSD"),
Family::Linux => write!(f, "Linux"),
Family::MacOS => write!(f, "MacOS"),
Family::SunOS => write!(f, "SunOS"),
Family::WindowsNT => write!(f, "Windows NT"),
_ => write!(f, "{:?}", self),
}
}
}
3 changes: 2 additions & 1 deletion os_info/src/freebsd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::str;

use log::{error, trace};

use crate::{bitness, uname::uname, Info, Type, Version};
use crate::{bitness, uname::uname, Family, Info, Type, Version};

pub fn current_platform() -> Info {
trace!("freebsd::current_platform is called");
Expand All @@ -16,6 +16,7 @@ pub fn current_platform() -> Info {
os_type: get_os(),
version,
bitness: bitness::get(),
family: Family::BSD,
..Default::default()
};

Expand Down
3 changes: 2 additions & 1 deletion os_info/src/illumos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::str;

use log::{error, trace};

use crate::{bitness, uname::uname, Info, Type, Version};
use crate::{bitness, uname::uname, Family, Info, Type, Version};

pub fn current_platform() -> Info {
trace!("illumos::current_platform is called");
Expand All @@ -16,6 +16,7 @@ pub fn current_platform() -> Info {
os_type: get_os(),
version,
bitness: bitness::get(),
family: Family::SunOS,
..Default::default()
};

Expand Down
20 changes: 19 additions & 1 deletion os_info/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::fmt::{self, Display, Formatter};

use super::{Bitness, Type, Version};
use super::{Bitness, Family, Type, Version};

/// Holds information about operating system (type, version, etc.).
///
Expand Down Expand Up @@ -31,6 +31,8 @@ pub struct Info {
/// Operating system architecture in terms of how many bits compose the basic values it can deal
/// with. See `Bitness` for details.
pub(crate) bitness: Bitness,
/// Get the family of operating system. See "Family" for details.
pub(crate) family: Family,
}

impl Info {
Expand All @@ -55,6 +57,7 @@ impl Info {
edition: None,
codename: None,
bitness: Bitness::Unknown,
family: Family::Unknown,
}
}

Expand Down Expand Up @@ -147,6 +150,20 @@ impl Info {
pub fn bitness(&self) -> Bitness {
self.bitness
}

/// Returns the operating system family. See 'Family' for details.
///
/// # Examples
///
/// ```
/// use os_info::{Info, Family};
///
/// let info = Info::unknown();
/// assert_eq!(Family::Unknown, info.family());
/// ```
pub fn family(&self) -> Family {
self.family
}
Comment on lines +164 to +166
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it makes sense to use match here instead of storing family as a separate field.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the recommendation here is something like, in a short hand version

match Type {
    Type::Debian => Family::Linux,
    Type::Gentoo => Family::Linux,
    Type::FreeBSD => Family::BSD,
    Type::Windows => Family::DOS,
     // and so forth
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I had exactly this in mind. Simply put this match into the family method instead of expanding the Info struct with an additional field. Do you see some disadvantages in this approach?

Copy link
Contributor Author

@martintc martintc Jun 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For BSDs, Windows, and MacOS, that is fine since those categories do not expand often. But for the Linux, this would require everytime a new distro is added as a Type, then this match would have to expand and add another arm. The current method should scale with any number of distros without having to update this function or add a new arm to a match.

That is at least my current thought process. This would be the low maintenance way to approach this.

}

impl Default for Info {
Expand Down Expand Up @@ -299,6 +316,7 @@ mod tests {
edition: Some("edition".to_owned()),
codename: Some("codename".to_owned()),
bitness: Bitness::X64,
family: Family::MacOS,
},
"Mac OS 10.2.0 (edition) (codename) [64-bit]",
),
Expand Down
4 changes: 3 additions & 1 deletion os_info/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ mod imp;
mod imp;

mod bitness;
mod family;
mod info;
#[cfg(not(windows))]
mod matcher;
Expand All @@ -85,7 +86,7 @@ mod os_type;
mod uname;
mod version;

pub use crate::{bitness::Bitness, info::Info, os_type::Type, version::Version};
pub use crate::{bitness::Bitness, family::Family, info::Info, os_type::Type, version::Version};

/// Returns information about the current operating system (type, version, edition, etc.).
///
Expand All @@ -105,6 +106,7 @@ pub use crate::{bitness::Bitness, info::Info, os_type::Type, version::Version};
/// println!("Edition: {:?}", info.edition());
/// println!("Codename: {:?}", info.codename());
/// println!("Bitness: {}", info.bitness());
/// println!("family: {}", info.family());
/// ```
pub fn get() -> Info {
imp::current_platform()
Expand Down
3 changes: 2 additions & 1 deletion os_info/src/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod lsb_release;

use log::trace;

use crate::{bitness, Info, Type};
use crate::{bitness, Family, Info, Type};

pub fn current_platform() -> Info {
trace!("linux::current_platform is called");
Expand All @@ -12,6 +12,7 @@ pub fn current_platform() -> Info {
.or_else(file_release::get)
.unwrap_or_else(|| Info::with_type(Type::Linux));
info.bitness = bitness::get();
info.family = Family::Linux;

trace!("Returning {:?}", info);
info
Expand Down
3 changes: 2 additions & 1 deletion os_info/src/macos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::process::Command;

use log::{trace, warn};

use crate::{bitness, matcher::Matcher, Info, Type, Version};
use crate::{bitness, matcher::Matcher, Family, Info, Type, Version};

pub fn current_platform() -> Info {
trace!("macos::current_platform is called");
Expand All @@ -11,6 +11,7 @@ pub fn current_platform() -> Info {
os_type: Type::Macos,
version: version(),
bitness: bitness::get(),
family: Family::MacOS,
..Default::default()
};
trace!("Returning {:?}", info);
Expand Down
3 changes: 2 additions & 1 deletion os_info/src/netbsd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::process::Command;

use log::{error, trace};

use crate::{bitness, uname::uname, Info, Type, Version};
use crate::{bitness, uname::uname, Family, Info, Type, Version};

pub fn current_platform() -> Info {
trace!("netbsd::current_platform is called");
Expand All @@ -15,6 +15,7 @@ pub fn current_platform() -> Info {
os_type: Type::NetBSD,
version,
bitness: bitness::get(),
family: Family::BSD,
..Default::default()
};

Expand Down
3 changes: 2 additions & 1 deletion os_info/src/openbsd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::process::Command;

use log::{error, trace};

use crate::{bitness, uname::uname, Info, Type, Version};
use crate::{bitness, uname::uname, Family, Info, Type, Version};

pub fn current_platform() -> Info {
trace!("openbsd::current_platform is called");
Expand All @@ -15,6 +15,7 @@ pub fn current_platform() -> Info {
os_type: Type::OpenBSD,
version,
bitness: bitness::get(),
family: Family::BSD,
..Default::default()
};

Expand Down
3 changes: 2 additions & 1 deletion os_info/src/redox/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{fs::File, io::Read};

use log::{error, trace};

use crate::{Bitness, Info, Type, Version};
use crate::{Bitness, Family, Info, Type, Version};

const UNAME_FILE: &str = "sys:uname";

Expand All @@ -18,6 +18,7 @@ pub fn current_platform() -> Info {
os_type: Type::Redox,
version,
bitness: Bitness::Unknown,
family: Family::WindowsNT,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also seems weird to me. 🙃

Copy link
Contributor Author

@martintc martintc Jun 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this one, @kraileth suggested changing since Windows is no longer truly "DOS," and I guess that has been true since the 90s. So calling it in the "DOS" family is misleading. He recommended changing it to either something NT since NT is the kernel architecture or just having the family also be Windows. I don't really know enough about Windows and its architecture to really know either way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought here: the OS enviroment variable expands to Windows_NT on windows systems

..Default::default()
};
trace!("Returning {:?}", info);
Expand Down
3 changes: 2 additions & 1 deletion os_info/src/windows/winapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use winapi::{
},
};

use crate::{Bitness, Info, Type, Version};
use crate::{Bitness, Family, Info, Type, Version};

#[cfg(target_arch = "x86")]
type OSVERSIONINFOEX = winapi::um::winnt::OSVERSIONINFOEXA;
Expand All @@ -46,6 +46,7 @@ pub fn get() -> Info {
version,
edition,
bitness: bitness(),
family: Family::WindowsNT,
..Default::default()
}
}
Expand Down