xshell 1.0.65 → 1.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Terminal.d.ts +3 -0
- package/Terminal.js +5 -1
- package/apps.d.ts +54 -0
- package/apps.js +93 -0
- package/file.d.ts +24 -0
- package/file.js +59 -1
- package/git.d.ts +36 -0
- package/git.js +136 -0
- package/package.json +5 -1
- package/process.d.ts +3 -2
- package/process.js +5 -4
- package/utils.browser.d.ts +1 -1
- package/utils.d.ts +1 -1
package/Terminal.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import 'xterm/css/xterm.css';
|
|
2
2
|
import { Terminal as XTermTerminal } from 'xterm';
|
|
3
|
+
import { FitAddon } from 'xterm-addon-fit';
|
|
3
4
|
import { Model } from 'react-object-model';
|
|
4
5
|
import type { Remote } from './net.browser.js';
|
|
5
6
|
export declare function Terminal({ font }: {
|
|
@@ -7,7 +8,9 @@ export declare function Terminal({ font }: {
|
|
|
7
8
|
}): import("react/jsx-runtime").JSX.Element;
|
|
8
9
|
declare class TerminalModel extends Model<TerminalModel> {
|
|
9
10
|
term: XTermTerminal;
|
|
11
|
+
fit_addon: FitAddon;
|
|
10
12
|
stdio_id: number;
|
|
13
|
+
fit(): void;
|
|
11
14
|
subscribe_stdio(remote: Remote): Promise<void>;
|
|
12
15
|
unsubscribe_stdio(remote: Remote): Promise<void>;
|
|
13
16
|
}
|
package/Terminal.js
CHANGED
|
@@ -29,14 +29,18 @@ export function Terminal({ font }) {
|
|
|
29
29
|
term.open(rterminal.current);
|
|
30
30
|
term.loadAddon(new WebglAddon());
|
|
31
31
|
fit_addon.fit();
|
|
32
|
-
terminal.set({ term });
|
|
32
|
+
terminal.set({ term, fit_addon });
|
|
33
33
|
})();
|
|
34
34
|
}, []);
|
|
35
35
|
return _jsx("div", { className: 'term', ref: rterminal });
|
|
36
36
|
}
|
|
37
37
|
class TerminalModel extends Model {
|
|
38
38
|
term;
|
|
39
|
+
fit_addon;
|
|
39
40
|
stdio_id = 0;
|
|
41
|
+
fit() {
|
|
42
|
+
this.fit_addon?.fit();
|
|
43
|
+
}
|
|
40
44
|
async subscribe_stdio(remote) {
|
|
41
45
|
assert(!this.stdio_id);
|
|
42
46
|
const id = this.stdio_id = genid();
|
package/apps.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import type { Readable } from 'stream';
|
|
3
|
+
import type OSS from 'ali-oss';
|
|
4
|
+
import { type CallOptions } from './process.js';
|
|
5
|
+
export declare let npm: {
|
|
6
|
+
bin: string;
|
|
7
|
+
call(cwd: string, bin: string, args: string[], options?: CallOptions): Promise<import("./process.js").CallResult<string>>;
|
|
8
|
+
/** node.exe E:/sdk/nodejs/node_modules/corepack/dist/pnpm.js install
|
|
9
|
+
- cwd?: `fpd_root`
|
|
10
|
+
- pkgs?: `[ ]` */
|
|
11
|
+
install(cwd?: string, pkgs?: string[], { save_dev, save_peer, legacy, force, term, inspect, break: _break, }?: {
|
|
12
|
+
save_dev?: boolean;
|
|
13
|
+
save_peer?: boolean;
|
|
14
|
+
legacy?: boolean;
|
|
15
|
+
force?: boolean;
|
|
16
|
+
term?: boolean;
|
|
17
|
+
inspect?: boolean;
|
|
18
|
+
break?: boolean;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
/** 使用 tsc 编译项目
|
|
22
|
+
- fpd: 项目目录
|
|
23
|
+
- options?:
|
|
24
|
+
- tsconfig?: `'<dir>/tsconfig.json'`
|
|
25
|
+
- typecheck?: `false` 是否只进行 typecheck, (使用 call_node 执行而非 term) */
|
|
26
|
+
export declare function tsc(fpd: string, { tsconfig, typecheck, }?: {
|
|
27
|
+
tsconfig?: string;
|
|
28
|
+
typecheck?: boolean;
|
|
29
|
+
}): Promise<import("./process.js").CallResult<string>>;
|
|
30
|
+
export declare let oss: {
|
|
31
|
+
client: OSS;
|
|
32
|
+
bucket: string;
|
|
33
|
+
region: string;
|
|
34
|
+
root: string;
|
|
35
|
+
init({ bucket, region, root, access_id, access_key }: {
|
|
36
|
+
bucket: string;
|
|
37
|
+
region: string;
|
|
38
|
+
root: string;
|
|
39
|
+
access_id: string;
|
|
40
|
+
access_key: string;
|
|
41
|
+
}): Promise<void>;
|
|
42
|
+
/** 上传文件到 OSS,返回文件 URL
|
|
43
|
+
- fp: 上传到 OSS 的路径, 如 assets/web.latest.zip
|
|
44
|
+
- data: 文件 (Uint8Array) | 本地文件完整路径 (string) | ReadableStream
|
|
45
|
+
- options?:
|
|
46
|
+
- private?: `false` 设置为私有,需要通过 URL 签名参数访问
|
|
47
|
+
- print?: `true` 打印消息 */
|
|
48
|
+
upload(fp: string, data: Uint8Array | string | Readable, { private: _private, print, }?: {
|
|
49
|
+
private?: boolean;
|
|
50
|
+
print?: boolean;
|
|
51
|
+
}): Promise<string>;
|
|
52
|
+
/** 获取经过签名后可访问的 url */
|
|
53
|
+
get_url(fp: string): Promise<string>;
|
|
54
|
+
};
|
package/apps.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import util from 'util';
|
|
2
|
+
import { call_nodejs, exe_nodejs, platform } from './process.js';
|
|
3
|
+
import { assert } from './utils.js';
|
|
4
|
+
import { path } from './path.js';
|
|
5
|
+
export let npm = {
|
|
6
|
+
bin: `${platform === 'win32' ? exe_nodejs.fdir : '/usr/lib/'}node_modules/corepack/dist/pnpm.js`,
|
|
7
|
+
async call(cwd, bin, args, options) {
|
|
8
|
+
return call_nodejs(bin, args, { cwd, ...options });
|
|
9
|
+
},
|
|
10
|
+
/** node.exe E:/sdk/nodejs/node_modules/corepack/dist/pnpm.js install
|
|
11
|
+
- cwd?: `fpd_root`
|
|
12
|
+
- pkgs?: `[ ]` */
|
|
13
|
+
async install(cwd, pkgs = [], { save_dev = false, save_peer = false, legacy = false, force = false, term = false, inspect = false, break: _break = false, } = {}) {
|
|
14
|
+
const args = [
|
|
15
|
+
'install',
|
|
16
|
+
...util.inspect.defaultOptions.colors ? ['--color'] : [],
|
|
17
|
+
...legacy ? ['--legacy-peer-deps'] : [],
|
|
18
|
+
...force ? ['--force'] : [],
|
|
19
|
+
...save_dev ? ['--save-dev'] : [],
|
|
20
|
+
...save_peer ? ['--save-peer'] : [],
|
|
21
|
+
...pkgs || []
|
|
22
|
+
];
|
|
23
|
+
await this.call(cwd, this.bin, args);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
/** 使用 tsc 编译项目
|
|
27
|
+
- fpd: 项目目录
|
|
28
|
+
- options?:
|
|
29
|
+
- tsconfig?: `'<dir>/tsconfig.json'`
|
|
30
|
+
- typecheck?: `false` 是否只进行 typecheck, (使用 call_node 执行而非 term) */
|
|
31
|
+
export async function tsc(fpd, { tsconfig = './tsconfig.json', typecheck = false, } = {}) {
|
|
32
|
+
return call_nodejs(`${fpd}/node_modules/typescript/bin/tsc`, [
|
|
33
|
+
'--project', tsconfig,
|
|
34
|
+
...typecheck ? ['--noEmit'] : []
|
|
35
|
+
], {
|
|
36
|
+
cwd: fpd,
|
|
37
|
+
print: { command: false, code: false, stdout: true, stderr: true }
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export let oss = {
|
|
41
|
+
client: null,
|
|
42
|
+
bucket: null,
|
|
43
|
+
region: null,
|
|
44
|
+
root: null,
|
|
45
|
+
async init({ bucket, region, root, access_id, access_key }) {
|
|
46
|
+
if (this.client)
|
|
47
|
+
return;
|
|
48
|
+
const OSS = (await import('ali-oss')).default;
|
|
49
|
+
this.bucket = bucket;
|
|
50
|
+
this.region = region;
|
|
51
|
+
this.root = root;
|
|
52
|
+
this.client = new OSS({
|
|
53
|
+
accessKeyId: access_id,
|
|
54
|
+
accessKeySecret: access_key,
|
|
55
|
+
region: this.region,
|
|
56
|
+
bucket: this.bucket,
|
|
57
|
+
secure: true
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
/** 上传文件到 OSS,返回文件 URL
|
|
61
|
+
- fp: 上传到 OSS 的路径, 如 assets/web.latest.zip
|
|
62
|
+
- data: 文件 (Uint8Array) | 本地文件完整路径 (string) | ReadableStream
|
|
63
|
+
- options?:
|
|
64
|
+
- private?: `false` 设置为私有,需要通过 URL 签名参数访问
|
|
65
|
+
- print?: `true` 打印消息 */
|
|
66
|
+
async upload(fp, data, { private: _private = false, print = true, } = {}) {
|
|
67
|
+
assert(this.client, 'OSS 应该已经初始化了');
|
|
68
|
+
assert(!fp.isdir, '不能使用 oss.upload 上传文件夹,请使用 oss.upload_dir');
|
|
69
|
+
if (typeof data === 'string')
|
|
70
|
+
assert(data[1] === ':' && path.isAbsolute(data), 'oss.upload 传入 data 参数类型为 string 时,必须为本地文件完整路径');
|
|
71
|
+
if (data instanceof Uint8Array && !Buffer.isBuffer(data))
|
|
72
|
+
data = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
73
|
+
await this.client.put(fp, data);
|
|
74
|
+
let url;
|
|
75
|
+
if (_private) {
|
|
76
|
+
await this.client.putACL(fp, 'private');
|
|
77
|
+
url = await this.get_url(fp);
|
|
78
|
+
}
|
|
79
|
+
else
|
|
80
|
+
url = new URL(this.root + fp).toString();
|
|
81
|
+
if (print)
|
|
82
|
+
console.log(`已上传到 OSS${_private ? ' (私有)' : ''}:`, url);
|
|
83
|
+
return url;
|
|
84
|
+
},
|
|
85
|
+
/** 获取经过签名后可访问的 url */
|
|
86
|
+
async get_url(fp) {
|
|
87
|
+
assert(this.client, 'OSS 应该已经初始化了');
|
|
88
|
+
const url = new URL(this.client.signatureUrl(fp, { expires: /* 十年 */ 3600 * 24 * 365 * 10 }));
|
|
89
|
+
const url_ = `${this.root}${url.pathname.slice(1)}${url.search}`;
|
|
90
|
+
return url_;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=apps.js.map
|
package/file.d.ts
CHANGED
|
@@ -171,6 +171,30 @@ export declare function flink(fp_real: string, fp_link: string, { junction, prin
|
|
|
171
171
|
junction?: boolean;
|
|
172
172
|
print?: boolean;
|
|
173
173
|
}): Promise<void>;
|
|
174
|
+
export interface ZipOptions {
|
|
175
|
+
dirname?: string;
|
|
176
|
+
print?: {
|
|
177
|
+
info: boolean;
|
|
178
|
+
files: boolean;
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/** 将文件夹压缩为 zip
|
|
182
|
+
返回 fp_zip 或压缩包数据
|
|
183
|
+
- data:
|
|
184
|
+
- 被压缩文件夹路径 (fpd_src: string) 或
|
|
185
|
+
- 文件索引对象 (entries: Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
186
|
+
- fp_zip?:
|
|
187
|
+
- 传压缩包完整路径时压缩到文件, 函数返回值为 Promise<zip 路径>
|
|
188
|
+
- 传 undefined 时压缩到内存, 函数返回值为 Promise<zip Uint8Array>
|
|
189
|
+
- options?:
|
|
190
|
+
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
191
|
+
- print?:
|
|
192
|
+
- info?: `true` 开始压缩、压缩完成
|
|
193
|
+
- files?: `true` 打印压缩文件列表 */
|
|
194
|
+
export declare function fzip(entries: Record<string, string | Uint8Array>, fp_zip?: undefined, options?: ZipOptions): Promise<Uint8Array>;
|
|
195
|
+
export declare function fzip(entries: Record<string, string | Uint8Array>, fp_zip: string, options?: ZipOptions): Promise<string>;
|
|
196
|
+
export declare function fzip(fpd_src: string, fp_zip?: undefined, options?: ZipOptions): Promise<Uint8Array>;
|
|
197
|
+
export declare function fzip(fpd_src: string, fp_zip: string, options?: ZipOptions): Promise<string>;
|
|
174
198
|
export declare let fwatchers: Record<string, fs.FSWatcher>;
|
|
175
199
|
/** 跟踪文本文件追加的内容,类似 tail -f */
|
|
176
200
|
export declare function ftail(fp: string, handler: (lines: string[]) => void | Promise<void>, { print }?: {
|
package/file.js
CHANGED
|
@@ -3,7 +3,7 @@ import { isUint8Array } from 'util/types';
|
|
|
3
3
|
import { path } from './path.js';
|
|
4
4
|
import { t } from './i18n/instance.js';
|
|
5
5
|
import { to_json } from './prototype.js';
|
|
6
|
-
import { assert, Lock } from './utils.js';
|
|
6
|
+
import { assert, Lock, WritableMemoryStream } from './utils.js';
|
|
7
7
|
export { fsp };
|
|
8
8
|
export const encodings = ['utf-8', 'gb18030', 'shift-jis', 'utf-16le'];
|
|
9
9
|
/** fp 所指向的 文件/ 文件夹 是否存在
|
|
@@ -367,6 +367,64 @@ export async function flink(fp_real, fp_link, { junction = false, print = true }
|
|
|
367
367
|
else
|
|
368
368
|
fsp.symlink(fp_real, fp_link, is_fpd_real ? 'dir' : 'file');
|
|
369
369
|
}
|
|
370
|
+
export async function fzip(data, fp_zip, { dirname, print = { files: true, info: true } } = {}) {
|
|
371
|
+
let entries;
|
|
372
|
+
let fpd_src;
|
|
373
|
+
if (typeof data === 'string') {
|
|
374
|
+
if (!path.isAbsolute(data) || !data.isdir)
|
|
375
|
+
throw new Error('fpd_src 必须是绝对路径且以 / 结尾');
|
|
376
|
+
fpd_src = data;
|
|
377
|
+
if (dirname === undefined)
|
|
378
|
+
dirname = fpd_src.fname;
|
|
379
|
+
if (!dirname.isdir)
|
|
380
|
+
throw new Error('dirname 需要以 / 结尾');
|
|
381
|
+
entries = Object.fromEntries((await flist(fpd_src, { print: false }))
|
|
382
|
+
.map(fp => ([dirname + fp, fpd_src + fp])));
|
|
383
|
+
}
|
|
384
|
+
else
|
|
385
|
+
entries = data;
|
|
386
|
+
if (print.info)
|
|
387
|
+
console.log(`开始压缩${fpd_src ? ` ${fpd_src}` : '文件索引'} -> ${fp_zip ? `${fp_zip}/${dirname}` : '内存'}`);
|
|
388
|
+
const { default: archiver } = await import('archiver');
|
|
389
|
+
let archive = archiver('zip', { zlib: { chunkSize: 16 * 2 ** 20 /* 16 MB */ } });
|
|
390
|
+
let ostream = fp_zip ?
|
|
391
|
+
fs.createWriteStream(fp_zip, { highWaterMark: 16 * 2 ** 20 /* 16 MB */ })
|
|
392
|
+
:
|
|
393
|
+
new WritableMemoryStream();
|
|
394
|
+
const size = await new Promise(async (resolve, reject) => {
|
|
395
|
+
ostream.once('close', () => {
|
|
396
|
+
resolve(archive.pointer());
|
|
397
|
+
});
|
|
398
|
+
ostream.once('error', reject);
|
|
399
|
+
archive.once('error', reject);
|
|
400
|
+
archive.on('warning', error => {
|
|
401
|
+
console.log(error);
|
|
402
|
+
});
|
|
403
|
+
archive.pipe(ostream);
|
|
404
|
+
for (const fp in entries) {
|
|
405
|
+
const fdata = entries[fp];
|
|
406
|
+
if (fdata instanceof Uint8Array) {
|
|
407
|
+
if (print.files)
|
|
408
|
+
console.log(`压缩 ${fdata.length.to_fsize_str()} -> ${fp}`);
|
|
409
|
+
archive.append(Buffer.isBuffer(fdata) ? fdata : Buffer.from(fdata.buffer), { name: fp });
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
assert(fp.isdir === fdata.isdir);
|
|
413
|
+
assert(path.isAbsolute(fdata));
|
|
414
|
+
if (print.files)
|
|
415
|
+
console.log(`压缩 ${fdata} -> ${fp}`);
|
|
416
|
+
if (fp.isdir)
|
|
417
|
+
archive.directory(fdata, fp);
|
|
418
|
+
else
|
|
419
|
+
archive.file(fdata, { name: fp });
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
await archive.finalize();
|
|
423
|
+
});
|
|
424
|
+
if (print.info)
|
|
425
|
+
console.log(`压缩完成,总大小 ${size.to_fsize_str()}`);
|
|
426
|
+
return fp_zip || ostream.pbuffer;
|
|
427
|
+
}
|
|
370
428
|
export let fwatchers = {};
|
|
371
429
|
/** 跟踪文本文件追加的内容,类似 tail -f */
|
|
372
430
|
export async function ftail(fp, handler, { print = true } = {}) {
|
package/git.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type CallOptions } from './process.js';
|
|
2
|
+
export declare class Git {
|
|
3
|
+
static exe: string;
|
|
4
|
+
cwd: string;
|
|
5
|
+
constructor(cwd: string);
|
|
6
|
+
static init(cwd: string): Promise<Git>;
|
|
7
|
+
static clone(repo: string, fpd: string): Promise<void>;
|
|
8
|
+
call(args?: any[], { color, print }?: {
|
|
9
|
+
color?: boolean;
|
|
10
|
+
print?: CallOptions['print'];
|
|
11
|
+
}): Promise<import("./process.js").CallResult<string>>;
|
|
12
|
+
get_branch(): Promise<string>;
|
|
13
|
+
/** - print: `true` */
|
|
14
|
+
get_branches(print?: boolean): Promise<string[]>;
|
|
15
|
+
has_branch(branch: string): Promise<boolean>;
|
|
16
|
+
fetch(print?: boolean): Promise<void>;
|
|
17
|
+
/** - branch?: `'main'` */
|
|
18
|
+
checkout(branch?: 'main'): Promise<void>;
|
|
19
|
+
checkout(branch?: string): Promise<void>;
|
|
20
|
+
_checkout(branch?: string): Promise<void>;
|
|
21
|
+
merge(branch: string, fast_forward?: boolean): Promise<void>;
|
|
22
|
+
/** 记住当前分支名
|
|
23
|
+
checkout 到 <目标分支>
|
|
24
|
+
merge 当前分支 */
|
|
25
|
+
merge_into(target_branch?: string): Promise<void>;
|
|
26
|
+
/** 1. fetch 远程修改
|
|
27
|
+
2. checkout `<branch>` 分支
|
|
28
|
+
3. merge `<remote>/<branch>`
|
|
29
|
+
|
|
30
|
+
执行前需要保证工作目录 clean
|
|
31
|
+
|
|
32
|
+
- branch?: `'main'` */
|
|
33
|
+
update(branch?: 'main'): Promise<void>;
|
|
34
|
+
update(branch: string): Promise<void>;
|
|
35
|
+
update(branch: string, remote?: string): Promise<void>;
|
|
36
|
+
}
|
package/git.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { assert } from './utils.js';
|
|
2
|
+
import { call } from './process.js';
|
|
3
|
+
import { fread, fmkdir } from './file.js';
|
|
4
|
+
export class Git {
|
|
5
|
+
static exe = 'git';
|
|
6
|
+
cwd;
|
|
7
|
+
constructor(cwd) {
|
|
8
|
+
this.cwd = cwd;
|
|
9
|
+
}
|
|
10
|
+
static async init(cwd) {
|
|
11
|
+
const git = new Git(cwd);
|
|
12
|
+
await git.call(['init']);
|
|
13
|
+
return git;
|
|
14
|
+
}
|
|
15
|
+
static async clone(repo, fpd) {
|
|
16
|
+
await fmkdir(fpd);
|
|
17
|
+
await new this(fpd).call(['clone', repo, '.']);
|
|
18
|
+
}
|
|
19
|
+
async call(args = [], { color = true, print } = {}) {
|
|
20
|
+
return call(Git.exe, [
|
|
21
|
+
...color ? [] : [
|
|
22
|
+
'-c', 'color.status=false',
|
|
23
|
+
'-c', 'color.ui=false',
|
|
24
|
+
'-c', 'color.branch=false',
|
|
25
|
+
],
|
|
26
|
+
...args,
|
|
27
|
+
], {
|
|
28
|
+
cwd: this.cwd,
|
|
29
|
+
print,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async get_branch() {
|
|
33
|
+
const head = (await fread(`${this.cwd}.git/HEAD`, { print: false })).trim();
|
|
34
|
+
const branch = head.find('ref: refs/heads/{branch}').branch || head;
|
|
35
|
+
if (!branch)
|
|
36
|
+
throw new Error(`${this.cwd} 仓库 Git.get_branch 无法获取到 branch`);
|
|
37
|
+
return branch;
|
|
38
|
+
// 需要 100+ ms ,性能太差
|
|
39
|
+
// this.branch = (await this.git('branch --show-current')).stdout.trim().strip_ansi()
|
|
40
|
+
}
|
|
41
|
+
/** - print: `true` */
|
|
42
|
+
async get_branches(print = true) {
|
|
43
|
+
return (await this.call(['branch', '-a'], { print })).stdout
|
|
44
|
+
.split_lines()
|
|
45
|
+
.map(l => l.strip_ansi())
|
|
46
|
+
.filter(branch => !branch.includes('origin/HEAD'))
|
|
47
|
+
.map(branch => branch.rm(/^\* /))
|
|
48
|
+
.trim_lines();
|
|
49
|
+
}
|
|
50
|
+
async has_branch(branch) {
|
|
51
|
+
return (await this.get_branches(false))
|
|
52
|
+
.includes(branch);
|
|
53
|
+
}
|
|
54
|
+
async fetch(print = true) {
|
|
55
|
+
if (print)
|
|
56
|
+
console.log('更新远程分支');
|
|
57
|
+
await this.call(['fetch', '--all', '--prune'], { print: { code: false, command: false, stdout: true, stderr: true } });
|
|
58
|
+
}
|
|
59
|
+
async checkout(branch = 'main') {
|
|
60
|
+
if (branch === 'main')
|
|
61
|
+
await this._checkout('main');
|
|
62
|
+
else {
|
|
63
|
+
const branches = await this.get_branches(false);
|
|
64
|
+
if (branches.includes(branch) || branches.find(b => b.endsWith(`/${branch}`) && b.startsWith('remotes/')))
|
|
65
|
+
await this._checkout(branch);
|
|
66
|
+
else {
|
|
67
|
+
console.log(`创建分支 ${branch}`);
|
|
68
|
+
await this.call(['checkout', '-b', branch], { print: { command: false, code: false, stdout: true, stderr: true } });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async _checkout(branch) {
|
|
73
|
+
try {
|
|
74
|
+
const { stdout, stderr } = await this.call(['checkout', branch], { print: false });
|
|
75
|
+
if (stdout)
|
|
76
|
+
console.log(stdout.trimEnd());
|
|
77
|
+
console.log(/Already on '.*'\n/.test(stderr) ?
|
|
78
|
+
`已经在 ${branch} 分支了`
|
|
79
|
+
: /Switched to branch '.*'/.test(stderr) ?
|
|
80
|
+
`已切换到 ${branch} 分支`
|
|
81
|
+
:
|
|
82
|
+
stderr.trimEnd());
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error.result) {
|
|
86
|
+
const { stdout, stderr } = error.result;
|
|
87
|
+
if (stdout)
|
|
88
|
+
console.log(stdout);
|
|
89
|
+
if (stderr)
|
|
90
|
+
console.log(stderr);
|
|
91
|
+
}
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async merge(branch, fast_forward = true) {
|
|
96
|
+
console.log(`合并 ${branch} 分支`);
|
|
97
|
+
try {
|
|
98
|
+
const { stdout, stderr } = await this.call([
|
|
99
|
+
'merge',
|
|
100
|
+
branch,
|
|
101
|
+
...fast_forward ? [] : ['--no-ff']
|
|
102
|
+
], { print: false });
|
|
103
|
+
if (stdout === 'Already up to date.\n')
|
|
104
|
+
console.log('当前分支无需更新');
|
|
105
|
+
else
|
|
106
|
+
console.log(stdout.trimEnd());
|
|
107
|
+
if (stderr)
|
|
108
|
+
console.log(stderr);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
if (error.result) {
|
|
112
|
+
const { stdout, stderr } = error.result;
|
|
113
|
+
if (stdout)
|
|
114
|
+
console.log(stdout);
|
|
115
|
+
if (stderr)
|
|
116
|
+
console.log(stderr);
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** 记住当前分支名
|
|
122
|
+
checkout 到 <目标分支>
|
|
123
|
+
merge 当前分支 */
|
|
124
|
+
async merge_into(target_branch = 'main') {
|
|
125
|
+
const branch = await this.get_branch();
|
|
126
|
+
assert(branch !== target_branch);
|
|
127
|
+
await this.checkout(target_branch);
|
|
128
|
+
await this.merge(branch, true);
|
|
129
|
+
}
|
|
130
|
+
async update(branch = 'main', remote = 'origin') {
|
|
131
|
+
await this.fetch();
|
|
132
|
+
await this.checkout(branch);
|
|
133
|
+
await this.merge(`${remote}/${branch}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=git.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xshell",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.67",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"bin": {
|
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
"@babel/traverse": "^7.23.5",
|
|
51
51
|
"@koa/cors": "^4.0.0",
|
|
52
52
|
"@types/ws": "^8.5.10",
|
|
53
|
+
"ali-oss": "^6.18.1",
|
|
54
|
+
"archiver": "^6.0.1",
|
|
53
55
|
"byte-size": "^8.1.1",
|
|
54
56
|
"chalk": "^5.3.0",
|
|
55
57
|
"chardet": "^2.0.0",
|
|
@@ -91,6 +93,8 @@
|
|
|
91
93
|
},
|
|
92
94
|
"devDependencies": {
|
|
93
95
|
"@babel/types": "^7.23.5",
|
|
96
|
+
"@types/ali-oss": "^6.16.11",
|
|
97
|
+
"@types/archiver": "^6.0.2",
|
|
94
98
|
"@types/babel__traverse": "^7.20.4",
|
|
95
99
|
"@types/byte-size": "^8.1.2",
|
|
96
100
|
"@types/chardet": "^0.8.3",
|
package/process.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ import './prototype.js';
|
|
|
6
6
|
import { Encoding } from './file.js';
|
|
7
7
|
import { inspect } from './utils.js';
|
|
8
8
|
export declare const exe_nodejs: string;
|
|
9
|
+
export declare const platform: NodeJS.Platform;
|
|
10
|
+
export declare const username: string;
|
|
9
11
|
interface StartOptions {
|
|
10
12
|
/** `继承当前工作目录 process.cwd()` 子进程的工作目录 `inherit the cwd` cwd of the child process. */
|
|
11
13
|
cwd?: string;
|
|
@@ -108,8 +110,7 @@ export declare const exe_winterm: string;
|
|
|
108
110
|
/** 新建 terminal 窗口执行进程 New Terminal window execution process
|
|
109
111
|
- exe: exe 文件路径 exe file path
|
|
110
112
|
- args: 调用参数 call parameter
|
|
111
|
-
- options?: WinTermOptions
|
|
112
|
-
*/
|
|
113
|
+
- options?: WinTermOptions */
|
|
113
114
|
export declare function term(exe: string, args?: string[], { cwd, print, title, }?: TermOptions): Promise<ChildProcess>;
|
|
114
115
|
export interface TermNodeOptions extends TermOptions {
|
|
115
116
|
/** nodejs debugger port */
|
package/process.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { spawn } from 'child_process';
|
|
2
|
-
import
|
|
2
|
+
import os from 'os';
|
|
3
3
|
import { t } from './i18n/instance.js';
|
|
4
4
|
import './prototype.js';
|
|
5
5
|
import { inspect, DecoderStream } from './utils.js';
|
|
6
6
|
export const exe_nodejs = process.execPath.fp;
|
|
7
|
+
export const platform = os.platform();
|
|
8
|
+
export const username = os.userInfo().username;
|
|
7
9
|
/** start process
|
|
8
10
|
- exe: .exe 路径或文件名 (建议使用完整路径,跳过 path 搜索,性能更高) path or filename (full path is recommanded to skip path searching for better perf)
|
|
9
11
|
- args: `[]` 参数列表 arguments list
|
|
@@ -184,12 +186,11 @@ export async function call_nodejs(js, args = [], { inspect, break: _break, ...op
|
|
|
184
186
|
...args
|
|
185
187
|
], options);
|
|
186
188
|
}
|
|
187
|
-
export const exe_winterm = `C:/Users/${
|
|
189
|
+
export const exe_winterm = `C:/Users/${username}/AppData/Local/Microsoft/WindowsApps/wt.exe`;
|
|
188
190
|
/** 新建 terminal 窗口执行进程 New Terminal window execution process
|
|
189
191
|
- exe: exe 文件路径 exe file path
|
|
190
192
|
- args: 调用参数 call parameter
|
|
191
|
-
- options?: WinTermOptions
|
|
192
|
-
*/
|
|
193
|
+
- options?: WinTermOptions */
|
|
193
194
|
export async function term(exe, args = [], { cwd = process.cwd().fpd, print = true, title,
|
|
194
195
|
// env
|
|
195
196
|
} = {}) {
|
package/utils.browser.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export declare class Lock<TResource = void> {
|
|
|
51
51
|
}
|
|
52
52
|
export declare function pause(milliseconds?: number): Promise<void>;
|
|
53
53
|
/** 字符串字典序比较 */
|
|
54
|
-
export declare function strcmp(l: string, r: string):
|
|
54
|
+
export declare function strcmp(l: string, r: string): 1 | 0 | -1;
|
|
55
55
|
/** 比较 1.10.02 这种版本号 */
|
|
56
56
|
export declare function vercmp(l: string, r: string): number;
|
|
57
57
|
export declare function get<TReturn = any>(obj: any, keypath: string): TReturn;
|
package/utils.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare function unique<T>(iterable: T[] | Iterable<T>, selector?: string
|
|
|
22
22
|
/** 排序对象中 key 的顺序,返回新的对象 */
|
|
23
23
|
export declare function sort_keys<T>(obj: T): T;
|
|
24
24
|
/** 字符串字典序比较 */
|
|
25
|
-
export declare function strcmp(l: string, r: string):
|
|
25
|
+
export declare function strcmp(l: string, r: string): 1 | 0 | -1;
|
|
26
26
|
/** 比较 1.10.02 这种版本号 */
|
|
27
27
|
export declare function vercmp(l: string, r: string): number;
|
|
28
28
|
export declare function get<TReturn = any>(obj: any, keypath: string): TReturn;
|