@seed-fe/mfa-git 0.1.0
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/LICENSE +22 -0
- package/README.md +107 -0
- package/README.zh-CN.md +107 -0
- package/dist/clone.d.ts +22 -0
- package/dist/clone.d.ts.map +1 -0
- package/dist/clone.js +33 -0
- package/dist/clone.js.map +1 -0
- package/dist/git.d.ts +22 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +59 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/release-version.d.ts +75 -0
- package/dist/release-version.d.ts.map +1 -0
- package/dist/release-version.js +85 -0
- package/dist/release-version.js.map +1 -0
- package/dist/repository.d.ts +46 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +68 -0
- package/dist/repository.js.map +1 -0
- package/dist/sync.d.ts +51 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +103 -0
- package/dist/sync.js.map +1 -0
- package/dist/tag.d.ts +26 -0
- package/dist/tag.d.ts.map +1 -0
- package/dist/tag.js +33 -0
- package/dist/tag.js.map +1 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nicholas Hsiang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @seed-fe/mfa-git
|
|
2
|
+
|
|
3
|
+
English | [简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
Git operations and release naming rules for [MFA](https://github.com/xianghongai/seed-fe-mfa) workspaces, used by the `mfa` CLI and the VS Code extension. Git runs on the `git` command line through [simple-git](https://github.com/steveukx/git-js). Authentication, SSH keys, credential helpers and proxies all stay with the developer's own Git setup; nothing here asks for or stores credentials, and no hosting service API is involved.
|
|
6
|
+
|
|
7
|
+
- Pulls only fetch and fast-forward, and never switch branches. When git refuses to fast-forward, the result says so instead of throwing.
|
|
8
|
+
- Pushes never force. A rejected push is a result, not an exception.
|
|
9
|
+
- Remotes are resolved from the branch upstream, then the only remote of the repository. The name is never assumed to be `origin`.
|
|
10
|
+
- ES modules only, for Node.js.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm install @seed-fe/mfa-git
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
Every function takes the directory to run in as `cwd`, plus optional `env`, `signal`, `onCommand` and `onOutput`:
|
|
21
|
+
|
|
22
|
+
- `env` is merged over `process.env`, for example to add an outbound proxy. `GIT_TERMINAL_PROMPT=0` is always set, so git never waits for a password prompt.
|
|
23
|
+
- `signal` cancels the running git process.
|
|
24
|
+
- `onCommand` receives each command line before it runs; `onOutput` receives stdout and stderr as they arrive.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { branchStatus, pullBranch, pushBranch } from '@seed-fe/mfa-git';
|
|
28
|
+
|
|
29
|
+
const status = await branchStatus({ cwd: '/path/to/repo', branch: 'release/1.0.0' });
|
|
30
|
+
// { branch, remote: 'upstream', state: 'ok', behind: 2, ahead: 1 }
|
|
31
|
+
|
|
32
|
+
const pulled = await pullBranch({ cwd: '/path/to/repo', branch: 'release/1.0.0' });
|
|
33
|
+
// outcome: 'updated' | 'upToDate' | 'fetchedOnly' | 'skipped'
|
|
34
|
+
|
|
35
|
+
const pushed = await pushBranch({ cwd: '/path/to/repo', branch: 'release/1.0.0' });
|
|
36
|
+
// outcome: 'pushed' | 'upToDate' | 'rejected' | 'skipped'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Branches
|
|
40
|
+
|
|
41
|
+
| Function | What it does |
|
|
42
|
+
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
43
|
+
| `branchStatus({ cwd, branch })` | Fetches, then counts commits `behind` and `ahead` of the remote branch. Changes no local branch or file. |
|
|
44
|
+
| `pullBranch({ cwd, branch })` | Fetches, then fast-forwards: `merge --ff-only` when the branch is checked out, otherwise only the branch pointer moves. |
|
|
45
|
+
| `pushBranch({ cwd, branch })` | Pushes the branch to the remote branch of the same name without checking it out, creating it when missing. |
|
|
46
|
+
|
|
47
|
+
`state` explains when a branch cannot be checked: `noRepository`, `noRemote`, `remoteBranchMissing` or `failed` (with `message`).
|
|
48
|
+
|
|
49
|
+
### Tags
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { createTag } from '@seed-fe/mfa-git';
|
|
53
|
+
|
|
54
|
+
await createTag({
|
|
55
|
+
cwd: '/path/to/repo',
|
|
56
|
+
name: '1.2.0',
|
|
57
|
+
commit: 'a1b2c3d',
|
|
58
|
+
message: 'Release notes\n\n#123 fixed paging', // optional: creates an annotated tag
|
|
59
|
+
force: true, // optional: overwrite an existing tag, on the remote too
|
|
60
|
+
push: { remote: 'upstream' }, // optional
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The message is kept as written, including lines starting with `#`. When the push fails, the local tag is removed, or restored when it was overwritten.
|
|
65
|
+
|
|
66
|
+
### Sources
|
|
67
|
+
|
|
68
|
+
| Function | What it does |
|
|
69
|
+
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
70
|
+
| `clone({ url, directory, branch?, submodules? })` | Clones into `directory`, creating its parents. Submodules are included by default. |
|
|
71
|
+
| `checkoutTag({ url, tag, directory })` | Shallow-fetches one tag by URL and checks it out as a detached HEAD, with submodules. Adds no remote. |
|
|
72
|
+
|
|
73
|
+
### Release versions
|
|
74
|
+
|
|
75
|
+
Versions follow the MFA naming conventions: an optional `v` prefix (a Tag equals `release.version`), the base version, a patch level (`HP`, `CP` or `SP`, for projects), the maturity (`alpha`, `beta` or `rc`; none once released) and, always last, a customer edition `C<customer>` with its delivery batch `-U<n>`. For example `1.7.1-alpha.3`, `2.6.0.SP1-rc.1` and `1.7.1-rc.1.CICBC-U2`. Every version is a valid Docker image tag, so `+` is rejected.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { releaseCandidates } from '@seed-fe/mfa-git';
|
|
79
|
+
|
|
80
|
+
releaseCandidates('1.7.1-alpha.3.CICBC-U2');
|
|
81
|
+
// { ok: true, candidates: { iterate: '1.7.1-alpha.4.CICBC-U2', advance: { stage: 'beta', version: '1.7.1-beta.1.CICBC-U2' } } }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Only the maturity moves; patch levels and customer editions are planned by the project and kept as written. A released version, a version with `+` and an invalid one give `released`, `plusNotAllowed` and `versionInvalid`. `parseReleaseVersion`, `formatReleaseVersion`, `releaseLine` and `compareReleaseVersions` read, write, group and order versions; only versions of the same line (base, patch level and customer edition) are compared.
|
|
85
|
+
|
|
86
|
+
### Repository
|
|
87
|
+
|
|
88
|
+
| Function | Returns |
|
|
89
|
+
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
90
|
+
| `isRepositoryRoot({ cwd })` | Whether `cwd` is itself a repository root, not a directory inside an outer repository |
|
|
91
|
+
| `currentBranch({ cwd })` | The checked-out branch; `undefined` on a detached HEAD |
|
|
92
|
+
| `resolveRemote({ cwd, branch? })` | The branch upstream remote, otherwise the only remote |
|
|
93
|
+
| `remoteUrl({ cwd, remote?, branch? })` | URL of the given or resolved remote |
|
|
94
|
+
| `resolveCommit({ cwd, ref })` / `commitInfo({ cwd, ref })` | Commit SHA; or `{ sha, shortSha, subject }` |
|
|
95
|
+
| `mergedTags({ cwd, ref })` / `tagExists({ cwd, name })` | Tags reachable from a ref; whether a tag exists |
|
|
96
|
+
| `sameTree({ cwd, a, b })` | Whether two refs have the same content |
|
|
97
|
+
| `worktreeChanges({ cwd })` | Number of tracked files with uncommitted changes |
|
|
98
|
+
|
|
99
|
+
`createGit(options)` gives the underlying runner (`run` and `probe`) for commands not covered here.
|
|
100
|
+
|
|
101
|
+
## Environment
|
|
102
|
+
|
|
103
|
+
simple-git rejects environment variables such as `GIT_SSH_COMMAND`, `GIT_ASKPASS`, `GIT_CONFIG_*` and even `PAGER` by default. This package runs fixed commands and uses the developer's own environment, so those checks are turned off for environment and configuration categories only.
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
[MIT](LICENSE)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @seed-fe/mfa-git
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 简体中文
|
|
4
|
+
|
|
5
|
+
[MFA](https://github.com/xianghongai/seed-fe-mfa) 工作区的 Git 操作与发布命名规则,供 `mfa` 命令行和 VS Code 扩展使用。Git 通过 [simple-git](https://github.com/steveukx/git-js) 调用本机的 `git` 命令行。认证、SSH 密钥、凭据助手和代理全部沿用开发者自己的 Git 配置:本包不索取、不保存凭据,也不调用任何托管平台的 API。
|
|
6
|
+
|
|
7
|
+
- 拉取只获取和快进,不切换分支。Git 拒绝快进时在结果中说明,不抛错。
|
|
8
|
+
- 推送不强推,被远程拒绝时作为结果返回,不抛错。
|
|
9
|
+
- 远程按分支的上游解析,其次是仓库唯一的远程,不假定叫 `origin`。
|
|
10
|
+
- 只提供 ES 模块,用于 Node.js。
|
|
11
|
+
|
|
12
|
+
## 安装
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm install @seed-fe/mfa-git
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 使用
|
|
19
|
+
|
|
20
|
+
每个函数都用 `cwd` 指定运行目录,可选 `env`、`signal`、`onCommand`、`onOutput`:
|
|
21
|
+
|
|
22
|
+
- `env` 合并到 `process.env` 之上,例如加入出站代理。始终设置 `GIT_TERMINAL_PROMPT=0`,Git 不会停下来等待输入密码。
|
|
23
|
+
- `signal` 取消正在运行的 Git 进程。
|
|
24
|
+
- `onCommand` 在每条命令运行前收到命令行;`onOutput` 实时收到标准输出和标准错误。
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { branchStatus, pullBranch, pushBranch } from '@seed-fe/mfa-git';
|
|
28
|
+
|
|
29
|
+
const status = await branchStatus({ cwd: '/path/to/repo', branch: 'release/1.0.0' });
|
|
30
|
+
// { branch, remote: 'upstream', state: 'ok', behind: 2, ahead: 1 }
|
|
31
|
+
|
|
32
|
+
const pulled = await pullBranch({ cwd: '/path/to/repo', branch: 'release/1.0.0' });
|
|
33
|
+
// outcome: 'updated' | 'upToDate' | 'fetchedOnly' | 'skipped'
|
|
34
|
+
|
|
35
|
+
const pushed = await pushBranch({ cwd: '/path/to/repo', branch: 'release/1.0.0' });
|
|
36
|
+
// outcome: 'pushed' | 'upToDate' | 'rejected' | 'skipped'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 分支
|
|
40
|
+
|
|
41
|
+
| 函数 | 作用 |
|
|
42
|
+
| ------------------------------- | --------------------------------------------------------------------------------- |
|
|
43
|
+
| `branchStatus({ cwd, branch })` | 获取远程后,统计落后(`behind`)与领先(`ahead`)的提交数。不改动本地分支和文件。 |
|
|
44
|
+
| `pullBranch({ cwd, branch })` | 获取远程后快进:分支已检出时 `merge --ff-only`,否则只移动分支指针。 |
|
|
45
|
+
| `pushBranch({ cwd, branch })` | 不检出分支,把它推送到远程同名分支;远程没有时创建。 |
|
|
46
|
+
|
|
47
|
+
无法检查时,`state` 说明原因:`noRepository`、`noRemote`、`remoteBranchMissing`,或 `failed`(附 `message`)。
|
|
48
|
+
|
|
49
|
+
### Tag
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { createTag } from '@seed-fe/mfa-git';
|
|
53
|
+
|
|
54
|
+
await createTag({
|
|
55
|
+
cwd: '/path/to/repo',
|
|
56
|
+
name: '1.2.0',
|
|
57
|
+
commit: 'a1b2c3d',
|
|
58
|
+
message: 'Release notes\n\n#123 fixed paging', // 可选:创建附注 Tag
|
|
59
|
+
force: true, // 可选:覆盖已有的同名 Tag,远程同样覆盖
|
|
60
|
+
push: { remote: 'upstream' }, // 可选
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
说明原样保留,包括以 `#` 开头的行。推送失败时,新建的本地 Tag 被删除;覆盖的则恢复原状。
|
|
65
|
+
|
|
66
|
+
### 源码
|
|
67
|
+
|
|
68
|
+
| 函数 | 作用 |
|
|
69
|
+
| ------------------------------------------------- | ---------------------------------------------------------------- |
|
|
70
|
+
| `clone({ url, directory, branch?, submodules? })` | 克隆到 `directory`,自动创建上级目录;默认包含子模块。 |
|
|
71
|
+
| `checkoutTag({ url, tag, directory })` | 按地址浅获取单个 Tag,检出为分离 HEAD 并更新子模块;不添加远程。 |
|
|
72
|
+
|
|
73
|
+
### 发布版本
|
|
74
|
+
|
|
75
|
+
版本遵循 MFA 命名规范:可选的 `v` 前缀(Tag 与 `release.version` 完全一致)、基线版本、补丁(`HP`、`CP`、`SP`,仅项目)、成熟度(`alpha`、`beta`、`rc`,正式版没有),以及始终在最后的客户定制 `C<客户代号>` 与更新批次 `-U<n>`。例如 `1.7.1-alpha.3`、`2.6.0.SP1-rc.1`、`1.7.1-rc.1.CICBC-U2`。每个版本都是合法的 Docker 镜像 Tag,因此不允许 `+`。
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { releaseCandidates } from '@seed-fe/mfa-git';
|
|
79
|
+
|
|
80
|
+
releaseCandidates('1.7.1-alpha.3.CICBC-U2');
|
|
81
|
+
// { ok: true, candidates: { iterate: '1.7.1-alpha.4.CICBC-U2', advance: { stage: 'beta', version: '1.7.1-beta.1.CICBC-U2' } } }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
只推进成熟度;补丁与客户定制由项目规划,原样保留。正式版、含 `+` 的版本和不合规的版本分别返回 `released`、`plusNotAllowed`、`versionInvalid`。`parseReleaseVersion`、`formatReleaseVersion`、`releaseLine`、`compareReleaseVersions` 用于解析、格式化、划分产品线与排序;只比较同一产品线(基线、补丁、客户定制)内的版本。
|
|
85
|
+
|
|
86
|
+
### 仓库
|
|
87
|
+
|
|
88
|
+
| 函数 | 返回 |
|
|
89
|
+
| ---------------------------------------------------------- | ------------------------------------------------ |
|
|
90
|
+
| `isRepositoryRoot({ cwd })` | `cwd` 本身是否为仓库根,而不是外层仓库里的子目录 |
|
|
91
|
+
| `currentBranch({ cwd })` | 当前分支;分离 HEAD 时为 `undefined` |
|
|
92
|
+
| `resolveRemote({ cwd, branch? })` | 分支上游的远程,否则为唯一的远程 |
|
|
93
|
+
| `remoteUrl({ cwd, remote?, branch? })` | 指定或解析出的远程地址 |
|
|
94
|
+
| `resolveCommit({ cwd, ref })` / `commitInfo({ cwd, ref })` | 提交 SHA;或 `{ sha, shortSha, subject }` |
|
|
95
|
+
| `mergedTags({ cwd, ref })` / `tagExists({ cwd, name })` | 从某个引用可达的 Tag;Tag 是否存在 |
|
|
96
|
+
| `sameTree({ cwd, a, b })` | 两个引用的内容是否相同 |
|
|
97
|
+
| `worktreeChanges({ cwd })` | 有未提交改动的已跟踪文件数 |
|
|
98
|
+
|
|
99
|
+
其它命令可以用 `createGit(options)` 取得底层的执行器(`run` 与 `probe`)。
|
|
100
|
+
|
|
101
|
+
## 环境变量
|
|
102
|
+
|
|
103
|
+
simple-git 默认拒绝 `GIT_SSH_COMMAND`、`GIT_ASKPASS`、`GIT_CONFIG_*`,甚至普通的 `PAGER` 等环境变量。本包执行的命令都是固定的,使用的是开发者自己的环境,因此只对环境变量与配置相关的类别关闭了这些检查。
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
[MIT](LICENSE)
|
package/dist/clone.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type GitOptions } from './git.js';
|
|
2
|
+
export interface CloneOptions extends Omit<GitOptions, 'cwd'> {
|
|
3
|
+
url: string;
|
|
4
|
+
directory: string;
|
|
5
|
+
/** Branch to check out; defaults to the remote's default branch. */
|
|
6
|
+
branch?: string | undefined;
|
|
7
|
+
/** Clones submodules too; defaults to `true`. */
|
|
8
|
+
submodules?: boolean | undefined;
|
|
9
|
+
}
|
|
10
|
+
/** Clones `url` into `directory`, creating its parent directories. */
|
|
11
|
+
export declare const clone: ({ url, directory, branch, submodules, ...options }: CloneOptions) => Promise<void>;
|
|
12
|
+
export interface CheckoutTagOptions extends Omit<GitOptions, 'cwd'> {
|
|
13
|
+
url: string;
|
|
14
|
+
tag: string;
|
|
15
|
+
directory: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Checks out exactly one tag of `url` into `directory` with a shallow fetch, as a detached HEAD, with submodules.
|
|
19
|
+
* The repository is fetched by URL, so no remote name is added or assumed.
|
|
20
|
+
*/
|
|
21
|
+
export declare const checkoutTag: ({ url, tag, directory, ...options }: CheckoutTagOptions) => Promise<void>;
|
|
22
|
+
//# sourceMappingURL=clone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AAKA,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtD,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,iDAAiD;IACjD,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAClC;AAED,sEAAsE;AACtE,eAAO,MAAM,KAAK,uDAAqE,YAAY,KAAG,OAAO,CAAC,IAAI,CAWjH,CAAC;AAEF,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,wCAA+C,kBAAkB,KAAG,OAAO,CAAC,IAAI,CAQvG,CAAC"}
|
package/dist/clone.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Getting sources: cloning a repository, or checking out a single tag into an empty directory.
|
|
3
|
+
*/
|
|
4
|
+
import { mkdir } from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { createGit } from './git.js';
|
|
7
|
+
/** Clones `url` into `directory`, creating its parent directories. */
|
|
8
|
+
export const clone = async ({ url, directory, branch, submodules = true, ...options }) => {
|
|
9
|
+
const parent = path.dirname(directory);
|
|
10
|
+
await mkdir(parent, { recursive: true });
|
|
11
|
+
await createGit({ ...options, cwd: parent }).run([
|
|
12
|
+
'clone',
|
|
13
|
+
...(branch ? ['--branch', branch] : []),
|
|
14
|
+
...(submodules ? ['--recurse-submodules'] : []),
|
|
15
|
+
'--',
|
|
16
|
+
url,
|
|
17
|
+
directory,
|
|
18
|
+
]);
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Checks out exactly one tag of `url` into `directory` with a shallow fetch, as a detached HEAD, with submodules.
|
|
22
|
+
* The repository is fetched by URL, so no remote name is added or assumed.
|
|
23
|
+
*/
|
|
24
|
+
export const checkoutTag = async ({ url, tag, directory, ...options }) => {
|
|
25
|
+
await mkdir(directory, { recursive: true });
|
|
26
|
+
const git = createGit({ ...options, cwd: directory });
|
|
27
|
+
const ref = `refs/tags/${tag}`;
|
|
28
|
+
await git.run(['init', '--quiet']);
|
|
29
|
+
await git.run(['fetch', '--depth=1', '--', url, `${ref}:${ref}`]);
|
|
30
|
+
await git.run(['checkout', '--detach', ref]);
|
|
31
|
+
await git.run(['submodule', 'update', '--init', '--recursive']);
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=clone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAmB,MAAM,UAAU,CAAC;AAWtD,sEAAsE;AACtE,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,GAAG,OAAO,EAAgB,EAAiB,EAAE;IACpH,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC;QAC/C,OAAO;QACP,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,IAAI;QACJ,GAAG;QACH,SAAS;KACV,CAAC,CAAC;AACL,CAAC,CAAC;AAQF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,OAAO,EAAsB,EAAiB,EAAE;IAC1G,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,aAAa,GAAG,EAAE,CAAC;IAC/B,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACnC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7C,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;AAClE,CAAC,CAAC"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface GitOptions {
|
|
2
|
+
/** Directory the commands run in. */
|
|
3
|
+
cwd: string;
|
|
4
|
+
/** Extra environment variables, e.g. an outbound proxy; merged over `process.env`. */
|
|
5
|
+
env?: Record<string, string | undefined> | undefined;
|
|
6
|
+
signal?: AbortSignal | undefined;
|
|
7
|
+
/** Called with each command line before it runs, e.g. `git fetch --tags -- origin`. */
|
|
8
|
+
onCommand?: ((command: string) => void) | undefined;
|
|
9
|
+
/** Called with stdout and stderr chunks as they arrive. */
|
|
10
|
+
onOutput?: ((text: string) => void) | undefined;
|
|
11
|
+
}
|
|
12
|
+
export interface Git {
|
|
13
|
+
/** Runs a command and returns its trimmed stdout; rejects when git exits with an error. */
|
|
14
|
+
run(args: string[]): Promise<string>;
|
|
15
|
+
/** Runs a command for probing: any failure other than cancellation resolves to `undefined`. */
|
|
16
|
+
probe(args: string[]): Promise<string | undefined>;
|
|
17
|
+
}
|
|
18
|
+
export declare const errorMessage: (error: unknown) => string;
|
|
19
|
+
export declare const createGit: (options: GitOptions) => Git;
|
|
20
|
+
/** simple-git requires an existing base directory; a missing one simply has no repository. */
|
|
21
|
+
export declare const directoryExists: (directory: string) => boolean;
|
|
22
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,sFAAsF;IACtF,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IACrD,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,uFAAuF;IACvF,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACpD,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACjD;AAED,MAAM,WAAW,GAAG;IAClB,2FAA2F;IAC3F,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,+FAA+F;IAC/F,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,MAAkE,CAAC;AAQjH,eAAO,MAAM,SAAS,YAAa,UAAU,KAAG,GA2C/C,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,eAAe,cAAe,MAAM,KAAG,OAAgC,CAAC"}
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs git through simple-git in a directory, with the developer's own environment and Git configuration.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { simpleGit } from 'simple-git';
|
|
6
|
+
export const errorMessage = (error) => (error instanceof Error ? error.message : String(error));
|
|
7
|
+
const throwIfAborted = (signal) => {
|
|
8
|
+
if (signal?.aborted) {
|
|
9
|
+
throw signal.reason ?? new Error('Aborted');
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export const createGit = (options) => {
|
|
13
|
+
// simple-git replaces the environment instead of merging it; never prompt for credentials interactively.
|
|
14
|
+
const env = { ...process.env, GIT_TERMINAL_PROMPT: '0', ...options.env };
|
|
15
|
+
const client = simpleGit({
|
|
16
|
+
baseDir: options.cwd,
|
|
17
|
+
trimmed: true,
|
|
18
|
+
...(options.signal ? { abort: options.signal } : {}),
|
|
19
|
+
// Commands and their arguments are fixed by this package; the environment and configuration are the
|
|
20
|
+
// developer's own (SSH command, askpass, credential helper, proxy, even an ordinary PAGER or GIT_EDITOR).
|
|
21
|
+
// simple-git rejects them by default, and its environment guard would throw on the ones passed on and
|
|
22
|
+
// silently drop the inherited ones, so the whole environment handed to git is allowed.
|
|
23
|
+
allowEnvironment: Object.keys(env),
|
|
24
|
+
unsafe: {
|
|
25
|
+
allowUnsafeAskPass: true,
|
|
26
|
+
allowUnsafeConfigEnvCount: true,
|
|
27
|
+
allowUnsafeConfigPaths: true,
|
|
28
|
+
allowUnsafeCredentialHelper: true,
|
|
29
|
+
allowUnsafeEditor: true,
|
|
30
|
+
allowUnsafeGitProxy: true,
|
|
31
|
+
allowUnsafePager: true,
|
|
32
|
+
allowUnsafeSshCommand: true,
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
.env(env)
|
|
36
|
+
.outputHandler((_command, stdout, stderr, args) => {
|
|
37
|
+
options.onCommand?.(['git', ...args].join(' '));
|
|
38
|
+
if (options.onOutput) {
|
|
39
|
+
stdout.on('data', (chunk) => options.onOutput?.(chunk.toString()));
|
|
40
|
+
stderr.on('data', (chunk) => options.onOutput?.(chunk.toString()));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const run = (args) => client.raw(args);
|
|
44
|
+
return {
|
|
45
|
+
run,
|
|
46
|
+
probe: async (args) => {
|
|
47
|
+
try {
|
|
48
|
+
return await run(args);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
throwIfAborted(options.signal);
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
/** simple-git requires an existing base directory; a missing one simply has no repository. */
|
|
58
|
+
export const directoryExists = (directory) => existsSync(directory);
|
|
59
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createGit, type Git, type GitOptions } from './git.js';
|
|
2
|
+
export { commitInfo, currentBranch, isRepositoryRoot, mergedTags, remoteUrl, resolveCommit, resolveRemote, sameTree, tagExists, worktreeChanges, type CommitInfo, } from './repository.js';
|
|
3
|
+
export { branchStatus, pullBranch, pushBranch, type BranchOptions, type BranchPullOutcome, type BranchPullResult, type BranchPushOutcome, type BranchPushResult, type BranchState, type BranchStatus, } from './sync.js';
|
|
4
|
+
export { createTag, type CreateTagOptions, type CreateTagResult } from './tag.js';
|
|
5
|
+
export { checkoutTag, clone, type CheckoutTagOptions, type CloneOptions } from './clone.js';
|
|
6
|
+
export { compareReleaseVersions, formatReleaseVersion, parseReleaseVersion, releaseCandidates, releaseLine, type Maturity, type PatchType, type ReleaseCandidates, type ReleaseCandidatesResult, type ReleaseStage, type ReleaseVersion, type ReleaseVersionIssue, } from './release-version.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,GAAG,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,EACL,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,aAAa,EACb,aAAa,EACb,QAAQ,EACR,SAAS,EACT,eAAe,EACf,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,YAAY,EACZ,UAAU,EACV,UAAU,EACV,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC5F,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,EACX,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createGit } from './git.js';
|
|
2
|
+
export { commitInfo, currentBranch, isRepositoryRoot, mergedTags, remoteUrl, resolveCommit, resolveRemote, sameTree, tagExists, worktreeChanges, } from './repository.js';
|
|
3
|
+
export { branchStatus, pullBranch, pushBranch, } from './sync.js';
|
|
4
|
+
export { createTag } from './tag.js';
|
|
5
|
+
export { checkoutTag, clone } from './clone.js';
|
|
6
|
+
export { compareReleaseVersions, formatReleaseVersion, parseReleaseVersion, releaseCandidates, releaseLine, } from './release-version.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA6B,MAAM,UAAU,CAAC;AAChE,OAAO,EACL,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,aAAa,EACb,aAAa,EACb,QAAQ,EACR,SAAS,EACT,eAAe,GAEhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,YAAY,EACZ,UAAU,EACV,UAAU,GAQX,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAA+C,MAAM,UAAU,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,KAAK,EAA8C,MAAM,YAAY,CAAC;AAC5F,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,GAQZ,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MFA release versions, following "微前端 6 - 命名规范与仓库规划":
|
|
3
|
+
*
|
|
4
|
+
* <release> ::= ["v"] <major> "." <minor> "." <patch>
|
|
5
|
+
* [ "." <patch-type> <patch-number> ] ; HP, CP or SP, project versions only
|
|
6
|
+
* [ "-" <maturity> "." <iteration> ] ; alpha, beta or rc; none means released
|
|
7
|
+
* [ "." "C" <customer> [ "-U" <delivery> ] ] ; customer edition and its delivery
|
|
8
|
+
*
|
|
9
|
+
* The customer edition comes last, like a Docker image variant, so every version is also a valid image tag.
|
|
10
|
+
* `+` is never allowed: Docker image tags reject it.
|
|
11
|
+
*
|
|
12
|
+
* Only the maturity moves here (next iteration, next stage). Patch and customer segments are planned by the
|
|
13
|
+
* project and kept as written, and a released version needs a new release plan instead of a computed one.
|
|
14
|
+
*/
|
|
15
|
+
export type ReleaseStage = 'beta' | 'rc' | 'release';
|
|
16
|
+
export type Maturity = 'alpha' | 'beta' | 'rc';
|
|
17
|
+
export type PatchType = 'HP' | 'CP' | 'SP';
|
|
18
|
+
export interface ReleaseVersion {
|
|
19
|
+
/** `v` when written with the Tag prefix. */
|
|
20
|
+
prefix: '' | 'v';
|
|
21
|
+
major: number;
|
|
22
|
+
minor: number;
|
|
23
|
+
patch: number;
|
|
24
|
+
/** Hot patch, cold patch or service pack, e.g. `SP1`. */
|
|
25
|
+
patchLevel?: {
|
|
26
|
+
type: PatchType;
|
|
27
|
+
number: number;
|
|
28
|
+
};
|
|
29
|
+
/** Absent for a released version. */
|
|
30
|
+
maturity?: {
|
|
31
|
+
stage: Maturity;
|
|
32
|
+
iteration: number;
|
|
33
|
+
};
|
|
34
|
+
/** Customer edition, e.g. `CICBC-U2`: code `ICBC` and delivery 2. */
|
|
35
|
+
customer?: {
|
|
36
|
+
code: string;
|
|
37
|
+
delivery?: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export interface ReleaseCandidates {
|
|
41
|
+
/** The next iteration of the same maturity, e.g. 1.1.0-alpha.83 → 1.1.0-alpha.84. */
|
|
42
|
+
iterate: string;
|
|
43
|
+
/** The next maturity stage, starting at iteration 1; after rc comes the release itself. */
|
|
44
|
+
advance: {
|
|
45
|
+
stage: ReleaseStage;
|
|
46
|
+
version: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* `versionInvalid`: not an MFA release version; `plusNotAllowed`: uses `+`, which Docker image tags reject
|
|
51
|
+
* (customer editions are written `.C<customer>`); `released`: already released, a new version needs a new plan.
|
|
52
|
+
*/
|
|
53
|
+
export type ReleaseVersionIssue = 'versionInvalid' | 'plusNotAllowed' | 'released';
|
|
54
|
+
export type ReleaseCandidatesResult = {
|
|
55
|
+
ok: true;
|
|
56
|
+
candidates: ReleaseCandidates;
|
|
57
|
+
} | {
|
|
58
|
+
ok: false;
|
|
59
|
+
reason: ReleaseVersionIssue;
|
|
60
|
+
};
|
|
61
|
+
export declare const parseReleaseVersion: (version: string) => ReleaseVersion | undefined;
|
|
62
|
+
export declare const formatReleaseVersion: (version: ReleaseVersion) => string;
|
|
63
|
+
/**
|
|
64
|
+
* The product line a version belongs to: base version, patch level and customer edition, without the maturity
|
|
65
|
+
* or the `v` prefix. Only versions of the same line are compared, so a standard release never stands in for a
|
|
66
|
+
* customer edition, nor one customer for another.
|
|
67
|
+
*/
|
|
68
|
+
export declare const releaseLine: (version: ReleaseVersion) => string;
|
|
69
|
+
/**
|
|
70
|
+
* Orders two versions of the same line by maturity and iteration; versions of different lines are ordered by
|
|
71
|
+
* their line so that sorting stays stable. Returns a negative number, zero or a positive number.
|
|
72
|
+
*/
|
|
73
|
+
export declare const compareReleaseVersions: (left: ReleaseVersion, right: ReleaseVersion) => number;
|
|
74
|
+
export declare const releaseCandidates: (version: string) => ReleaseCandidatesResult;
|
|
75
|
+
//# sourceMappingURL=release-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-version.d.ts","sourceRoot":"","sources":["../src/release-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AACrD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;AAC/C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,MAAM,EAAE,EAAE,GAAG,GAAG,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,qCAAqC;IACrC,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,qEAAqE;IACrE,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED,MAAM,WAAW,iBAAiB;IAChC,qFAAqF;IACrF,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,OAAO,EAAE;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,UAAU,CAAC;AAEnF,MAAM,MAAM,uBAAuB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,iBAAiB,CAAA;CAAE,GAC3C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAK/C,eAAO,MAAM,mBAAmB,YAAa,MAAM,KAAG,cAAc,GAAG,SAetE,CAAC;AAKF,eAAO,MAAM,oBAAoB,YAAa,cAAc,KAAG,MAOnD,CAAC;AAEb;;;;GAIG;AACH,eAAO,MAAM,WAAW,YAAa,cAAc,KAAG,MACa,CAAC;AAMpE;;;GAGG;AACH,eAAO,MAAM,sBAAsB,SAAU,cAAc,SAAS,cAAc,KAAG,MAOpF,CAAC;AAIF,eAAO,MAAM,iBAAiB,YAAa,MAAM,KAAG,uBAsBnD,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MFA release versions, following "微前端 6 - 命名规范与仓库规划":
|
|
3
|
+
*
|
|
4
|
+
* <release> ::= ["v"] <major> "." <minor> "." <patch>
|
|
5
|
+
* [ "." <patch-type> <patch-number> ] ; HP, CP or SP, project versions only
|
|
6
|
+
* [ "-" <maturity> "." <iteration> ] ; alpha, beta or rc; none means released
|
|
7
|
+
* [ "." "C" <customer> [ "-U" <delivery> ] ] ; customer edition and its delivery
|
|
8
|
+
*
|
|
9
|
+
* The customer edition comes last, like a Docker image variant, so every version is also a valid image tag.
|
|
10
|
+
* `+` is never allowed: Docker image tags reject it.
|
|
11
|
+
*
|
|
12
|
+
* Only the maturity moves here (next iteration, next stage). Patch and customer segments are planned by the
|
|
13
|
+
* project and kept as written, and a released version needs a new release plan instead of a computed one.
|
|
14
|
+
*/
|
|
15
|
+
const pattern = /^(v)?(\d+)\.(\d+)\.(\d+)(?:\.(HP|CP|SP)(\d+))?(?:-(alpha|beta|rc)\.(\d+))?(?:\.C([A-Z0-9]+)(?:-U(\d+))?)?$/u;
|
|
16
|
+
export const parseReleaseVersion = (version) => {
|
|
17
|
+
const match = pattern.exec(version);
|
|
18
|
+
if (!match) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const [, prefix, major, minor, patch, patchType, patchNumber, stage, iteration, customer, delivery] = match;
|
|
22
|
+
return {
|
|
23
|
+
prefix: prefix ? 'v' : '',
|
|
24
|
+
major: Number(major),
|
|
25
|
+
minor: Number(minor),
|
|
26
|
+
patch: Number(patch),
|
|
27
|
+
...(patchType ? { patchLevel: { type: patchType, number: Number(patchNumber) } } : {}),
|
|
28
|
+
...(stage ? { maturity: { stage: stage, iteration: Number(iteration) } } : {}),
|
|
29
|
+
...(customer ? { customer: { code: customer, ...(delivery ? { delivery: Number(delivery) } : {}) } } : {}),
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/** The same version without its maturity, i.e. its released form. */
|
|
33
|
+
const withoutMaturity = ({ maturity: _maturity, ...version }) => version;
|
|
34
|
+
export const formatReleaseVersion = (version) => [
|
|
35
|
+
`${version.prefix}${version.major}.${version.minor}.${version.patch}`,
|
|
36
|
+
version.patchLevel ? `.${version.patchLevel.type}${version.patchLevel.number}` : '',
|
|
37
|
+
version.maturity ? `-${version.maturity.stage}.${version.maturity.iteration}` : '',
|
|
38
|
+
version.customer ? `.C${version.customer.code}` : '',
|
|
39
|
+
version.customer?.delivery !== undefined ? `-U${version.customer.delivery}` : '',
|
|
40
|
+
].join('');
|
|
41
|
+
/**
|
|
42
|
+
* The product line a version belongs to: base version, patch level and customer edition, without the maturity
|
|
43
|
+
* or the `v` prefix. Only versions of the same line are compared, so a standard release never stands in for a
|
|
44
|
+
* customer edition, nor one customer for another.
|
|
45
|
+
*/
|
|
46
|
+
export const releaseLine = (version) => formatReleaseVersion({ ...withoutMaturity(version), prefix: '' });
|
|
47
|
+
const maturityRank = { alpha: 0, beta: 1, rc: 2 };
|
|
48
|
+
// A released version comes after every prerelease of the same line.
|
|
49
|
+
const rank = (version) => (version.maturity ? maturityRank[version.maturity.stage] : 3);
|
|
50
|
+
/**
|
|
51
|
+
* Orders two versions of the same line by maturity and iteration; versions of different lines are ordered by
|
|
52
|
+
* their line so that sorting stays stable. Returns a negative number, zero or a positive number.
|
|
53
|
+
*/
|
|
54
|
+
export const compareReleaseVersions = (left, right) => {
|
|
55
|
+
const leftLine = releaseLine(left);
|
|
56
|
+
const rightLine = releaseLine(right);
|
|
57
|
+
if (leftLine !== rightLine) {
|
|
58
|
+
return leftLine < rightLine ? -1 : 1;
|
|
59
|
+
}
|
|
60
|
+
return rank(left) - rank(right) || (left.maturity?.iteration ?? 0) - (right.maturity?.iteration ?? 0);
|
|
61
|
+
};
|
|
62
|
+
const nextStage = { alpha: 'beta', beta: 'rc', rc: 'release' };
|
|
63
|
+
export const releaseCandidates = (version) => {
|
|
64
|
+
if (version.includes('+')) {
|
|
65
|
+
return { ok: false, reason: 'plusNotAllowed' };
|
|
66
|
+
}
|
|
67
|
+
const parsed = parseReleaseVersion(version);
|
|
68
|
+
if (!parsed) {
|
|
69
|
+
return { ok: false, reason: 'versionInvalid' };
|
|
70
|
+
}
|
|
71
|
+
const { maturity } = parsed;
|
|
72
|
+
if (!maturity) {
|
|
73
|
+
return { ok: false, reason: 'released' };
|
|
74
|
+
}
|
|
75
|
+
const stage = nextStage[maturity.stage];
|
|
76
|
+
const next = stage === 'release' ? withoutMaturity(parsed) : { ...parsed, maturity: { stage, iteration: 1 } };
|
|
77
|
+
return {
|
|
78
|
+
ok: true,
|
|
79
|
+
candidates: {
|
|
80
|
+
iterate: formatReleaseVersion({ ...parsed, maturity: { ...maturity, iteration: maturity.iteration + 1 } }),
|
|
81
|
+
advance: { stage, version: formatReleaseVersion(next) },
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=release-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-version.js","sourceRoot":"","sources":["../src/release-version.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Git, type GitOptions } from './git.js';
|
|
2
|
+
export interface CommitInfo {
|
|
3
|
+
sha: string;
|
|
4
|
+
shortSha: string;
|
|
5
|
+
subject: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const lines: (value: string | undefined) => string[];
|
|
8
|
+
/**
|
|
9
|
+
* Whether `cwd` is itself the root of a repository, not a directory inside an outer one
|
|
10
|
+
* (for example a workspace that is also under Git).
|
|
11
|
+
*/
|
|
12
|
+
export declare const isRepositoryRoot: (options: GitOptions) => Promise<boolean>;
|
|
13
|
+
/** The checked-out branch; `undefined` on a detached HEAD or outside a repository. */
|
|
14
|
+
export declare const currentBranch: (options: GitOptions) => Promise<string | undefined>;
|
|
15
|
+
/** The remote of `branch`: its upstream, otherwise the only remote of the repository. */
|
|
16
|
+
export declare const resolveRemote: (options: GitOptions & {
|
|
17
|
+
branch?: string | undefined;
|
|
18
|
+
}) => Promise<string | undefined>;
|
|
19
|
+
/** URL of `remote`, or of the remote that `resolveRemote` picks. */
|
|
20
|
+
export declare const remoteUrl: (options: GitOptions & {
|
|
21
|
+
remote?: string | undefined;
|
|
22
|
+
branch?: string | undefined;
|
|
23
|
+
}) => Promise<string | undefined>;
|
|
24
|
+
export declare const resolveCommitWith: (git: Git, ref: string) => Promise<string | undefined>;
|
|
25
|
+
/** Commit SHA of `ref`, or `undefined` when it does not exist. */
|
|
26
|
+
export declare const resolveCommit: (options: GitOptions & {
|
|
27
|
+
ref: string;
|
|
28
|
+
}) => Promise<string | undefined>;
|
|
29
|
+
export declare const commitInfo: (options: GitOptions & {
|
|
30
|
+
ref: string;
|
|
31
|
+
}) => Promise<CommitInfo | undefined>;
|
|
32
|
+
/** Whether two refs point at the same content, regardless of history. */
|
|
33
|
+
export declare const sameTree: (options: GitOptions & {
|
|
34
|
+
a: string;
|
|
35
|
+
b: string;
|
|
36
|
+
}) => Promise<boolean>;
|
|
37
|
+
/** Tags reachable from `ref`. */
|
|
38
|
+
export declare const mergedTags: (options: GitOptions & {
|
|
39
|
+
ref: string;
|
|
40
|
+
}) => Promise<string[]>;
|
|
41
|
+
export declare const tagExists: (options: GitOptions & {
|
|
42
|
+
name: string;
|
|
43
|
+
}) => Promise<boolean>;
|
|
44
|
+
/** Number of tracked files with uncommitted changes. */
|
|
45
|
+
export declare const worktreeChanges: (options: GitOptions) => Promise<number>;
|
|
46
|
+
//# sourceMappingURL=repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAIA,OAAO,EAA8B,KAAK,GAAG,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAEjF,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,KAAK,UAAW,MAAM,GAAG,SAAS,KAAG,MAAM,EAIpC,CAAC;AAErB;;;GAGG;AACH,eAAO,MAAM,gBAAgB,YAAmB,UAAU,KAAG,OAAO,CAAC,OAAO,CAM3E,CAAC;AAEF,sFAAsF;AACtF,eAAO,MAAM,aAAa,YAAmB,UAAU,KAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CACW,CAAC;AAchG,yFAAyF;AACzF,eAAO,MAAM,aAAa,YAAmB,UAAU,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,gCACzC,CAAC;AAEjD,oEAAoE;AACpE,eAAO,MAAM,SAAS,YACX,UAAU,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,KACjF,OAAO,CAAC,MAAM,GAAG,SAAS,CAI5B,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAe,GAAG,OAAO,MAAM,KAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CACD,CAAC;AAE1F,kEAAkE;AAClE,eAAO,MAAM,aAAa,YAAa,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,gCACf,CAAC;AAErD,eAAO,MAAM,UAAU,YAAmB,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,KAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAQtG,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,QAAQ,YAAmB,UAAU,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,OAAO,CAAC,OAAO,CAO9F,CAAC;AAEF,iCAAiC;AACjC,eAAO,MAAM,UAAU,YAAmB,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,KAAG,OAAO,CAAC,MAAM,EAAE,CAClB,CAAC;AAExE,eAAO,MAAM,SAAS,YAAmB,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,KAAG,OAAO,CAAC,OAAO,CACoB,CAAC;AAE7G,wDAAwD;AACxD,eAAO,MAAM,eAAe,YAAmB,UAAU,KAAG,OAAO,CAAC,MAAM,CACqB,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only questions about a repository: its root, branch, remote, commits and tags.
|
|
3
|
+
*/
|
|
4
|
+
import { realpath } from 'node:fs/promises';
|
|
5
|
+
import { createGit, directoryExists } from './git.js';
|
|
6
|
+
export const lines = (value) => (value ?? '')
|
|
7
|
+
.split('\n')
|
|
8
|
+
.map((line) => line.trim())
|
|
9
|
+
.filter(Boolean);
|
|
10
|
+
/**
|
|
11
|
+
* Whether `cwd` is itself the root of a repository, not a directory inside an outer one
|
|
12
|
+
* (for example a workspace that is also under Git).
|
|
13
|
+
*/
|
|
14
|
+
export const isRepositoryRoot = async (options) => {
|
|
15
|
+
if (!directoryExists(options.cwd)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const topLevel = await createGit(options).probe(['rev-parse', '--show-toplevel']);
|
|
19
|
+
return Boolean(topLevel) && (await realpath(topLevel)) === (await realpath(options.cwd));
|
|
20
|
+
};
|
|
21
|
+
/** The checked-out branch; `undefined` on a detached HEAD or outside a repository. */
|
|
22
|
+
export const currentBranch = async (options) => (await createGit(options).probe(['symbolic-ref', '--quiet', '--short', 'HEAD'])) || undefined;
|
|
23
|
+
const findRemote = async (git, branch) => {
|
|
24
|
+
if (branch) {
|
|
25
|
+
const upstream = await git.probe(['for-each-ref', '--format=%(upstream:remotename)', `refs/heads/${branch}`]);
|
|
26
|
+
if (upstream) {
|
|
27
|
+
return upstream;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Without an upstream, only a single remote is unambiguous; the name is never assumed to be origin.
|
|
31
|
+
const remotes = lines(await git.probe(['remote']));
|
|
32
|
+
return remotes.length === 1 ? remotes[0] : undefined;
|
|
33
|
+
};
|
|
34
|
+
/** The remote of `branch`: its upstream, otherwise the only remote of the repository. */
|
|
35
|
+
export const resolveRemote = async (options) => findRemote(createGit(options), options.branch);
|
|
36
|
+
/** URL of `remote`, or of the remote that `resolveRemote` picks. */
|
|
37
|
+
export const remoteUrl = async (options) => {
|
|
38
|
+
const git = createGit(options);
|
|
39
|
+
const remote = options.remote ?? (await findRemote(git, options.branch));
|
|
40
|
+
return remote ? (await git.probe(['remote', 'get-url', '--', remote])) || undefined : undefined;
|
|
41
|
+
};
|
|
42
|
+
export const resolveCommitWith = async (git, ref) => (await git.probe(['rev-parse', '--verify', '--quiet', `${ref}^{commit}`])) || undefined;
|
|
43
|
+
/** Commit SHA of `ref`, or `undefined` when it does not exist. */
|
|
44
|
+
export const resolveCommit = (options) => resolveCommitWith(createGit(options), options.ref);
|
|
45
|
+
export const commitInfo = async (options) => {
|
|
46
|
+
const git = createGit(options);
|
|
47
|
+
const sha = await resolveCommitWith(git, options.ref);
|
|
48
|
+
if (!sha) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const [shortSha = '', subject = ''] = (await git.run(['log', '-1', '--format=%h%x00%s', sha])).split('\0');
|
|
52
|
+
return { sha, shortSha, subject };
|
|
53
|
+
};
|
|
54
|
+
/** Whether two refs point at the same content, regardless of history. */
|
|
55
|
+
export const sameTree = async (options) => {
|
|
56
|
+
const git = createGit(options);
|
|
57
|
+
const [a, b] = await Promise.all([
|
|
58
|
+
git.probe(['rev-parse', `${options.a}^{tree}`]),
|
|
59
|
+
git.probe(['rev-parse', `${options.b}^{tree}`]),
|
|
60
|
+
]);
|
|
61
|
+
return a !== undefined && a === b;
|
|
62
|
+
};
|
|
63
|
+
/** Tags reachable from `ref`. */
|
|
64
|
+
export const mergedTags = async (options) => lines(await createGit(options).run(['tag', '--merged', options.ref]));
|
|
65
|
+
export const tagExists = async (options) => Boolean(await createGit(options).probe(['rev-parse', '--verify', '--quiet', `refs/tags/${options.name}`]));
|
|
66
|
+
/** Number of tracked files with uncommitted changes. */
|
|
67
|
+
export const worktreeChanges = async (options) => lines(await createGit(options).run(['status', '--porcelain', '--untracked-files=no'])).length;
|
|
68
|
+
//# sourceMappingURL=repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
|
package/dist/sync.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keeping a branch in step with its remote. Pulling only fetches and fast-forwards; pushing never forces.
|
|
3
|
+
*
|
|
4
|
+
* Checking only fetches: remote-tracking branches and tags move, the worktree and local branches do not.
|
|
5
|
+
* Pulling fast-forwards the branch after fetching: `merge --ff-only` when it is checked out, otherwise it only
|
|
6
|
+
* moves the branch pointer. Branches are never switched. When git refuses to fast-forward (diverged history, or
|
|
7
|
+
* local changes that would be overwritten), the result is `fetchedOnly`, not an error.
|
|
8
|
+
* Pushing sends the local branch to the remote branch of the same name without checking it out, creating it when
|
|
9
|
+
* missing; a non-fast-forward push is rejected by the remote and reported as `rejected`.
|
|
10
|
+
*/
|
|
11
|
+
import { type GitOptions } from './git.js';
|
|
12
|
+
/** `ok` means `behind` and `ahead` are known; the other states explain why the branch could not be checked. */
|
|
13
|
+
export type BranchState = 'ok' | 'noRepository' | 'noRemote' | 'remoteBranchMissing' | 'failed';
|
|
14
|
+
export interface BranchStatus {
|
|
15
|
+
branch: string;
|
|
16
|
+
remote?: string;
|
|
17
|
+
state: BranchState;
|
|
18
|
+
/** Commits on the remote branch that the local branch lacks; all of them when there is no local branch yet. */
|
|
19
|
+
behind?: number;
|
|
20
|
+
/** Local commits not on the remote branch; all of them when the remote branch does not exist yet. */
|
|
21
|
+
ahead?: number;
|
|
22
|
+
/** Why the check failed. */
|
|
23
|
+
message?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* `updated`: fast-forwarded; `upToDate`: nothing to pull; `fetchedOnly`: git refused to fast-forward, so only the
|
|
27
|
+
* fetch happened; `skipped`: there is no remote branch to pull from.
|
|
28
|
+
*/
|
|
29
|
+
export type BranchPullOutcome = 'updated' | 'upToDate' | 'fetchedOnly' | 'skipped';
|
|
30
|
+
export interface BranchPullResult extends BranchStatus {
|
|
31
|
+
outcome: BranchPullOutcome;
|
|
32
|
+
/** Commits fast-forwarded when `updated`. */
|
|
33
|
+
count?: number;
|
|
34
|
+
}
|
|
35
|
+
/** `pushed`; `upToDate`: nothing to push; `rejected` by the remote, usually pull first; `skipped`: nothing to push to. */
|
|
36
|
+
export type BranchPushOutcome = 'pushed' | 'upToDate' | 'rejected' | 'skipped';
|
|
37
|
+
export interface BranchPushResult extends BranchStatus {
|
|
38
|
+
outcome: BranchPushOutcome;
|
|
39
|
+
/** Commits pushed when `pushed`. */
|
|
40
|
+
count?: number;
|
|
41
|
+
}
|
|
42
|
+
export interface BranchOptions extends GitOptions {
|
|
43
|
+
branch: string;
|
|
44
|
+
}
|
|
45
|
+
/** Fetches and counts how far the branch is behind and ahead of its remote; changes no local branch or file. */
|
|
46
|
+
export declare const branchStatus: (options: BranchOptions) => Promise<BranchStatus>;
|
|
47
|
+
/** Fetches, then fast-forwards the branch to its remote; only fetches when a fast-forward is impossible. */
|
|
48
|
+
export declare const pullBranch: (options: BranchOptions) => Promise<BranchPullResult>;
|
|
49
|
+
/** Pushes the local branch to the remote branch of the same name, creating it when missing. Never forces. */
|
|
50
|
+
export declare const pushBranch: (options: BranchOptions) => Promise<BranchPushResult>;
|
|
51
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAqC,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAG9E,+GAA+G;AAC/G,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,cAAc,GAAG,UAAU,GAAG,qBAAqB,GAAG,QAAQ,CAAC;AAEhG,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,WAAW,CAAC;IACnB,+GAA+G;IAC/G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qGAAqG;IACrG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC;AAEnF,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,OAAO,EAAE,iBAAiB,CAAC;IAC3B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,0HAA0H;AAC1H,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;AAE/E,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,OAAO,EAAE,iBAAiB,CAAC;IAC3B,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,MAAM,EAAE,MAAM,CAAC;CAChB;AA6CD,gHAAgH;AAChH,eAAO,MAAM,YAAY,YAAmB,aAAa,KAAG,OAAO,CAAC,YAAY,CAAoC,CAAC;AAErH,4GAA4G;AAC5G,eAAO,MAAM,UAAU,YAAmB,aAAa,KAAG,OAAO,CAAC,gBAAgB,CAyBjF,CAAC;AAEF,6GAA6G;AAC7G,eAAO,MAAM,UAAU,YAAmB,aAAa,KAAG,OAAO,CAAC,gBAAgB,CAoBjF,CAAC"}
|
package/dist/sync.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keeping a branch in step with its remote. Pulling only fetches and fast-forwards; pushing never forces.
|
|
3
|
+
*
|
|
4
|
+
* Checking only fetches: remote-tracking branches and tags move, the worktree and local branches do not.
|
|
5
|
+
* Pulling fast-forwards the branch after fetching: `merge --ff-only` when it is checked out, otherwise it only
|
|
6
|
+
* moves the branch pointer. Branches are never switched. When git refuses to fast-forward (diverged history, or
|
|
7
|
+
* local changes that would be overwritten), the result is `fetchedOnly`, not an error.
|
|
8
|
+
* Pushing sends the local branch to the remote branch of the same name without checking it out, creating it when
|
|
9
|
+
* missing; a non-fast-forward push is rejected by the remote and reported as `rejected`.
|
|
10
|
+
*/
|
|
11
|
+
import { createGit, errorMessage } from './git.js';
|
|
12
|
+
import { isRepositoryRoot, resolveCommitWith, resolveRemote } from './repository.js';
|
|
13
|
+
const inspect = async (options) => {
|
|
14
|
+
const { branch } = options;
|
|
15
|
+
const status = { branch, state: 'ok' };
|
|
16
|
+
try {
|
|
17
|
+
if (!(await isRepositoryRoot(options))) {
|
|
18
|
+
return { status: { ...status, state: 'noRepository' } };
|
|
19
|
+
}
|
|
20
|
+
const remote = await resolveRemote(options);
|
|
21
|
+
if (!remote) {
|
|
22
|
+
return { status: { ...status, state: 'noRemote' } };
|
|
23
|
+
}
|
|
24
|
+
status.remote = remote;
|
|
25
|
+
const git = createGit(options);
|
|
26
|
+
await git.run(['fetch', '--tags', '--', remote]);
|
|
27
|
+
const remoteRef = `refs/remotes/${remote}/${branch}`;
|
|
28
|
+
const localRef = `refs/heads/${branch}`;
|
|
29
|
+
const hasLocal = (await resolveCommitWith(git, localRef)) !== undefined;
|
|
30
|
+
const count = async (range) => Number(await git.run(['rev-list', '--count', range]));
|
|
31
|
+
if (!(await resolveCommitWith(git, remoteRef))) {
|
|
32
|
+
return {
|
|
33
|
+
status: { ...status, state: 'remoteBranchMissing', ...(hasLocal ? { ahead: await count(localRef) } : {}) },
|
|
34
|
+
git,
|
|
35
|
+
hasLocal,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
status.behind = await count(hasLocal ? `${localRef}..${remoteRef}` : remoteRef);
|
|
39
|
+
status.ahead = hasLocal ? await count(`${remoteRef}..${localRef}`) : 0;
|
|
40
|
+
return { status, git, remoteRef, hasLocal };
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (options.signal?.aborted) {
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
return { status: { ...status, state: 'failed', message: errorMessage(error) } };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
/** Fetches and counts how far the branch is behind and ahead of its remote; changes no local branch or file. */
|
|
50
|
+
export const branchStatus = async (options) => (await inspect(options)).status;
|
|
51
|
+
/** Fetches, then fast-forwards the branch to its remote; only fetches when a fast-forward is impossible. */
|
|
52
|
+
export const pullBranch = async (options) => {
|
|
53
|
+
const { status, git, remoteRef } = await inspect(options);
|
|
54
|
+
if (status.state !== 'ok' || !git || !remoteRef) {
|
|
55
|
+
return { ...status, outcome: 'skipped' };
|
|
56
|
+
}
|
|
57
|
+
const count = status.behind ?? 0;
|
|
58
|
+
if (count === 0) {
|
|
59
|
+
return { ...status, outcome: 'upToDate' };
|
|
60
|
+
}
|
|
61
|
+
const current = await git.probe(['symbolic-ref', '--quiet', '--short', 'HEAD']);
|
|
62
|
+
try {
|
|
63
|
+
if (current === status.branch) {
|
|
64
|
+
// Updates the worktree; git refuses when uncommitted changes would be overwritten and keeps them.
|
|
65
|
+
await git.run(['merge', '--ff-only', remoteRef]);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Moves the branch pointer only, creating the branch when missing; without `+`, git refuses non-fast-forwards.
|
|
69
|
+
await git.run(['fetch', '.', `${remoteRef}:refs/heads/${status.branch}`]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (options.signal?.aborted) {
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
return { ...status, outcome: 'fetchedOnly', message: errorMessage(error) };
|
|
77
|
+
}
|
|
78
|
+
return { ...status, behind: 0, outcome: 'updated', count };
|
|
79
|
+
};
|
|
80
|
+
/** Pushes the local branch to the remote branch of the same name, creating it when missing. Never forces. */
|
|
81
|
+
export const pushBranch = async (options) => {
|
|
82
|
+
const { status, git, hasLocal } = await inspect(options);
|
|
83
|
+
const canPush = status.state === 'ok' || status.state === 'remoteBranchMissing';
|
|
84
|
+
if (!canPush || !git || !hasLocal || !status.remote) {
|
|
85
|
+
return { ...status, outcome: 'skipped' };
|
|
86
|
+
}
|
|
87
|
+
const count = status.ahead ?? 0;
|
|
88
|
+
if (status.state === 'ok' && count === 0) {
|
|
89
|
+
return { ...status, outcome: 'upToDate' };
|
|
90
|
+
}
|
|
91
|
+
const ref = `refs/heads/${status.branch}`;
|
|
92
|
+
try {
|
|
93
|
+
await git.run(['push', '--', status.remote, `${ref}:${ref}`]);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (options.signal?.aborted) {
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
return { ...status, outcome: 'rejected', message: errorMessage(error) };
|
|
100
|
+
}
|
|
101
|
+
return { ...status, state: 'ok', behind: status.behind ?? 0, ahead: 0, outcome: 'pushed', count };
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=sync.js.map
|
package/dist/sync.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
|
package/dist/tag.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creating a tag, optionally annotated, overwriting and pushed; a failed push leaves the local tags as they were.
|
|
3
|
+
*/
|
|
4
|
+
import { type GitOptions } from './git.js';
|
|
5
|
+
export interface CreateTagOptions extends GitOptions {
|
|
6
|
+
name: string;
|
|
7
|
+
/** Commit (or any ref) to tag. */
|
|
8
|
+
commit: string;
|
|
9
|
+
/** Creates an annotated tag when not blank; the message is kept as written, including lines starting with `#`. */
|
|
10
|
+
message?: string | undefined;
|
|
11
|
+
/** Overwrites an existing tag of the same name, locally and on the remote. */
|
|
12
|
+
force?: boolean | undefined;
|
|
13
|
+
/** Pushes the tag to this remote after creating it. */
|
|
14
|
+
push?: {
|
|
15
|
+
remote: string;
|
|
16
|
+
} | undefined;
|
|
17
|
+
}
|
|
18
|
+
export interface CreateTagResult {
|
|
19
|
+
name: string;
|
|
20
|
+
commit: string;
|
|
21
|
+
/** Whether an existing tag was overwritten. */
|
|
22
|
+
overwritten: boolean;
|
|
23
|
+
pushed: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare const createTag: (options: CreateTagOptions) => Promise<CreateTagResult>;
|
|
26
|
+
//# sourceMappingURL=tag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../src/tag.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtD,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,kHAAkH;IAClH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,uDAAuD;IACvD,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACvC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,SAAS,YAAmB,gBAAgB,KAAG,OAAO,CAAC,eAAe,CA0BlF,CAAC"}
|
package/dist/tag.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creating a tag, optionally annotated, overwriting and pushed; a failed push leaves the local tags as they were.
|
|
3
|
+
*/
|
|
4
|
+
import { createGit } from './git.js';
|
|
5
|
+
export const createTag = async (options) => {
|
|
6
|
+
const git = createGit(options);
|
|
7
|
+
const ref = `refs/tags/${options.name}`;
|
|
8
|
+
// The object the tag pointed at before, restored when the push fails.
|
|
9
|
+
const previous = (await git.probe(['rev-parse', '--verify', '--quiet', ref])) || undefined;
|
|
10
|
+
if (previous && !options.force) {
|
|
11
|
+
throw new Error(`Tag ${options.name} already exists; pass force to overwrite it`);
|
|
12
|
+
}
|
|
13
|
+
const message = options.message?.trim();
|
|
14
|
+
// The default `strip` cleanup would drop lines starting with `#`, such as issue references.
|
|
15
|
+
const annotation = message ? ['-a', '-m', message, '--cleanup=whitespace'] : [];
|
|
16
|
+
await git.run(['tag', ...(previous ? ['-f'] : []), ...annotation, '--', options.name, options.commit]);
|
|
17
|
+
if (options.push) {
|
|
18
|
+
try {
|
|
19
|
+
await git.run(['push', '--', options.push.remote, `${previous ? '+' : ''}${ref}`]);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
await git.run(previous ? ['update-ref', ref, previous] : ['tag', '-d', '--', options.name]);
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
name: options.name,
|
|
28
|
+
commit: await git.run(['rev-parse', `${ref}^{commit}`]),
|
|
29
|
+
overwritten: previous !== undefined,
|
|
30
|
+
pushed: options.push !== undefined,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=tag.js.map
|
package/dist/tag.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag.js","sourceRoot":"","sources":["../src/tag.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,SAAS,EAAmB,MAAM,UAAU,CAAC;AAsBtD,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,OAAyB,EAA4B,EAAE;IACrF,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,aAAa,OAAO,CAAC,IAAI,EAAE,CAAC;IACxC,sEAAsE;IACtE,MAAM,QAAQ,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;IAC3F,IAAI,QAAQ,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,OAAO,OAAO,CAAC,IAAI,6CAA6C,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IACxC,4FAA4F;IAC5F,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChF,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACvG,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;QACrF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5F,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,WAAW,CAAC,CAAC;QACvD,WAAW,EAAE,QAAQ,KAAK,SAAS;QACnC,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK,SAAS;KACnC,CAAC;AACJ,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seed-fe/mfa-git",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Git operations and release naming rules for MFA (seed-fe-mfa) workspaces: branch status, fast-forward pull, push, tags with rollback, clone, tag checkout and release version calculation. Authentication stays with the developer's own Git setup.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"git",
|
|
7
|
+
"mfa",
|
|
8
|
+
"micro-frontend",
|
|
9
|
+
"release",
|
|
10
|
+
"seed-fe",
|
|
11
|
+
"semver",
|
|
12
|
+
"tag"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/xianghongai/seed-fe-mfa-git#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/xianghongai/seed-fe-mfa-git/issues"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "Nicholas Hsiang",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/xianghongai/seed-fe-mfa-git.git"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"README.zh-CN.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"type": "module",
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"default": "./dist/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"simple-git": "^4.0.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@changesets/changelog-github": "^1.0.1",
|
|
48
|
+
"@changesets/cli": "^3.0.3",
|
|
49
|
+
"@types/node": "^26.6.2",
|
|
50
|
+
"oxfmt": "^0.65.0",
|
|
51
|
+
"oxlint": "^1.85.0",
|
|
52
|
+
"typescript": "^7.0.2",
|
|
53
|
+
"vitest": "^4.1.11"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=20"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc -p tsconfig.build.json",
|
|
60
|
+
"changeset": "changeset",
|
|
61
|
+
"check-types": "tsc --noEmit",
|
|
62
|
+
"format": "oxfmt",
|
|
63
|
+
"format:check": "oxfmt --check",
|
|
64
|
+
"lint": "oxlint src test",
|
|
65
|
+
"release": "changeset publish",
|
|
66
|
+
"test": "vitest run"
|
|
67
|
+
}
|
|
68
|
+
}
|