From def9e494122a79440ac53bdcc2326a56179f73da Mon Sep 17 00:00:00 2001 From: DragonBillow Date: Sun, 3 Mar 2024 15:51:45 +0800 Subject: [PATCH] fix: fix version with target_platform close #18 Signed-off-by: DragonBillow --- .../gallery_extension/extension_version.rs | 2 +- src/dump.rs | 44 ++--- src/jinja.rs | 21 ++- src/jinja/context.rs | 2 +- src/jinja/filters.rs | 31 +++- src/jinja/template/nix_expression.nix.j2 | 71 ++++++++ src/main.rs | 158 ++++++++---------- 7 files changed, 218 insertions(+), 111 deletions(-) diff --git a/src/data_struct/gallery_extension/extension_version.rs b/src/data_struct/gallery_extension/extension_version.rs index f5bec5e..d7c6e11 100644 --- a/src/data_struct/gallery_extension/extension_version.rs +++ b/src/data_struct/gallery_extension/extension_version.rs @@ -14,7 +14,7 @@ pub struct IRawGalleryExtensionVersion { pub fallback_asset_uri: String, pub files: Vec, pub properties: Vec, - pub target_platform: String, + pub target_platform: Option, } impl Display for IRawGalleryExtensionVersion { diff --git a/src/dump.rs b/src/dump.rs index cd12607..c94f53b 100644 --- a/src/dump.rs +++ b/src/dump.rs @@ -69,6 +69,7 @@ pub async fn dump<'a>( .into_iter() .flat_map(|item| item.extensions.into_iter()) .map(|item| async move { + let mut res = vec![]; for version in &item.versions { match version.get_engine() { Ok(ver) => { @@ -121,30 +122,35 @@ pub async fn dump<'a>( Ok(sha256) => sha256, Err(err) => { error!("{err}"); - return None; + return vec![]; } }; - return Some(NixContext { - extension_name: item.extension_name.clone(), - publisher_name: item.publisher.publisher_name.clone(), - extension_version: version.version.clone(), - asset_url: if has_asset_url { - Some(asset_url.clone()) - } else { - None - }, - sha256, - target_platform: client - .get_extension_target_platform( - item.publisher.publisher_name, - item.extension_name, - ) - .await, - }); + let v: Vec<_> = client + .get_extension_target_platform( + item.publisher.publisher_name.clone(), + item.extension_name.clone(), + ) + .await + .into_iter() + .map(|target_platform| NixContext { + extension_name: item.extension_name.clone(), + publisher_name: item.publisher.publisher_name.clone(), + extension_version: version.version.clone(), + asset_url: if has_asset_url { + Some(asset_url.clone()) + } else { + None + }, + sha256: sha256.clone(), + target_platform, + }) + .collect(); + + res.extend(v.into_iter()); } - None + res }), ); } diff --git a/src/jinja.rs b/src/jinja.rs index 53c82c5..8ebc9a3 100644 --- a/src/jinja.rs +++ b/src/jinja.rs @@ -22,6 +22,18 @@ impl Generator<'_> { ("codelldb", include_str!("./jinja/template/codelldb.j2")); } +macro_rules! add_filter { + ($jinja:ident, $ty:expr) => { + $jinja.add_filter(stringify!($ty), $ty); + }; +} + +macro_rules! add_function { + ($jinja:ident, $ty:expr) => { + $jinja.add_function(stringify!($ty), $ty); + }; +} + impl<'a> Generator<'a> { pub fn new() -> Self { let mut engine = Environment::new(); @@ -30,8 +42,13 @@ impl<'a> Generator<'a> { .add_template(Self::NIX_EXPRESSION.0, Self::NIX_EXPRESSION.1) .unwrap(); - engine.add_filter("nixfmt", nixfmt); - engine.add_filter("to_string", to_string); + add_filter!(engine, nixfmt); + add_filter!(engine, to_string); + add_function!(engine, is_universal); + add_function!(engine, is_linux_x86); + add_function!(engine, is_linux_arm); + add_function!(engine, is_darwin_x86); + add_function!(engine, is_darwin_arm); Self { engine } } diff --git a/src/jinja/context.rs b/src/jinja/context.rs index 3caa9f4..34c7c2c 100644 --- a/src/jinja/context.rs +++ b/src/jinja/context.rs @@ -21,5 +21,5 @@ pub struct NixContext { pub extension_version: String, pub asset_url: Option, pub sha256: String, - pub target_platform: Vec, + pub target_platform: TargetPlatform, } diff --git a/src/jinja/filters.rs b/src/jinja/filters.rs index 1f508bf..cc031e7 100644 --- a/src/jinja/filters.rs +++ b/src/jinja/filters.rs @@ -1,6 +1,8 @@ -use minijinja::Value; +use minijinja::{value::ViaDeserialize, Value}; use nixpkgs_fmt::reformat_string; +use crate::data_struct::TargetPlatform; + pub fn nixfmt(value: &str) -> String { reformat_string(value) } @@ -8,3 +10,30 @@ pub fn nixfmt(value: &str) -> String { pub fn to_string(value: Value) -> String { format!(r#""{value}""#) } + +pub fn is_universal(target_platform: String) -> bool { + let target_platform: TargetPlatform = target_platform.as_str().into(); + matches!( + target_platform, + TargetPlatform::Universal | TargetPlatform::Web + ) +} + +pub fn is_linux_x86(target_platform: String) -> bool { + let target_platform: TargetPlatform = target_platform.as_str().into(); + matches!(target_platform, TargetPlatform::LinuxX64) +} + +pub fn is_linux_arm(target_platform: String) -> bool { + let target_platform: TargetPlatform = target_platform.as_str().into(); + matches!(target_platform, TargetPlatform::LinuxArm64) +} +pub fn is_darwin_x86(target_platform: String) -> bool { + let target_platform: TargetPlatform = target_platform.as_str().into(); + matches!(target_platform, TargetPlatform::DarwinX64) +} + +pub fn is_darwin_arm(target_platform: String) -> bool { + let target_platform: TargetPlatform = target_platform.as_str().into(); + matches!(target_platform, TargetPlatform::DarwinArm64) +} diff --git a/src/jinja/template/nix_expression.nix.j2 b/src/jinja/template/nix_expression.nix.j2 index 2cc49ba..c8cacf0 100644 --- a/src/jinja/template/nix_expression.nix.j2 +++ b/src/jinja/template/nix_expression.nix.j2 @@ -5,6 +5,7 @@ { pkgs, lib }: let + inherit (pkgs.stdenv) isDarwin isLinux isi686 isx86_64 isAarch32 isAarch64; vscode-utils = pkgs.vscode-utils; in { @@ -30,12 +31,82 @@ in {%- for item in extensions %} {%- if item.asset_url == None %} {%- with uniqueId = [ item.publisher_name | to_string, '.', item.extension_name | to_string ] | join %} + {%- if is_universal(item.target_platform) %} {{ uniqueId }} = vscode-utils.extensionFromVscodeMarketplace { name = "{{ item.extension_name }}"; publisher = "{{ item.publisher_name }}"; version = "{{ item.extension_version }}"; sha256 = "{{ item.sha256 }}"; }; + {%- endif %} + {%- endwith %} + {%- endif %} + {%- endfor %} +}// +lib.attrsets.optionalAttrs(isLinux && (isi686 || isx86_64) ){ + {%- for item in extensions %} + {%- if item.asset_url == None %} + {%- with uniqueId = [ item.publisher_name | to_string, '.', item.extension_name | to_string ] | join %} + {%- if is_linux_x86(item.target_platform) %} + {{ uniqueId }} = vscode-utils.extensionFromVscodeMarketplace { + name = "{{ item.extension_name }}"; + publisher = "{{ item.publisher_name }}"; + version = "{{ item.extension_version }}"; + sha256 = "{{ item.sha256 }}"; + arch = "linux-x64"; + }; + {%- endif %} + {%- endwith %} + {%- endif %} + {%- endfor %} +}// +lib.attrsets.optionalAttrs(isLinux && (isAarch32 || isAarch64) ){ + {%- for item in extensions %} + {%- if item.asset_url == None %} + {%- with uniqueId = [ item.publisher_name | to_string, '.', item.extension_name | to_string ] | join %} + {%- if is_linux_arm(item.target_platform) %} + {{ uniqueId }} = vscode-utils.extensionFromVscodeMarketplace { + name = "{{ item.extension_name }}"; + publisher = "{{ item.publisher_name }}"; + version = "{{ item.extension_version }}"; + sha256 = "{{ item.sha256 }}"; + arch = "linux-arm64"; + }; + {%- endif %} + {%- endwith %} + {%- endif %} + {%- endfor %} +}// +lib.attrsets.optionalAttrs(isDarwin && (isi686 || isx86_64) ){ + {%- for item in extensions %} + {%- if item.asset_url == None %} + {%- with uniqueId = [ item.publisher_name | to_string, '.', item.extension_name | to_string ] | join %} + {%- if is_darwin_x86(item.target_platform) %} + {{ uniqueId }} = vscode-utils.extensionFromVscodeMarketplace { + name = "{{ item.extension_name }}"; + publisher = "{{ item.publisher_name }}"; + version = "{{ item.extension_version }}"; + sha256 = "{{ item.sha256 }}"; + arch = "darwin-x64"; + }; + {%- endif %} + {%- endwith %} + {%- endif %} + {%- endfor %} +}// +lib.attrsets.optionalAttrs(isDarwin && (isAarch32 || isAarch64) ){ + {%- for item in extensions %} + {%- if item.asset_url == None %} + {%- with uniqueId = [ item.publisher_name | to_string, '.', item.extension_name | to_string ] | join %} + {%- if is_darwin_arm(item.target_platform) %} + {{ uniqueId }} = vscode-utils.extensionFromVscodeMarketplace { + name = "{{ item.extension_name }}"; + publisher = "{{ item.publisher_name }}"; + version = "{{ item.extension_version }}"; + sha256 = "{{ item.sha256 }}"; + arch = "darwin-arm64"; + }; + {%- endif %} {%- endwith %} {%- endif %} {%- endfor %} diff --git a/src/main.rs b/src/main.rs index af5cb28..2e57954 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,7 @@ use clap::Parser; use config::Config; use crate::{ - data_struct::AssetType, + data_struct::{AssetType, TargetPlatform}, jinja::{AssetUrlContext, Generator, GeneratorContext, NixContext}, request::HttpClient, }; @@ -50,23 +50,41 @@ async fn get_matched_versoin( client: HttpClient, config: Arc, generator: Generator<'_>, -) -> Option { - for version in &item.versions { - match version.get_engine() { +) -> Vec { + let mx = item + .versions + .iter() + .filter(|v| match v.get_engine() { Ok(ver) => { if !ver.matches(&vscode_ver) { - continue; + trace!("{ver} doesn't match {vscode_ver}"); + return false; } + true } Err(_) => { warn!( "Cannot get engine version for {}.{} {}", - item.publisher.publisher_name, item.extension_name, version + item.publisher.publisher_name, item.extension_name, v ); - trace!("{version:#?}"); + trace!("{v:#?}"); + false + } + }) + .max_by(|a, b| a.version.cmp(&b.version)) + .map(|item| item.version.clone()); + + trace!(?mx); + + let mut res = vec![]; + for version in &item.versions { + if let Some(mx) = mx.as_ref() { + if mx != &version.version { continue; } } + trace!("{:?}", version.version); + let (has_asset_url, asset_url) = match config .get_asset_url(&item.publisher.publisher_name, &item.extension_name) { @@ -95,27 +113,54 @@ async fn get_matched_versoin( let sha256 = match utils::get_sha256(&asset_url).await { Ok(sha256) => sha256, Err(err) => { - error!("{err}"); - return None; + error!("get sha256 failed: {err}"); + continue; } }; - return Some(NixContext { - extension_name: item.extension_name.to_lowercase(), - publisher_name: item.publisher.publisher_name.to_lowercase(), - extension_version: version.version.clone(), - asset_url: if has_asset_url { - Some(asset_url.clone()) - } else { - None - }, - sha256, - target_platform: client - .get_extension_target_platform(item.publisher.publisher_name, item.extension_name) - .await, - }); + let target_platform = match version.target_platform { + Some(ref t) => vec![t.as_str().into()], + None => { + client + .get_extension_target_platform( + item.publisher.publisher_name.clone(), + item.extension_name.clone(), + ) + .await + } + }; + trace!(?target_platform); + + let a = target_platform + .into_iter() + .filter(|item| { + matches!( + *item, + TargetPlatform::LinuxX64 + | TargetPlatform::LinuxArm64 + | TargetPlatform::Universal + | TargetPlatform::Web + | TargetPlatform::DarwinX64 + | TargetPlatform::DarwinArm64 + ) + }) + .map(|target_platform| NixContext { + extension_name: item.extension_name.to_lowercase(), + publisher_name: item.publisher.publisher_name.to_lowercase(), + extension_version: version.version.clone(), + asset_url: if has_asset_url { + Some(asset_url.clone()) + } else { + None + }, + sha256: sha256.clone(), + target_platform, + }); + + res.extend(a); } - None + + res } #[tokio::main] @@ -130,69 +175,7 @@ async fn main() -> anyhow::Result<()> { let vscode_ver = semver::Version::from_str(&config.vscode_version).unwrap(); let mut generator = Generator::new(); - let res: Vec<_> = if args.openvsx { - let vsx_config = Configuration::default(); - - let res: Vec<_> = config - .extensions - .iter() - .map(|item| { - let vscode_ver = vscode_ver.clone(); - let vsx_config = vsx_config.clone(); - let client = vsx_config.client.clone(); - async move { - openvsx_ext::get_matched_version_of( - &vsx_config, - &item.publisher_name, - &item.extension_name, - &vscode_ver, - ) - .await - .into_iter() - .map(move |ver| { - let publisher_name = item.publisher_name.clone(); - let extension_name = item.extension_name.clone(); - let client = client.clone(); - async move { - ( - publisher_name, - extension_name, - client - .get( - ver.clone() - .files - .unwrap() - .get("sha256") - .unwrap() - .to_string(), - ) - .send() - .await - .unwrap() - .text() - .await - .unwrap(), - ver, - ) - } - }) - } - }) - .collect(); - - join_all(join_all(res).await.into_iter().flatten()) - .await - .into_iter() - .map(|item| NixContext { - extension_name: item.1, - publisher_name: item.0, - extension_version: item.3.version.unwrap(), - asset_url: item.3.files.clone().unwrap().get("download").cloned(), - sha256: item.2, - target_platform: vec![item.3.target_platform.unwrap().as_str().into()], - }) - .collect() - } else { + let res: Vec<_> = { if args.dump { let res = dump::dump(&client, &vscode_ver, &config, &generator).await; debug!("find dump of vscode marketplace: \n{res:#?}"); @@ -237,6 +220,7 @@ async fn main() -> anyhow::Result<()> { join_all(futures).await.into_iter().flatten().collect() }; + debug!("{res:#?}"); if args.export { let res = serde_json::to_string(&res).unwrap();