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
29 changes: 25 additions & 4 deletions crates/qt-build-utils/src/installation/qt_minimal/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use std::path::{Path, PathBuf};

use semver::Version;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};

#[derive(Debug, Serialize, Deserialize)]
/// A Qt manifest.json file, which specifies a set of artifacts needed for installation
Expand All @@ -17,7 +17,7 @@ pub(crate) struct ParsedQtManifest {
#[derive(Debug, Serialize, Deserialize, PartialEq)]
/// Descriptor for a Qt artifact, included download information
pub(crate) struct ParsedQtArtifact {
pub(crate) version: semver::Version,
pub(crate) version: Version,
pub(crate) arch: String,
pub(crate) os: String,
pub(crate) url: String,
Expand All @@ -29,7 +29,10 @@ impl ParsedQtArtifact {
/// Download the artifact and extract to the given target path
pub fn download_and_extract(&self, target_path: &Path) -> PathBuf {
// Download to a temporary location
let http_client = reqwest::blocking::Client::new();
let http_client = reqwest::blocking::Client::builder()
.timeout(None)
.build()
.expect("Http client failed to build");
let temp_dir = tempfile::TempDir::new().expect("Could not create temporary directory");
let archive_path =
super::download::download_from_url(&self.url, &self.sha256, &temp_dir, &http_client)
Expand All @@ -46,6 +49,24 @@ impl ParsedQtArtifact {
target_path.to_path_buf()
}

/// Used to create a found artifact without a checksum, used by local artifact discovery
pub fn new(
version: Version,
arch: String,
os: String,
url: String,
content_type: String,
) -> Self {
Self {
version,
arch,
os,
url,
sha256: "".to_string(),
content: vec![content_type],
}
}

/// Assert that the hashes are the same, from bytes
pub fn verify(&self, hash: &[u8]) -> anyhow::Result<()> {
let mut hash_string = String::new();
Expand Down
72 changes: 70 additions & 2 deletions crates/qt-build-utils/src/installation/qt_minimal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ mod checksum;
mod download;
mod extract;

use std::path::PathBuf;
use std::fs::DirEntry;
use std::path::{Path, PathBuf};

use crate::installation::qt_minimal::artifact::ParsedQtArtifact;
use crate::{QtBuildError, QtInstallation};

/// A implementation of [QtInstallation] using qtminimal
Expand Down Expand Up @@ -84,7 +86,7 @@ impl TryFrom<semver::Version> for QtInstallationQtMinimal {
let os = target_parts
.get(2)
.expect("TARGET to have a <sys> component");
let artifacts: Vec<artifact::ParsedQtArtifact> = manifest
let artifacts: Vec<ParsedQtArtifact> = manifest
.artifacts
.into_iter()
.filter(|artifact| {
Expand Down Expand Up @@ -185,4 +187,70 @@ impl QtInstallationQtMinimal {

path
}

/// Get a collection of the locally installed Qt artifacts
pub(crate) fn local_artifacts() -> anyhow::Result<Vec<ParsedQtArtifact>> {
let base_dir = Self::qt_minimal_root();

// Expects folder structure like:
// version/os/arch/qt/{bin, include}
// e.g. will find an artifact at 6.10.0/linux/x86_64/qt/bin
let mut artifacts = vec![];

// Iterate versions
for version in list_dirs(&base_dir) {
let path = version;
// TODO: Later skip unknown folders,
// this will error if a directory exists which isn't a version number
let semver = semver::Version::parse(path.file_name().to_str().unwrap())
.expect("Could not parse semver from directory name");

for os in list_dirs(&path.path()) {
let path = os;
let os = path.file_name().to_str().unwrap().to_string();

for arch in list_dirs(&path.path()) {
let path = arch;
let dir_entries = list_dirs(&path.path());

// Expects one qt dir
let qt_dir_path = dir_entries
.iter()
.filter(|dir| dir.file_name() == "qt")
.last()
.expect("Expected to find a Qt dir in this folder");

let qt_folders = list_dirs(&qt_dir_path.path());
for dir in qt_folders {
let filename = dir.file_name();
// Will be set if bin or include dirs are found
let mut artifact_type = None;

if filename == "bin" {
artifact_type = Some("bin");
} else if filename == "include" {
artifact_type = Some("include");
}

if let Some(artifact_type) = artifact_type {
artifacts.push(ParsedQtArtifact::new(
semver.clone(),
path.file_name().to_string_lossy().to_string(),
os.clone(),
qt_dir_path.path().to_string_lossy().to_string(),
artifact_type.to_string(),
))
}
}
}
}
}

Ok(artifacts)
}
}

/// Get all valid directories in path bufs, ignoring errors
fn list_dirs(path: &Path) -> Vec<DirEntry> {
path.read_dir().unwrap().flatten().collect()
}
1 change: 1 addition & 0 deletions crates/qt-build-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ impl QtBuild {
// Search existing installed qt_minimal versions
//
// TODO: have API to do this
let _ = QtInstallationQtMinimal::local_artifacts();

// Download from Qt artifacts
//
Expand Down
Loading