@foss.global/gitmanager 2.0.0 → 2.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/changelog.md +19 -0
- package/dist_rust/rustgitmanager_linux_amd64 +0 -0
- package/dist_rust/rustgitmanager_linux_amd64.tsrust-build.json +5 -5
- package/dist_rust/rustgitmanager_linux_arm64 +0 -0
- package/dist_rust/rustgitmanager_linux_arm64.tsrust-build.json +5 -5
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.archiveinspection.d.ts +11 -0
- package/dist_ts/classes.archiveinspection.js +205 -0
- package/dist_ts/classes.gitmanager.d.ts +19 -1
- package/dist_ts/classes.gitmanager.js +54 -1
- package/dist_ts/classes.gitmanagererror.d.ts +11 -0
- package/dist_ts/classes.gitmanagererror.js +22 -0
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts/models.d.ts +54 -0
- package/dist_ts/rust-gitmanager-bridge.d.ts +5 -1
- package/dist_ts/rust-gitmanager-bridge.js +41 -2
- package/package.json +6 -6
- package/readme.md +38 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.archiveinspection.ts +245 -0
- package/ts/classes.gitmanager.ts +62 -0
- package/ts/classes.gitmanagererror.ts +28 -0
- package/ts/index.ts +2 -0
- package/ts/models.ts +65 -0
- package/ts/rust-gitmanager-bridge.ts +48 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TGitManagerErrorCode } from './models.js';
|
|
2
|
+
|
|
3
|
+
const gitManagerErrorCodes: ReadonlySet<string> = new Set<TGitManagerErrorCode>([
|
|
4
|
+
'invalidObjectId',
|
|
5
|
+
'objectNotFound',
|
|
6
|
+
'objectNotCommit',
|
|
7
|
+
'ancestryBudgetExceeded',
|
|
8
|
+
'archiveLimitExceeded',
|
|
9
|
+
'archiveRejected',
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
export const isGitManagerErrorCode = (valueArg: unknown): valueArg is TGitManagerErrorCode =>
|
|
13
|
+
typeof valueArg === 'string' && gitManagerErrorCodes.has(valueArg);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A failure callers can branch on through its stable `code`. Other failures,
|
|
17
|
+
* such as an unknown repository or an engine that is not running, remain
|
|
18
|
+
* plain errors.
|
|
19
|
+
*/
|
|
20
|
+
export class GitManagerError extends Error {
|
|
21
|
+
public readonly code: TGitManagerErrorCode;
|
|
22
|
+
|
|
23
|
+
constructor(codeArg: TGitManagerErrorCode, messageArg: string, optionsArg?: ErrorOptions) {
|
|
24
|
+
super(messageArg, optionsArg);
|
|
25
|
+
this.name = 'GitManagerError';
|
|
26
|
+
this.code = codeArg;
|
|
27
|
+
}
|
|
28
|
+
}
|
package/ts/index.ts
CHANGED
|
@@ -2,3 +2,5 @@ export * from './models.js';
|
|
|
2
2
|
export * from './rust-gitmanager-bridge.js';
|
|
3
3
|
export * from './classes.gitmanager.js';
|
|
4
4
|
export * from './classes.repositoryservice.js';
|
|
5
|
+
export * from './classes.gitmanagererror.js';
|
|
6
|
+
export { gitManagerArchivePathMetadataCeilingBytes } from './classes.archiveinspection.js';
|
package/ts/models.ts
CHANGED
|
@@ -89,6 +89,71 @@ export interface IGitManagerRepositoryArchive
|
|
|
89
89
|
entryCount: number;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Asks whether `ancestorObjectId` is reachable from `descendantObjectId`
|
|
94
|
+
* (`git merge-base --is-ancestor`; a commit is its own ancestor). Both must be
|
|
95
|
+
* full lowercase object IDs of commits in the repository; revision
|
|
96
|
+
* expressions, abbreviations, and tag objects are refused.
|
|
97
|
+
*/
|
|
98
|
+
export interface IGitManagerAncestryRequest extends IGitManagerRepositorySelector {
|
|
99
|
+
ancestorObjectId: string;
|
|
100
|
+
descendantObjectId: string;
|
|
101
|
+
/**
|
|
102
|
+
* Wall-clock work budget for the object lookup and the history walk,
|
|
103
|
+
* 1 to 60000 ms, default 10000. Exceeding it throws a `GitManagerError`
|
|
104
|
+
* with code `ancestryBudgetExceeded`.
|
|
105
|
+
*/
|
|
106
|
+
timeoutMs?: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Limits for inspecting one `tar.gz` archive. Every limit is inclusive.
|
|
111
|
+
*/
|
|
112
|
+
export interface IGitManagerArchiveInspectionRequest {
|
|
113
|
+
/** The archive bytes, or a stream of them; it is consumed and closed. */
|
|
114
|
+
archive: Uint8Array | AsyncIterable<Uint8Array>;
|
|
115
|
+
maxCompressedBytes: number;
|
|
116
|
+
maxExtractedBytes: number;
|
|
117
|
+
maxEntries: number;
|
|
118
|
+
/**
|
|
119
|
+
* Ceiling for the UTF-8 bytes of every effective entry path and symlink
|
|
120
|
+
* target, 1 to 134217728 (the fixed ci-spec ceiling, and the default).
|
|
121
|
+
*/
|
|
122
|
+
maxPathMetadataBytes?: number;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface IGitManagerArchiveInspectionOptions {
|
|
126
|
+
signal?: AbortSignal;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Metadata recomputed from an accepted archive; nothing is taken on trust. */
|
|
130
|
+
export interface IGitManagerArchiveInspection {
|
|
131
|
+
sizeBytes: number;
|
|
132
|
+
sha256: string;
|
|
133
|
+
extractedSizeBytes: number;
|
|
134
|
+
entryCount: number;
|
|
135
|
+
pathMetadataBytes: number;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Stable codes of `GitManagerError`.
|
|
140
|
+
*
|
|
141
|
+
* - `invalidObjectId`: an object ID is not a full lowercase SHA-1 or SHA-256.
|
|
142
|
+
* - `objectNotFound`: the object does not exist in the repository.
|
|
143
|
+
* - `objectNotCommit`: the object exists but is not a commit.
|
|
144
|
+
* - `ancestryBudgetExceeded`: the ancestry check exceeded `timeoutMs`; the
|
|
145
|
+
* answer is unknown, never `false`.
|
|
146
|
+
* - `archiveLimitExceeded`: the archive exceeds a requested limit.
|
|
147
|
+
* - `archiveRejected`: the archive breaks a format, path, or link rule.
|
|
148
|
+
*/
|
|
149
|
+
export type TGitManagerErrorCode =
|
|
150
|
+
| 'invalidObjectId'
|
|
151
|
+
| 'objectNotFound'
|
|
152
|
+
| 'objectNotCommit'
|
|
153
|
+
| 'ancestryBudgetExceeded'
|
|
154
|
+
| 'archiveLimitExceeded'
|
|
155
|
+
| 'archiveRejected';
|
|
156
|
+
|
|
92
157
|
export interface IGitManagerRepositoryLfsPointer {
|
|
93
158
|
oid: string;
|
|
94
159
|
sizeBytes: number;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
|
+
import { GitManagerError, isGitManagerErrorCode } from './classes.gitmanagererror.js';
|
|
2
3
|
import type {
|
|
4
|
+
IGitManagerAncestryRequest,
|
|
3
5
|
IGitManagerCommitDetail,
|
|
4
6
|
IGitManagerCommitRequest,
|
|
5
7
|
IGitManagerCommitSummary,
|
|
@@ -74,6 +76,7 @@ type TGitManagerCommands = {
|
|
|
74
76
|
mergeRepository: { params: IGitManagerMergeRequest; result: IGitManagerMergeResult };
|
|
75
77
|
listTree: { params: IGitManagerTreeRequest; result: IGitManagerTreeEntry[] };
|
|
76
78
|
readFile: { params: IGitManagerReadFileRequest; result: IGitManagerFileContent };
|
|
79
|
+
isAncestor: { params: IGitManagerAncestryRequest; result: boolean };
|
|
77
80
|
listCommits: { params: IGitManagerListCommitsRequest; result: IGitManagerCommitSummary[] };
|
|
78
81
|
getCommit: { params: IGitManagerCommitRequest; result: IGitManagerCommitDetail };
|
|
79
82
|
getDiff: { params: IGitManagerDiffRequest; result: IGitManagerDiff };
|
|
@@ -109,16 +112,37 @@ function buildLocalPaths(): string[] {
|
|
|
109
112
|
return paths;
|
|
110
113
|
}
|
|
111
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Rethrows a Rust response that carries a stable GitManager error code as a
|
|
117
|
+
* `GitManagerError`; every other failure is rethrown unchanged.
|
|
118
|
+
*/
|
|
119
|
+
const rethrowCodedError = (errorArg: unknown): never => {
|
|
120
|
+
if (
|
|
121
|
+
errorArg instanceof plugins.smartrust.RustBridgeRequestError
|
|
122
|
+
&& isGitManagerErrorCode(errorArg.responseErrorCode)
|
|
123
|
+
) {
|
|
124
|
+
throw new GitManagerError(errorArg.responseErrorCode, errorArg.message, {
|
|
125
|
+
cause: errorArg,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
throw errorArg;
|
|
129
|
+
};
|
|
130
|
+
|
|
112
131
|
export class RustGitManagerBridge extends plugins.EventEmitter {
|
|
113
132
|
private bridge: plugins.smartrust.RustBridge<TGitManagerCommands>;
|
|
133
|
+
private binaryLocator: plugins.smartrust.RustBinaryLocator;
|
|
114
134
|
|
|
115
135
|
constructor() {
|
|
116
136
|
super();
|
|
117
|
-
|
|
137
|
+
const binaryLocatorOptions: plugins.smartrust.IBinaryLocatorOptions = {
|
|
118
138
|
binaryName: 'rustgitmanager',
|
|
119
139
|
envVarName: 'GITMANAGER_RUST_BINARY',
|
|
120
140
|
platformPackagePrefix: '@foss.global/gitmanager',
|
|
121
141
|
localPaths: buildLocalPaths(),
|
|
142
|
+
};
|
|
143
|
+
this.binaryLocator = new plugins.smartrust.RustBinaryLocator(binaryLocatorOptions);
|
|
144
|
+
this.bridge = new plugins.smartrust.RustBridge<TGitManagerCommands>({
|
|
145
|
+
...binaryLocatorOptions,
|
|
122
146
|
requestTimeoutMs: 130000,
|
|
123
147
|
readyTimeoutMs: 10000,
|
|
124
148
|
});
|
|
@@ -135,6 +159,15 @@ export class RustGitManagerBridge extends plugins.EventEmitter {
|
|
|
135
159
|
return this.bridge.spawn();
|
|
136
160
|
}
|
|
137
161
|
|
|
162
|
+
/** Resolves the engine binary the bridge spawns, for its one-shot modes. */
|
|
163
|
+
public async findBinary(): Promise<string> {
|
|
164
|
+
const binaryPath = await this.binaryLocator.findBinary();
|
|
165
|
+
if (!binaryPath) {
|
|
166
|
+
throw new Error('Unable to locate the rustgitmanager binary');
|
|
167
|
+
}
|
|
168
|
+
return binaryPath;
|
|
169
|
+
}
|
|
170
|
+
|
|
138
171
|
public kill(): void {
|
|
139
172
|
this.bridge.kill();
|
|
140
173
|
}
|
|
@@ -304,6 +337,20 @@ export class RustGitManagerBridge extends plugins.EventEmitter {
|
|
|
304
337
|
return this.bridge.sendCommand('readFile', requestArg);
|
|
305
338
|
}
|
|
306
339
|
|
|
340
|
+
public async isAncestor(requestArg: IGitManagerAncestryRequest): Promise<boolean> {
|
|
341
|
+
const result = await this.bridge.sendCommand('isAncestor', {
|
|
342
|
+
org: requestArg.org,
|
|
343
|
+
repo: requestArg.repo,
|
|
344
|
+
ancestorObjectId: requestArg.ancestorObjectId,
|
|
345
|
+
descendantObjectId: requestArg.descendantObjectId,
|
|
346
|
+
...(requestArg.timeoutMs === undefined ? {} : { timeoutMs: requestArg.timeoutMs }),
|
|
347
|
+
}).catch(rethrowCodedError);
|
|
348
|
+
if (typeof result !== 'boolean') {
|
|
349
|
+
throw new Error('Rust GitManager returned an invalid ancestry result');
|
|
350
|
+
}
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
353
|
+
|
|
307
354
|
public async listCommits(requestArg: IGitManagerListCommitsRequest): Promise<IGitManagerCommitSummary[]> {
|
|
308
355
|
return this.bridge.sendCommand('listCommits', requestArg);
|
|
309
356
|
}
|