Skip to content
This repository was archived by the owner on Jun 7, 2024. It is now read-only.

Commit f3737ab

Browse files
authored
rf: 替换 Deno.run (zsqk#48)
* rf: 替换 Deno.run * rf: 替换掉 Deno.run * fix: 完善测试 * rf: 调整测试 * chore: 调整依赖 * fix: 重新使用子进程, 避免超时后的内存泄漏隐患 * feat: 重新补充上找不到命令错误重定义
1 parent cf6a8df commit f3737ab

File tree

4 files changed

+101
-89
lines changed

4 files changed

+101
-89
lines changed

.github/workflows/deno.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ jobs:
2525
uses: actions/checkout@v2
2626

2727
- name: Setup Deno
28-
# uses: denoland/setup-deno@v1
29-
uses: denoland/setup-deno@004814556e37c54a2f6e31384c9e18e983317366
28+
uses: denoland/setup-deno@v1
29+
# uses: denoland/setup-deno@004814556e37c54a2f6e31384c9e18e983317366
3030
with:
3131
deno-version: v1.x
3232

deno/git.test.ts

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
1-
import { assertEquals } from 'https://deno.land/[email protected]/testing/asserts.ts';
1+
import {
2+
assert,
3+
assertEquals,
4+
} from 'https://deno.land/[email protected]/testing/asserts.ts';
25
import { gitChanges, pullGitRepo } from './git.ts';
36

7+
// git clone https://github.com/zsqk/deno-fn.git --depth 1
8+
// Cloning into 'deno-fn'...
9+
// remote: Enumerating objects: 57, done.
10+
// remote: Counting objects: 100% (57/57), done.
11+
// remote: Compressing objects: 100% (52/52), done.
12+
// remote: Total 57 (delta 0), reused 36 (delta 0), pack-reused 0
13+
// Receiving objects: 100% (57/57), 31.94 KiB | 281.00 KiB/s, done.
14+
Deno.test('pullGitRepo-o1', async () => {
15+
const dir = Deno.makeTempDirSync();
16+
const c = new Deno.Command('git', {
17+
args: ['clone', 'https://github.com/zsqk/deno-fn.git', '--depth', '1'],
18+
cwd: dir,
19+
});
20+
const o = await c.output();
21+
const stdout = new TextDecoder().decode(o.stdout);
22+
const stderr = new TextDecoder().decode(o.stderr);
23+
assert(o.success);
24+
console.log({ stdout, stderr, dir });
25+
assert((stdout + stderr).includes('Cloning into'));
26+
// assert(stdout.includes('Cloning into'));
27+
// assert(stdout.includes('remote: Enumerating objects'));
28+
// assert(stdout.includes('remote: Counting objects'));
29+
// assert(stdout.includes('remote: Compressing objects'));
30+
// assert(stdout.includes('remote: Total'));
31+
});
32+
433
Deno.test('pullGitRepo-https', async () => {
534
const res = await pullGitRepo('https://github.com/zsqk/deno-fn.git');
635
console.log(res);
@@ -29,9 +58,11 @@ Deno.test('gitChanges-newfile', async () => {
2958
notStagedFiles: [{ type: 'newfile', fileName: 'test.txt' }],
3059
});
3160

32-
const p2 = Deno.run({ cmd: ['git', 'add', '.'], cwd: path + '/deno-fn' });
33-
await p2.status();
34-
p2.close();
61+
const p2 = new Deno.Command('git', {
62+
args: ['add', '.'],
63+
cwd: path + '/deno-fn',
64+
});
65+
await p2.output();
3566

3667
const res2 = await gitChanges(path + '/deno-fn');
3768
assertEquals(res2, {
@@ -51,9 +82,11 @@ Deno.test('gitChanges-modified', async () => {
5182
notStagedFiles: [{ type: 'modified', fileName: 'README.md' }],
5283
});
5384

54-
const p2 = Deno.run({ cmd: ['git', 'add', '.'], cwd: path + '/deno-fn' });
55-
await p2.status();
56-
p2.close();
85+
const p2 = new Deno.Command('git', {
86+
args: ['add', '.'],
87+
cwd: path + '/deno-fn',
88+
});
89+
await p2.output();
5790

5891
const res2 = await gitChanges(path + '/deno-fn');
5992
assertEquals(res2, {
@@ -64,7 +97,7 @@ Deno.test('gitChanges-modified', async () => {
6497

6598
Deno.test('gitChanges-rename', async () => {
6699
const path = await pullGitRepo('https://github.com/zsqk/deno-fn.git');
67-
console.log(path);
100+
console.log('path', path);
68101

69102
Deno.rename(path + '/deno-fn/README.md', path + '/deno-fn/README1.md');
70103
const res1 = await gitChanges(path + '/deno-fn');
@@ -76,9 +109,11 @@ Deno.test('gitChanges-rename', async () => {
76109
],
77110
});
78111

79-
const p2 = Deno.run({ cmd: ['git', 'add', '.'], cwd: path + '/deno-fn' });
80-
await p2.status();
81-
p2.close();
112+
const p2 = new Deno.Command('git', {
113+
args: ['add', '.'],
114+
cwd: path + '/deno-fn',
115+
});
116+
await p2.output();
82117

83118
const res2 = await gitChanges(path + '/deno-fn');
84119
assertEquals(res2, {
@@ -102,9 +137,11 @@ Deno.test('gitChanges-delete', async () => {
102137
notStagedFiles: [{ type: 'deleted', fileName: 'README.md' }],
103138
});
104139

105-
const p2 = Deno.run({ cmd: ['git', 'add', '.'], cwd: path + '/deno-fn' });
106-
await p2.status();
107-
p2.close();
140+
const p2 = new Deno.Command('git', {
141+
args: ['add', '.'],
142+
cwd: path + '/deno-fn',
143+
});
144+
await p2.output();
108145

109146
const res2 = await gitChanges(path + '/deno-fn');
110147
assertEquals(res2, {

deno/run.ts

Lines changed: 38 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { delay } from 'https://deno.land/std@0.177.0/async/delay.ts';
1+
import { delay } from 'https://deno.land/std@0.190.0/async/delay.ts';
22

33
/**
44
* [Deno] 执行命令
@@ -11,30 +11,22 @@ export async function getRunData(
1111
path?: string,
1212
): Promise<string> {
1313
/** 进程 */
14-
const run = Deno.run({
15-
cmd: command,
14+
const run = new Deno.Command(command[0], {
15+
args: command.slice(1),
1616
cwd: path,
17-
stdout: 'piped',
18-
stderr: 'piped',
1917
});
2018

21-
try {
22-
/** 状态 */
23-
const s1 = await run.status();
19+
const o = await run.output();
2420

25-
/** 信息 */
26-
const stderr = await run.stderrOutput();
27-
if (!s1.success) {
28-
const r1err = new TextDecoder().decode(stderr);
29-
throw new Error(`${s1.code} ${r1err}`);
30-
}
21+
/** 信息 */
22+
if (!o.success) {
23+
const r1err = new TextDecoder().decode(o.stderr);
24+
throw new Error(`${o.code} ${r1err}`);
25+
}
3126

32-
const res = new TextDecoder().decode(await run.output());
27+
const res = new TextDecoder().decode(o.stdout);
3328

34-
return res;
35-
} finally {
36-
run.close();
37-
}
29+
return res;
3830
}
3931

4032
/**
@@ -55,7 +47,7 @@ export async function run(
5547
*/
5648
timeout = 5000,
5749
...opt
58-
}: Omit<Parameters<typeof Deno.run>[0], 'cmd'> & { timeout?: number } = {},
50+
}: Deno.CommandOptions & { timeout?: number } = {},
5951
): Promise<{
6052
/** 返回结果 */
6153
res: string;
@@ -66,63 +58,50 @@ export async function run(
6658
}> {
6759
let res = '';
6860
let errMsg = '';
69-
let code = 0;
7061

71-
/** 进程 */
72-
let p: Deno.Process;
7362
const cmd = typeof command === 'string' ? command.split(' ') : command;
7463

7564
/** 超时中断控制器 */
7665
const ac = new AbortController();
7766

67+
/** 命令 */
68+
const c = new Deno.Command(cmd[0], {
69+
args: cmd.slice(1),
70+
stdout,
71+
stderr,
72+
...opt,
73+
});
74+
75+
/** 进程 */
76+
let p: Deno.ChildProcess;
7877
try {
79-
p = Deno.run({
80-
stdout,
81-
stderr,
82-
...opt,
83-
cmd,
84-
});
78+
p = c.spawn();
8579
} catch (err) {
8680
if (!(err instanceof Error)) {
8781
throw new Error(`${err}`);
8882
}
8983
if (err.name === 'NotFound') {
90-
console.error(err);
9184
err.message = `command or file not found: ${cmd[0]}`;
9285
}
9386
throw err;
9487
}
9588

9689
const timeoutPromise = delay(timeout, { signal: ac.signal }).then(() => {
9790
p.kill();
98-
p.close();
9991
throw new Error('timeout');
10092
});
10193

10294
const exePromise = (async () => {
103-
try {
104-
/** 执行状态 */
105-
const s = await p.status();
106-
code = s.code;
107-
108-
// 返回信息
109-
if (stdout === 'piped') {
110-
res = new TextDecoder().decode(await p.output());
111-
}
112-
113-
// 错误信息
114-
if (stderr === 'piped') {
115-
const stderr = await p.stderrOutput();
116-
if (s.success) {
117-
errMsg += `no error.`;
118-
}
119-
errMsg += new TextDecoder().decode(stderr);
120-
}
121-
ac.abort();
122-
return { res, errMsg, code };
123-
} finally {
124-
p.close();
95+
// 返回信息
96+
/** 执行结果 */
97+
const o = await p.output();
98+
res = new TextDecoder().decode(o.stdout);
99+
if (o.success) {
100+
errMsg += `no error.`;
125101
}
102+
errMsg += new TextDecoder().decode(o.stderr);
103+
ac.abort();
104+
return { res, errMsg, code: o.code };
126105
})();
127106

128107
return Promise.race([timeoutPromise, exePromise]);
@@ -136,14 +115,14 @@ export async function run(
136115
*/
137116
export async function onlyRun(
138117
command: string[] | string,
139-
opt?: Omit<Parameters<typeof Deno.run>[0], 'cmd' | 'stdout' | 'stderr'> & {
118+
opt?: Omit<Deno.CommandOptions, 'stdout' | 'stderr'> & {
140119
timeout?: number;
141120
},
142121
): Promise<number> {
143-
const { code } = await run(command, {
144-
...opt,
145-
stderr: 'inherit',
146-
stdout: 'inherit',
147-
});
122+
const { code, res, errMsg } = await run(command, opt);
123+
if (code !== 0) {
124+
throw new Error(errMsg);
125+
}
126+
res && console.log(res);
148127
return code;
149128
}

mod.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,29 +65,26 @@ export async function getComputeInfo(): Promise<ComputeInfo> {
6565

6666
// get hostname
6767
if (Deno.build.os === 'darwin' || Deno.build.os === 'linux') {
68-
const p = Deno.run({ cmd: ['hostname'], stdout: 'piped' });
69-
hostname = new TextDecoder().decode(await p.output()).replace('\n', '');
70-
p.close();
68+
const p = new Deno.Command('hostname');
69+
const s = await p.output();
70+
hostname = new TextDecoder().decode(s.stdout).replace('\n', '');
7171
}
7272

7373
// get os
74-
if (Deno.build.os === 'darwin') {
74+
if (os === 'darwin') {
7575
os = 'mac';
7676
}
7777

7878
// get version
7979
if (Deno.build.os === 'darwin') {
80-
const p = Deno.run({
81-
cmd: ['sw_vers', '-productVersion'],
82-
stdout: 'piped',
80+
const p = new Deno.Command('sw_vers', {
81+
args: ['-productVersion'],
8382
});
84-
version = new TextDecoder().decode(await p.output()).replace('\n', '');
85-
p.close();
83+
version = new TextDecoder().decode(p.outputSync().stdout).replace('\n', '');
8684
}
8785
if (Deno.build.os === 'linux') {
88-
const p = Deno.run({
89-
cmd: ['cat', '/etc/os-release'],
90-
stdout: 'piped',
86+
const p = new Deno.Command('cat', {
87+
args: ['/etc/os-release'],
9188
});
9289
// cat /etc/os-release demo
9390
// PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
@@ -98,10 +95,9 @@ export async function getComputeInfo(): Promise<ComputeInfo> {
9895
// HOME_URL="https://www.debian.org/"
9996
// SUPPORT_URL="https://www.debian.org/support"
10097
// BUG_REPORT_URL="https://bugs.debian.org/"
101-
const osRelease = parseEnv(new TextDecoder().decode(await p.output()));
98+
const osRelease = parseEnv(new TextDecoder().decode(p.outputSync().stdout));
10299
version = (osRelease.get('ID') ?? 'linux') +
103100
(osRelease.get('VERSION_ID') ?? '');
104-
p.close();
105101
}
106102

107103
return { hostname, os, version };

0 commit comments

Comments
 (0)