Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ shellexpand = "2.1.0"
env_proxy = "0.4.1"

[target.'cfg(windows)'.dependencies]
windows = { version = "0.38.0", features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_System_Console", "Services_Store", "Foundation", "Foundation_Collections"] }
ureq = { version = "2", features = ["native-tls"] }
native-tls = "0.2.10"
windows = { version = "0.38.0", features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_System_Console", "Services_Store", "Foundation", "Foundation_Collections", "Web_Http", "Storage_Streams",] }

[target.'cfg(macos)'.dependencies]
ureq = { version = "2", features = ["native-tls"] }
Expand Down
103 changes: 102 additions & 1 deletion src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ where
Ok(())
}

#[cfg(not(windows))]
fn get_proxy(url: &str) -> Option<Result<ureq::Proxy>> {
trace!("identifying proxy for url: {url}");
use log::trace;
Expand All @@ -67,7 +68,7 @@ pub fn get_ureq_agent(url: &str) -> Result<ureq::Agent> {
Ok(agent)
}

#[cfg(any(windows, macos))]
#[cfg(macos)]
pub fn get_ureq_agent(url: &str) -> Result<ureq::Agent> {
use native_tls::TlsConnector;
use std::sync::Arc;
Expand All @@ -85,6 +86,8 @@ pub fn get_ureq_agent(url: &str) -> Result<ureq::Agent> {
Ok(agent)
}


#[cfg(not(windows))]
pub fn download_extract_sans_parent(url: &str, target_path: &Path, levels_to_skip: usize) -> Result<()> {
let agent = get_ureq_agent(url)
.with_context(|| format!("Failed to construct download agent."))?;
Expand Down Expand Up @@ -115,6 +118,82 @@ pub fn download_extract_sans_parent(url: &str, target_path: &Path, levels_to_ski
Ok(())
}

#[cfg(windows)]
struct DataReaderWrap(windows::Storage::Streams::DataReader);

#[cfg(windows)]
impl std::io::Read for DataReaderWrap {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let mut bytes =
self.0
.LoadAsync(buf.len() as u32)
.map_err(|e| std::io::Error::from_raw_os_error(e.code().0))?
.get()
.map_err(|e| std::io::Error::from_raw_os_error(e.code().0))? as usize;
bytes = bytes.min(buf.len());
self.0
.ReadBytes(&mut buf[0..bytes])
.map_err(|e| std::io::Error::from_raw_os_error(e.code().0))
.map(|_| bytes)
}
}

#[cfg(windows)]
pub fn download_extract_sans_parent(url: &str, target_path: &Path, levels_to_skip: usize) -> Result<()> {
let http_client = windows::Web::Http::HttpClient::new()
.with_context(|| "Failed to create HttpClient.")?;

let request_uri = windows::Foundation::Uri::CreateUri(&windows::core::HSTRING::from(url))
.with_context(|| "Failed to convert url string to Uri.")?;

let http_response = http_client.GetAsync(&request_uri)
.with_context(|| "Failed to initiate download.")?
.get()
.with_context(|| "Failed to complete async download operation.")?;

http_response.EnsureSuccessStatusCode()
.with_context(|| "HTTP download reported error status code.")?;

let http_response_content = http_response.Content()
.with_context(|| "Failed to obtain content from http response.")?;

let response_stream = http_response_content.ReadAsInputStreamAsync()
.with_context(|| "Failed to initiate get input stream from response")?
.get()
.with_context(|| "Failed to obtain input stream from http response")?;

let reader = windows::Storage::Streams::DataReader::CreateDataReader(response_stream)
.with_context(|| "Failed to create DataReader.")?;

reader.SetInputStreamOptions(windows::Storage::Streams::InputStreamOptions::ReadAhead)
.with_context(|| "Failed to set input stream options.")?;

let mut content_length: u64 = 0;
let pb = if http_response_content.TryComputeLength(&mut content_length)? {
ProgressBar::new(content_length)
} else {
ProgressBar::new_spinner()
};

pb.set_prefix(" Downloading:");
pb.set_style(ProgressStyle::default_bar()
.template("{prefix:.cyan.bold} [{bar}] {bytes}/{total_bytes} eta: {eta}")
.unwrap()
.progress_chars("=> "));

let foo = pb.wrap_read(DataReaderWrap(reader));

let tar = GzDecoder::new(foo);

let archive = Archive::new(tar);

unpack_sans_parent(archive, &target_path, levels_to_skip)
.with_context(|| format!("Failed to extract downloaded file from url `{}`.", url))?;

Ok(())
}

#[cfg(not(windows))]
pub fn download_juliaup_version(url: &str) -> Result<Version> {
let agent = get_ureq_agent(url)
.with_context(|| format!("Failed to construct download agent."))?;
Expand All @@ -132,6 +211,28 @@ pub fn download_juliaup_version(url: &str) -> Result<Version> {
Ok(version)
}

#[cfg(windows)]
pub fn download_juliaup_version(url: &str) -> Result<Version> {
let http_client = windows::Web::Http::HttpClient::new()
.with_context(|| "Failed to create HttpClient.")?;

let request_uri = windows::Foundation::Uri::CreateUri(&windows::core::HSTRING::from(url))
.with_context(|| "Failed to convert url string to Uri.")?;

let response = http_client.GetStringAsync(request_uri)
.with_context(|| "")?
.get()
.with_context(|| "")?
.to_string();

let trimmed_response = response.trim();

let version = Version::parse(trimmed_response)
.with_context(|| format!("`download_juliaup_version` failed to parse `{}` as a valid semversion.", trimmed_response))?;

Ok(version)
}

pub fn install_version(
fullversion: &String,
config_data: &mut JuliaupConfig,
Expand Down