@foss.global/gitmanager 0.2.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.
@@ -0,0 +1,42 @@
1
+ {
2
+ "@git.zone/cli": {
3
+ "projectType": "npm",
4
+ "module": {
5
+ "githost": "code.foss.global",
6
+ "gitscope": "foss.global",
7
+ "gitrepo": "gitmanager",
8
+ "description": "Headless Git manager for the foss.global Git platform, with a TypeScript API and Rust engine.",
9
+ "npmPackagename": "@foss.global/gitmanager",
10
+ "license": "MIT",
11
+ "projectDomain": "foss.global",
12
+ "keywords": [
13
+ "foss.global",
14
+ "git",
15
+ "gitmanager",
16
+ "forge",
17
+ "rust",
18
+ "typescript",
19
+ "smartrust",
20
+ "tsrust"
21
+ ]
22
+ },
23
+ "release": {
24
+ "targets": {
25
+ "npm": {
26
+ "registries": [
27
+ "https://verdaccio.lossless.digital",
28
+ "https://registry.npmjs.org"
29
+ ],
30
+ "accessLevel": "public"
31
+ }
32
+ }
33
+ },
34
+ "schemaVersion": 2
35
+ },
36
+ "@git.zone/tsrust": {
37
+ "targets": [
38
+ "linux_amd64",
39
+ "linux_arm64"
40
+ ]
41
+ }
42
+ }
package/changelog.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## 2026-06-22 - 0.2.0
4
+
5
+ ### Features
6
+
7
+ - add TypeScript facade and Rust-backed Git repository engine (core)
8
+ - Add GitManager lifecycle, status, repository, ref, tree, file, and commit APIs.
9
+ - Implement a typed smartrust bridge and Rust IPC management loop for local Git operations.
10
+ - Add package configuration, Rust workspace setup, and integration tests.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export declare const commitinfo: {
5
+ name: string;
6
+ version: string;
7
+ description: string;
8
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export const commitinfo = {
5
+ name: '@foss.global/gitmanager',
6
+ version: '0.2.0',
7
+ description: 'Headless Git manager for the foss.global Git platform, with a TypeScript API and Rust engine.'
8
+ };
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLCtGQUErRjtDQUM3RyxDQUFBIn0=
@@ -0,0 +1,23 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { IGitManagerCommitSummary, IGitManagerFileContent, IGitManagerImportMirrorRequest, IGitManagerInitBareRepositoryRequest, IGitManagerListCommitsRequest, IGitManagerReadFileRequest, IGitManagerRef, IGitManagerRefRequest, IGitManagerRepositoryInfo, IGitManagerStatus, IGitManagerTreeEntry, IGitManagerTreeRequest, IGitManagerOptions } from './models.js';
3
+ export declare class GitManager extends plugins.EventEmitter {
4
+ private bridge;
5
+ private started;
6
+ private startPromise;
7
+ private stopRequested;
8
+ private config;
9
+ constructor(optionsArg?: IGitManagerOptions);
10
+ start(): Promise<void>;
11
+ stop(): Promise<void>;
12
+ getStatus(): Promise<IGitManagerStatus>;
13
+ get running(): boolean;
14
+ initBareRepository(requestArg: IGitManagerInitBareRepositoryRequest): Promise<IGitManagerRepositoryInfo>;
15
+ importMirror(requestArg: IGitManagerImportMirrorRequest): Promise<IGitManagerRepositoryInfo>;
16
+ listRepositories(): Promise<IGitManagerRepositoryInfo[]>;
17
+ listRefs(requestArg: IGitManagerRefRequest): Promise<IGitManagerRef[]>;
18
+ listTree(requestArg: IGitManagerTreeRequest): Promise<IGitManagerTreeEntry[]>;
19
+ readFile(requestArg: IGitManagerReadFileRequest): Promise<IGitManagerFileContent>;
20
+ listCommits(requestArg: IGitManagerListCommitsRequest): Promise<IGitManagerCommitSummary[]>;
21
+ private startInternal;
22
+ private assertRunning;
23
+ }
@@ -0,0 +1,130 @@
1
+ import * as plugins from './plugins.js';
2
+ import { RustGitManagerBridge } from './rust-gitmanager-bridge.js';
3
+ export class GitManager extends plugins.EventEmitter {
4
+ constructor(optionsArg = {}) {
5
+ super();
6
+ this.bridge = new RustGitManagerBridge();
7
+ this.started = false;
8
+ this.startPromise = null;
9
+ this.stopRequested = false;
10
+ this.config = {
11
+ dataDir: optionsArg.dataDir ?? plugins.path.resolve(process.cwd(), '.nogit', 'gitmanager'),
12
+ };
13
+ this.bridge.on('exit', (code, signal) => {
14
+ this.started = false;
15
+ this.emit('exit', code, signal);
16
+ });
17
+ this.bridge.on('stderr', (line) => {
18
+ this.emit('stderr', line);
19
+ });
20
+ }
21
+ async start() {
22
+ if (this.started) {
23
+ throw new Error('GitManager is already running');
24
+ }
25
+ if (this.startPromise) {
26
+ throw new Error('GitManager is already starting');
27
+ }
28
+ this.stopRequested = false;
29
+ this.startPromise = this.startInternal();
30
+ try {
31
+ await this.startPromise;
32
+ }
33
+ finally {
34
+ this.startPromise = null;
35
+ }
36
+ }
37
+ async stop() {
38
+ this.stopRequested = true;
39
+ if (this.startPromise) {
40
+ await this.startPromise.catch(() => undefined);
41
+ }
42
+ if (!this.bridge.running) {
43
+ this.started = false;
44
+ return;
45
+ }
46
+ try {
47
+ await this.bridge.stopGitManager();
48
+ }
49
+ finally {
50
+ this.bridge.kill();
51
+ this.started = false;
52
+ }
53
+ }
54
+ async getStatus() {
55
+ if (!this.bridge.running) {
56
+ return {
57
+ running: false,
58
+ dataDir: this.config.dataDir,
59
+ uptimeMs: 0,
60
+ };
61
+ }
62
+ return this.bridge.getStatus();
63
+ }
64
+ get running() {
65
+ return this.started && this.bridge.running;
66
+ }
67
+ async initBareRepository(requestArg) {
68
+ this.assertRunning();
69
+ return this.bridge.initBareRepository(requestArg);
70
+ }
71
+ async importMirror(requestArg) {
72
+ this.assertRunning();
73
+ return this.bridge.importMirror(requestArg);
74
+ }
75
+ async listRepositories() {
76
+ this.assertRunning();
77
+ return this.bridge.listRepositories();
78
+ }
79
+ async listRefs(requestArg) {
80
+ this.assertRunning();
81
+ return this.bridge.listRefs(requestArg);
82
+ }
83
+ async listTree(requestArg) {
84
+ this.assertRunning();
85
+ return this.bridge.listTree(requestArg);
86
+ }
87
+ async readFile(requestArg) {
88
+ this.assertRunning();
89
+ return this.bridge.readFile(requestArg);
90
+ }
91
+ async listCommits(requestArg) {
92
+ this.assertRunning();
93
+ return this.bridge.listCommits(requestArg);
94
+ }
95
+ async startInternal() {
96
+ const spawned = await this.bridge.spawn();
97
+ if (!spawned) {
98
+ throw new Error('Failed to spawn rustgitmanager binary');
99
+ }
100
+ if (this.stopRequested) {
101
+ this.bridge.kill();
102
+ throw new Error('GitManager start was cancelled');
103
+ }
104
+ try {
105
+ await this.bridge.startGitManager(this.config);
106
+ if (this.stopRequested) {
107
+ try {
108
+ await this.bridge.stopGitManager();
109
+ }
110
+ finally {
111
+ this.bridge.kill();
112
+ this.started = false;
113
+ }
114
+ throw new Error('GitManager start was cancelled');
115
+ }
116
+ this.started = true;
117
+ }
118
+ catch (error) {
119
+ this.bridge.kill();
120
+ this.started = false;
121
+ throw error;
122
+ }
123
+ }
124
+ assertRunning() {
125
+ if (!this.running) {
126
+ throw new Error('GitManager is not running');
127
+ }
128
+ }
129
+ }
130
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5naXRtYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5naXRtYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBaUJ4QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVuRSxNQUFNLE9BQU8sVUFBVyxTQUFRLE9BQU8sQ0FBQyxZQUFZO0lBT2xELFlBQVksYUFBaUMsRUFBRTtRQUM3QyxLQUFLLEVBQUUsQ0FBQztRQVBGLFdBQU0sR0FBRyxJQUFJLG9CQUFvQixFQUFFLENBQUM7UUFDcEMsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUNoQixpQkFBWSxHQUF5QixJQUFJLENBQUM7UUFDMUMsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFLNUIsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNaLE9BQU8sRUFBRSxVQUFVLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxRQUFRLEVBQUUsWUFBWSxDQUFDO1NBQzNGLENBQUM7UUFDRixJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFtQixFQUFFLE1BQXFCLEVBQUUsRUFBRTtZQUNwRSxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztZQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDbEMsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxJQUFZLEVBQUUsRUFBRTtZQUN4QyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM1QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFF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
@@ -0,0 +1,3 @@
1
+ export * from './models.js';
2
+ export * from './rust-gitmanager-bridge.js';
3
+ export * from './classes.gitmanager.js';
@@ -0,0 +1,4 @@
1
+ export * from './models.js';
2
+ export * from './rust-gitmanager-bridge.js';
3
+ export * from './classes.gitmanager.js';
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMseUJBQXlCLENBQUMifQ==
@@ -0,0 +1,12 @@
1
+ export interface IGitManagerOptions {
2
+ dataDir?: string;
3
+ }
4
+ export interface IRustGitManagerConfig {
5
+ dataDir: string;
6
+ }
7
+ export interface IGitManagerStatus {
8
+ running: boolean;
9
+ dataDir: string;
10
+ uptimeMs: number;
11
+ }
12
+ export type { IGitManagerCommitSummary, IGitManagerFileContent, IGitManagerImportMirrorRequest, IGitManagerInitBareRepositoryRequest, IGitManagerListCommitsRequest, IGitManagerReadFileRequest, IGitManagerRef, IGitManagerRefRequest, IGitManagerRepositoryInfo, IGitManagerRepositorySelector, IGitManagerTreeEntry, IGitManagerTreeRequest, TGitManagerObjectType, TGitManagerRefType, TGitManagerTreeEntryType, } from '@foss.global/interfaces';
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvbW9kZWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
@@ -0,0 +1,6 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import * as path from 'node:path';
3
+ import * as url from 'node:url';
4
+ export { EventEmitter, path, url };
5
+ import * as smartrust from '@push.rocks/smartrust';
6
+ export { smartrust };
@@ -0,0 +1,9 @@
1
+ // node native scope
2
+ import { EventEmitter } from 'node:events';
3
+ import * as path from 'node:path';
4
+ import * as url from 'node:url';
5
+ export { EventEmitter, path, url };
6
+ // @push.rocks scope
7
+ import * as smartrust from '@push.rocks/smartrust';
8
+ export { smartrust };
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDM0MsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxVQUFVLENBQUM7QUFFaEMsT0FBTyxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFFbkMsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxTQUFTLE1BQU0sdUJBQXVCLENBQUM7QUFFbkQsT0FBTyxFQUFFLFNBQVMsRUFBRSxDQUFDIn0=
@@ -0,0 +1,19 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { IGitManagerCommitSummary, IGitManagerFileContent, IGitManagerImportMirrorRequest, IGitManagerInitBareRepositoryRequest, IGitManagerListCommitsRequest, IGitManagerReadFileRequest, IGitManagerRef, IGitManagerRefRequest, IGitManagerRepositoryInfo, IGitManagerStatus, IGitManagerTreeEntry, IGitManagerTreeRequest, IRustGitManagerConfig } from './models.js';
3
+ export declare class RustGitManagerBridge extends plugins.EventEmitter {
4
+ private bridge;
5
+ constructor();
6
+ spawn(): Promise<boolean>;
7
+ kill(): void;
8
+ get running(): boolean;
9
+ startGitManager(configArg: IRustGitManagerConfig): Promise<void>;
10
+ stopGitManager(): Promise<void>;
11
+ getStatus(): Promise<IGitManagerStatus>;
12
+ initBareRepository(requestArg: IGitManagerInitBareRepositoryRequest): Promise<IGitManagerRepositoryInfo>;
13
+ importMirror(requestArg: IGitManagerImportMirrorRequest): Promise<IGitManagerRepositoryInfo>;
14
+ listRepositories(): Promise<IGitManagerRepositoryInfo[]>;
15
+ listRefs(requestArg: IGitManagerRefRequest): Promise<IGitManagerRef[]>;
16
+ listTree(requestArg: IGitManagerTreeRequest): Promise<IGitManagerTreeEntry[]>;
17
+ readFile(requestArg: IGitManagerReadFileRequest): Promise<IGitManagerFileContent>;
18
+ listCommits(requestArg: IGitManagerListCommitsRequest): Promise<IGitManagerCommitSummary[]>;
19
+ }
@@ -0,0 +1,83 @@
1
+ import * as plugins from './plugins.js';
2
+ function getPackageRoot() {
3
+ const thisDir = plugins.path.dirname(plugins.url.fileURLToPath(import.meta.url));
4
+ return plugins.path.resolve(thisDir, '..');
5
+ }
6
+ function getTsrustPlatformSuffix() {
7
+ const archMap = { x64: 'amd64', arm64: 'arm64' };
8
+ const osMap = { linux: 'linux', darwin: 'macos' };
9
+ const os = osMap[process.platform];
10
+ const arch = archMap[process.arch];
11
+ return os && arch ? `${os}_${arch}` : null;
12
+ }
13
+ function buildLocalPaths() {
14
+ const packageRoot = getPackageRoot();
15
+ const suffix = getTsrustPlatformSuffix();
16
+ const paths = [];
17
+ if (suffix) {
18
+ paths.push(plugins.path.join(packageRoot, 'dist_rust', `rustgitmanager_${suffix}`));
19
+ }
20
+ paths.push(plugins.path.join(packageRoot, 'dist_rust', 'rustgitmanager'));
21
+ paths.push(plugins.path.resolve(process.cwd(), 'rust', 'target', 'release', 'rustgitmanager'));
22
+ paths.push(plugins.path.resolve(process.cwd(), 'rust', 'target', 'debug', 'rustgitmanager'));
23
+ return paths;
24
+ }
25
+ export class RustGitManagerBridge extends plugins.EventEmitter {
26
+ constructor() {
27
+ super();
28
+ this.bridge = new plugins.smartrust.RustBridge({
29
+ binaryName: 'rustgitmanager',
30
+ envVarName: 'GITMANAGER_RUST_BINARY',
31
+ platformPackagePrefix: '@foss.global/gitmanager',
32
+ localPaths: buildLocalPaths(),
33
+ requestTimeoutMs: 130000,
34
+ readyTimeoutMs: 10000,
35
+ });
36
+ this.bridge.on('exit', (code, signal) => {
37
+ this.emit('exit', code, signal);
38
+ });
39
+ this.bridge.on('stderr', (line) => {
40
+ this.emit('stderr', line);
41
+ });
42
+ }
43
+ async spawn() {
44
+ return this.bridge.spawn();
45
+ }
46
+ kill() {
47
+ this.bridge.kill();
48
+ }
49
+ get running() {
50
+ return this.bridge.running;
51
+ }
52
+ async startGitManager(configArg) {
53
+ await this.bridge.sendCommand('start', { config: configArg });
54
+ }
55
+ async stopGitManager() {
56
+ await this.bridge.sendCommand('stop', {});
57
+ }
58
+ async getStatus() {
59
+ return this.bridge.sendCommand('getStatus', {});
60
+ }
61
+ async initBareRepository(requestArg) {
62
+ return this.bridge.sendCommand('initBareRepository', requestArg);
63
+ }
64
+ async importMirror(requestArg) {
65
+ return this.bridge.sendCommand('importMirror', requestArg);
66
+ }
67
+ async listRepositories() {
68
+ return this.bridge.sendCommand('listRepositories', {});
69
+ }
70
+ async listRefs(requestArg) {
71
+ return this.bridge.sendCommand('listRefs', requestArg);
72
+ }
73
+ async listTree(requestArg) {
74
+ return this.bridge.sendCommand('listTree', requestArg);
75
+ }
76
+ async readFile(requestArg) {
77
+ return this.bridge.sendCommand('readFile', requestArg);
78
+ }
79
+ async listCommits(requestArg) {
80
+ return this.bridge.sendCommand('listCommits', requestArg);
81
+ }
82
+ }
83
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVzdC1naXRtYW5hZ2VyLWJyaWRnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3J1c3QtZ2l0bWFuYWdlci1icmlkZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUE4QnhDLFNBQVMsY0FBYztJQUNyQixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDakYsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUVELFNBQVMsdUJBQXVCO0lBQzlCLE1BQU0sT0FBTyxHQUEyQixFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3pFLE1BQU0sS0FBSyxHQUEyQixFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBQzFFLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbkMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuQyxPQUFPLEVBQUUsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDN0MsQ0FBQztBQUVELFNBQVMsZUFBZTtJQUN0QixNQUFNLFdBQVcsR0FBRyxjQUFjLEVBQUUsQ0FBQztJQUNyQyxNQUFNLE1BQU0sR0FBRyx1QkFBdUIsRUFBRSxDQUFDO0lBQ3pDLE1BQU0sS0FBSyxHQUFhLEVBQUUsQ0FBQztJQUUzQixJQUFJLE1BQU0sRUFBRSxD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
package/license.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Task Venture Capital GmbH
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.
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@foss.global/gitmanager",
3
+ "version": "0.2.0",
4
+ "private": false,
5
+ "description": "Headless Git manager for the foss.global Git platform, with a TypeScript API and Rust engine.",
6
+ "exports": {
7
+ ".": "./dist_ts/index.js"
8
+ },
9
+ "type": "module",
10
+ "author": "Task Venture Capital GmbH",
11
+ "license": "MIT",
12
+ "dependencies": {
13
+ "@foss.global/interfaces": "^0.2.0",
14
+ "@push.rocks/smartrust": "^1.4.0"
15
+ },
16
+ "devDependencies": {
17
+ "@git.zone/tsbuild": "^4.4.2",
18
+ "@git.zone/tsdoc": "^2.1.1",
19
+ "@git.zone/tsrun": "^2.0.4",
20
+ "@git.zone/tsrust": "^1.5.0",
21
+ "@git.zone/tstest": "^3.6.6",
22
+ "@types/node": "^26.0.0"
23
+ },
24
+ "files": [
25
+ "ts/**/*",
26
+ "dist/**/*",
27
+ "dist_*/**/*",
28
+ "dist_ts/**/*",
29
+ "dist_rust/**/*",
30
+ ".smartconfig.json",
31
+ "readme.md",
32
+ "changelog.md",
33
+ "license.md",
34
+ "thirdparty.md"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+ssh://git@code.foss.global:29419/foss.global/gitmanager.git"
39
+ },
40
+ "bugs": {
41
+ "url": "https://code.foss.global/foss.global/gitmanager/issues"
42
+ },
43
+ "homepage": "https://code.foss.global/foss.global/gitmanager#readme",
44
+ "keywords": [
45
+ "foss.global",
46
+ "git",
47
+ "gitmanager",
48
+ "forge",
49
+ "rust",
50
+ "typescript",
51
+ "smartrust",
52
+ "tsrust"
53
+ ],
54
+ "browserslist": [
55
+ "last 1 chrome versions"
56
+ ],
57
+ "scripts": {
58
+ "pretest": "(tsrust)",
59
+ "test": "tstest test/ --verbose --logfile --timeout 60",
60
+ "test:rust": "(cd rust && cargo test)",
61
+ "build": "(tsbuild tsfolders) && (tsrust)",
62
+ "buildDocs": "tsdoc"
63
+ }
64
+ }
package/readme.md ADDED
@@ -0,0 +1,115 @@
1
+ # @foss.global/gitmanager
2
+
3
+ Headless Git manager for the foss.global Git platform.
4
+
5
+ This package follows the push.rocks Rust-backed package pattern: TypeScript owns the public package API and lifecycle, while Rust owns the Git/storage/protocol engine. TypeScript controls the Rust binary through `@push.rocks/smartrust`, and builds use `@git.zone/tsrust`.
6
+
7
+ The current implementation provides lifecycle IPC plus initial local bare repository management and read APIs. Git protocol serving, mirror refresh, authorization, and write/admin features are planned in `../readme.plan.md`.
8
+
9
+ ## Issue Reporting and Security
10
+
11
+ For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pnpm add @foss.global/gitmanager
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```ts
22
+ import { GitManager } from '@foss.global/gitmanager';
23
+
24
+ const gitManager = new GitManager({
25
+ dataDir: '/var/lib/foss-global/gitmanager',
26
+ });
27
+
28
+ await gitManager.start();
29
+ const status = await gitManager.getStatus();
30
+ console.log(status.running, status.dataDir);
31
+
32
+ await gitManager.importMirror({
33
+ org: 'foss.global',
34
+ repo: 'interfaces',
35
+ remoteUrl: 'ssh://git@code.foss.global:29419/foss.global/interfaces.git',
36
+ });
37
+
38
+ const refs = await gitManager.listRefs({ org: 'foss.global', repo: 'interfaces' });
39
+ const tree = await gitManager.listTree({ org: 'foss.global', repo: 'interfaces', ref: 'main' });
40
+ const readme = await gitManager.readFile({
41
+ org: 'foss.global',
42
+ repo: 'interfaces',
43
+ ref: 'main',
44
+ path: 'readme.md',
45
+ });
46
+
47
+ await gitManager.stop();
48
+ ```
49
+
50
+ ## Public API
51
+
52
+ - `GitManager`: TypeScript facade for the Rust engine lifecycle.
53
+ - `GitManager.start()`: spawns the Rust binary through `smartrust` and starts the engine.
54
+ - `GitManager.stop()`: asks the engine to stop and always kills the bridge process in cleanup.
55
+ - `GitManager.getStatus()`: returns `{ running, dataDir, uptimeMs }`.
56
+ - `GitManager.initBareRepository()`: creates an empty local bare repository.
57
+ - `GitManager.importMirror()`: imports a remote repository with `git clone --mirror`. Supported remote forms are `https://`, `http://`, `ssh://`, `git://`, `file://`, and SCP-like `git@host:org/repo.git` URLs.
58
+ - `GitManager.listRepositories()`: lists local repositories managed below the configured data directory.
59
+ - `GitManager.listRefs()`: lists branch and tag refs.
60
+ - `GitManager.listTree()`: lists tree entries at a ref and optional path.
61
+ - `GitManager.readFile()`: reads a blob as base64 after checking the blob size limit.
62
+ - `GitManager.listCommits()`: lists commit summaries for a ref.
63
+ - `GitManager.running`: local facade running state.
64
+ - `RustGitManagerBridge`: lower-level typed bridge around `@push.rocks/smartrust`.
65
+ - `IGitManagerOptions`, `IGitManagerStatus`, `IRustGitManagerConfig`: exported option/status contracts.
66
+
67
+ Repository/read DTO contracts are re-exported from the published `@foss.global/interfaces` package.
68
+
69
+ Read/list APIs go through JSON IPC. Git packfile streaming for clone/fetch/push must not go through JSON IPC; future Git HTTP/SSH transport work belongs in the Rust engine or controlled Git subprocesses.
70
+
71
+ The initial read APIs use the system `git` CLI with explicit arguments, non-interactive environment variables, command timeouts, ref-to-object-id resolution, path validation, bounded stdout/stderr capture, ref/tree result caps, and a 1 MiB file read cap.
72
+
73
+ ## Rust Build
74
+
75
+ The package builds a Rust binary named `rustgitmanager` from `rust/` using `@git.zone/tsrust`.
76
+
77
+ Configured targets:
78
+
79
+ - `linux_amd64`
80
+ - `linux_arm64`
81
+
82
+ The ARM64 target uses `rust/.cargo/config.toml` with `aarch64-linux-gnu-gcc` as linker.
83
+
84
+ ## Testing
85
+
86
+ ```bash
87
+ pnpm test
88
+ pnpm run test:rust
89
+ pnpm run build
90
+ ```
91
+
92
+ `pnpm test` runs the `pretest` hook first, which builds the Rust binaries with `tsrust`, and then runs lifecycle plus local mirror import/read API tests through `smartrust`.
93
+
94
+ ## License and Legal Information
95
+
96
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the repository license file.
97
+
98
+ Bundled Rust binaries include third-party Rust crates under their respective licenses. See `thirdparty.md` for the packaged notice list.
99
+
100
+ **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
101
+
102
+ ### Trademarks
103
+
104
+ This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
105
+
106
+ Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
107
+
108
+ ### Company Information
109
+
110
+ Task Venture Capital GmbH<br>
111
+ Registered at District Court Bremen HRB 35230 HB, Germany
112
+
113
+ For any legal inquiries or further information, please contact us via email at hello@task.vc.
114
+
115
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
package/thirdparty.md ADDED
@@ -0,0 +1,70 @@
1
+ # Third-Party Notices
2
+
3
+ This package bundles Rust binaries in `dist_rust/`. Those binaries are built from the Rust crates listed below. Each dependency remains licensed by its respective authors under the stated license expression.
4
+
5
+ | Crate | Version | License |
6
+ | --- | --- | --- |
7
+ | aho-corasick | 1.1.4 | MIT OR Unlicense |
8
+ | anstream | 1.0.0 | Apache-2.0 OR MIT |
9
+ | anstyle | 1.0.14 | Apache-2.0 OR MIT |
10
+ | anstyle-parse | 1.0.0 | Apache-2.0 OR MIT |
11
+ | anstyle-query | 1.1.5 | Apache-2.0 OR MIT |
12
+ | anstyle-wincon | 3.0.11 | Apache-2.0 OR MIT |
13
+ | anyhow | 1.0.102 | Apache-2.0 OR MIT |
14
+ | base64 | 0.22.1 | Apache-2.0 OR MIT |
15
+ | bitflags | 2.13.0 | Apache-2.0 OR MIT |
16
+ | bytes | 1.12.0 | MIT |
17
+ | cfg-if | 1.0.4 | Apache-2.0 OR MIT |
18
+ | clap | 4.6.1 | Apache-2.0 OR MIT |
19
+ | clap_builder | 4.6.0 | Apache-2.0 OR MIT |
20
+ | clap_derive | 4.6.1 | Apache-2.0 OR MIT |
21
+ | clap_lex | 1.1.0 | Apache-2.0 OR MIT |
22
+ | colorchoice | 1.0.5 | Apache-2.0 OR MIT |
23
+ | errno | 0.3.14 | Apache-2.0 OR MIT |
24
+ | heck | 0.5.0 | Apache-2.0 OR MIT |
25
+ | is_terminal_polyfill | 1.70.2 | Apache-2.0 OR MIT |
26
+ | itoa | 1.0.18 | Apache-2.0 OR MIT |
27
+ | lazy_static | 1.5.0 | Apache-2.0 OR MIT |
28
+ | libc | 0.2.186 | Apache-2.0 OR MIT |
29
+ | lock_api | 0.4.14 | Apache-2.0 OR MIT |
30
+ | log | 0.4.33 | Apache-2.0 OR MIT |
31
+ | matchers | 0.2.0 | MIT |
32
+ | memchr | 2.8.2 | MIT OR Unlicense |
33
+ | mio | 1.2.1 | MIT |
34
+ | nu-ansi-term | 0.50.3 | MIT |
35
+ | once_cell | 1.21.4 | Apache-2.0 OR MIT |
36
+ | once_cell_polyfill | 1.70.2 | Apache-2.0 OR MIT |
37
+ | parking_lot | 0.12.5 | Apache-2.0 OR MIT |
38
+ | parking_lot_core | 0.9.12 | Apache-2.0 OR MIT |
39
+ | pin-project-lite | 0.2.17 | Apache-2.0 OR MIT |
40
+ | proc-macro2 | 1.0.106 | Apache-2.0 OR MIT |
41
+ | quote | 1.0.45 | Apache-2.0 OR MIT |
42
+ | redox_syscall | 0.5.18 | MIT |
43
+ | regex-automata | 0.4.14 | Apache-2.0 OR MIT |
44
+ | regex-syntax | 0.8.11 | Apache-2.0 OR MIT |
45
+ | scopeguard | 1.2.0 | Apache-2.0 OR MIT |
46
+ | serde | 1.0.228 | Apache-2.0 OR MIT |
47
+ | serde_core | 1.0.228 | Apache-2.0 OR MIT |
48
+ | serde_derive | 1.0.228 | Apache-2.0 OR MIT |
49
+ | serde_json | 1.0.150 | Apache-2.0 OR MIT |
50
+ | sharded-slab | 0.1.7 | MIT |
51
+ | signal-hook-registry | 1.4.8 | Apache-2.0 OR MIT |
52
+ | smallvec | 1.15.2 | Apache-2.0 OR MIT |
53
+ | socket2 | 0.6.4 | Apache-2.0 OR MIT |
54
+ | strsim | 0.11.1 | MIT |
55
+ | syn | 2.0.118 | Apache-2.0 OR MIT |
56
+ | thread_local | 1.1.9 | Apache-2.0 OR MIT |
57
+ | tokio | 1.52.3 | MIT |
58
+ | tokio-macros | 2.7.0 | MIT |
59
+ | tracing | 0.1.44 | MIT |
60
+ | tracing-attributes | 0.1.31 | MIT |
61
+ | tracing-core | 0.1.36 | MIT |
62
+ | tracing-log | 0.2.0 | MIT |
63
+ | tracing-subscriber | 0.3.23 | MIT |
64
+ | unicode-ident | 1.0.24 | (Apache-2.0 OR MIT) AND Unicode-3.0 |
65
+ | utf8parse | 0.2.2 | Apache-2.0 OR MIT |
66
+ | valuable | 0.1.1 | MIT |
67
+ | wasi | 0.11.1+wasi-snapshot-preview1 | Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT |
68
+ | windows-link | 0.2.1 | Apache-2.0 OR MIT |
69
+ | windows-sys | 0.61.2 | Apache-2.0 OR MIT |
70
+ | zmij | 1.0.21 | MIT |
@@ -0,0 +1,8 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export const commitinfo = {
5
+ name: '@foss.global/gitmanager',
6
+ version: '0.2.0',
7
+ description: 'Headless Git manager for the foss.global Git platform, with a TypeScript API and Rust engine.'
8
+ }
@@ -0,0 +1,159 @@
1
+ import * as plugins from './plugins.js';
2
+ import type {
3
+ IGitManagerCommitSummary,
4
+ IGitManagerFileContent,
5
+ IGitManagerImportMirrorRequest,
6
+ IGitManagerInitBareRepositoryRequest,
7
+ IGitManagerListCommitsRequest,
8
+ IGitManagerReadFileRequest,
9
+ IGitManagerRef,
10
+ IGitManagerRefRequest,
11
+ IGitManagerRepositoryInfo,
12
+ IGitManagerStatus,
13
+ IGitManagerTreeEntry,
14
+ IGitManagerTreeRequest,
15
+ IGitManagerOptions,
16
+ IRustGitManagerConfig,
17
+ } from './models.js';
18
+ import { RustGitManagerBridge } from './rust-gitmanager-bridge.js';
19
+
20
+ export class GitManager extends plugins.EventEmitter {
21
+ private bridge = new RustGitManagerBridge();
22
+ private started = false;
23
+ private startPromise: Promise<void> | null = null;
24
+ private stopRequested = false;
25
+ private config: IRustGitManagerConfig;
26
+
27
+ constructor(optionsArg: IGitManagerOptions = {}) {
28
+ super();
29
+ this.config = {
30
+ dataDir: optionsArg.dataDir ?? plugins.path.resolve(process.cwd(), '.nogit', 'gitmanager'),
31
+ };
32
+ this.bridge.on('exit', (code: number | null, signal: string | null) => {
33
+ this.started = false;
34
+ this.emit('exit', code, signal);
35
+ });
36
+ this.bridge.on('stderr', (line: string) => {
37
+ this.emit('stderr', line);
38
+ });
39
+ }
40
+
41
+ public async start(): Promise<void> {
42
+ if (this.started) {
43
+ throw new Error('GitManager is already running');
44
+ }
45
+ if (this.startPromise) {
46
+ throw new Error('GitManager is already starting');
47
+ }
48
+
49
+ this.stopRequested = false;
50
+ this.startPromise = this.startInternal();
51
+ try {
52
+ await this.startPromise;
53
+ } finally {
54
+ this.startPromise = null;
55
+ }
56
+ }
57
+
58
+ public async stop(): Promise<void> {
59
+ this.stopRequested = true;
60
+ if (this.startPromise) {
61
+ await this.startPromise.catch(() => undefined);
62
+ }
63
+ if (!this.bridge.running) {
64
+ this.started = false;
65
+ return;
66
+ }
67
+ try {
68
+ await this.bridge.stopGitManager();
69
+ } finally {
70
+ this.bridge.kill();
71
+ this.started = false;
72
+ }
73
+ }
74
+
75
+ public async getStatus(): Promise<IGitManagerStatus> {
76
+ if (!this.bridge.running) {
77
+ return {
78
+ running: false,
79
+ dataDir: this.config.dataDir,
80
+ uptimeMs: 0,
81
+ };
82
+ }
83
+ return this.bridge.getStatus();
84
+ }
85
+
86
+ public get running(): boolean {
87
+ return this.started && this.bridge.running;
88
+ }
89
+
90
+ public async initBareRepository(requestArg: IGitManagerInitBareRepositoryRequest): Promise<IGitManagerRepositoryInfo> {
91
+ this.assertRunning();
92
+ return this.bridge.initBareRepository(requestArg);
93
+ }
94
+
95
+ public async importMirror(requestArg: IGitManagerImportMirrorRequest): Promise<IGitManagerRepositoryInfo> {
96
+ this.assertRunning();
97
+ return this.bridge.importMirror(requestArg);
98
+ }
99
+
100
+ public async listRepositories(): Promise<IGitManagerRepositoryInfo[]> {
101
+ this.assertRunning();
102
+ return this.bridge.listRepositories();
103
+ }
104
+
105
+ public async listRefs(requestArg: IGitManagerRefRequest): Promise<IGitManagerRef[]> {
106
+ this.assertRunning();
107
+ return this.bridge.listRefs(requestArg);
108
+ }
109
+
110
+ public async listTree(requestArg: IGitManagerTreeRequest): Promise<IGitManagerTreeEntry[]> {
111
+ this.assertRunning();
112
+ return this.bridge.listTree(requestArg);
113
+ }
114
+
115
+ public async readFile(requestArg: IGitManagerReadFileRequest): Promise<IGitManagerFileContent> {
116
+ this.assertRunning();
117
+ return this.bridge.readFile(requestArg);
118
+ }
119
+
120
+ public async listCommits(requestArg: IGitManagerListCommitsRequest): Promise<IGitManagerCommitSummary[]> {
121
+ this.assertRunning();
122
+ return this.bridge.listCommits(requestArg);
123
+ }
124
+
125
+ private async startInternal(): Promise<void> {
126
+ const spawned = await this.bridge.spawn();
127
+ if (!spawned) {
128
+ throw new Error('Failed to spawn rustgitmanager binary');
129
+ }
130
+ if (this.stopRequested) {
131
+ this.bridge.kill();
132
+ throw new Error('GitManager start was cancelled');
133
+ }
134
+
135
+ try {
136
+ await this.bridge.startGitManager(this.config);
137
+ if (this.stopRequested) {
138
+ try {
139
+ await this.bridge.stopGitManager();
140
+ } finally {
141
+ this.bridge.kill();
142
+ this.started = false;
143
+ }
144
+ throw new Error('GitManager start was cancelled');
145
+ }
146
+ this.started = true;
147
+ } catch (error) {
148
+ this.bridge.kill();
149
+ this.started = false;
150
+ throw error;
151
+ }
152
+ }
153
+
154
+ private assertRunning(): void {
155
+ if (!this.running) {
156
+ throw new Error('GitManager is not running');
157
+ }
158
+ }
159
+ }
package/ts/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './models.js';
2
+ export * from './rust-gitmanager-bridge.js';
3
+ export * from './classes.gitmanager.js';
package/ts/models.ts ADDED
@@ -0,0 +1,31 @@
1
+ export interface IGitManagerOptions {
2
+ dataDir?: string;
3
+ }
4
+
5
+ export interface IRustGitManagerConfig {
6
+ dataDir: string;
7
+ }
8
+
9
+ export interface IGitManagerStatus {
10
+ running: boolean;
11
+ dataDir: string;
12
+ uptimeMs: number;
13
+ }
14
+
15
+ export type {
16
+ IGitManagerCommitSummary,
17
+ IGitManagerFileContent,
18
+ IGitManagerImportMirrorRequest,
19
+ IGitManagerInitBareRepositoryRequest,
20
+ IGitManagerListCommitsRequest,
21
+ IGitManagerReadFileRequest,
22
+ IGitManagerRef,
23
+ IGitManagerRefRequest,
24
+ IGitManagerRepositoryInfo,
25
+ IGitManagerRepositorySelector,
26
+ IGitManagerTreeEntry,
27
+ IGitManagerTreeRequest,
28
+ TGitManagerObjectType,
29
+ TGitManagerRefType,
30
+ TGitManagerTreeEntryType,
31
+ } from '@foss.global/interfaces';
package/ts/plugins.ts ADDED
@@ -0,0 +1,11 @@
1
+ // node native scope
2
+ import { EventEmitter } from 'node:events';
3
+ import * as path from 'node:path';
4
+ import * as url from 'node:url';
5
+
6
+ export { EventEmitter, path, url };
7
+
8
+ // @push.rocks scope
9
+ import * as smartrust from '@push.rocks/smartrust';
10
+
11
+ export { smartrust };
@@ -0,0 +1,132 @@
1
+ import * as plugins from './plugins.js';
2
+ import type {
3
+ IGitManagerCommitSummary,
4
+ IGitManagerFileContent,
5
+ IGitManagerImportMirrorRequest,
6
+ IGitManagerInitBareRepositoryRequest,
7
+ IGitManagerListCommitsRequest,
8
+ IGitManagerReadFileRequest,
9
+ IGitManagerRef,
10
+ IGitManagerRefRequest,
11
+ IGitManagerRepositoryInfo,
12
+ IGitManagerStatus,
13
+ IGitManagerTreeEntry,
14
+ IGitManagerTreeRequest,
15
+ IRustGitManagerConfig,
16
+ } from './models.js';
17
+
18
+ type TGitManagerCommands = {
19
+ start: { params: { config: IRustGitManagerConfig }; result: Record<string, never> };
20
+ stop: { params: Record<string, never>; result: Record<string, never> };
21
+ getStatus: { params: Record<string, never>; result: IGitManagerStatus };
22
+ initBareRepository: { params: IGitManagerInitBareRepositoryRequest; result: IGitManagerRepositoryInfo };
23
+ importMirror: { params: IGitManagerImportMirrorRequest; result: IGitManagerRepositoryInfo };
24
+ listRepositories: { params: Record<string, never>; result: IGitManagerRepositoryInfo[] };
25
+ listRefs: { params: IGitManagerRefRequest; result: IGitManagerRef[] };
26
+ listTree: { params: IGitManagerTreeRequest; result: IGitManagerTreeEntry[] };
27
+ readFile: { params: IGitManagerReadFileRequest; result: IGitManagerFileContent };
28
+ listCommits: { params: IGitManagerListCommitsRequest; result: IGitManagerCommitSummary[] };
29
+ };
30
+
31
+ function getPackageRoot(): string {
32
+ const thisDir = plugins.path.dirname(plugins.url.fileURLToPath(import.meta.url));
33
+ return plugins.path.resolve(thisDir, '..');
34
+ }
35
+
36
+ function getTsrustPlatformSuffix(): string | null {
37
+ const archMap: Record<string, string> = { x64: 'amd64', arm64: 'arm64' };
38
+ const osMap: Record<string, string> = { linux: 'linux', darwin: 'macos' };
39
+ const os = osMap[process.platform];
40
+ const arch = archMap[process.arch];
41
+ return os && arch ? `${os}_${arch}` : null;
42
+ }
43
+
44
+ function buildLocalPaths(): string[] {
45
+ const packageRoot = getPackageRoot();
46
+ const suffix = getTsrustPlatformSuffix();
47
+ const paths: string[] = [];
48
+
49
+ if (suffix) {
50
+ paths.push(plugins.path.join(packageRoot, 'dist_rust', `rustgitmanager_${suffix}`));
51
+ }
52
+ paths.push(plugins.path.join(packageRoot, 'dist_rust', 'rustgitmanager'));
53
+ paths.push(plugins.path.resolve(process.cwd(), 'rust', 'target', 'release', 'rustgitmanager'));
54
+ paths.push(plugins.path.resolve(process.cwd(), 'rust', 'target', 'debug', 'rustgitmanager'));
55
+
56
+ return paths;
57
+ }
58
+
59
+ export class RustGitManagerBridge extends plugins.EventEmitter {
60
+ private bridge: plugins.smartrust.RustBridge<TGitManagerCommands>;
61
+
62
+ constructor() {
63
+ super();
64
+ this.bridge = new plugins.smartrust.RustBridge<TGitManagerCommands>({
65
+ binaryName: 'rustgitmanager',
66
+ envVarName: 'GITMANAGER_RUST_BINARY',
67
+ platformPackagePrefix: '@foss.global/gitmanager',
68
+ localPaths: buildLocalPaths(),
69
+ requestTimeoutMs: 130000,
70
+ readyTimeoutMs: 10000,
71
+ });
72
+
73
+ this.bridge.on('exit', (code: number | null, signal: string | null) => {
74
+ this.emit('exit', code, signal);
75
+ });
76
+ this.bridge.on('stderr', (line: string) => {
77
+ this.emit('stderr', line);
78
+ });
79
+ }
80
+
81
+ public async spawn(): Promise<boolean> {
82
+ return this.bridge.spawn();
83
+ }
84
+
85
+ public kill(): void {
86
+ this.bridge.kill();
87
+ }
88
+
89
+ public get running(): boolean {
90
+ return this.bridge.running;
91
+ }
92
+
93
+ public async startGitManager(configArg: IRustGitManagerConfig): Promise<void> {
94
+ await this.bridge.sendCommand('start', { config: configArg });
95
+ }
96
+
97
+ public async stopGitManager(): Promise<void> {
98
+ await this.bridge.sendCommand('stop', {});
99
+ }
100
+
101
+ public async getStatus(): Promise<IGitManagerStatus> {
102
+ return this.bridge.sendCommand('getStatus', {});
103
+ }
104
+
105
+ public async initBareRepository(requestArg: IGitManagerInitBareRepositoryRequest): Promise<IGitManagerRepositoryInfo> {
106
+ return this.bridge.sendCommand('initBareRepository', requestArg);
107
+ }
108
+
109
+ public async importMirror(requestArg: IGitManagerImportMirrorRequest): Promise<IGitManagerRepositoryInfo> {
110
+ return this.bridge.sendCommand('importMirror', requestArg);
111
+ }
112
+
113
+ public async listRepositories(): Promise<IGitManagerRepositoryInfo[]> {
114
+ return this.bridge.sendCommand('listRepositories', {});
115
+ }
116
+
117
+ public async listRefs(requestArg: IGitManagerRefRequest): Promise<IGitManagerRef[]> {
118
+ return this.bridge.sendCommand('listRefs', requestArg);
119
+ }
120
+
121
+ public async listTree(requestArg: IGitManagerTreeRequest): Promise<IGitManagerTreeEntry[]> {
122
+ return this.bridge.sendCommand('listTree', requestArg);
123
+ }
124
+
125
+ public async readFile(requestArg: IGitManagerReadFileRequest): Promise<IGitManagerFileContent> {
126
+ return this.bridge.sendCommand('readFile', requestArg);
127
+ }
128
+
129
+ public async listCommits(requestArg: IGitManagerListCommitsRequest): Promise<IGitManagerCommitSummary[]> {
130
+ return this.bridge.sendCommand('listCommits', requestArg);
131
+ }
132
+ }