@aigne/afs-git 1.11.0-beta.6 → 1.11.0-beta.7
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/dist/index.cjs +707 -58
- package/dist/index.d.cts +87 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +87 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +706 -59
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { tmpdir } from "node:os";
|
|
|
6
6
|
import { basename, dirname, isAbsolute, join } from "node:path";
|
|
7
7
|
import { promisify } from "node:util";
|
|
8
8
|
import { AFSNotFoundError } from "@aigne/afs";
|
|
9
|
-
import { AFSBaseProvider, Delete, List, Meta, Read, Rename, Search, Stat, Write } from "@aigne/afs/provider";
|
|
9
|
+
import { AFSBaseProvider, Actions, Delete, Explain, List, Meta, Read, Rename, Search, Stat, Write } from "@aigne/afs/provider";
|
|
10
10
|
import { camelize, optionalize, zodParse } from "@aigne/afs/utils/zod";
|
|
11
11
|
import { simpleGit } from "simple-git";
|
|
12
12
|
import { z } from "zod";
|
|
@@ -37,10 +37,10 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
37
37
|
static schema() {
|
|
38
38
|
return afsGitOptionsSchema;
|
|
39
39
|
}
|
|
40
|
-
static async load({
|
|
40
|
+
static async load({ basePath, config } = {}) {
|
|
41
41
|
const instance = new AFSGit({
|
|
42
|
-
...await AFSGit.schema().parseAsync(
|
|
43
|
-
cwd:
|
|
42
|
+
...await AFSGit.schema().parseAsync(config),
|
|
43
|
+
cwd: basePath
|
|
44
44
|
});
|
|
45
45
|
await instance.ready();
|
|
46
46
|
return instance;
|
|
@@ -145,21 +145,24 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
145
145
|
}
|
|
146
146
|
/**
|
|
147
147
|
* List root (branches)
|
|
148
|
+
* Note: list() returns only children (branches), never the path itself (per new semantics)
|
|
148
149
|
*/
|
|
149
150
|
async listRootHandler(ctx) {
|
|
150
151
|
await this.ready();
|
|
151
152
|
const options = ctx.options;
|
|
152
153
|
const maxDepth = options?.maxDepth ?? 1;
|
|
153
154
|
const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);
|
|
155
|
+
if (maxDepth === 0) return { data: [] };
|
|
154
156
|
const branches = await this.getBranches();
|
|
155
|
-
if (maxDepth === 0) return { data: [this.buildEntry("/", { metadata: { childrenCount: branches.length } })] };
|
|
156
157
|
const entries = [];
|
|
157
|
-
entries.push(this.buildEntry("/", { metadata: { childrenCount: branches.length } }));
|
|
158
158
|
for (const name of branches) {
|
|
159
159
|
if (entries.length >= limit) break;
|
|
160
160
|
const encodedPath = this.buildBranchPath(name);
|
|
161
161
|
const branchChildrenCount = await this.getChildrenCount(name, "");
|
|
162
|
-
entries.push(this.buildEntry(encodedPath, {
|
|
162
|
+
entries.push(this.buildEntry(encodedPath, { meta: {
|
|
163
|
+
kind: "git:branch",
|
|
164
|
+
childrenCount: branchChildrenCount
|
|
165
|
+
} }));
|
|
163
166
|
if (maxDepth > 1) {
|
|
164
167
|
const branchResult = await this.listWithGitLsTree(name, "", {
|
|
165
168
|
maxDepth: maxDepth - 1,
|
|
@@ -195,7 +198,7 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
195
198
|
async readRootMetaHandler(_ctx) {
|
|
196
199
|
await this.ready();
|
|
197
200
|
const branches = await this.getBranches();
|
|
198
|
-
return this.buildEntry("/.meta", {
|
|
201
|
+
return this.buildEntry("/.meta", { meta: {
|
|
199
202
|
childrenCount: branches.length,
|
|
200
203
|
type: "root"
|
|
201
204
|
} });
|
|
@@ -209,9 +212,11 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
209
212
|
await this.ensureBranchExists(branch);
|
|
210
213
|
const childrenCount = await this.getChildrenCount(branch, "");
|
|
211
214
|
const metaPath = `${`/${this.encodeBranchName(branch)}`}/.meta`;
|
|
212
|
-
|
|
215
|
+
const lastCommit = await this.getLastCommit(branch);
|
|
216
|
+
return this.buildEntry(metaPath, { meta: {
|
|
213
217
|
childrenCount,
|
|
214
|
-
type: "branch"
|
|
218
|
+
type: "branch",
|
|
219
|
+
lastCommit
|
|
215
220
|
} });
|
|
216
221
|
}
|
|
217
222
|
/**
|
|
@@ -232,7 +237,7 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
232
237
|
const metaPath = `/${this.encodeBranchName(branch)}/${filePath}/.meta`;
|
|
233
238
|
let childrenCount;
|
|
234
239
|
if (isDir) childrenCount = await this.getChildrenCount(branch, filePath);
|
|
235
|
-
return this.buildEntry(metaPath, {
|
|
240
|
+
return this.buildEntry(metaPath, { meta: {
|
|
236
241
|
childrenCount,
|
|
237
242
|
type: isDir ? "directory" : "file",
|
|
238
243
|
gitObjectType: objectType
|
|
@@ -244,7 +249,7 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
244
249
|
async readRootHandler(_ctx) {
|
|
245
250
|
await this.ready();
|
|
246
251
|
const branches = await this.getBranches();
|
|
247
|
-
return this.buildEntry("/", {
|
|
252
|
+
return this.buildEntry("/", { meta: { childrenCount: branches.length } });
|
|
248
253
|
}
|
|
249
254
|
/**
|
|
250
255
|
* Read branch root
|
|
@@ -255,7 +260,11 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
255
260
|
await this.ensureBranchExists(branch);
|
|
256
261
|
const branchPath = this.buildBranchPath(branch);
|
|
257
262
|
const childrenCount = await this.getChildrenCount(branch, "");
|
|
258
|
-
|
|
263
|
+
const lastCommit = await this.getLastCommit(branch);
|
|
264
|
+
return this.buildEntry(branchPath, { meta: {
|
|
265
|
+
childrenCount,
|
|
266
|
+
lastCommit
|
|
267
|
+
} });
|
|
259
268
|
}
|
|
260
269
|
/**
|
|
261
270
|
* Read file or directory in branch
|
|
@@ -272,23 +281,23 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
272
281
|
if (stats.isDirectory()) {
|
|
273
282
|
const files = await readdir(fullPath);
|
|
274
283
|
const afsPath$2 = this.buildBranchPath(branch, filePath);
|
|
275
|
-
return this.buildEntry(afsPath$2, {
|
|
284
|
+
return this.buildEntry(afsPath$2, { meta: { childrenCount: files.length } });
|
|
276
285
|
}
|
|
277
286
|
const mimeType$1 = this.getMimeType(filePath);
|
|
278
287
|
const isBinary$1 = this.isBinaryFile(filePath);
|
|
279
288
|
let content$1;
|
|
280
|
-
const
|
|
289
|
+
const meta$1 = {
|
|
281
290
|
size: stats.size,
|
|
282
291
|
mimeType: mimeType$1
|
|
283
292
|
};
|
|
284
293
|
if (isBinary$1) {
|
|
285
294
|
content$1 = (await readFile(fullPath)).toString("base64");
|
|
286
|
-
|
|
295
|
+
meta$1.contentType = "base64";
|
|
287
296
|
} else content$1 = await readFile(fullPath, "utf8");
|
|
288
297
|
const afsPath$1 = this.buildBranchPath(branch, filePath);
|
|
289
298
|
return this.buildEntry(afsPath$1, {
|
|
290
299
|
content: content$1,
|
|
291
|
-
|
|
300
|
+
meta: meta$1,
|
|
292
301
|
createdAt: stats.birthtime,
|
|
293
302
|
updatedAt: stats.mtime
|
|
294
303
|
});
|
|
@@ -302,7 +311,7 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
302
311
|
if (objectType === "tree") {
|
|
303
312
|
const afsPath$1 = this.buildBranchPath(branch, filePath);
|
|
304
313
|
const childrenCount = await this.getChildrenCount(branch, filePath);
|
|
305
|
-
return this.buildEntry(afsPath$1, {
|
|
314
|
+
return this.buildEntry(afsPath$1, { meta: { childrenCount } });
|
|
306
315
|
}
|
|
307
316
|
const size = await this.git.raw([
|
|
308
317
|
"cat-file",
|
|
@@ -312,7 +321,7 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
312
321
|
const mimeType = this.getMimeType(filePath);
|
|
313
322
|
const isBinary = this.isBinaryFile(filePath);
|
|
314
323
|
let content;
|
|
315
|
-
const
|
|
324
|
+
const meta = {
|
|
316
325
|
size,
|
|
317
326
|
mimeType
|
|
318
327
|
};
|
|
@@ -327,12 +336,12 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
327
336
|
maxBuffer: 10 * 1024 * 1024
|
|
328
337
|
});
|
|
329
338
|
content = stdout.toString("base64");
|
|
330
|
-
|
|
339
|
+
meta.contentType = "base64";
|
|
331
340
|
} else content = await this.git.show([`${branch}:${filePath}`]);
|
|
332
341
|
const afsPath = this.buildBranchPath(branch, filePath);
|
|
333
342
|
return this.buildEntry(afsPath, {
|
|
334
343
|
content,
|
|
335
|
-
|
|
344
|
+
meta
|
|
336
345
|
});
|
|
337
346
|
}
|
|
338
347
|
/**
|
|
@@ -385,8 +394,8 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
385
394
|
summary: payload.summary,
|
|
386
395
|
createdAt: stats.birthtime,
|
|
387
396
|
updatedAt: stats.mtime,
|
|
388
|
-
|
|
389
|
-
...payload.
|
|
397
|
+
meta: {
|
|
398
|
+
...payload.meta,
|
|
390
399
|
size: stats.size
|
|
391
400
|
},
|
|
392
401
|
userId: payload.userId,
|
|
@@ -553,30 +562,611 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
553
562
|
*/
|
|
554
563
|
async statRootHandler(_ctx) {
|
|
555
564
|
const entry = await this.readRootHandler(_ctx);
|
|
556
|
-
return { data:
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
} };
|
|
565
|
+
if (!entry) return { data: void 0 };
|
|
566
|
+
const { content: _content, ...rest } = entry;
|
|
567
|
+
return { data: rest };
|
|
560
568
|
}
|
|
561
569
|
/**
|
|
562
570
|
* Stat branch root
|
|
563
571
|
*/
|
|
564
572
|
async statBranchRootHandler(ctx) {
|
|
565
573
|
const entry = await this.readBranchRootHandler(ctx);
|
|
566
|
-
return { data:
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
} };
|
|
574
|
+
if (!entry) return { data: void 0 };
|
|
575
|
+
const { content: _content, ...rest } = entry;
|
|
576
|
+
return { data: rest };
|
|
570
577
|
}
|
|
571
578
|
/**
|
|
572
579
|
* Stat file or directory in branch
|
|
573
580
|
*/
|
|
574
581
|
async statHandler(ctx) {
|
|
575
582
|
const entry = await this.readBranchHandler(ctx);
|
|
576
|
-
return { data:
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
583
|
+
if (!entry) return { data: void 0 };
|
|
584
|
+
const { content: _content, ...rest } = entry;
|
|
585
|
+
return { data: rest };
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Explain root → repo info, branch list, default branch
|
|
589
|
+
*/
|
|
590
|
+
async explainRootHandler(_ctx) {
|
|
591
|
+
await this.ready();
|
|
592
|
+
const format = _ctx.options?.format || "markdown";
|
|
593
|
+
const branches = await this.getBranches();
|
|
594
|
+
const currentBranch = await this.git.revparse(["--abbrev-ref", "HEAD"]).then((b) => b.trim());
|
|
595
|
+
let remoteUrl;
|
|
596
|
+
try {
|
|
597
|
+
remoteUrl = await this.git.remote(["get-url", "origin"]).then((u) => u?.trim());
|
|
598
|
+
} catch {}
|
|
599
|
+
const lines = [];
|
|
600
|
+
lines.push("# Git Repository");
|
|
601
|
+
lines.push("");
|
|
602
|
+
lines.push(`**Provider:** ${this.name}`);
|
|
603
|
+
if (this.description) lines.push(`**Description:** ${this.description}`);
|
|
604
|
+
lines.push(`**Default Branch:** ${currentBranch}`);
|
|
605
|
+
if (remoteUrl) lines.push(`**Remote:** ${remoteUrl}`);
|
|
606
|
+
lines.push(`**Branches:** ${branches.length}`);
|
|
607
|
+
lines.push("");
|
|
608
|
+
lines.push("## Branches");
|
|
609
|
+
lines.push("");
|
|
610
|
+
for (const branch of branches) lines.push(`- ${branch}`);
|
|
611
|
+
return {
|
|
612
|
+
content: lines.join("\n"),
|
|
613
|
+
format
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Explain branch → branch name, HEAD commit, file count
|
|
618
|
+
*/
|
|
619
|
+
async explainBranchHandler(ctx) {
|
|
620
|
+
await this.ready();
|
|
621
|
+
const format = ctx.options?.format || "markdown";
|
|
622
|
+
const branch = this.decodeBranchName(ctx.params.branch);
|
|
623
|
+
await this.ensureBranchExists(branch);
|
|
624
|
+
const lastCommit = await this.getLastCommit(branch);
|
|
625
|
+
const fileCount = await this.getTreeFileCount(branch, "");
|
|
626
|
+
const lines = [];
|
|
627
|
+
lines.push(`# Branch: ${branch}`);
|
|
628
|
+
lines.push("");
|
|
629
|
+
lines.push(`**HEAD Commit:** ${lastCommit.shortHash} - ${lastCommit.message}`);
|
|
630
|
+
lines.push(`**Author:** ${lastCommit.author}`);
|
|
631
|
+
lines.push(`**Date:** ${lastCommit.date}`);
|
|
632
|
+
lines.push(`**Files:** ${fileCount} entries in tree`);
|
|
633
|
+
return {
|
|
634
|
+
content: lines.join("\n"),
|
|
635
|
+
format
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Explain file or directory → path, size, last modified commit
|
|
640
|
+
*/
|
|
641
|
+
async explainPathHandler(ctx) {
|
|
642
|
+
await this.ready();
|
|
643
|
+
const format = ctx.options?.format || "markdown";
|
|
644
|
+
const branch = this.decodeBranchName(ctx.params.branch);
|
|
645
|
+
await this.ensureBranchExists(branch);
|
|
646
|
+
const filePath = ctx.params.path;
|
|
647
|
+
const objectType = await this.git.raw([
|
|
648
|
+
"cat-file",
|
|
649
|
+
"-t",
|
|
650
|
+
`${branch}:${filePath}`
|
|
651
|
+
]).then((t) => t.trim()).catch(() => null);
|
|
652
|
+
if (objectType === null) throw new AFSNotFoundError(this.buildBranchPath(branch, filePath));
|
|
653
|
+
const isDir = objectType === "tree";
|
|
654
|
+
const lines = [];
|
|
655
|
+
lines.push(`# ${basename(filePath)}`);
|
|
656
|
+
lines.push("");
|
|
657
|
+
lines.push(`**Path:** ${filePath}`);
|
|
658
|
+
lines.push(`**Type:** ${isDir ? "directory" : "file"}`);
|
|
659
|
+
if (!isDir) {
|
|
660
|
+
const size = await this.git.raw([
|
|
661
|
+
"cat-file",
|
|
662
|
+
"-s",
|
|
663
|
+
`${branch}:${filePath}`
|
|
664
|
+
]).then((s) => Number.parseInt(s.trim(), 10));
|
|
665
|
+
lines.push(`**Size:** ${size} bytes`);
|
|
666
|
+
}
|
|
667
|
+
try {
|
|
668
|
+
const logLines = (await this.git.raw([
|
|
669
|
+
"log",
|
|
670
|
+
"-1",
|
|
671
|
+
"--format=%H%n%h%n%an%n%aI%n%s",
|
|
672
|
+
branch,
|
|
673
|
+
"--",
|
|
674
|
+
filePath
|
|
675
|
+
])).trim().split("\n");
|
|
676
|
+
if (logLines.length >= 5) {
|
|
677
|
+
lines.push("");
|
|
678
|
+
lines.push("## Last Modified");
|
|
679
|
+
lines.push(`**Commit:** ${logLines[1]} - ${logLines[4]}`);
|
|
680
|
+
lines.push(`**Author:** ${logLines[2]}`);
|
|
681
|
+
lines.push(`**Date:** ${logLines[3]}`);
|
|
682
|
+
}
|
|
683
|
+
} catch {}
|
|
684
|
+
return {
|
|
685
|
+
content: lines.join("\n"),
|
|
686
|
+
format
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
async readCapabilitiesHandler(_ctx) {
|
|
690
|
+
const operations = [
|
|
691
|
+
"list",
|
|
692
|
+
"read",
|
|
693
|
+
"stat",
|
|
694
|
+
"explain",
|
|
695
|
+
"search"
|
|
696
|
+
];
|
|
697
|
+
if (this.accessMode === "readwrite") operations.push("write", "delete", "rename");
|
|
698
|
+
const actionCatalogs = [];
|
|
699
|
+
if (this.accessMode === "readwrite") actionCatalogs.push({
|
|
700
|
+
description: "Git workflow actions",
|
|
701
|
+
catalog: [
|
|
702
|
+
{
|
|
703
|
+
name: "diff",
|
|
704
|
+
description: "Compare two branches or refs",
|
|
705
|
+
inputSchema: {
|
|
706
|
+
type: "object",
|
|
707
|
+
properties: {
|
|
708
|
+
from: {
|
|
709
|
+
type: "string",
|
|
710
|
+
description: "Source ref"
|
|
711
|
+
},
|
|
712
|
+
to: {
|
|
713
|
+
type: "string",
|
|
714
|
+
description: "Target ref"
|
|
715
|
+
},
|
|
716
|
+
path: {
|
|
717
|
+
type: "string",
|
|
718
|
+
description: "Optional path filter"
|
|
719
|
+
}
|
|
720
|
+
},
|
|
721
|
+
required: ["from", "to"]
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
name: "create-branch",
|
|
726
|
+
description: "Create a new branch",
|
|
727
|
+
inputSchema: {
|
|
728
|
+
type: "object",
|
|
729
|
+
properties: {
|
|
730
|
+
name: {
|
|
731
|
+
type: "string",
|
|
732
|
+
description: "New branch name"
|
|
733
|
+
},
|
|
734
|
+
from: {
|
|
735
|
+
type: "string",
|
|
736
|
+
description: "Source ref (defaults to current HEAD)"
|
|
737
|
+
}
|
|
738
|
+
},
|
|
739
|
+
required: ["name"]
|
|
740
|
+
}
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
name: "commit",
|
|
744
|
+
description: "Commit staged changes",
|
|
745
|
+
inputSchema: {
|
|
746
|
+
type: "object",
|
|
747
|
+
properties: {
|
|
748
|
+
message: {
|
|
749
|
+
type: "string",
|
|
750
|
+
description: "Commit message"
|
|
751
|
+
},
|
|
752
|
+
author: {
|
|
753
|
+
type: "object",
|
|
754
|
+
properties: {
|
|
755
|
+
name: { type: "string" },
|
|
756
|
+
email: { type: "string" }
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
required: ["message"]
|
|
761
|
+
}
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
name: "merge",
|
|
765
|
+
description: "Merge a branch into the current branch",
|
|
766
|
+
inputSchema: {
|
|
767
|
+
type: "object",
|
|
768
|
+
properties: {
|
|
769
|
+
branch: {
|
|
770
|
+
type: "string",
|
|
771
|
+
description: "Branch to merge"
|
|
772
|
+
},
|
|
773
|
+
message: {
|
|
774
|
+
type: "string",
|
|
775
|
+
description: "Custom merge message"
|
|
776
|
+
}
|
|
777
|
+
},
|
|
778
|
+
required: ["branch"]
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
],
|
|
782
|
+
discovery: {
|
|
783
|
+
pathTemplate: "/:branch/.actions",
|
|
784
|
+
note: "Git workflow actions (readwrite mode only)"
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
return {
|
|
788
|
+
id: "/.meta/.capabilities",
|
|
789
|
+
path: "/.meta/.capabilities",
|
|
790
|
+
content: {
|
|
791
|
+
schemaVersion: 1,
|
|
792
|
+
provider: this.name,
|
|
793
|
+
description: this.description || "Git repository provider",
|
|
794
|
+
tools: [],
|
|
795
|
+
actions: actionCatalogs,
|
|
796
|
+
operations: this.getOperationsDeclaration()
|
|
797
|
+
},
|
|
798
|
+
meta: {
|
|
799
|
+
kind: "afs:capabilities",
|
|
800
|
+
operations
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* List available actions for a branch
|
|
806
|
+
*/
|
|
807
|
+
async listBranchActions(ctx) {
|
|
808
|
+
if (this.accessMode !== "readwrite") return { data: [] };
|
|
809
|
+
const basePath = `/${ctx.params.branch}/.actions`;
|
|
810
|
+
return { data: [
|
|
811
|
+
{
|
|
812
|
+
id: "diff",
|
|
813
|
+
path: `${basePath}/diff`,
|
|
814
|
+
summary: "Compare two branches or refs",
|
|
815
|
+
meta: {
|
|
816
|
+
kind: "afs:executable",
|
|
817
|
+
kinds: ["afs:executable", "afs:node"],
|
|
818
|
+
inputSchema: {
|
|
819
|
+
type: "object",
|
|
820
|
+
properties: {
|
|
821
|
+
from: {
|
|
822
|
+
type: "string",
|
|
823
|
+
description: "Source ref"
|
|
824
|
+
},
|
|
825
|
+
to: {
|
|
826
|
+
type: "string",
|
|
827
|
+
description: "Target ref"
|
|
828
|
+
},
|
|
829
|
+
path: {
|
|
830
|
+
type: "string",
|
|
831
|
+
description: "Optional path filter"
|
|
832
|
+
}
|
|
833
|
+
},
|
|
834
|
+
required: ["from", "to"]
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
id: "create-branch",
|
|
840
|
+
path: `${basePath}/create-branch`,
|
|
841
|
+
summary: "Create a new branch from this ref",
|
|
842
|
+
meta: {
|
|
843
|
+
kind: "afs:executable",
|
|
844
|
+
kinds: ["afs:executable", "afs:node"],
|
|
845
|
+
inputSchema: {
|
|
846
|
+
type: "object",
|
|
847
|
+
properties: {
|
|
848
|
+
name: {
|
|
849
|
+
type: "string",
|
|
850
|
+
description: "New branch name"
|
|
851
|
+
},
|
|
852
|
+
from: {
|
|
853
|
+
type: "string",
|
|
854
|
+
description: "Source ref (defaults to current HEAD)"
|
|
855
|
+
}
|
|
856
|
+
},
|
|
857
|
+
required: ["name"]
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
id: "commit",
|
|
863
|
+
path: `${basePath}/commit`,
|
|
864
|
+
summary: "Commit staged changes",
|
|
865
|
+
meta: {
|
|
866
|
+
kind: "afs:executable",
|
|
867
|
+
kinds: ["afs:executable", "afs:node"],
|
|
868
|
+
inputSchema: {
|
|
869
|
+
type: "object",
|
|
870
|
+
properties: {
|
|
871
|
+
message: {
|
|
872
|
+
type: "string",
|
|
873
|
+
description: "Commit message"
|
|
874
|
+
},
|
|
875
|
+
author: {
|
|
876
|
+
type: "object",
|
|
877
|
+
properties: {
|
|
878
|
+
name: { type: "string" },
|
|
879
|
+
email: { type: "string" }
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
},
|
|
883
|
+
required: ["message"]
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
id: "merge",
|
|
889
|
+
path: `${basePath}/merge`,
|
|
890
|
+
summary: "Merge another branch into this branch",
|
|
891
|
+
meta: {
|
|
892
|
+
kind: "afs:executable",
|
|
893
|
+
kinds: ["afs:executable", "afs:node"],
|
|
894
|
+
inputSchema: {
|
|
895
|
+
type: "object",
|
|
896
|
+
properties: {
|
|
897
|
+
branch: {
|
|
898
|
+
type: "string",
|
|
899
|
+
description: "Branch to merge"
|
|
900
|
+
},
|
|
901
|
+
message: {
|
|
902
|
+
type: "string",
|
|
903
|
+
description: "Custom merge message"
|
|
904
|
+
}
|
|
905
|
+
},
|
|
906
|
+
required: ["branch"]
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
] };
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* diff action — compare two branches or refs
|
|
914
|
+
*/
|
|
915
|
+
async diffAction(_ctx, args) {
|
|
916
|
+
await this.ready();
|
|
917
|
+
const from = args.from;
|
|
918
|
+
const to = args.to;
|
|
919
|
+
const pathFilter = args.path;
|
|
920
|
+
if (!from || !to) return {
|
|
921
|
+
success: false,
|
|
922
|
+
error: {
|
|
923
|
+
code: "INVALID_ARGS",
|
|
924
|
+
message: "from and to are required"
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
try {
|
|
928
|
+
const diffArgs = [
|
|
929
|
+
"diff",
|
|
930
|
+
"--stat",
|
|
931
|
+
"--name-only",
|
|
932
|
+
`${from}...${to}`
|
|
933
|
+
];
|
|
934
|
+
if (pathFilter) diffArgs.push("--", pathFilter);
|
|
935
|
+
const files = (await this.git.raw(diffArgs)).trim().split("\n").filter((l) => l.trim()).map((path) => ({ path }));
|
|
936
|
+
const patchArgs = ["diff", `${from}...${to}`];
|
|
937
|
+
if (pathFilter) patchArgs.push("--", pathFilter);
|
|
938
|
+
return {
|
|
939
|
+
success: true,
|
|
940
|
+
data: {
|
|
941
|
+
from,
|
|
942
|
+
to,
|
|
943
|
+
files,
|
|
944
|
+
patch: await this.git.raw(patchArgs),
|
|
945
|
+
filesChanged: files.length
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
} catch (error) {
|
|
949
|
+
return {
|
|
950
|
+
success: false,
|
|
951
|
+
error: {
|
|
952
|
+
code: "DIFF_FAILED",
|
|
953
|
+
message: error.message.replace(this.repoPath, "<repo>")
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* create-branch action — create a new branch
|
|
960
|
+
*/
|
|
961
|
+
async createBranchAction(_ctx, args) {
|
|
962
|
+
await this.ready();
|
|
963
|
+
const name = args.name;
|
|
964
|
+
const from = args.from;
|
|
965
|
+
if (!name) return {
|
|
966
|
+
success: false,
|
|
967
|
+
error: {
|
|
968
|
+
code: "INVALID_ARGS",
|
|
969
|
+
message: "name is required"
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
if (name.includes("..")) return {
|
|
973
|
+
success: false,
|
|
974
|
+
error: {
|
|
975
|
+
code: "INVALID_NAME",
|
|
976
|
+
message: "Branch name contains invalid characters"
|
|
977
|
+
}
|
|
978
|
+
};
|
|
979
|
+
try {
|
|
980
|
+
if (from) await this.git.raw([
|
|
981
|
+
"branch",
|
|
982
|
+
name,
|
|
983
|
+
from
|
|
984
|
+
]);
|
|
985
|
+
else await this.git.raw(["branch", name]);
|
|
986
|
+
return {
|
|
987
|
+
success: true,
|
|
988
|
+
data: {
|
|
989
|
+
branch: name,
|
|
990
|
+
hash: await this.git.revparse([name]).then((h) => h.trim())
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
} catch (error) {
|
|
994
|
+
return {
|
|
995
|
+
success: false,
|
|
996
|
+
error: {
|
|
997
|
+
code: "CREATE_BRANCH_FAILED",
|
|
998
|
+
message: error.message.replace(this.repoPath, "<repo>")
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* commit action — commit staged changes
|
|
1005
|
+
*/
|
|
1006
|
+
async commitAction(_ctx, args) {
|
|
1007
|
+
await this.ready();
|
|
1008
|
+
const message = args.message;
|
|
1009
|
+
if (!message) return {
|
|
1010
|
+
success: false,
|
|
1011
|
+
error: {
|
|
1012
|
+
code: "INVALID_ARGS",
|
|
1013
|
+
message: "message is required"
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
const author = args.author;
|
|
1017
|
+
try {
|
|
1018
|
+
const git = simpleGit(this.repoPath);
|
|
1019
|
+
const status = await git.status();
|
|
1020
|
+
if (status.staged.length === 0 && status.files.filter((f) => f.index !== " " && f.index !== "?").length === 0) return {
|
|
1021
|
+
success: false,
|
|
1022
|
+
error: {
|
|
1023
|
+
code: "NO_CHANGES",
|
|
1024
|
+
message: "No staged changes to commit"
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
if (author?.name) await git.addConfig("user.name", author.name, void 0, "local");
|
|
1028
|
+
if (author?.email) await git.addConfig("user.email", author.email, void 0, "local");
|
|
1029
|
+
const result = await git.commit(message);
|
|
1030
|
+
return {
|
|
1031
|
+
success: true,
|
|
1032
|
+
data: {
|
|
1033
|
+
hash: result.commit || "",
|
|
1034
|
+
message,
|
|
1035
|
+
filesChanged: result.summary.changes
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
} catch (error) {
|
|
1039
|
+
return {
|
|
1040
|
+
success: false,
|
|
1041
|
+
error: {
|
|
1042
|
+
code: "COMMIT_FAILED",
|
|
1043
|
+
message: error.message.replace(this.repoPath, "<repo>")
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
/**
|
|
1049
|
+
* merge action — merge a branch into current branch
|
|
1050
|
+
*/
|
|
1051
|
+
async mergeAction(_ctx, args) {
|
|
1052
|
+
await this.ready();
|
|
1053
|
+
const branch = args.branch;
|
|
1054
|
+
if (!branch) return {
|
|
1055
|
+
success: false,
|
|
1056
|
+
error: {
|
|
1057
|
+
code: "INVALID_ARGS",
|
|
1058
|
+
message: "branch is required"
|
|
1059
|
+
}
|
|
1060
|
+
};
|
|
1061
|
+
const customMessage = args.message;
|
|
1062
|
+
try {
|
|
1063
|
+
const git = simpleGit(this.repoPath);
|
|
1064
|
+
if (!(await git.branchLocal()).all.includes(branch)) return {
|
|
1065
|
+
success: false,
|
|
1066
|
+
error: {
|
|
1067
|
+
code: "BRANCH_NOT_FOUND",
|
|
1068
|
+
message: `Branch '${branch}' not found`
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1071
|
+
const mergeArgs = [branch];
|
|
1072
|
+
if (customMessage) mergeArgs.push("-m", customMessage);
|
|
1073
|
+
const result = await git.merge(mergeArgs);
|
|
1074
|
+
return {
|
|
1075
|
+
success: true,
|
|
1076
|
+
data: {
|
|
1077
|
+
hash: await git.revparse(["HEAD"]).then((h) => h.trim()),
|
|
1078
|
+
merged: branch,
|
|
1079
|
+
conflicts: result.conflicts || []
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
} catch (error) {
|
|
1083
|
+
try {
|
|
1084
|
+
await simpleGit(this.repoPath).merge(["--abort"]);
|
|
1085
|
+
} catch {}
|
|
1086
|
+
return {
|
|
1087
|
+
success: false,
|
|
1088
|
+
error: {
|
|
1089
|
+
code: "MERGE_FAILED",
|
|
1090
|
+
message: error.message.replace(this.repoPath, "<repo>")
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* List .log/ → commit list with pagination
|
|
1097
|
+
*/
|
|
1098
|
+
async listLogHandler(ctx) {
|
|
1099
|
+
await this.ready();
|
|
1100
|
+
const branch = this.decodeBranchName(ctx.params.branch);
|
|
1101
|
+
await this.ensureBranchExists(branch);
|
|
1102
|
+
const options = ctx.options;
|
|
1103
|
+
const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);
|
|
1104
|
+
const offset = options?.offset || 0;
|
|
1105
|
+
const commits = await this.getCommitList(branch, limit, offset);
|
|
1106
|
+
const branchEncoded = this.encodeBranchName(branch);
|
|
1107
|
+
return { data: commits.map((commit, i) => this.buildEntry(`/${branchEncoded}/.log/${offset + i}`, { meta: {
|
|
1108
|
+
hash: commit.hash,
|
|
1109
|
+
shortHash: commit.shortHash,
|
|
1110
|
+
author: commit.author,
|
|
1111
|
+
date: commit.date,
|
|
1112
|
+
message: commit.message
|
|
1113
|
+
} })) };
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Read .log/{index} → commit diff/patch content
|
|
1117
|
+
*/
|
|
1118
|
+
async readLogEntryHandler(ctx) {
|
|
1119
|
+
await this.ready();
|
|
1120
|
+
const branch = this.decodeBranchName(ctx.params.branch);
|
|
1121
|
+
await this.ensureBranchExists(branch);
|
|
1122
|
+
const index = Number.parseInt(ctx.params.index, 10);
|
|
1123
|
+
if (Number.isNaN(index) || index < 0) throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${ctx.params.index}`);
|
|
1124
|
+
const commits = await this.getCommitList(branch, 1, index);
|
|
1125
|
+
if (commits.length === 0) throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${index}`);
|
|
1126
|
+
const commit = commits[0];
|
|
1127
|
+
let diff;
|
|
1128
|
+
try {
|
|
1129
|
+
diff = await this.git.raw([
|
|
1130
|
+
"show",
|
|
1131
|
+
"--stat",
|
|
1132
|
+
"--patch",
|
|
1133
|
+
commit.hash
|
|
1134
|
+
]);
|
|
1135
|
+
} catch {
|
|
1136
|
+
diff = "";
|
|
1137
|
+
}
|
|
1138
|
+
const branchEncoded = this.encodeBranchName(branch);
|
|
1139
|
+
return this.buildEntry(`/${branchEncoded}/.log/${index}`, {
|
|
1140
|
+
content: diff,
|
|
1141
|
+
meta: {
|
|
1142
|
+
hash: commit.hash,
|
|
1143
|
+
shortHash: commit.shortHash,
|
|
1144
|
+
author: commit.author,
|
|
1145
|
+
date: commit.date,
|
|
1146
|
+
message: commit.message
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Read .log/{index}/.meta → commit metadata only (no diff)
|
|
1152
|
+
*/
|
|
1153
|
+
async readLogEntryMetaHandler(ctx) {
|
|
1154
|
+
await this.ready();
|
|
1155
|
+
const branch = this.decodeBranchName(ctx.params.branch);
|
|
1156
|
+
await this.ensureBranchExists(branch);
|
|
1157
|
+
const index = Number.parseInt(ctx.params.index, 10);
|
|
1158
|
+
if (Number.isNaN(index) || index < 0) throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${ctx.params.index}/.meta`);
|
|
1159
|
+
const commits = await this.getCommitList(branch, 1, index);
|
|
1160
|
+
if (commits.length === 0) throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${index}/.meta`);
|
|
1161
|
+
const commit = commits[0];
|
|
1162
|
+
const branchEncoded = this.encodeBranchName(branch);
|
|
1163
|
+
return this.buildEntry(`/${branchEncoded}/.log/${index}/.meta`, { meta: {
|
|
1164
|
+
hash: commit.hash,
|
|
1165
|
+
shortHash: commit.shortHash,
|
|
1166
|
+
author: commit.author,
|
|
1167
|
+
date: commit.date,
|
|
1168
|
+
message: commit.message
|
|
1169
|
+
} });
|
|
580
1170
|
}
|
|
581
1171
|
/**
|
|
582
1172
|
* Decode branch name (replace ~ with /)
|
|
@@ -640,6 +1230,65 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
640
1230
|
}
|
|
641
1231
|
}
|
|
642
1232
|
/**
|
|
1233
|
+
* Get the last commit on a branch
|
|
1234
|
+
*/
|
|
1235
|
+
async getLastCommit(branch) {
|
|
1236
|
+
const lines = (await this.git.raw([
|
|
1237
|
+
"log",
|
|
1238
|
+
"-1",
|
|
1239
|
+
"--format=%H%n%h%n%an%n%aI%n%s",
|
|
1240
|
+
branch
|
|
1241
|
+
])).trim().split("\n");
|
|
1242
|
+
return {
|
|
1243
|
+
hash: lines[0] || "",
|
|
1244
|
+
shortHash: lines[1] || "",
|
|
1245
|
+
author: lines[2] || "",
|
|
1246
|
+
date: lines[3] || "",
|
|
1247
|
+
message: lines[4] || ""
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
/**
|
|
1251
|
+
* Count total files in a tree (recursively)
|
|
1252
|
+
*/
|
|
1253
|
+
async getTreeFileCount(branch, path) {
|
|
1254
|
+
try {
|
|
1255
|
+
const treeish = path ? `${branch}:${path}` : branch;
|
|
1256
|
+
return (await this.git.raw([
|
|
1257
|
+
"ls-tree",
|
|
1258
|
+
"-r",
|
|
1259
|
+
treeish
|
|
1260
|
+
])).split("\n").filter((line) => line.trim()).length;
|
|
1261
|
+
} catch {
|
|
1262
|
+
return 0;
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* Get a list of commits on a branch with limit/offset
|
|
1267
|
+
*/
|
|
1268
|
+
async getCommitList(branch, limit, offset) {
|
|
1269
|
+
try {
|
|
1270
|
+
const args = [
|
|
1271
|
+
"log",
|
|
1272
|
+
`--skip=${offset}`,
|
|
1273
|
+
`-${limit}`,
|
|
1274
|
+
"--format=%H%n%h%n%an%n%aI%n%s%n---COMMIT_SEP---",
|
|
1275
|
+
branch
|
|
1276
|
+
];
|
|
1277
|
+
return (await this.git.raw(args)).split("---COMMIT_SEP---").filter((b) => b.trim()).map((block) => {
|
|
1278
|
+
const lines = block.trim().split("\n");
|
|
1279
|
+
return {
|
|
1280
|
+
hash: lines[0] || "",
|
|
1281
|
+
shortHash: lines[1] || "",
|
|
1282
|
+
author: lines[2] || "",
|
|
1283
|
+
date: lines[3] || "",
|
|
1284
|
+
message: lines[4] || ""
|
|
1285
|
+
};
|
|
1286
|
+
});
|
|
1287
|
+
} catch {
|
|
1288
|
+
return [];
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
643
1292
|
* Ensure worktree exists for a branch (lazy creation)
|
|
644
1293
|
*/
|
|
645
1294
|
async ensureWorktree(branch) {
|
|
@@ -663,6 +1312,7 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
663
1312
|
}
|
|
664
1313
|
/**
|
|
665
1314
|
* List files using git ls-tree (no worktree needed)
|
|
1315
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
666
1316
|
*/
|
|
667
1317
|
async listWithGitLsTree(branch, path, options) {
|
|
668
1318
|
const maxDepth = options?.maxDepth ?? 1;
|
|
@@ -677,25 +1327,8 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
677
1327
|
treeish
|
|
678
1328
|
]).then((t) => t.trim()).catch(() => null);
|
|
679
1329
|
if (pathType === null) throw new AFSNotFoundError(this.buildBranchPath(branch, path));
|
|
680
|
-
if (pathType === "blob") {
|
|
681
|
-
|
|
682
|
-
"cat-file",
|
|
683
|
-
"-s",
|
|
684
|
-
treeish
|
|
685
|
-
]).then((s) => Number.parseInt(s.trim(), 10));
|
|
686
|
-
const afsPath$1 = this.buildBranchPath(branch, path);
|
|
687
|
-
entries.push(this.buildEntry(afsPath$1, { metadata: { size } }));
|
|
688
|
-
return { data: entries };
|
|
689
|
-
}
|
|
690
|
-
if (maxDepth === 0) {
|
|
691
|
-
const afsPath$1 = this.buildBranchPath(branch, path);
|
|
692
|
-
const childrenCount$1 = await this.getChildrenCount(branch, path);
|
|
693
|
-
entries.push(this.buildEntry(afsPath$1, { metadata: { childrenCount: childrenCount$1 } }));
|
|
694
|
-
return { data: entries };
|
|
695
|
-
}
|
|
696
|
-
const afsPath = this.buildBranchPath(branch, path);
|
|
697
|
-
const childrenCount = await this.getChildrenCount(branch, path);
|
|
698
|
-
entries.push(this.buildEntry(afsPath, { metadata: { childrenCount } }));
|
|
1330
|
+
if (pathType === "blob") return { data: [] };
|
|
1331
|
+
if (maxDepth === 0) return { data: [] };
|
|
699
1332
|
const queue = [{
|
|
700
1333
|
path: targetPath,
|
|
701
1334
|
depth: 0
|
|
@@ -717,11 +1350,12 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
717
1350
|
const isDirectory = type === "tree";
|
|
718
1351
|
const size = sizeStr === "-" ? void 0 : Number.parseInt(sizeStr, 10);
|
|
719
1352
|
const fullPath = itemPath ? `${itemPath}/${name}` : name;
|
|
720
|
-
const afsPath
|
|
721
|
-
const childrenCount
|
|
722
|
-
entries.push(this.buildEntry(afsPath
|
|
1353
|
+
const afsPath = this.buildBranchPath(branch, fullPath);
|
|
1354
|
+
const childrenCount = isDirectory ? await this.getChildrenCount(branch, fullPath) : void 0;
|
|
1355
|
+
entries.push(this.buildEntry(afsPath, { meta: {
|
|
1356
|
+
kind: isDirectory ? "git:directory" : "git:file",
|
|
723
1357
|
size,
|
|
724
|
-
childrenCount
|
|
1358
|
+
childrenCount
|
|
725
1359
|
} }));
|
|
726
1360
|
if (isDirectory && depth + 1 < maxDepth) queue.push({
|
|
727
1361
|
path: fullPath,
|
|
@@ -856,7 +1490,20 @@ __decorate([Search("/:branch/:path+")], AFSGit.prototype, "searchHandler", null)
|
|
|
856
1490
|
__decorate([Stat("/")], AFSGit.prototype, "statRootHandler", null);
|
|
857
1491
|
__decorate([Stat("/:branch")], AFSGit.prototype, "statBranchRootHandler", null);
|
|
858
1492
|
__decorate([Stat("/:branch/:path+")], AFSGit.prototype, "statHandler", null);
|
|
1493
|
+
__decorate([Explain("/")], AFSGit.prototype, "explainRootHandler", null);
|
|
1494
|
+
__decorate([Explain("/:branch")], AFSGit.prototype, "explainBranchHandler", null);
|
|
1495
|
+
__decorate([Explain("/:branch/:path+")], AFSGit.prototype, "explainPathHandler", null);
|
|
1496
|
+
__decorate([Read("/.meta/.capabilities")], AFSGit.prototype, "readCapabilitiesHandler", null);
|
|
1497
|
+
__decorate([Actions("/:branch")], AFSGit.prototype, "listBranchActions", null);
|
|
1498
|
+
__decorate([Actions.Exec("/:branch", "diff")], AFSGit.prototype, "diffAction", null);
|
|
1499
|
+
__decorate([Actions.Exec("/:branch", "create-branch")], AFSGit.prototype, "createBranchAction", null);
|
|
1500
|
+
__decorate([Actions.Exec("/:branch", "commit")], AFSGit.prototype, "commitAction", null);
|
|
1501
|
+
__decorate([Actions.Exec("/:branch", "merge")], AFSGit.prototype, "mergeAction", null);
|
|
1502
|
+
__decorate([List("/:branch/.log")], AFSGit.prototype, "listLogHandler", null);
|
|
1503
|
+
__decorate([Read("/:branch/.log/:index")], AFSGit.prototype, "readLogEntryHandler", null);
|
|
1504
|
+
__decorate([Read("/:branch/.log/:index/.meta")], AFSGit.prototype, "readLogEntryMetaHandler", null);
|
|
1505
|
+
var src_default = AFSGit;
|
|
859
1506
|
|
|
860
1507
|
//#endregion
|
|
861
|
-
export { AFSGit };
|
|
1508
|
+
export { AFSGit, src_default as default };
|
|
862
1509
|
//# sourceMappingURL=index.mjs.map
|