Skip to content

Commit

Permalink
feat: 支持自动纠正大小写
Browse files Browse the repository at this point in the history
  • Loading branch information
Cnotech committed May 5, 2024
1 parent 5405b01 commit e607368
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 104 deletions.
48 changes: 24 additions & 24 deletions examples/CallInstaller/package.toml
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
# nep 版本号
nep = "0.2"

[package]
# 包名
name = "CallInstaller"
# 包模板 仅可取 "Software"
template = "Software"
# 版本号
version = "1.75.0.0"
# 打包者/作者
authors = ["Cno <[email protected]>","Microsoft"]
# 许可证缩写或链接(可选)
license = "MIT"
description = "Visual Studio Code"

[software]
scope = "Microsoft"
# 上游发布页面 URL
upstream = "https://code.visualstudio.com/"
# 软件分类
category = "办公编辑"
tags = ["Electron"]
language = "Multi"
# nep 版本号
nep = "0.2"

[package]
# 包名
name = "CallInstaller"
# 包模板 仅可取 "Software"
template = "Software"
# 版本号
version = "1.75.0.0"
# 打包者/作者
authors = ["Cno <[email protected]>","Microsoft"]
# 许可证缩写或链接(可选)
license = "MIT"
description = "Visual Studio Code"

[software]
scope = "Microsoft"
# 上游发布页面 URL
upstream = "https://code.visualstudio.com/"
# 软件分类
category = "办公编辑"
tags = ["Electron"]
language = "Multi"
main_program = "${Desktop}/Call.exe"
14 changes: 5 additions & 9 deletions src/entrances/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,8 @@ pub fn info_online(
}

