Skip to content

Commit

Permalink
doc: 添加校验规则
Browse files Browse the repository at this point in the history
  • Loading branch information
Cnotech committed Nov 11, 2023
1 parent 5f31775 commit e22e0e7
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 36 deletions.
47 changes: 43 additions & 4 deletions doc/nep/definition/4-steps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ import { Tag } from "../../components/tag.tsx"
# 绝对路径通配符写法
from = "${SystemDrive}/Windows/system32/*.dll"
```
* 校验规则:
* 是合法路径
* 符合通配符用法
#### to
目标路径,支持相对路径和绝对路径。
* 类型:`String`
* 示例:`to = "./config"`
* 校验规则:
* 是合法路径
#### overwrite
<Tag>可选</Tag> 是否覆盖,缺省为 `false`
* 类型:`bool`
Expand All @@ -41,6 +46,9 @@ import { Tag } from "../../components/tag.tsx"
# 绝对路径通配符写法
at = "${AppData}/vscode/*.txt"
```
* 校验规则:
* 是合法路径
* 符合通配符用法
#### force
<Tag>可选</Tag> 是否强制删除,缺省为 `false`
* 类型:`bool`
Expand All @@ -52,10 +60,15 @@ import { Tag } from "../../components/tag.tsx"
需要执行的命令,使用终端为 cmd。
* 类型:`String`
* 示例:`command = "./installer.exe /S"`
* 校验规则:
* 是有效的 POSIX 命令
* 不得出现绝对路径(使用[内置变量](/nep/workflow/2-context.html#内置变量)
#### pwd
<Tag>可选</Tag> 执行目录,缺省为包安装目录。
* 类型:`String`
* 示例:`pwd = "${AppData}/Microsoft"`
* 校验规则:
* 是合法路径
#### call_installer
<Tag>可选</Tag> 当前命令的语义是否为正在调用安装器,缺省为 `false`;请务必正确指定此项,因为这会影响包权限、工作流静态检查等行为。
* 类型:`bool`
Expand All @@ -75,16 +88,20 @@ import { Tag } from "../../components/tag.tsx"
杀死某个进程。
### 字段
#### target
进程名称,大小写敏感且必须以 `.exe` 结尾
进程名称,注意大小写敏感
* 类型:`String`
* 示例:`target = "code.exe"`
* 示例:`target = "code.exe"`
* 校验规则:
*`.exe` 结尾
## Link
创建快捷方式。
### 字段
#### source_file
源文件路径,支持相对路径和绝对路径。
* 类型:`String`
* 示例:`source_file = "code.exe"`
* 校验规则:
* 是合法路径
#### target_name
<Tag>可选</Tag> 快捷方式名称,支持使用 `FOLDER/NAME` 的模式表示在创建位置的文件夾中放置快捷方式。
* 类型:`String`
Expand All @@ -96,6 +113,10 @@ import { Tag } from "../../components/tag.tsx"
# 在文件夹中创建快捷方式
target_name = "Microsoft/Visual Studio Code"
```
* 校验规则:
* 符合模式 `NAME``FOLDER/NAME`
* 不包含 `..`
* 不以 `.lnk` 结尾
#### target_args
<Tag>可选</Tag> 快捷方式的启动参数。
* 类型:`String`
Expand Down Expand Up @@ -137,10 +158,15 @@ import { Tag } from "../../components/tag.tsx"
# 绝对路径通配符写法
from = "${Desktop}/Visual Studio Code.lnk"
```
* 校验规则:
* 是合法路径
* 符合通配符用法
#### to
目标路径,支持相对路径和绝对路径。
* 类型:`String`
* 示例:`to = "./bin"`
* 校验规则:
* 是合法路径
#### overwrite
<Tag>可选</Tag> 是否覆盖,缺省为 `false`
* 类型:`bool`
Expand All @@ -159,6 +185,8 @@ import { Tag } from "../../components/tag.tsx"
# 创建文件夹
at = "${Desktop}/Microsoft/"
```
* 校验规则:
* 是合法路径
#### overwrite
<Tag>可选</Tag> 是否覆盖,缺省为 false。
* 类型:`bool`
Expand All @@ -179,6 +207,8 @@ import { Tag } from "../../components/tag.tsx"
# 添加文件夹到 PATH 变量
record = "./bin"
```
* 校验规则:
* 是合法路径
#### alias
<Tag>可选</Tag> 别名,仅对可执行文件生效,缺省为原文件名。
* 类型:`String`
Expand All @@ -192,10 +222,15 @@ import { Tag } from "../../components/tag.tsx"
目标路径,支持相对路径和绝对路径。
* 类型:`String`
* 示例:`from = "./config.toml.example"`
* 校验规则:
* 是合法路径
* 不包含通配符
#### to
新的名称。
* 类型:`String`
* 示例:`to = "config.toml"`
* 示例:`to = "config.toml"`
* 校验规则:
* 是合法的文件名或文件夹名而非路径
## Toast
弹出消息通知。
### 字段
Expand All @@ -214,7 +249,11 @@ import { Tag } from "../../components/tag.tsx"
等待的时长,单位为 ms。
* 类型:`u64`
* 示例:`timeout = "3000"`
* 校验规则:
* 不超过 30min(1800000ms)
#### break_if
<Tag>可选</Tag> 若满足指定条件则提前结束等待,该条件会在等待过程中每 500ms 检查一次。
* 类型:`String`
* 示例:`break_if = 'Exist("${Desktop}/Visual Studio Code.lnk")'`
* 示例:`break_if = 'Exist("${Desktop}/Visual Studio Code.lnk")'`
* 校验规则:
* 是合法的条件
2 changes: 1 addition & 1 deletion scripts/step/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function fieldRenderer(
: "";
const demoText = field.demo ? `\n* 示例:${field.demo}` : "";
const rulesText = field.rules?.length
? "\n" + field.rules.map((rule) => `* ${rule}`).join("\n")
? "\n* 校验规则:\n" + field.rules.map((rule) => ` * ${rule}`).join("\n")
: "";
return `${"#".repeat(titleLevel)} ${field.name}
${field.type.optional ? "<Tag>可选</Tag> " : ""}${field.wiki ?? ""}
Expand Down
3 changes: 3 additions & 0 deletions src/types/steps/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ pub struct StepCopy {
//# # 绝对路径通配符写法
//# from = "${SystemDrive}/Windows/system32/*.dll"
//# ```
//@ 是合法路径
//@ 符合通配符用法
pub from: String,
/// 目标路径,支持相对路径和绝对路径。
//# `to = "./config"`
//@ 是合法路径
pub to: String,
/// 是否覆盖,缺省为 `false`。
//# `overwrite = true`
Expand Down
2 changes: 2 additions & 0 deletions src/types/steps/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub struct StepDelete {
//# # 绝对路径通配符写法
//# at = "${AppData}/vscode/*.txt"
//# ```
//@ 是合法路径
//@ 符合通配符用法
pub at: String,
/// 是否强制删除,缺省为 `false`。
//# `force = "true"`
Expand Down
53 changes: 23 additions & 30 deletions src/types/steps/execute.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::executor::{values_replacer, values_validator_path};
use crate::types::interpretable::Interpretable;
use crate::types::mixed_fs::MixedFS;
use crate::types::permissions::{Generalizable, Permission, PermissionKey, PermissionLevel};
Expand All @@ -19,9 +20,12 @@ use std::time::Instant;
pub struct StepExecute {
/// 需要执行的命令,使用终端为 cmd。
//# `command = "./installer.exe /S"`
//@ 是有效的 POSIX 命令
//@ 不得出现绝对路径(使用[内置变量](/nep/workflow/2-context.html#内置变量))
pub command: String,
/// 执行目录,缺省为包安装目录。
//# `pwd = "${AppData}/Microsoft"`
//@ 是合法路径
pub pwd: Option<String>,
/// 当前命令的语义是否为正在调用安装器,缺省为 `false`;请务必正确指定此项,因为这会影响包权限、工作流静态检查等行为。
//# `call_installer = true`
Expand Down Expand Up @@ -58,8 +62,11 @@ impl TStep for StepExecute {
self.command = format!("\"{c}\"", c = &self.command);
}

// 解释内置变量
let command_str = values_replacer(self.command, cx.exit_code, &cx.located);

// 解析命令传入
let cmd = c.args(split_command(&self.command)?);
let cmd = c.args(split_command(&command_str)?);

// 指定工作目录
let workshop = self.pwd.unwrap_or(cx.located.to_owned());
Expand All @@ -72,16 +79,10 @@ impl TStep for StepExecute {
let wait = self.wait.unwrap_or("Sync".to_string());
if wait == "Sync".to_string() {
// 同步执行并收集结果
log!(
"Info(Execute):Running sync command '{cmd}' in '{workshop}'",
cmd = self.command,
);
log!("Info(Execute):Running sync command '{command_str}' in '{workshop}'");
let start_instant = Instant::now();
let output = cmd.output().map_err(|err| {
anyhow!(
"Error(Execute):Command '{cmd}' execution failed : {err}",
cmd = self.command,
)
anyhow!("Error(Execute):Command '{command_str}' execution failed : {err}")
})?;

// 如果在调用安装器,检查是否过快退出
Expand All @@ -99,43 +100,29 @@ impl TStep for StepExecute {
match output.status.code() {
Some(val) => {
if val == 0 {
log!(
"{level}(Execute):Command '{cmd}' {hint}, output :",
cmd = self.command
);
log!("{level}(Execute):Command '{command_str}' {hint}, output :");
println!("{output}", output = read_console(output.stdout));
} else {
log!(
"Error(Execute):Failed command '{cmd}' {hint}, output(code={val}) : \n{o}",
cmd = self.command,
"Error(Execute):Failed command '{command_str}' {hint}, output(code={val}) : \n{o}",
o = read_console(output.stderr)
);
println!("{output}", output = read_console(output.stdout));
}
Ok(val)
}
None => Err(anyhow!(
"Error(Execute):Command '{cmd}' terminated by outer signal",
cmd = self.command
"Error(Execute):Command '{command_str}' terminated by outer signal"
)),
}
} else {
// 异步执行
log!(
"Info(Execute):Running async command('{wait}') '{cmd}' in '{workshop}'",
cmd = self.command,
);
log!("Info(Execute):Running async command('{wait}') '{command_str}' in '{workshop}'");
let handler = cmd.spawn().map_err(|e| {
anyhow!(
"Error(Execute):Command '{cmd}' spawn failed : {e}",
cmd = self.command
)
anyhow!("Error(Execute):Command '{command_str}' spawn failed : {e}")
})?;
cx.async_execution_handlers.push((
self.command,
handler,
wait == "Abandon".to_string(),
));
cx.async_execution_handlers
.push((command_str, handler, wait == "Abandon".to_string()));

Ok(0)
}
Expand Down Expand Up @@ -177,6 +164,12 @@ impl Interpretable for StepExecute {

impl Verifiable for StepExecute {
fn verify_self(&self, _: &String) -> Result<()> {
// 校验 pwd 为合法路径
if let Some(pwd) = &self.pwd {
values_validator_path(pwd)?;
}

// 校验命令前进行路径格式化
let formatted_cmd = format_path(&self.command);

// 禁止出现 :/
Expand Down
3 changes: 2 additions & 1 deletion src/types/steps/kill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ use sysinfo::{ProcessExt, System, SystemExt};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct StepKill {
/// 进程名称,大小写敏感且必须以 `.exe` 结尾
/// 进程名称,注意大小写敏感
//# `target = "code.exe"`
//@ 以 `.exe` 结尾
pub target: String,
}

Expand Down
4 changes: 4 additions & 0 deletions src/types/steps/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ fn update_start_menu() {
pub struct StepLink {
/// 源文件路径,支持相对路径和绝对路径。
//# `source_file = "code.exe"`
//@ 是合法路径
pub source_file: String,
/// 快捷方式名称,支持使用 `FOLDER/NAME` 的模式表示在创建位置的文件夾中放置快捷方式。
//# ```toml
Expand All @@ -120,6 +121,9 @@ pub struct StepLink {
//# # 在文件夹中创建快捷方式
//# target_name = "Microsoft/Visual Studio Code"
//# ```
//@ 符合模式 `NAME` 或 `FOLDER/NAME`
//@ 不包含 `..`
//@ 不以 `.lnk` 结尾
pub target_name: Option<String>,
/// 快捷方式的启动参数。
//# `target_args = "--debug"`
Expand Down
3 changes: 3 additions & 0 deletions src/types/steps/mv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ pub struct StepMove {
//# # 绝对路径通配符写法
//# from = "${Desktop}/Visual Studio Code.lnk"
//# ```
//@ 是合法路径
//@ 符合通配符用法
pub from: String,
/// 目标路径,支持相对路径和绝对路径。
//# `to = "./bin"`
//@ 是合法路径
pub to: String,
/// 是否覆盖,缺省为 `false`。
//# `overwrite = "true"`
Expand Down
1 change: 1 addition & 0 deletions src/types/steps/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct StepNew {
//# # 创建文件夹
//# at = "${Desktop}/Microsoft/"
//# ```
//@ 是合法路径
pub at: String,
/// 是否覆盖,缺省为 false。
//# `overwrite = "true"`
Expand Down
1 change: 1 addition & 0 deletions src/types/steps/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub struct StepPath {
//# # 添加文件夹到 PATH 变量
//# record = "./bin"
//# ```
//@ 是合法路径
pub record: String,
/// 别名,仅对可执行文件生效,缺省为原文件名。
//# `alias = "code.exe"`
Expand Down
3 changes: 3 additions & 0 deletions src/types/steps/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@ lazy_static! {
pub struct StepRename {
/// 目标路径,支持相对路径和绝对路径。
//# `from = "./config.toml.example"`
//@ 是合法路径
//@ 不包含通配符
pub from: String,
/// 新的名称。
//# `to = "config.toml"`
//@ 是合法的文件名或文件夹名而非路径
pub to: String,
}

Expand Down
2 changes: 2 additions & 0 deletions src/types/steps/wait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ use std::{thread::sleep, time::Duration};
pub struct StepWait {
/// 等待的时长,单位为 ms。
//# `timeout = "3000"`
//@ 不超过 30min(1800000ms)
pub timeout: u64,
/// 若满足指定条件则提前结束等待,该条件会在等待过程中每 500ms 检查一次。
//# `break_if = 'Exist("${Desktop}/Visual Studio Code.lnk")'`
//@ 是合法的条件
pub break_if: Option<String>,
}

Expand Down

0 comments on commit e22e0e7

Please sign in to comment.