200 lines
6.3 KiB
Rust
200 lines
6.3 KiB
Rust
use std::borrow::Cow;
|
|
use std::collections::HashMap;
|
|
use std::convert::TryFrom;
|
|
use std::io::BufRead;
|
|
use std::path::PathBuf;
|
|
|
|
use crate::setup_config::{EnumSetupInstances, SetupInstance};
|
|
|
|
pub enum VsInstance {
|
|
Com(SetupInstance),
|
|
Vswhere(VswhereInstance),
|
|
}
|
|
|
|
impl VsInstance {
|
|
pub fn installation_name(&self) -> Option<Cow<str>> {
|
|
match self {
|
|
VsInstance::Com(s) => s
|
|
.installation_name()
|
|
.ok()
|
|
.and_then(|s| s.into_string().ok())
|
|
.map(Cow::from),
|
|
VsInstance::Vswhere(v) => v.map.get("installationName").map(Cow::from),
|
|
}
|
|
}
|
|
|
|
pub fn installation_path(&self) -> Option<PathBuf> {
|
|
match self {
|
|
VsInstance::Com(s) => s.installation_path().ok().map(PathBuf::from),
|
|
VsInstance::Vswhere(v) => v.map.get("installationPath").map(PathBuf::from),
|
|
}
|
|
}
|
|
|
|
pub fn installation_version(&self) -> Option<Cow<str>> {
|
|
match self {
|
|
VsInstance::Com(s) => s
|
|
.installation_version()
|
|
.ok()
|
|
.and_then(|s| s.into_string().ok())
|
|
.map(Cow::from),
|
|
VsInstance::Vswhere(v) => v.map.get("installationVersion").map(Cow::from),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub enum VsInstances {
|
|
ComBased(EnumSetupInstances),
|
|
VswhereBased(VswhereInstance),
|
|
}
|
|
|
|
impl IntoIterator for VsInstances {
|
|
type Item = VsInstance;
|
|
#[allow(bare_trait_objects)]
|
|
type IntoIter = Box<Iterator<Item = Self::Item>>;
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
match self {
|
|
VsInstances::ComBased(e) => {
|
|
Box::new(e.into_iter().filter_map(Result::ok).map(VsInstance::Com))
|
|
}
|
|
VsInstances::VswhereBased(v) => Box::new(std::iter::once(VsInstance::Vswhere(v))),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct VswhereInstance {
|
|
map: HashMap<String, String>,
|
|
}
|
|
|
|
impl TryFrom<&Vec<u8>> for VswhereInstance {
|
|
type Error = &'static str;
|
|
|
|
fn try_from(output: &Vec<u8>) -> Result<Self, Self::Error> {
|
|
let map: HashMap<_, _> = output
|
|
.lines()
|
|
.filter_map(Result::ok)
|
|
.filter_map(|s| {
|
|
let mut splitn = s.splitn(2, ": ");
|
|
Some((splitn.next()?.to_owned(), splitn.next()?.to_owned()))
|
|
})
|
|
.collect();
|
|
|
|
if !map.contains_key("installationName")
|
|
|| !map.contains_key("installationPath")
|
|
|| !map.contains_key("installationVersion")
|
|
{
|
|
return Err("required properties not found");
|
|
}
|
|
|
|
Ok(Self { map })
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests_ {
|
|
use std::borrow::Cow;
|
|
use std::convert::TryFrom;
|
|
use std::path::PathBuf;
|
|
|
|
#[test]
|
|
fn it_parses_vswhere_output_correctly() {
|
|
let output = br"instanceId: 58104422
|
|
installDate: 21/02/2021 21:50:33
|
|
installationName: VisualStudio/16.9.2+31112.23
|
|
installationPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools
|
|
installationVersion: 16.9.31112.23
|
|
productId: Microsoft.VisualStudio.Product.BuildTools
|
|
productPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\LaunchDevCmd.bat
|
|
state: 4294967295
|
|
isComplete: 1
|
|
isLaunchable: 1
|
|
isPrerelease: 0
|
|
isRebootRequired: 0
|
|
displayName: Visual Studio Build Tools 2019
|
|
description: The Visual Studio Build Tools allows you to build native and managed MSBuild-based applications without requiring the Visual Studio IDE. There are options to install the Visual C++ compilers and libraries, MFC, ATL, and C++/CLI support.
|
|
channelId: VisualStudio.16.Release
|
|
channelUri: https://aka.ms/vs/16/release/channel
|
|
enginePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\ServiceHub\Services\Microsoft.VisualStudio.Setup.Service
|
|
releaseNotes: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-v16.9#16.9.2
|
|
thirdPartyNotices: https://go.microsoft.com/fwlink/?LinkId=660909
|
|
updateDate: 2021-03-17T21:16:46.5963702Z
|
|
catalog_buildBranch: d16.9
|
|
catalog_buildVersion: 16.9.31112.23
|
|
catalog_id: VisualStudio/16.9.2+31112.23
|
|
catalog_localBuild: build-lab
|
|
catalog_manifestName: VisualStudio
|
|
catalog_manifestType: installer
|
|
catalog_productDisplayVersion: 16.9.2
|
|
catalog_productLine: Dev16
|
|
catalog_productLineVersion: 2019
|
|
catalog_productMilestone: RTW
|
|
catalog_productMilestoneIsPreRelease: False
|
|
catalog_productName: Visual Studio
|
|
catalog_productPatchVersion: 2
|
|
catalog_productPreReleaseMilestoneSuffix: 1.0
|
|
catalog_productSemanticVersion: 16.9.2+31112.23
|
|
catalog_requiredEngineVersion: 2.9.3365.38425
|
|
properties_campaignId: 156063665.1613940062
|
|
properties_channelManifestId: VisualStudio.16.Release/16.9.2+31112.23
|
|
properties_nickname:
|
|
properties_setupEngineFilePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installershell.exe
|
|
"
|
|
.to_vec();
|
|
|
|
let vswhere_instance = super::VswhereInstance::try_from(&output);
|
|
assert!(vswhere_instance.is_ok());
|
|
|
|
let vs_instance = super::VsInstance::Vswhere(vswhere_instance.unwrap());
|
|
assert_eq!(
|
|
vs_instance.installation_name(),
|
|
Some(Cow::from("VisualStudio/16.9.2+31112.23"))
|
|
);
|
|
assert_eq!(
|
|
vs_instance.installation_path(),
|
|
Some(PathBuf::from(
|
|
r"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools"
|
|
))
|
|
);
|
|
assert_eq!(
|
|
vs_instance.installation_version(),
|
|
Some(Cow::from("16.9.31112.23"))
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_returns_an_error_for_empty_output() {
|
|
let output = b"".to_vec();
|
|
|
|
let vswhere_instance = super::VswhereInstance::try_from(&output);
|
|
|
|
assert!(vswhere_instance.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn it_returns_an_error_for_output_consisting_of_empty_lines() {
|
|
let output = br"
|
|
|
|
"
|
|
.to_vec();
|
|
|
|
let vswhere_instance = super::VswhereInstance::try_from(&output);
|
|
|
|
assert!(vswhere_instance.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn it_returns_an_error_for_output_without_required_properties() {
|
|
let output = br"instanceId: 58104422
|
|
installDate: 21/02/2021 21:50:33
|
|
productId: Microsoft.VisualStudio.Product.BuildTools
|
|
productPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\LaunchDevCmd.bat
|
|
"
|
|
.to_vec();
|
|
|
|
let vswhere_instance = super::VswhereInstance::try_from(&output);
|
|
|
|
assert!(vswhere_instance.is_err());
|
|
}
|
|
}
|