try parse manifest
This commit is contained in:
@ -1,9 +1,20 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use crate::manifest::Manifest;
|
||||
use crate::repo::github::GithubRepo;
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use apk::AndroidManifest;
|
||||
use async_zip::tokio::read::seek::ZipFileReader;
|
||||
use async_zip::ZipFile;
|
||||
use log::info;
|
||||
use nostr_sdk::async_utility::futures_util::TryStreamExt;
|
||||
use nostr_sdk::prelude::{hex, StreamExt};
|
||||
use reqwest::Url;
|
||||
use semver::Version;
|
||||
use serde::Deserialize;
|
||||
use sha2::Digest;
|
||||
use std::env::temp_dir;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tokio::fs::File;
|
||||
use tokio::io::{AsyncWriteExt, BufReader};
|
||||
|
||||
mod github;
|
||||
|
||||
@ -14,16 +25,11 @@ pub struct RepoArtifact {
|
||||
pub location: RepoResource,
|
||||
pub content_type: String,
|
||||
pub platform: Platform,
|
||||
pub metadata: ArtifactMetadata
|
||||
pub metadata: ArtifactMetadata,
|
||||
}
|
||||
|
||||
pub enum ArtifactMetadata {
|
||||
APK {
|
||||
version_code: u32,
|
||||
min_sdk_version: u32,
|
||||
target_sdk_version: u32,
|
||||
sig_hash: String,
|
||||
}
|
||||
APK { manifest: AndroidManifest },
|
||||
}
|
||||
|
||||
pub enum Platform {
|
||||
@ -79,10 +85,78 @@ impl TryInto<Box<dyn Repo>> for &Manifest {
|
||||
}
|
||||
}
|
||||
|
||||
/// Download an artifact and create a [RepoArtifact]
|
||||
async fn load_artifact_url(url: &str) -> Result<RepoArtifact> {
|
||||
|
||||
info!("Downloading artifact {}", url);
|
||||
let u = Url::parse(url)?;
|
||||
let rsp = reqwest::get(u.clone()).await?;
|
||||
let id = hex::encode(sha2::Sha256::digest(url.as_bytes()));
|
||||
let mut tmp = temp_dir().join(id);
|
||||
tmp.set_extension(
|
||||
PathBuf::from(u.path())
|
||||
.extension()
|
||||
.ok_or(anyhow!("Missing extension in URL"))?
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
);
|
||||
if !tmp.exists() {
|
||||
let mut tmp_file = File::create(&tmp).await?;
|
||||
let mut rsp_stream = rsp.bytes_stream();
|
||||
while let Some(data) = rsp_stream.next().await {
|
||||
if let Ok(data) = data {
|
||||
tmp_file.write_all(&data).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
load_artifact(&tmp).await
|
||||
}
|
||||
|
||||
async fn load_artifact(path: &Path) -> Result<RepoArtifact> {
|
||||
match path
|
||||
.extension()
|
||||
.ok_or(anyhow!("missing file extension"))?
|
||||
.to_str()
|
||||
.unwrap()
|
||||
{
|
||||
"apk" => load_apk_artifact(path).await,
|
||||
_ => bail!("unknown file extension"),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
async fn load_apk_artifact(path: &Path) -> Result<RepoArtifact> {
|
||||
let file = File::open(path).await?;
|
||||
|
||||
let mut zip = ZipFileReader::with_tokio(BufReader::new(file)).await?;
|
||||
|
||||
const ANDROID_MANIFEST: &'static str = "AndroidManifest.xml";
|
||||
|
||||
let idx = zip
|
||||
.file()
|
||||
.entries()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(i, entry)| {
|
||||
if entry.filename().as_bytes() == ANDROID_MANIFEST.as_bytes() {
|
||||
Some(i)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.ok_or(anyhow!("missing AndroidManifest file"))?;
|
||||
let mut manifest = zip.reader_with_entry(idx).await?;
|
||||
let mut manifest_data = String::with_capacity(8192);
|
||||
manifest.read_to_string_checked(&mut manifest_data).await?;
|
||||
info!("Successfully loaded AndroidManifest: {}", &manifest_data);
|
||||
let manifest: AndroidManifest = quick_xml::de::from_str(&manifest_data)?;
|
||||
|
||||
Ok(RepoArtifact {
|
||||
name: path.file_name().unwrap().to_str().unwrap().to_string(),
|
||||
size: path.metadata()?.len(),
|
||||
location: RepoResource::Local(path.to_path_buf()),
|
||||
content_type: "application/apk".to_string(),
|
||||
platform: Platform::Android {
|
||||
arch: Architecture::ARMv8,
|
||||
},
|
||||
metadata: ArtifactMetadata::APK { manifest },
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user