pub fn info(scope: Option<String>, package_name: &String) -> Result<Info> {
// 查找 scope
let scope = if let Some(s) = scope {
s
} else {
find_scope_with_name(package_name)?
};
// 查找 scope 并使用 scope 更新纠正大小写
let (scope, package_name) = find_scope_with_name(package_name, scope)?;

// 创建结果结构体
let mut info = Info {
Expand All @@ -98,16 +94,16 @@ pub fn info(scope: Option<String>, package_name: &String) -> Result<Info> {
};

// 扫描本地安装目录
let local_path = get_path_apps(&scope, package_name, false)?;
let local_path = get_path_apps(&scope, &package_name, false)?;
if local_path.exists() {
let (global, local) = info_local(&scope, package_name)?;
let (global, local) = info_local(&scope, &package_name)?;
info.license = global.package.license;
info.local = Some(local);
info.software = global.software;
}

// 在线检查
if let Ok((item, _)) = info_online(&scope, package_name, None) {
if let Ok((item, _)) = info_online(&scope, &package_name, None) {
let latest = filter_release(item.releases, None)?;
info.online = Some(InfoDiff {
version: latest.version.to_string(),
Expand Down
12 changes: 4 additions & 8 deletions src/entrances/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,13 @@ pub fn install_using_package_matcher(
matcher: PackageMatcher,
verify_signature: bool,
) -> Result<()> {
// 查找 scope
let scope = if let Some(s) = matcher.scope.clone() {
s
} else {
find_scope_with_name(&matcher.name)?
};
// 查找 scope 并使用 scope 更新纠正大小写
let (scope, package_name) = find_scope_with_name(&matcher.name, matcher.scope.clone())?;
// 检查对应包名有没有被安装过
if let Ok((_, diff)) = info_local(&scope, &matcher.name) {
if let Ok((_, diff)) = info_local(&scope, &package_name) {
log!(
"Warning:Package '{name}' has been installed({ver}), switch to update entrance",
name = matcher.name,
name = package_name,
ver = diff.version,
);
update_using_package_matcher(matcher, verify_signature)?;
Expand Down
61 changes: 42 additions & 19 deletions src/entrances/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
p2s,
parsers::parse_workflow,
types::{
matcher::PackageInputEnum,
meta::MetaResult,
package::GlobalPackage,
permissions::{Generalizable, Permission, PermissionKey, PermissionLevel},
Expand All @@ -23,31 +24,39 @@ use super::{

// 返回 (临时目录,工作流所在目录,全局包)
fn find_meta_target(
input: &String,
input: PackageInputEnum,
verify_signature: bool,
) -> Result<(PathBuf, PathBuf, GlobalPackage)> {
// 作为路径使用,可以是一个包或者已经解包的目录
let p = Path::new(input);
if p.exists() {
let (path, pkg) = unpack_nep(input, verify_signature)?;
verify(&p2s!(path))?;
return Ok((path.clone(), path.join("workflows"), pkg));
}

// 作为名称使用,在本地已安装列表中搜索
if let Ok(scope) = find_scope_with_name(input) {
let path = get_path_apps(&scope, input, false)?;
let (pkg, _) = info_local(&scope, input)?;
installed_validator(&p2s!(path))?;
return Ok((path.clone(), path.join(".nep_context/workflows"), pkg));
match input {
PackageInputEnum::LocalPath(local_path) => {
// 作为路径使用,可以是一个包或者已经解包的目录
let p = Path::new(&local_path);
if p.exists() {
let (path, pkg) = unpack_nep(&local_path, verify_signature)?;
verify(&p2s!(path))?;
return Ok((path.clone(), path.join("workflows"), pkg));
}
}
PackageInputEnum::PackageMatcher(matcher) => {
// 作为名称使用,在本地已安装列表中搜索
if let Ok((scope, package_name)) = find_scope_with_name(&matcher.name, matcher.scope) {
let path = get_path_apps(&scope, &package_name, false)?;
let (pkg, _) = info_local(&scope, &package_name)?;
installed_validator(&p2s!(path))?;
return Ok((path.clone(), path.join(".nep_context/workflows"), pkg));
}
}
PackageInputEnum::Url(_) => {
return Err(anyhow!("Error:URL is not acceptable"));
}
}

Err(anyhow!(
"Error:Failed to find meta by '{input}', input valid path or installed package name"
"Error:Failed to find meta by input, input valid path or installed package matcher"
))
}

pub fn meta(input: &String, verify_signature: bool) -> Result<MetaResult> {
pub fn meta(input: PackageInputEnum, verify_signature: bool) -> Result<MetaResult> {
// 解包
let (temp_dir_inner_path, workflow_path, global) = find_meta_target(input, verify_signature)?;
let temp_dir = p2s!(temp_dir_inner_path);
Expand Down Expand Up @@ -114,8 +123,13 @@ pub fn meta(input: &String, verify_signature: bool) -> Result<MetaResult> {

#[test]
fn test_meta() {
use crate::types::matcher::PackageMatcher;
envmnt::set("CONFIRM", "true");
let res = meta(&"examples/PermissionsTest".to_string(), false).unwrap();
let res = meta(
PackageInputEnum::LocalPath("examples/PermissionsTest".to_string()),
false,
)
.unwrap();
let mut sorted_permissions: Vec<Permission> = res
.permissions
.into_iter()
Expand Down Expand Up @@ -210,6 +224,15 @@ fn test_meta() {

// 从本地安装中生成 meta
crate::utils::test::_ensure_testing_vscode();
meta(&"VSCode".to_string(), false).unwrap();
meta(
PackageInputEnum::PackageMatcher(PackageMatcher {
name: "VSCode".to_string(),
scope: None,
mirror: None,
version_req: None,
}),
false,
)
.unwrap();
crate::utils::test::_ensure_testing_vscode_uninstalled();
}
10 changes: 3 additions & 7 deletions src/entrances/uninstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,11 @@ fn get_manifest(flow: Vec<WorkflowNode>) -> Vec<String> {
pub fn uninstall(scope: Option<String>, package_name: &String) -> Result<()> {
log!("Info:Preparing to uninstall '{package_name}'");

// 解析 scope
let scope = if let Some(s) = scope {
s
} else {
find_scope_with_name(package_name)?
};
// 查找 scope 并使用 scope 更新纠正大小写
let (scope, package_name) = find_scope_with_name(package_name, scope)?;

// 解析安装路径
let app_path = get_path_apps(&scope, package_name, false)?;
let app_path = get_path_apps(&scope, &package_name, false)?;
if !app_path.exists() {
return Err(anyhow!("Error:Can't find package '{package_name}'"));
}
Expand Down
16 changes: 6 additions & 10 deletions src/entrances/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,24 +156,20 @@ pub fn update_using_package_matcher(
matcher: PackageMatcher,
verify_signature: bool,
) -> Result<(String, String)> {
// 查找 scope
let scope = if let Some(s) = matcher.scope.clone() {
s
} else {
find_scope_with_name(&matcher.name)?
};
// 查找 scope 并使用 scope 更新纠正大小写
let (scope, package_name) = find_scope_with_name(&matcher.name, matcher.scope.clone())?;
// 检查对应包名有没有被安装过
let (_global, local_diff) = info_local(&scope, &matcher.name).map_err(|_| {
let (_global, local_diff) = info_local(&scope, &package_name).map_err(|_| {
anyhow!(
"Error:Package '{name}' hasn't been installed, use 'ept install \"{name}\"' instead",
name = &matcher.name,
name = package_name
)
})?;
// 检查包的版本号是否允许升级
let (online_item, _url_template) = info_online(&scope, &matcher.name, matcher.mirror.clone())?;
let (online_item, _url_template) = info_online(&scope, &package_name, matcher.mirror.clone())?;
let selected_release = filter_release(online_item.releases, matcher.version_req.clone())?;
if selected_release.version <= ExSemVer::parse(&local_diff.version)? {
return Err(anyhow!("Error:Package '{name}' has been up to date ({local_version}), can't update to the version of given package ({fresh_version})",name=matcher.name,local_version=&local_diff.version,fresh_version=&selected_release.version));
return Err(anyhow!("Error:Package '{name}' has been up to date ({local_version}), can't update to the version of given package ({fresh_version})",name=package_name,local_version=&local_diff.version,fresh_version=&selected_release.version));
}
// 解析 url
let url = get_url_with_version_req(matcher)?;
Expand Down
8 changes: 3 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,9 @@ fn router(action: Action) -> Result<String> {
into_file,
} => pack(&source_dir, into_file, verify_signature)
.map(|location| format!("Success:Package has been stored at '{location}'")),
Action::Meta {
source_package,
save_at,
} => {
let res = meta(&source_package, verify_signature)?;
Action::Meta { package, save_at } => {
let package_input_enum = PackageInputEnum::parse(package, true, true)?;
let res = meta(package_input_enum, verify_signature)?;
let text = serde_json::to_string_pretty(&res)
.map_err(|e| anyhow!("Error:Failed to deserialize result : {e}"))?;
if let Some(into) = save_at {
Expand Down
4 changes: 2 additions & 2 deletions src/types/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ pub enum Action {

/// Get meta data of given package
Meta {
/// Source package
source_package: String,
/// Package matcher, expect pattern (SCOPE/)NAME or Nep package local path
package: String,
/// (Optional) Save meta report at
save_at: Option<String>,
},
Expand Down
10 changes: 3 additions & 7 deletions src/utils/mirror.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,10 @@ pub fn filter_release(

// 通过匹配 VersionReq 解析出包的 url
pub fn get_url_with_version_req(matcher: PackageMatcher) -> Result<String> {
// 查找 scope
let scope = if let Some(s) = matcher.scope {
s
} else {
find_scope_with_name(&matcher.name)?
};
// 查找 scope 并使用 scope 更新纠正大小写
let (scope, package_name) = find_scope_with_name(&matcher.name, matcher.scope)?;
// 拿到 info online
let (info, url_template) = info_online(&scope, &matcher.name, matcher.mirror)?;
let (info, url_template) = info_online(&scope, &package_name, matcher.mirror)?;
// 匹配版本
let matched_release = filter_release(info.releases, matcher.version_req)?;
// 填充模板获取 url
Expand Down
32 changes: 21 additions & 11 deletions src/utils/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,41 +61,51 @@ pub fn parse_relative_path_with_located(relative: &String, located: &String) ->
}

/// name 大小写不敏感
fn find_scope_with_name_locally(name: &String) -> Result<String> {
fn find_scope_with_name_locally(name: &String, scope: Option<String>) -> Result<(String, String)> {
let scope_input_str = scope.clone().unwrap_or("".to_string());
let app_dir = get_bare_apps()?;
for scope in read_sub_dir(app_dir.clone())? {
for dir_name in read_sub_dir(app_dir.join(&scope))? {

for scope_dir_name in read_sub_dir(app_dir.clone())? {
if scope.is_some() && scope_dir_name.to_lowercase() != scope_input_str.to_lowercase() {
continue;
}
for dir_name in read_sub_dir(app_dir.join(&scope_dir_name))? {
if dir_name.to_ascii_lowercase() == name.to_ascii_lowercase() {
return Ok(scope);
return Ok((scope_dir_name, dir_name));
}
}
}

Err(anyhow!("Error:Can't find scope for '{name}'"))
}

fn find_scope_with_name_online(name: &String) -> Result<String> {
fn find_scope_with_name_online(name: &String, scope: Option<String>) -> Result<(String, String)> {
let scope_input_str = scope.clone().unwrap_or("".to_string());
// 遍历 mirrors
let p = get_path_mirror()?;
let mirror_names = read_sub_dir(&p)?;
for mirror_name in mirror_names {
let pkg_software = read_local_mirror_pkg_software(&mirror_name)?;
for (scope, tree) in pkg_software.tree {
for (scope_real_name, tree) in pkg_software.tree {
if scope.is_some() && scope_real_name.to_lowercase() != scope_input_str.to_lowercase() {
continue;
}
for node in tree {
if &node.name == name {
return Ok(scope);
if node.name.to_lowercase() == name.to_lowercase() {
return Ok((scope_real_name, node.name));
}
}
}
}
Err(anyhow!("Error:Can't find scope for '{name}'"))
}

pub fn find_scope_with_name(name: &String) -> Result<String> {
let local_res = find_scope_with_name_locally(name);
pub fn find_scope_with_name(name: &String, scope: Option<String>) -> Result<(String, String)> {
let local_res = find_scope_with_name_locally(name, scope.clone());
if local_res.is_ok() {
return local_res;
}
find_scope_with_name_online(name)
find_scope_with_name_online(name, scope)
}

#[test]
Expand Down
Loading

0 comments on commit e607368

Please sign in to comment.