@skaile/workspaces 1.16.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 +309 -0
- package/dist/{asset-feeds-WIBEP37F.js → asset-feeds-FBGBQEYD.js} +25 -24
- package/dist/asset-feeds-FBGBQEYD.js.map +1 -0
- package/dist/asset-manager/catalog-deployer.js +13 -1
- package/dist/asset-manager/index.js +10 -9
- package/dist/asset-manager/installer.js +7 -6
- package/dist/asset-manager/src/catalog-deployer.d.ts +70 -5
- package/dist/asset-manager/src/catalog-deployer.d.ts.map +1 -1
- package/dist/asset-manager/src/index.d.ts +41 -17
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/asset-manager/src/mcp-config.d.ts +58 -0
- package/dist/asset-manager/src/mcp-config.d.ts.map +1 -0
- package/dist/bridge/drivers/claude-sdk.js +108 -56
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +3 -2
- package/dist/bridge/drivers/codex.js.map +1 -1
- package/dist/bridge/drivers/continue.js +4 -3
- package/dist/bridge/drivers/continue.js.map +1 -1
- package/dist/bridge/drivers/echo.js +3 -2
- package/dist/bridge/drivers/echo.js.map +1 -1
- package/dist/bridge/drivers/gemini.js +5 -4
- package/dist/bridge/drivers/goose.js +4 -3
- package/dist/bridge/drivers/goose.js.map +1 -1
- package/dist/bridge/drivers/omp.js +3 -2
- package/dist/bridge/drivers/omp.js.map +1 -1
- package/dist/bridge/drivers/opencode.js +4 -3
- package/dist/bridge/drivers/opencode.js.map +1 -1
- package/dist/bridge/drivers/qwen.js +5 -4
- package/dist/bridge/drivers/qwen.js.map +1 -1
- package/dist/bridge/index.js +4 -3
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/bridge/src/drivers/scrub-transcript.d.ts +21 -1
- package/dist/bridge/src/drivers/scrub-transcript.d.ts.map +1 -1
- package/dist/{chunk-MO43URUI.js → chunk-2BSXXTUP.js} +7 -7
- package/dist/{chunk-MO43URUI.js.map → chunk-2BSXXTUP.js.map} +1 -1
- package/dist/{chunk-FIUGSIKC.js → chunk-43TAGQ3Z.js} +19 -11
- package/dist/chunk-43TAGQ3Z.js.map +1 -0
- package/dist/{chunk-7J7LQP6T.js → chunk-5BGEYZ7I.js} +31 -19
- package/dist/chunk-5BGEYZ7I.js.map +1 -0
- package/dist/chunk-7GOCNYUV.js +300 -0
- package/dist/chunk-7GOCNYUV.js.map +1 -0
- package/dist/{chunk-KY5NY7LB.js → chunk-BCTU4TN7.js} +11 -11
- package/dist/chunk-BCTU4TN7.js.map +1 -0
- package/dist/chunk-BEAIJRVF.js +159 -0
- package/dist/chunk-BEAIJRVF.js.map +1 -0
- package/dist/{chunk-2TSSCHCQ.js → chunk-BHLNQ4L5.js} +5 -5
- package/dist/{chunk-2TSSCHCQ.js.map → chunk-BHLNQ4L5.js.map} +1 -1
- package/dist/chunk-BK3WL3QK.js +10 -0
- package/dist/chunk-BK3WL3QK.js.map +1 -0
- package/dist/{chunk-TFIFNDT2.js → chunk-BTR3ZJ7S.js} +4 -4
- package/dist/{chunk-TFIFNDT2.js.map → chunk-BTR3ZJ7S.js.map} +1 -1
- package/dist/{chunk-BI2NKPA4.js → chunk-CA5CWLGN.js} +3 -2
- package/dist/chunk-CA5CWLGN.js.map +1 -0
- package/dist/{chunk-STQOPWPS.js → chunk-CTWE7I7Z.js} +4 -4
- package/dist/{chunk-STQOPWPS.js.map → chunk-CTWE7I7Z.js.map} +1 -1
- package/dist/{chunk-GXC3TYMQ.js → chunk-CZZRDYT4.js} +70 -32
- package/dist/chunk-CZZRDYT4.js.map +1 -0
- package/dist/chunk-DYMWJAL4.js +552 -0
- package/dist/chunk-DYMWJAL4.js.map +1 -0
- package/dist/{chunk-ACXLKNIM.js → chunk-E7HKNQTH.js} +10 -4
- package/dist/chunk-E7HKNQTH.js.map +1 -0
- package/dist/{chunk-2BQBWWFX.js → chunk-GUKMNUQK.js} +6 -6
- package/dist/chunk-GUKMNUQK.js.map +1 -0
- package/dist/{chunk-6POODADP.js → chunk-HOL5KD7U.js} +453 -250
- package/dist/chunk-HOL5KD7U.js.map +1 -0
- package/dist/{chunk-C4KVFALU.js → chunk-L26NGI43.js} +3 -3
- package/dist/{chunk-C4KVFALU.js.map → chunk-L26NGI43.js.map} +1 -1
- package/dist/{chunk-MZV6WCF3.js → chunk-MAN7AGQJ.js} +3 -3
- package/dist/{chunk-MZV6WCF3.js.map → chunk-MAN7AGQJ.js.map} +1 -1
- package/dist/{chunk-YULV7UTU.js → chunk-MLYV6WEM.js} +10 -10
- package/dist/{chunk-YULV7UTU.js.map → chunk-MLYV6WEM.js.map} +1 -1
- package/dist/{chunk-O5VCUU6D.js → chunk-N6TYW6EB.js} +4 -4
- package/dist/{chunk-O5VCUU6D.js.map → chunk-N6TYW6EB.js.map} +1 -1
- package/dist/{chunk-EPWY2ABE.js → chunk-PSVF3LDU.js} +5 -5
- package/dist/{chunk-EPWY2ABE.js.map → chunk-PSVF3LDU.js.map} +1 -1
- package/dist/{chunk-M5GJT3D7.js → chunk-PYYL5XMA.js} +3 -3
- package/dist/{chunk-M5GJT3D7.js.map → chunk-PYYL5XMA.js.map} +1 -1
- package/dist/{chunk-BG4XVMG2.js → chunk-RBOPTTTK.js} +286 -151
- package/dist/chunk-RBOPTTTK.js.map +1 -0
- package/dist/{chunk-2IJFUAZB.js → chunk-RK3HU3H3.js} +123 -18
- package/dist/chunk-RK3HU3H3.js.map +1 -0
- package/dist/{chunk-5NZ56R63.js → chunk-RTLQAZAE.js} +18 -6
- package/dist/chunk-RTLQAZAE.js.map +1 -0
- package/dist/{chunk-MNKUZUN2.js → chunk-SGLGA2AZ.js} +3 -3
- package/dist/{chunk-MNKUZUN2.js.map → chunk-SGLGA2AZ.js.map} +1 -1
- package/dist/{chunk-JB35MVBN.js → chunk-U5POE4BA.js} +4 -298
- package/dist/chunk-U5POE4BA.js.map +1 -0
- package/dist/{chunk-A22KZ7GZ.js → chunk-VPXBAEWE.js} +274 -40
- package/dist/chunk-VPXBAEWE.js.map +1 -0
- package/dist/{chunk-ACWCVB5Q.js → chunk-WVPL4OGD.js} +3 -3
- package/dist/{chunk-ACWCVB5Q.js.map → chunk-WVPL4OGD.js.map} +1 -1
- package/dist/{chunk-MB6563TL.js → chunk-XQVP6XWR.js} +3 -3
- package/dist/{chunk-MB6563TL.js.map → chunk-XQVP6XWR.js.map} +1 -1
- package/dist/{chunk-344DEXZS.js → chunk-XSIXGVH6.js} +4 -4
- package/dist/{chunk-344DEXZS.js.map → chunk-XSIXGVH6.js.map} +1 -1
- package/dist/{chunk-BYS6JDZB.js → chunk-Y6VSFX2A.js} +3 -3
- package/dist/{chunk-BYS6JDZB.js.map → chunk-Y6VSFX2A.js.map} +1 -1
- package/dist/{chunk-ISA7R7PK.js → chunk-YODP3STD.js} +90 -40
- package/dist/chunk-YODP3STD.js.map +1 -0
- package/dist/{chunk-WSTY3AWY.js → chunk-ZWFLEMI4.js} +4 -4
- package/dist/{chunk-WSTY3AWY.js.map → chunk-ZWFLEMI4.js.map} +1 -1
- package/dist/cli/index.js +347 -127
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/asset-feeds.d.ts +2 -2
- package/dist/cli/src/asset-feeds.d.ts.map +1 -1
- package/dist/cli/src/commands/catalog.d.ts +51 -2
- package/dist/cli/src/commands/catalog.d.ts.map +1 -1
- package/dist/cli/src/commands/connector.d.ts +1 -1
- package/dist/cli/src/commands/connector.d.ts.map +1 -1
- package/dist/cli/src/commands/logs.d.ts.map +1 -1
- package/dist/cli/src/commands/manage.d.ts +30 -3
- package/dist/cli/src/commands/manage.d.ts.map +1 -1
- package/dist/cli/src/commands/project.d.ts +5 -2
- package/dist/cli/src/commands/project.d.ts.map +1 -1
- package/dist/connectors/config.js +7 -6
- package/dist/connectors/index.js +8 -7
- package/dist/connectors/src/connector-manager.d.ts.map +1 -1
- package/dist/connectors/src/watcher.d.ts.map +1 -1
- package/dist/connectors/src/worktree.d.ts +20 -2
- package/dist/connectors/src/worktree.d.ts.map +1 -1
- package/dist/core/index.js +6 -5
- package/dist/core/logging.js +2 -1
- package/dist/core/manifest.js +2 -1
- package/dist/core/runtime-assets.js +4 -3
- package/dist/core/src/fs-deadline.d.ts +84 -0
- package/dist/core/src/fs-deadline.d.ts.map +1 -0
- package/dist/core/src/index.d.ts +4 -3
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/manifest.d.ts +142 -18
- package/dist/core/src/manifest.d.ts.map +1 -1
- package/dist/core/src/repo-manager.d.ts +2 -2
- package/dist/core/src/repo-manager.d.ts.map +1 -1
- package/dist/core/src/runtime-assets.d.ts.map +1 -1
- package/dist/core/src/subprocess.d.ts +33 -1
- package/dist/core/src/subprocess.d.ts.map +1 -1
- package/dist/core/src/walker.d.ts +1 -1
- package/dist/core/src/walker.d.ts.map +1 -1
- package/dist/core/src/workspace-config.d.ts +19 -2
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/workspace-config.js +3 -2
- package/dist/deploy/index.js +12 -7
- package/dist/deploy/index.js.map +1 -1
- package/dist/deploy/src/targets/container-runtime.d.ts.map +1 -1
- package/dist/discovery/index.js +3 -2
- package/dist/{ensure-sources-RSTZONIE.js → ensure-sources-AVCVX7CV.js} +13 -12
- package/dist/ensure-sources-AVCVX7CV.js.map +1 -0
- package/dist/factory-assets/connectors/box.js +8 -7
- package/dist/factory-assets/connectors/deploy/CONNECTOR.md +19 -0
- package/dist/factory-assets/connectors/deploy/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/deploy.js +8 -7
- package/dist/factory-assets/connectors/devserver/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/devserver.js +8 -7
- package/dist/factory-assets/connectors/flow/adapter.js +8 -7
- package/dist/factory-assets/connectors/flow/engine.js +6 -5
- package/dist/factory-assets/connectors/flow/run-flow.js +10 -9
- package/dist/factory-assets/connectors/flow.js +8 -7
- package/dist/factory-assets/connectors/git/driver.d.ts +12 -1
- package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/git.js +8 -7
- package/dist/factory-assets/connectors/gmail.js +8 -7
- package/dist/factory-assets/connectors/googledrive.js +8 -7
- package/dist/factory-assets/connectors/local/driver.d.ts +25 -1
- package/dist/factory-assets/connectors/local/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/local.js +8 -7
- package/dist/factory-assets/connectors/mattermost.js +8 -7
- package/dist/factory-assets/connectors/memory.js +8 -7
- package/dist/factory-assets/connectors/minio.js +8 -7
- package/dist/factory-assets/connectors/postgres.js +8 -7
- package/dist/factory-assets/connectors/s3/driver.d.ts +15 -0
- package/dist/factory-assets/connectors/s3/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/s3.js +8 -7
- package/dist/factory-assets/connectors/sharepoint.js +8 -7
- package/dist/factory-assets/connectors/sqlite/adapter.d.ts +8 -1
- package/dist/factory-assets/connectors/sqlite/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/sqlite.js +8 -7
- package/dist/factory-assets/connectors/static-server/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/static-server.js +8 -7
- package/dist/factory-assets/connectors/tunnel.js +8 -7
- package/dist/factory-assets/connectors/webdav.js +8 -7
- package/dist/factory-assets/connectors/xstate/adapter.d.ts +6 -0
- package/dist/factory-assets/connectors/xstate/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/xstate-store.js +8 -7
- package/dist/factory-assets/connectors/xstate.js +8 -7
- package/dist/flows-CXVFGR27.js +20 -0
- package/dist/{flows-FHWBCLXF.js.map → flows-CXVFGR27.js.map} +1 -1
- package/dist/{helpers-GUUWPPAX.js → helpers-M5SXB4LL.js} +13 -12
- package/dist/{helpers-GUUWPPAX.js.map → helpers-M5SXB4LL.js.map} +1 -1
- package/dist/library/index.js +8 -7
- package/dist/library/install.js +6 -5
- package/dist/{library-publish-UKKSJP7V.js → library-publish-HVIIQMI6.js} +16 -15
- package/dist/library-publish-HVIIQMI6.js.map +1 -0
- package/dist/{open-library-VALRYGFV.js → open-library-EJQISBWV.js} +14 -13
- package/dist/{open-library-VALRYGFV.js.map → open-library-EJQISBWV.js.map} +1 -1
- package/dist/{paths-5QJJBAND.js → paths-2HMHL25W.js} +11 -10
- package/dist/{paths-5QJJBAND.js.map → paths-2HMHL25W.js.map} +1 -1
- package/dist/plugin-registry/src/deploy-helpers.d.ts +1 -1
- package/dist/{plugin-store-ZBJZ7F6D.js → plugin-store-TLBQ5XRS.js} +8 -7
- package/dist/plugin-store-TLBQ5XRS.js.map +1 -0
- package/dist/{project-IRUJLIVX.js → project-M2COJFPZ.js} +14 -13
- package/dist/{project-IRUJLIVX.js.map → project-M2COJFPZ.js.map} +1 -1
- package/dist/resolver/index.js +13 -1
- package/dist/resolver/src/types.d.ts +7 -0
- package/dist/resolver/src/types.d.ts.map +1 -1
- package/dist/resolver/src/validator.d.ts +8 -1
- package/dist/resolver/src/validator.d.ts.map +1 -1
- package/dist/runner/index.js +13 -12
- package/dist/runner/src/external-mcp.d.ts +1 -1
- package/dist/runner/src/external-mcp.d.ts.map +1 -1
- package/dist/runner/src/mcp-prompt.d.ts +7 -3
- package/dist/runner/src/mcp-prompt.d.ts.map +1 -1
- package/dist/runner/src/mcp-runtime-handlers.d.ts +12 -0
- package/dist/runner/src/mcp-runtime-handlers.d.ts.map +1 -1
- package/dist/runner/src/mixin-resolver.d.ts.map +1 -1
- package/dist/runner/src/recipe-resolver.d.ts +20 -6
- package/dist/runner/src/recipe-resolver.d.ts.map +1 -1
- package/dist/runner/src/resource-handler.d.ts +43 -0
- package/dist/runner/src/resource-handler.d.ts.map +1 -1
- package/dist/runner/src/resources.d.ts +12 -5
- package/dist/runner/src/resources.d.ts.map +1 -1
- package/dist/runner/src/serve.d.ts +31 -5
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/runner/src/session-builder.d.ts +9 -0
- package/dist/runner/src/session-builder.d.ts.map +1 -1
- package/dist/runner/src/session-capability-wiring.d.ts +5 -0
- package/dist/runner/src/session-capability-wiring.d.ts.map +1 -1
- package/dist/runner/src/workspace-migration.d.ts +37 -3
- package/dist/runner/src/workspace-migration.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +10 -9
- package/dist/sdk/bridge.js +4 -3
- package/dist/sdk/core.js +6 -5
- package/dist/sdk/flow.js +6 -5
- package/dist/sdk/index.js +13 -12
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/resolver.js +13 -1
- package/dist/sdk/runner.js +13 -12
- package/dist/sdk/session.js +1 -1
- package/dist/sdk/store.js +1 -1
- package/dist/session/index.js +1 -1
- package/dist/session/src/dispatcher.d.ts.map +1 -1
- package/dist/{setup-WJPNUE32.js → setup-GWXEG3G2.js} +10 -9
- package/dist/setup-GWXEG3G2.js.map +1 -0
- package/dist/skills-YTMGG23D.js +20 -0
- package/dist/{skills-BMI6H7HI.js.map → skills-YTMGG23D.js.map} +1 -1
- package/dist/{source-5KDURFBS.js → source-WMXH2OBW.js} +15 -14
- package/dist/{source-5KDURFBS.js.map → source-WMXH2OBW.js.map} +1 -1
- package/dist/{source-manifest-publish-DPQI44D3.js → source-manifest-publish-MTHUGBAY.js} +17 -16
- package/dist/source-manifest-publish-MTHUGBAY.js.map +1 -0
- package/dist/store/index.js +1 -1
- package/dist/store/src/store.d.ts +9 -0
- package/dist/store/src/store.d.ts.map +1 -1
- package/dist/tui/index.js +13 -12
- package/dist/tui/index.js.map +1 -1
- package/dist/validator-RN64BKFW.js +5 -0
- package/dist/{validator-VF5M764T.js.map → validator-RN64BKFW.js.map} +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +18 -5
- package/dist/workspace-plugin/adapters/mcp.js.map +1 -1
- package/dist/workspace-plugin/adapters/omp.js +10 -10
- package/dist/workspace-plugin/index.js +3 -2
- package/dist/workspace-plugin/src/tools/validator.d.ts.map +1 -1
- package/dist/workspace-plugin/src/utils/ai-assets.d.ts +11 -6
- package/dist/workspace-plugin/src/utils/ai-assets.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/asset-feeds-WIBEP37F.js.map +0 -1
- package/dist/chunk-2BQBWWFX.js.map +0 -1
- package/dist/chunk-2IJFUAZB.js.map +0 -1
- package/dist/chunk-5NZ56R63.js.map +0 -1
- package/dist/chunk-6POODADP.js.map +0 -1
- package/dist/chunk-7J7LQP6T.js.map +0 -1
- package/dist/chunk-A22KZ7GZ.js.map +0 -1
- package/dist/chunk-ACXLKNIM.js.map +0 -1
- package/dist/chunk-BG4XVMG2.js.map +0 -1
- package/dist/chunk-BI2NKPA4.js.map +0 -1
- package/dist/chunk-BQCGFPHW.js +0 -345
- package/dist/chunk-BQCGFPHW.js.map +0 -1
- package/dist/chunk-FIUGSIKC.js.map +0 -1
- package/dist/chunk-GXC3TYMQ.js.map +0 -1
- package/dist/chunk-ISA7R7PK.js.map +0 -1
- package/dist/chunk-JB35MVBN.js.map +0 -1
- package/dist/chunk-KY5NY7LB.js.map +0 -1
- package/dist/chunk-LV2HPH3C.js +0 -73
- package/dist/chunk-LV2HPH3C.js.map +0 -1
- package/dist/chunk-XCBG2KDC.js +0 -23
- package/dist/chunk-XCBG2KDC.js.map +0 -1
- package/dist/ensure-sources-RSTZONIE.js.map +0 -1
- package/dist/flows-FHWBCLXF.js +0 -7
- package/dist/library-publish-UKKSJP7V.js.map +0 -1
- package/dist/plugin-store-ZBJZ7F6D.js.map +0 -1
- package/dist/setup-WJPNUE32.js.map +0 -1
- package/dist/skills-BMI6H7HI.js +0 -7
- package/dist/source-manifest-publish-DPQI44D3.js.map +0 -1
- package/dist/validator-VF5M764T.js +0 -5
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import { resolveAuthRef } from './chunk-
|
|
1
|
+
import { resolveAuthRef } from './chunk-BHLNQ4L5.js';
|
|
2
2
|
import { pluginRegistry } from './chunk-6E6PKKAD.js';
|
|
3
3
|
import { computeFlowStateFromSnapshots } from './chunk-HPGV54O4.js';
|
|
4
4
|
import { renderStimulusPrompt } from './chunk-Y662DNQQ.js';
|
|
5
5
|
import { computeStimulus } from './chunk-IFGTRL2I.js';
|
|
6
|
-
import { portableSpawn } from './chunk-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { portableSpawn } from './chunk-RTLQAZAE.js';
|
|
7
|
+
import { withFsDeadline, tryWithFsDeadline, FsDeadlineError, fsDeadlineMs } from './chunk-DYMWJAL4.js';
|
|
8
|
+
import { createLogger } from './chunk-7GOCNYUV.js';
|
|
9
|
+
import { mkdir, rename, writeFile, readFile, stat, cp, readdir, chmod, realpath } from 'fs/promises';
|
|
9
10
|
import { join, dirname, resolve, sep, relative } from 'path';
|
|
10
11
|
import * as zNS from 'zod';
|
|
11
|
-
import {
|
|
12
|
+
import { execFile } from 'child_process';
|
|
13
|
+
import { promisify } from 'util';
|
|
14
|
+
import { createReadStream, readFileSync, existsSync, mkdirSync, openSync, writeSync, closeSync, chmodSync, renameSync } from 'fs';
|
|
12
15
|
import { createServer } from 'http';
|
|
13
16
|
import mime from 'mime';
|
|
14
|
-
import { stat, readdir, mkdir, chmod, readFile, realpath } from 'fs/promises';
|
|
15
17
|
import { createRequire } from 'module';
|
|
16
18
|
import { pathToFileURL } from 'url';
|
|
17
19
|
import { createConnection } from 'net';
|
|
@@ -51,6 +53,8 @@ var AbstractConnector = class {
|
|
|
51
53
|
};
|
|
52
54
|
}
|
|
53
55
|
};
|
|
56
|
+
var execFileAsync = promisify(execFile);
|
|
57
|
+
var GIT_REV_PARSE_TIMEOUT_MS = 15e3;
|
|
54
58
|
var DeployConnector = class extends AbstractConnector {
|
|
55
59
|
name = "deploy";
|
|
56
60
|
tools;
|
|
@@ -69,12 +73,16 @@ var DeployConnector = class extends AbstractConnector {
|
|
|
69
73
|
for (const [k, v] of Object.entries(declaration.options ?? {})) {
|
|
70
74
|
if (k !== "provider" && typeof v === "string") defaults[k] = v;
|
|
71
75
|
}
|
|
76
|
+
const repoDir = String(declaration.options?.repo_root ?? process.cwd());
|
|
72
77
|
let repoRoot = null;
|
|
73
78
|
try {
|
|
74
|
-
|
|
79
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
|
|
80
|
+
cwd: repoDir,
|
|
75
81
|
encoding: "utf-8",
|
|
76
|
-
|
|
77
|
-
|
|
82
|
+
timeout: GIT_REV_PARSE_TIMEOUT_MS,
|
|
83
|
+
killSignal: "SIGKILL"
|
|
84
|
+
});
|
|
85
|
+
repoRoot = stdout.trim();
|
|
78
86
|
} catch {
|
|
79
87
|
}
|
|
80
88
|
return this.makeHandle(declaration, {
|
|
@@ -82,7 +90,7 @@ var DeployConnector = class extends AbstractConnector {
|
|
|
82
90
|
defaults,
|
|
83
91
|
deployments: /* @__PURE__ */ new Map(),
|
|
84
92
|
repoRoot,
|
|
85
|
-
worktreeDir:
|
|
93
|
+
worktreeDir: repoDir
|
|
86
94
|
});
|
|
87
95
|
}
|
|
88
96
|
async disconnect(handle) {
|
|
@@ -317,7 +325,7 @@ var DevServerConnector = class extends AbstractConnector {
|
|
|
317
325
|
const portRange = opts.port_range ?? [3e3, 3099];
|
|
318
326
|
let repoRoot = null;
|
|
319
327
|
try {
|
|
320
|
-
repoRoot = findGitRoot(process.cwd());
|
|
328
|
+
repoRoot = await findGitRoot(process.cwd());
|
|
321
329
|
} catch {
|
|
322
330
|
}
|
|
323
331
|
const state = {
|
|
@@ -546,8 +554,8 @@ var DevServerConnector = class extends AbstractConnector {
|
|
|
546
554
|
detached: true
|
|
547
555
|
});
|
|
548
556
|
const logBuffer = new LogBuffer(state.logBufferSize);
|
|
549
|
-
pipeToBuffer(proc.stdout, logBuffer);
|
|
550
|
-
pipeToBuffer(proc.stderr, logBuffer);
|
|
557
|
+
void pipeToBuffer(proc.stdout, logBuffer);
|
|
558
|
+
void pipeToBuffer(proc.stderr, logBuffer);
|
|
551
559
|
const instance = {
|
|
552
560
|
id: label,
|
|
553
561
|
pid: proc.pid,
|
|
@@ -838,24 +846,29 @@ function resolveGitConfig(args) {
|
|
|
838
846
|
};
|
|
839
847
|
}
|
|
840
848
|
var modeLog = createLogger({ kind: "connector", subkind: "git" });
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
}
|
|
844
|
-
function gitCommand(cwd) {
|
|
845
|
-
return `git -c safe.directory=${shellQuote(cwd)}`;
|
|
849
|
+
var execFileAsync2 = promisify(execFile);
|
|
850
|
+
function gitPrefix(cwd) {
|
|
851
|
+
return ["-c", `safe.directory=${cwd}`];
|
|
846
852
|
}
|
|
847
|
-
function
|
|
848
|
-
|
|
849
|
-
cwd,
|
|
853
|
+
async function runGit(args, options) {
|
|
854
|
+
const { stdout } = await execFileAsync2("git", args, {
|
|
850
855
|
encoding: "utf-8",
|
|
851
|
-
timeout,
|
|
852
|
-
|
|
853
|
-
|
|
856
|
+
timeout: options.timeout,
|
|
857
|
+
killSignal: "SIGKILL",
|
|
858
|
+
...options.cwd === void 0 ? {} : { cwd: options.cwd }
|
|
859
|
+
});
|
|
860
|
+
return stdout.trim();
|
|
854
861
|
}
|
|
855
|
-
function
|
|
856
|
-
|
|
862
|
+
function git(args, cwd, timeout = 3e4) {
|
|
863
|
+
return runGit([...gitPrefix(cwd), ...args], { cwd, timeout });
|
|
864
|
+
}
|
|
865
|
+
function pathExists(path) {
|
|
866
|
+
return tryWithFsDeadline(`stat ${path}`, () => stat(path).then(() => true), false);
|
|
867
|
+
}
|
|
868
|
+
async function syncSubmodules(cwd) {
|
|
869
|
+
if (!await pathExists(join(cwd, ".gitmodules"))) return;
|
|
857
870
|
try {
|
|
858
|
-
git("submodule update --init --recursive", cwd, 12e4);
|
|
871
|
+
await git(["submodule", "update", "--init", "--recursive"], cwd, 12e4);
|
|
859
872
|
} catch {
|
|
860
873
|
}
|
|
861
874
|
}
|
|
@@ -867,19 +880,19 @@ function isValidGitRefOrSha(ref) {
|
|
|
867
880
|
if (ref.includes("..") || ref.includes("@{")) return false;
|
|
868
881
|
return true;
|
|
869
882
|
}
|
|
870
|
-
function hasChanges(cwd) {
|
|
871
|
-
const status = git("status --porcelain", cwd);
|
|
883
|
+
async function hasChanges(cwd) {
|
|
884
|
+
const status = await git(["status", "--porcelain"], cwd);
|
|
872
885
|
return status.length > 0;
|
|
873
886
|
}
|
|
874
|
-
function gitOrNull(
|
|
887
|
+
async function gitOrNull(args, cwd) {
|
|
875
888
|
try {
|
|
876
|
-
return git(
|
|
889
|
+
return await git(args, cwd);
|
|
877
890
|
} catch {
|
|
878
891
|
return null;
|
|
879
892
|
}
|
|
880
893
|
}
|
|
881
|
-
function countAheadBehind(cwd, remoteRef) {
|
|
882
|
-
const out = gitOrNull(
|
|
894
|
+
async function countAheadBehind(cwd, remoteRef) {
|
|
895
|
+
const out = await gitOrNull(["rev-list", "--left-right", "--count", `${remoteRef}...HEAD`], cwd);
|
|
883
896
|
if (!out) {
|
|
884
897
|
return { ahead: 0, behind: 0 };
|
|
885
898
|
}
|
|
@@ -891,15 +904,15 @@ function countAheadBehind(cwd, remoteRef) {
|
|
|
891
904
|
behind: Number.isFinite(behind) ? behind : 0
|
|
892
905
|
};
|
|
893
906
|
}
|
|
894
|
-
function readGitSyncStatus(cwd, baseBranch) {
|
|
895
|
-
const branchRaw = gitOrNull("rev-parse --abbrev-ref HEAD", cwd);
|
|
907
|
+
async function readGitSyncStatus(cwd, baseBranch) {
|
|
908
|
+
const branchRaw = await gitOrNull(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
|
|
896
909
|
const branch = branchRaw && branchRaw !== "HEAD" ? branchRaw : null;
|
|
897
|
-
const dirty = (gitOrNull("status --porcelain", cwd) ?? "") !== "";
|
|
898
|
-
const hasUpstream = branch !== null && gitOrNull("rev-parse --abbrev-ref @{upstream}", cwd) !== null;
|
|
899
|
-
const upstream = countAheadBehind(cwd, "@{upstream}");
|
|
910
|
+
const dirty = (await gitOrNull(["status", "--porcelain"], cwd) ?? "") !== "";
|
|
911
|
+
const hasUpstream = branch !== null && await gitOrNull(["rev-parse", "--abbrev-ref", "@{upstream}"], cwd) !== null;
|
|
912
|
+
const upstream = await countAheadBehind(cwd, "@{upstream}");
|
|
900
913
|
const baseRef = isValidGitRefOrSha(baseBranch) ? `origin/${baseBranch}` : "origin/main";
|
|
901
|
-
const base = countAheadBehind(cwd, baseRef);
|
|
902
|
-
const commitSha = gitOrNull("rev-parse HEAD", cwd);
|
|
914
|
+
const base = await countAheadBehind(cwd, baseRef);
|
|
915
|
+
const commitSha = await gitOrNull(["rev-parse", "HEAD"], cwd);
|
|
903
916
|
return {
|
|
904
917
|
branch,
|
|
905
918
|
dirty,
|
|
@@ -911,25 +924,22 @@ function readGitSyncStatus(cwd, baseBranch) {
|
|
|
911
924
|
commitSha
|
|
912
925
|
};
|
|
913
926
|
}
|
|
914
|
-
function localBranchExists(branch, cwd) {
|
|
927
|
+
async function localBranchExists(branch, cwd) {
|
|
915
928
|
try {
|
|
916
|
-
git(
|
|
929
|
+
await git(["rev-parse", "--verify", "--quiet", `refs/heads/${branch}`], cwd);
|
|
917
930
|
return true;
|
|
918
931
|
} catch {
|
|
919
932
|
return false;
|
|
920
933
|
}
|
|
921
934
|
}
|
|
922
|
-
function isDirEmpty(dir) {
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
} catch {
|
|
926
|
-
return true;
|
|
927
|
-
}
|
|
935
|
+
async function isDirEmpty(dir) {
|
|
936
|
+
const entries = await tryWithFsDeadline(`readdir ${dir}`, () => readdir(dir), []);
|
|
937
|
+
return entries.length === 0;
|
|
928
938
|
}
|
|
929
|
-
function commitAll(cwd, message) {
|
|
930
|
-
if (!hasChanges(cwd)) return null;
|
|
931
|
-
git("add -A", cwd);
|
|
932
|
-
return git(
|
|
939
|
+
async function commitAll(cwd, message) {
|
|
940
|
+
if (!await hasChanges(cwd)) return null;
|
|
941
|
+
await git(["add", "-A"], cwd);
|
|
942
|
+
return git(["commit", "-m", message], cwd);
|
|
933
943
|
}
|
|
934
944
|
var TokenMediatorError = class extends Error {
|
|
935
945
|
code;
|
|
@@ -969,7 +979,7 @@ var GitConnector = class extends AbstractConnector {
|
|
|
969
979
|
throw new Error("git sync_status: mount path unavailable");
|
|
970
980
|
}
|
|
971
981
|
const state = handle.state;
|
|
972
|
-
return JSON.stringify(readGitSyncStatus(cwd, state.branch));
|
|
982
|
+
return JSON.stringify(await readGitSyncStatus(cwd, state.branch));
|
|
973
983
|
}
|
|
974
984
|
default:
|
|
975
985
|
throw new Error(`GitConnector has no operation: ${operation}`);
|
|
@@ -1014,9 +1024,9 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1014
1024
|
tokenMediator: initial.authRef?.kind === "backend" ? tokenMediator : void 0
|
|
1015
1025
|
};
|
|
1016
1026
|
const authUrl = this.authUrl(state);
|
|
1017
|
-
this.prepareCheckout(targetDir, url, branch, authUrl, started);
|
|
1027
|
+
await this.prepareCheckout(targetDir, url, branch, authUrl, started);
|
|
1018
1028
|
if (session.enabled && !session.isMain && session.slug) {
|
|
1019
|
-
this.checkoutSessionBranch(state, session, targetDir);
|
|
1029
|
+
await this.checkoutSessionBranch(state, session, targetDir);
|
|
1020
1030
|
}
|
|
1021
1031
|
if (sync.fetchIntervalSec > 0) {
|
|
1022
1032
|
this.startPeriodicFetch(state, targetDir);
|
|
@@ -1030,9 +1040,9 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1030
1040
|
}
|
|
1031
1041
|
}
|
|
1032
1042
|
if (state.managedGitconfig) {
|
|
1033
|
-
this.stripRemoteInlineToken(targetDir);
|
|
1043
|
+
await this.stripRemoteInlineToken(targetDir);
|
|
1034
1044
|
} else {
|
|
1035
|
-
this.rebakeRemoteAuth(targetDir, state);
|
|
1045
|
+
await this.rebakeRemoteAuth(targetDir, state);
|
|
1036
1046
|
if (initial.authRef?.kind === "backend" && initial.expiresAt && state.tokenMediator) {
|
|
1037
1047
|
this.scheduleRefresh(declaration.id, state, initial.expiresAt);
|
|
1038
1048
|
}
|
|
@@ -1061,31 +1071,37 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1061
1071
|
* reset, no clean. Existing files become uncommitted-on-init; the
|
|
1062
1072
|
* agent or `pushAfterCommit` reconciles with remote later.
|
|
1063
1073
|
*/
|
|
1064
|
-
prepareCheckout(targetDir, url, branch, authUrl, started) {
|
|
1074
|
+
async prepareCheckout(targetDir, url, branch, authUrl, started) {
|
|
1065
1075
|
try {
|
|
1066
|
-
if (
|
|
1067
|
-
if (this.isInitialisedCheckout(targetDir)) {
|
|
1076
|
+
if (await pathExists(join(targetDir, ".git"))) {
|
|
1077
|
+
if (await this.isInitialisedCheckout(targetDir)) {
|
|
1068
1078
|
this.log.info("found existing checkout \u2014 using as-is", { branch, targetDir });
|
|
1069
1079
|
} else {
|
|
1070
1080
|
this.log.info("found empty .git \u2014 bootstrapping from origin", { branch });
|
|
1071
|
-
this.bootstrapFromOrigin(targetDir, branch, authUrl);
|
|
1081
|
+
await this.bootstrapFromOrigin(targetDir, branch, authUrl);
|
|
1072
1082
|
this.log.info("bootstrap ok", { branch, durationMs: Date.now() - started });
|
|
1073
1083
|
}
|
|
1074
1084
|
} else {
|
|
1075
|
-
|
|
1076
|
-
if (isDirEmpty(targetDir)) {
|
|
1085
|
+
await withFsDeadline(`mkdir ${targetDir}`, () => mkdir(targetDir, { recursive: true }));
|
|
1086
|
+
if (await isDirEmpty(targetDir)) {
|
|
1077
1087
|
this.log.info("clone start", { url, branch });
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1088
|
+
await runGit(
|
|
1089
|
+
[
|
|
1090
|
+
...gitPrefix(targetDir),
|
|
1091
|
+
"clone",
|
|
1092
|
+
"--branch",
|
|
1093
|
+
branch,
|
|
1094
|
+
"--single-branch",
|
|
1095
|
+
"--recurse-submodules",
|
|
1096
|
+
authUrl,
|
|
1097
|
+
targetDir
|
|
1098
|
+
],
|
|
1099
|
+
{ timeout: 12e4 }
|
|
1084
1100
|
);
|
|
1085
1101
|
this.log.info("clone ok", { branch, durationMs: Date.now() - started });
|
|
1086
1102
|
} else {
|
|
1087
1103
|
this.log.warn("target non-empty without .git \u2014 initialising in place", { targetDir });
|
|
1088
|
-
this.initInPlace(targetDir, authUrl);
|
|
1104
|
+
await this.initInPlace(targetDir, authUrl);
|
|
1089
1105
|
this.log.info("init in place ok", { durationMs: Date.now() - started });
|
|
1090
1106
|
}
|
|
1091
1107
|
}
|
|
@@ -1101,37 +1117,37 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1101
1117
|
* fork flow) when supplied and valid, else off the currently-checked-out
|
|
1102
1118
|
* HEAD (== base branch).
|
|
1103
1119
|
*/
|
|
1104
|
-
checkoutSessionBranch(state, session, targetDir) {
|
|
1120
|
+
async checkoutSessionBranch(state, session, targetDir) {
|
|
1105
1121
|
const sessionBranch = `${session.branchPrefix}${session.slug}`;
|
|
1106
1122
|
if (!isValidGitRefOrSha(sessionBranch)) {
|
|
1107
1123
|
throw new Error(`Git connector: invalid session branch name "${sessionBranch}"`);
|
|
1108
1124
|
}
|
|
1109
1125
|
let created = false;
|
|
1110
|
-
if (localBranchExists(sessionBranch, targetDir)) {
|
|
1111
|
-
git(
|
|
1126
|
+
if (await localBranchExists(sessionBranch, targetDir)) {
|
|
1127
|
+
await git(["checkout", sessionBranch], targetDir);
|
|
1112
1128
|
this.log.info("reusing existing local session branch", { sessionBranch });
|
|
1113
1129
|
} else {
|
|
1114
1130
|
let originHasBranch = false;
|
|
1115
1131
|
try {
|
|
1116
|
-
git(
|
|
1132
|
+
await git(["rev-parse", "--verify", `origin/${sessionBranch}`], targetDir);
|
|
1117
1133
|
originHasBranch = true;
|
|
1118
1134
|
} catch {
|
|
1119
1135
|
}
|
|
1120
1136
|
if (originHasBranch) {
|
|
1121
|
-
git(
|
|
1122
|
-
} else if (!this.branchFromRef(session, sessionBranch, targetDir)) {
|
|
1123
|
-
git(
|
|
1137
|
+
await git(["checkout", "-B", sessionBranch, `origin/${sessionBranch}`], targetDir);
|
|
1138
|
+
} else if (!await this.branchFromRef(session, sessionBranch, targetDir)) {
|
|
1139
|
+
await git(["checkout", "-b", sessionBranch], targetDir);
|
|
1124
1140
|
created = true;
|
|
1125
1141
|
} else {
|
|
1126
1142
|
created = true;
|
|
1127
1143
|
}
|
|
1128
1144
|
}
|
|
1129
|
-
syncSubmodules(targetDir);
|
|
1145
|
+
await syncSubmodules(targetDir);
|
|
1130
1146
|
state.activeBranch = sessionBranch;
|
|
1131
1147
|
this.log.info("session branch checked out", { sessionBranch });
|
|
1132
1148
|
if (created && state.lifecycle.publishOnCreate) {
|
|
1133
1149
|
try {
|
|
1134
|
-
git(
|
|
1150
|
+
await git(["push", "-u", "origin", sessionBranch], targetDir, 6e4);
|
|
1135
1151
|
this.log.info("published new session branch", { sessionBranch });
|
|
1136
1152
|
} catch (err) {
|
|
1137
1153
|
this.log.warn("publish-on-create push failed; deferring to lifecycle push", {
|
|
@@ -1146,7 +1162,7 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1146
1162
|
* true when the branch was created from the anchor; false when no valid
|
|
1147
1163
|
* `fromRef` was supplied or the fetch failed (caller falls back to base).
|
|
1148
1164
|
*/
|
|
1149
|
-
branchFromRef(session, sessionBranch, targetDir) {
|
|
1165
|
+
async branchFromRef(session, sessionBranch, targetDir) {
|
|
1150
1166
|
if (!session.fromRef) return false;
|
|
1151
1167
|
if (!isValidGitRefOrSha(session.fromRef)) {
|
|
1152
1168
|
this.log.warn("fromRef rejected by refname validation, falling back to base branch", {
|
|
@@ -1156,8 +1172,8 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1156
1172
|
return false;
|
|
1157
1173
|
}
|
|
1158
1174
|
try {
|
|
1159
|
-
git(
|
|
1160
|
-
git(
|
|
1175
|
+
await git(["fetch", "origin", session.fromRef], targetDir);
|
|
1176
|
+
await git(["checkout", "-b", sessionBranch, "FETCH_HEAD"], targetDir);
|
|
1161
1177
|
this.log.info("session branch created from fromRef", {
|
|
1162
1178
|
sessionBranch,
|
|
1163
1179
|
fromRef: session.fromRef
|
|
@@ -1189,7 +1205,7 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1189
1205
|
await ensureFleetMounted(targetDir, this.log);
|
|
1190
1206
|
let activeBranch = "unknown";
|
|
1191
1207
|
try {
|
|
1192
|
-
activeBranch = git("rev-parse --abbrev-ref HEAD", targetDir, 5e3);
|
|
1208
|
+
activeBranch = await git(["rev-parse", "--abbrev-ref", "HEAD"], targetDir, 5e3);
|
|
1193
1209
|
} catch {
|
|
1194
1210
|
}
|
|
1195
1211
|
const fleetConfig = resolveGitConfig({
|
|
@@ -1265,6 +1281,7 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1265
1281
|
async disconnect(handle) {
|
|
1266
1282
|
this.log.info("unmount");
|
|
1267
1283
|
const s = handle.state;
|
|
1284
|
+
s.disposed = true;
|
|
1268
1285
|
if (s.fleetManaged) {
|
|
1269
1286
|
await s.fleetWatcher?.close();
|
|
1270
1287
|
s.fleetWatcher = void 0;
|
|
@@ -1289,8 +1306,8 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1289
1306
|
}
|
|
1290
1307
|
this.log.debug("sync (pull) start", { branch: s.activeBranch });
|
|
1291
1308
|
try {
|
|
1292
|
-
git(
|
|
1293
|
-
syncSubmodules(handle.mountPath);
|
|
1309
|
+
await git(["pull", "origin", s.activeBranch], handle.mountPath, 6e4);
|
|
1310
|
+
await syncSubmodules(handle.mountPath);
|
|
1294
1311
|
this.log.debug("sync ok");
|
|
1295
1312
|
} catch (err) {
|
|
1296
1313
|
this.log.error("sync failed", err, { branch: s.activeBranch });
|
|
@@ -1341,12 +1358,12 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1341
1358
|
}
|
|
1342
1359
|
const lc = s.lifecycle;
|
|
1343
1360
|
if (!lc.commitOnHibernate) return;
|
|
1344
|
-
const result = commitAll(handle.mountPath, `skaile: hibernate snapshot`);
|
|
1361
|
+
const result = await commitAll(handle.mountPath, `skaile: hibernate snapshot`);
|
|
1345
1362
|
if (!result) return "Nothing to commit.";
|
|
1346
|
-
const sha = git("rev-parse --short HEAD", handle.mountPath);
|
|
1363
|
+
const sha = await git(["rev-parse", "--short", "HEAD"], handle.mountPath);
|
|
1347
1364
|
if (lc.pushOnHibernate) {
|
|
1348
1365
|
try {
|
|
1349
|
-
git(
|
|
1366
|
+
await git(["push", "origin", s.activeBranch], handle.mountPath, 6e4);
|
|
1350
1367
|
this.log.info("push ok", { branch: s.activeBranch });
|
|
1351
1368
|
} catch (err) {
|
|
1352
1369
|
this.log.error("push failed", err, { branch: s.activeBranch });
|
|
@@ -1363,29 +1380,29 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1363
1380
|
}
|
|
1364
1381
|
const lc = s.lifecycle;
|
|
1365
1382
|
const details = [];
|
|
1366
|
-
const commitResult = commitAll(handle.mountPath, `skaile: session close`);
|
|
1383
|
+
const commitResult = await commitAll(handle.mountPath, `skaile: session close`);
|
|
1367
1384
|
if (commitResult) {
|
|
1368
|
-
const sha = git("rev-parse --short HEAD", handle.mountPath);
|
|
1385
|
+
const sha = await git(["rev-parse", "--short", "HEAD"], handle.mountPath);
|
|
1369
1386
|
details.push(`Committed ${sha}`);
|
|
1370
1387
|
}
|
|
1371
1388
|
if (lc.pushOnClose || lc.mergeOnClose) {
|
|
1372
|
-
git(
|
|
1389
|
+
await git(["push", "origin", s.activeBranch], handle.mountPath, 6e4);
|
|
1373
1390
|
details.push(`Pushed ${s.activeBranch}`);
|
|
1374
1391
|
}
|
|
1375
1392
|
if (lc.mergeOnClose && s.activeBranch !== s.branch) {
|
|
1376
|
-
git(
|
|
1377
|
-
git(
|
|
1378
|
-
syncSubmodules(handle.mountPath);
|
|
1393
|
+
await git(["checkout", s.branch], handle.mountPath);
|
|
1394
|
+
await git(["pull", "origin", s.branch], handle.mountPath, 6e4);
|
|
1395
|
+
await syncSubmodules(handle.mountPath);
|
|
1379
1396
|
try {
|
|
1380
|
-
git(
|
|
1397
|
+
await git(["merge", s.activeBranch], handle.mountPath);
|
|
1381
1398
|
} catch {
|
|
1382
|
-
const resolved = this.resolveConflictsOrAbort(s, handle.mountPath, "merge");
|
|
1399
|
+
const resolved = await this.resolveConflictsOrAbort(s, handle.mountPath, "merge");
|
|
1383
1400
|
if (resolved) {
|
|
1384
1401
|
details.push("Resolved merge conflicts (created .conflict files)");
|
|
1385
1402
|
}
|
|
1386
1403
|
}
|
|
1387
1404
|
if (lc.pushOnClose) {
|
|
1388
|
-
git(
|
|
1405
|
+
await git(["push", "origin", s.branch], handle.mountPath, 6e4);
|
|
1389
1406
|
}
|
|
1390
1407
|
details.push(`Merged ${s.activeBranch} into ${s.branch}`);
|
|
1391
1408
|
}
|
|
@@ -1592,7 +1609,7 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1592
1609
|
credentialsPath: state.managedGitconfig.credentialsPath
|
|
1593
1610
|
});
|
|
1594
1611
|
} else if (state.targetDir) {
|
|
1595
|
-
this.rebakeRemoteAuth(state.targetDir, state);
|
|
1612
|
+
await this.rebakeRemoteAuth(state.targetDir, state);
|
|
1596
1613
|
}
|
|
1597
1614
|
this.log.info("refresh", {
|
|
1598
1615
|
event: "refresh",
|
|
@@ -1662,18 +1679,13 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1662
1679
|
* handling is external to this method (managed-gitconfig credential
|
|
1663
1680
|
* helper refresh in Tier-2 connectors).
|
|
1664
1681
|
*/
|
|
1665
|
-
initInPlace(targetDir, authUrl) {
|
|
1666
|
-
git("init", targetDir, 1e4);
|
|
1682
|
+
async initInPlace(targetDir, authUrl) {
|
|
1683
|
+
await git(["init"], targetDir, 1e4);
|
|
1667
1684
|
try {
|
|
1668
|
-
git("remote remove origin", targetDir, 5e3);
|
|
1685
|
+
await git(["remote", "remove", "origin"], targetDir, 5e3);
|
|
1669
1686
|
} catch {
|
|
1670
1687
|
}
|
|
1671
|
-
|
|
1672
|
-
cwd: targetDir,
|
|
1673
|
-
encoding: "utf-8",
|
|
1674
|
-
timeout: 5e3,
|
|
1675
|
-
stdio: "pipe"
|
|
1676
|
-
});
|
|
1688
|
+
await git(["remote", "add", "origin", authUrl], targetDir, 5e3);
|
|
1677
1689
|
}
|
|
1678
1690
|
/**
|
|
1679
1691
|
* True when `<targetDir>/.git` contains at least one resolvable commit
|
|
@@ -1684,9 +1696,9 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1684
1696
|
* checkout (preserve, don't touch) and a half-initialised one
|
|
1685
1697
|
* (bootstrap by fetching from origin).
|
|
1686
1698
|
*/
|
|
1687
|
-
isInitialisedCheckout(targetDir) {
|
|
1699
|
+
async isInitialisedCheckout(targetDir) {
|
|
1688
1700
|
try {
|
|
1689
|
-
git("rev-parse HEAD", targetDir, 5e3);
|
|
1701
|
+
await git(["rev-parse", "HEAD"], targetDir, 5e3);
|
|
1690
1702
|
return true;
|
|
1691
1703
|
} catch {
|
|
1692
1704
|
return false;
|
|
@@ -1712,23 +1724,18 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1712
1724
|
* the same way `git clone <authUrl>` does — token-rotation handling
|
|
1713
1725
|
* is external to this connector method.
|
|
1714
1726
|
*/
|
|
1715
|
-
bootstrapFromOrigin(targetDir, branch, authUrl) {
|
|
1727
|
+
async bootstrapFromOrigin(targetDir, branch, authUrl) {
|
|
1716
1728
|
try {
|
|
1717
|
-
git("remote remove origin", targetDir, 5e3);
|
|
1729
|
+
await git(["remote", "remove", "origin"], targetDir, 5e3);
|
|
1718
1730
|
} catch {
|
|
1719
1731
|
}
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
});
|
|
1726
|
-
git(`fetch --depth=1 origin ${branch}`, targetDir, 12e4);
|
|
1727
|
-
this.preserveConflictingUntracked(targetDir, branch);
|
|
1728
|
-
git(`checkout -B ${branch} origin/${branch}`, targetDir, 3e4);
|
|
1729
|
-
syncSubmodules(targetDir);
|
|
1732
|
+
await git(["remote", "add", "origin", authUrl], targetDir, 5e3);
|
|
1733
|
+
await git(["fetch", "--depth=1", "origin", branch], targetDir, 12e4);
|
|
1734
|
+
await this.preserveConflictingUntracked(targetDir, branch);
|
|
1735
|
+
await git(["checkout", "-B", branch, `origin/${branch}`], targetDir, 3e4);
|
|
1736
|
+
await syncSubmodules(targetDir);
|
|
1730
1737
|
try {
|
|
1731
|
-
git(
|
|
1738
|
+
await git(["branch", `--set-upstream-to=origin/${branch}`, branch], targetDir, 5e3);
|
|
1732
1739
|
} catch {
|
|
1733
1740
|
}
|
|
1734
1741
|
}
|
|
@@ -1747,10 +1754,10 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1747
1754
|
* left untouched — they are pure local additions and survive the
|
|
1748
1755
|
* bootstrap.
|
|
1749
1756
|
*/
|
|
1750
|
-
preserveConflictingUntracked(targetDir, branch) {
|
|
1757
|
+
async preserveConflictingUntracked(targetDir, branch) {
|
|
1751
1758
|
let remoteFiles = [];
|
|
1752
1759
|
try {
|
|
1753
|
-
remoteFiles = git(
|
|
1760
|
+
remoteFiles = (await git(["ls-tree", "-r", `origin/${branch}`, "--name-only"], targetDir, 3e4)).split("\n").filter(Boolean);
|
|
1754
1761
|
} catch (err) {
|
|
1755
1762
|
this.log.warn("ls-tree failed \u2014 skipping untracked preservation", {
|
|
1756
1763
|
branch,
|
|
@@ -1760,13 +1767,13 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1760
1767
|
}
|
|
1761
1768
|
for (const relPath of remoteFiles) {
|
|
1762
1769
|
const fullPath = join(targetDir, relPath);
|
|
1763
|
-
if (!
|
|
1770
|
+
if (!await pathExists(fullPath)) continue;
|
|
1764
1771
|
let dest = `${fullPath}.local`;
|
|
1765
|
-
if (
|
|
1772
|
+
if (await pathExists(dest)) {
|
|
1766
1773
|
dest = `${fullPath}.local.${Date.now()}`;
|
|
1767
1774
|
}
|
|
1768
1775
|
try {
|
|
1769
|
-
|
|
1776
|
+
await withFsDeadline(`rename ${fullPath}`, () => rename(fullPath, dest));
|
|
1770
1777
|
this.log.info("preserved local file as .local", { path: relPath, dest });
|
|
1771
1778
|
} catch (err) {
|
|
1772
1779
|
this.log.warn("failed to preserve local file \u2014 checkout may fail", {
|
|
@@ -1793,15 +1800,15 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1793
1800
|
* carries creds — so the baked-in token must go. Best-effort: a missing
|
|
1794
1801
|
* origin or a non-http(s) remote (e.g. file:// in tests) is left untouched.
|
|
1795
1802
|
*/
|
|
1796
|
-
stripRemoteInlineToken(targetDir) {
|
|
1803
|
+
async stripRemoteInlineToken(targetDir) {
|
|
1797
1804
|
try {
|
|
1798
|
-
const current = git("remote get-url origin", targetDir, 5e3);
|
|
1805
|
+
const current = await git(["remote", "get-url", "origin"], targetDir, 5e3);
|
|
1799
1806
|
if (!current.startsWith("https://") && !current.startsWith("http://")) return;
|
|
1800
1807
|
const u = new URL(current);
|
|
1801
1808
|
if (!u.username && !u.password) return;
|
|
1802
1809
|
u.username = "";
|
|
1803
1810
|
u.password = "";
|
|
1804
|
-
git(
|
|
1811
|
+
await git(["remote", "set-url", "origin", u.toString()], targetDir, 5e3);
|
|
1805
1812
|
} catch (err) {
|
|
1806
1813
|
this.log.warn("managed-gitconfig: failed to strip inline token from origin", {
|
|
1807
1814
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -1815,10 +1822,10 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1815
1822
|
* a Tier-2 helper this URL token is the sole credential, so it must be
|
|
1816
1823
|
* refreshed here. No-op for anonymous (no token) or non-https remotes.
|
|
1817
1824
|
*/
|
|
1818
|
-
rebakeRemoteAuth(targetDir, state) {
|
|
1825
|
+
async rebakeRemoteAuth(targetDir, state) {
|
|
1819
1826
|
if (!state.token || !state.url.startsWith("https://")) return;
|
|
1820
1827
|
try {
|
|
1821
|
-
git(
|
|
1828
|
+
await git(["remote", "set-url", "origin", this.authUrl(state)], targetDir, 5e3);
|
|
1822
1829
|
} catch (err) {
|
|
1823
1830
|
this.log.warn("failed to refresh inline token on origin", {
|
|
1824
1831
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -1830,22 +1837,41 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1830
1837
|
if (s.fetchTimer) clearInterval(s.fetchTimer);
|
|
1831
1838
|
const intervalMs = s.sync.fetchIntervalSec * 1e3;
|
|
1832
1839
|
s.fetchTimer = setInterval(() => {
|
|
1840
|
+
if (s.fetchInFlight) {
|
|
1841
|
+
this.log.warn("periodic fetch skipped \u2014 previous tick still running", {
|
|
1842
|
+
branch: s.activeBranch,
|
|
1843
|
+
intervalMs
|
|
1844
|
+
});
|
|
1845
|
+
return;
|
|
1846
|
+
}
|
|
1847
|
+
if (s.disposed) return;
|
|
1848
|
+
s.fetchInFlight = true;
|
|
1849
|
+
void this.runPeriodicFetch(s, mountPath).catch((err) => {
|
|
1850
|
+
this.log.debug("periodic fetch failed", {
|
|
1851
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1852
|
+
});
|
|
1853
|
+
}).finally(() => {
|
|
1854
|
+
s.fetchInFlight = false;
|
|
1855
|
+
});
|
|
1856
|
+
}, intervalMs);
|
|
1857
|
+
}
|
|
1858
|
+
/** One periodic-fetch tick. Bails out at each resumption point once disconnected. */
|
|
1859
|
+
async runPeriodicFetch(s, mountPath) {
|
|
1860
|
+
await git(["fetch", "origin"], mountPath, 6e4);
|
|
1861
|
+
if (s.disposed) return;
|
|
1862
|
+
if (s.sync.autoRebase && s.activeBranch !== s.branch) {
|
|
1833
1863
|
try {
|
|
1834
|
-
git("
|
|
1835
|
-
if (s.sync.autoRebase && s.activeBranch !== s.branch) {
|
|
1836
|
-
try {
|
|
1837
|
-
git(`rebase origin/${s.branch}`, mountPath, 6e4);
|
|
1838
|
-
} catch {
|
|
1839
|
-
this.resolveConflictsOrAbort(s, mountPath, "rebase");
|
|
1840
|
-
}
|
|
1841
|
-
syncSubmodules(mountPath);
|
|
1842
|
-
} else if (s.sync.autoPull) {
|
|
1843
|
-
git(`pull origin ${s.activeBranch}`, mountPath, 6e4);
|
|
1844
|
-
syncSubmodules(mountPath);
|
|
1845
|
-
}
|
|
1864
|
+
await git(["rebase", `origin/${s.branch}`], mountPath, 6e4);
|
|
1846
1865
|
} catch {
|
|
1866
|
+
await this.resolveConflictsOrAbort(s, mountPath, "rebase");
|
|
1847
1867
|
}
|
|
1848
|
-
|
|
1868
|
+
if (s.disposed) return;
|
|
1869
|
+
await syncSubmodules(mountPath);
|
|
1870
|
+
} else if (s.sync.autoPull) {
|
|
1871
|
+
await git(["pull", "origin", s.activeBranch], mountPath, 6e4);
|
|
1872
|
+
if (s.disposed) return;
|
|
1873
|
+
await syncSubmodules(mountPath);
|
|
1874
|
+
}
|
|
1849
1875
|
}
|
|
1850
1876
|
// ── Conflict resolution ──────────────────────────────────────────────────
|
|
1851
1877
|
/**
|
|
@@ -1853,17 +1879,17 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1853
1879
|
* "theirs" to a .conflict file. If resolution fails entirely, abort.
|
|
1854
1880
|
* Returns true if conflicts were resolved, false if aborted.
|
|
1855
1881
|
*/
|
|
1856
|
-
resolveConflictsOrAbort(s, mountPath, mode) {
|
|
1882
|
+
async resolveConflictsOrAbort(s, mountPath, mode) {
|
|
1857
1883
|
try {
|
|
1858
|
-
const conflicted = git("diff --name-only --diff-filter=U", mountPath).split("\n").filter(Boolean);
|
|
1884
|
+
const conflicted = (await git(["diff", "--name-only", "--diff-filter=U"], mountPath)).split("\n").filter(Boolean);
|
|
1859
1885
|
if (conflicted.length === 0) return false;
|
|
1860
1886
|
for (const file of conflicted) {
|
|
1861
|
-
this.resolveFileConflict(mountPath, file);
|
|
1887
|
+
await this.resolveFileConflict(mountPath, file);
|
|
1862
1888
|
}
|
|
1863
1889
|
if (mode === "rebase") {
|
|
1864
|
-
git("-c core.editor=true rebase --continue", mountPath, 3e4);
|
|
1890
|
+
await git(["-c", "core.editor=true", "rebase", "--continue"], mountPath, 3e4);
|
|
1865
1891
|
} else {
|
|
1866
|
-
git(
|
|
1892
|
+
await git(["commit", "--no-edit"], mountPath);
|
|
1867
1893
|
}
|
|
1868
1894
|
for (const file of conflicted) {
|
|
1869
1895
|
const ext = file.includes(".") ? file.slice(file.lastIndexOf(".")) : "";
|
|
@@ -1878,9 +1904,9 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1878
1904
|
} catch {
|
|
1879
1905
|
try {
|
|
1880
1906
|
if (mode === "rebase") {
|
|
1881
|
-
git("rebase --abort", mountPath);
|
|
1907
|
+
await git(["rebase", "--abort"], mountPath);
|
|
1882
1908
|
} else {
|
|
1883
|
-
git("merge --abort", mountPath);
|
|
1909
|
+
await git(["merge", "--abort"], mountPath);
|
|
1884
1910
|
}
|
|
1885
1911
|
} catch {
|
|
1886
1912
|
}
|
|
@@ -1890,31 +1916,48 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1890
1916
|
/**
|
|
1891
1917
|
* For a single conflicted file: keep "ours", save "theirs" as .conflict file.
|
|
1892
1918
|
*/
|
|
1893
|
-
resolveFileConflict(root, file) {
|
|
1919
|
+
async resolveFileConflict(root, file) {
|
|
1894
1920
|
const ext = file.includes(".") ? file.slice(file.lastIndexOf(".")) : "";
|
|
1895
1921
|
const base = file.includes(".") ? file.slice(0, file.lastIndexOf(".")) : file;
|
|
1896
1922
|
const conflictPath = `${base}.conflict${ext}`;
|
|
1897
1923
|
try {
|
|
1898
|
-
const theirs = git(
|
|
1899
|
-
|
|
1924
|
+
const theirs = await git(["show", `:3:${file}`], root);
|
|
1925
|
+
await withFsDeadline(
|
|
1926
|
+
`write ${conflictPath}`,
|
|
1927
|
+
() => writeFile(join(root, conflictPath), theirs)
|
|
1928
|
+
);
|
|
1900
1929
|
} catch {
|
|
1901
1930
|
const fullPath = join(root, file);
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1931
|
+
const content = await tryWithFsDeadline(
|
|
1932
|
+
`read ${file}`,
|
|
1933
|
+
() => readFile(fullPath, "utf-8"),
|
|
1934
|
+
null
|
|
1935
|
+
);
|
|
1936
|
+
if (content !== null) {
|
|
1937
|
+
await withFsDeadline(
|
|
1938
|
+
`write ${conflictPath}`,
|
|
1939
|
+
() => writeFile(join(root, conflictPath), content)
|
|
1940
|
+
);
|
|
1905
1941
|
}
|
|
1906
1942
|
}
|
|
1907
1943
|
try {
|
|
1908
|
-
const ours = git(
|
|
1909
|
-
|
|
1944
|
+
const ours = await git(["show", `:2:${file}`], root);
|
|
1945
|
+
await withFsDeadline(`write ${file}`, () => writeFile(join(root, file), ours));
|
|
1910
1946
|
} catch {
|
|
1911
1947
|
const fullPath = join(root, file);
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1948
|
+
const content = await tryWithFsDeadline(
|
|
1949
|
+
`read ${file}`,
|
|
1950
|
+
() => readFile(fullPath, "utf-8"),
|
|
1951
|
+
null
|
|
1952
|
+
);
|
|
1953
|
+
if (content !== null) {
|
|
1954
|
+
await withFsDeadline(
|
|
1955
|
+
`write ${file}`,
|
|
1956
|
+
() => writeFile(fullPath, this.stripConflictKeepOurs(content))
|
|
1957
|
+
);
|
|
1915
1958
|
}
|
|
1916
1959
|
}
|
|
1917
|
-
git(
|
|
1960
|
+
await git(["add", file, conflictPath], root);
|
|
1918
1961
|
}
|
|
1919
1962
|
stripConflictKeepOurs(content) {
|
|
1920
1963
|
return content.replace(/<<<<<<< .*\n/g, "").replace(/=======\n[\s\S]*?>>>>>>> .*\n/g, "");
|
|
@@ -1922,30 +1965,48 @@ var GitConnector = class extends AbstractConnector {
|
|
|
1922
1965
|
// ── Auto-commit on idle ────────────────────────────────────────────────────
|
|
1923
1966
|
resetAutoCommitTimer(s, mountPath) {
|
|
1924
1967
|
if (s.lifecycle.autoCommitIdleMs <= 0) return;
|
|
1968
|
+
if (s.disposed) return;
|
|
1925
1969
|
if (s.autoCommitTimer) clearTimeout(s.autoCommitTimer);
|
|
1926
1970
|
s.autoCommitTimer = setTimeout(() => {
|
|
1927
|
-
|
|
1971
|
+
s.autoCommitTimer = void 0;
|
|
1972
|
+
if (s.disposed) return;
|
|
1973
|
+
if (s.autoCommitInFlight) {
|
|
1974
|
+
this.log.warn("auto-commit skipped \u2014 previous run still in flight", {
|
|
1975
|
+
branch: s.activeBranch
|
|
1976
|
+
});
|
|
1977
|
+
this.resetAutoCommitTimer(s, mountPath);
|
|
1978
|
+
return;
|
|
1979
|
+
}
|
|
1980
|
+
s.autoCommitInFlight = true;
|
|
1981
|
+
void this.performAutoCommit(s, mountPath).catch((err) => {
|
|
1982
|
+
this.log.debug("auto-commit failed", {
|
|
1983
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1984
|
+
});
|
|
1985
|
+
}).finally(() => {
|
|
1986
|
+
s.autoCommitInFlight = false;
|
|
1987
|
+
});
|
|
1928
1988
|
}, s.lifecycle.autoCommitIdleMs);
|
|
1929
1989
|
}
|
|
1930
|
-
performAutoCommit(s, mountPath) {
|
|
1990
|
+
async performAutoCommit(s, mountPath) {
|
|
1931
1991
|
try {
|
|
1932
|
-
const message = this.generateCommitMessage(mountPath);
|
|
1933
|
-
|
|
1934
|
-
|
|
1992
|
+
const message = await this.generateCommitMessage(mountPath);
|
|
1993
|
+
if (s.disposed) return;
|
|
1994
|
+
const result = await commitAll(mountPath, message);
|
|
1995
|
+
if (!result || s.disposed) return;
|
|
1935
1996
|
if (s.lifecycle.pushAfterCommit) {
|
|
1936
1997
|
try {
|
|
1937
|
-
git(
|
|
1998
|
+
await git(["push", "origin", s.activeBranch], mountPath, 6e4);
|
|
1938
1999
|
} catch {
|
|
1939
2000
|
}
|
|
1940
2001
|
}
|
|
1941
2002
|
} catch {
|
|
1942
2003
|
}
|
|
1943
2004
|
}
|
|
1944
|
-
generateCommitMessage(mountPath) {
|
|
2005
|
+
async generateCommitMessage(mountPath) {
|
|
1945
2006
|
try {
|
|
1946
|
-
git("add -A", mountPath);
|
|
1947
|
-
const
|
|
1948
|
-
const lines =
|
|
2007
|
+
await git(["add", "-A"], mountPath);
|
|
2008
|
+
const stat5 = await git(["diff", "--cached", "--stat"], mountPath);
|
|
2009
|
+
const lines = stat5.split("\n").filter((l) => l.includes("|"));
|
|
1949
2010
|
if (lines.length === 0) return "skaile: auto-save";
|
|
1950
2011
|
const files = lines.map((l) => l.split("|")[0].trim());
|
|
1951
2012
|
if (files.length === 1) return `Update ${files[0]}`;
|
|
@@ -2217,6 +2278,7 @@ function syncFleetManaged2(options) {
|
|
|
2217
2278
|
});
|
|
2218
2279
|
return Promise.resolve({ filesWritten: 0, filesDeleted: 0, bytesTransferred: 0 });
|
|
2219
2280
|
}
|
|
2281
|
+
var COPY_DEADLINE_FACTOR = 20;
|
|
2220
2282
|
var LocalConnector = class extends AbstractConnector {
|
|
2221
2283
|
name = "local";
|
|
2222
2284
|
filesystem = {
|
|
@@ -2231,20 +2293,24 @@ var LocalConnector = class extends AbstractConnector {
|
|
|
2231
2293
|
}
|
|
2232
2294
|
const started = Date.now();
|
|
2233
2295
|
const source = declaration.mount?.source ?? "";
|
|
2234
|
-
this.log.info("mount start", { source, targetDir });
|
|
2235
2296
|
const sourceDir = resolve(String(source));
|
|
2236
|
-
if (
|
|
2237
|
-
this.log.
|
|
2238
|
-
|
|
2297
|
+
if (isFleetManaged(declaration.id)) {
|
|
2298
|
+
this.log.info("mount handled by host fleet \u2014 skipping local copy", {
|
|
2299
|
+
connectorId: declaration.id,
|
|
2300
|
+
targetDir
|
|
2239
2301
|
});
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2302
|
+
await ensureFleetMounted(targetDir, this.log);
|
|
2303
|
+
this.log.info("mount ok", { targetDir, durationMs: Date.now() - started });
|
|
2304
|
+
return this.makeHandle(
|
|
2305
|
+
declaration,
|
|
2306
|
+
{ sourceDir, fleetManaged: true },
|
|
2307
|
+
targetDir
|
|
2308
|
+
);
|
|
2247
2309
|
}
|
|
2310
|
+
this.log.info("mount start", { source, targetDir });
|
|
2311
|
+
await this.assertSourceExists(sourceDir);
|
|
2312
|
+
await withFsDeadline(`mkdir ${targetDir}`, () => mkdir(targetDir, { recursive: true }));
|
|
2313
|
+
await this.copyTree(sourceDir, targetDir);
|
|
2248
2314
|
this.log.info("mount ok", { targetDir, durationMs: Date.now() - started });
|
|
2249
2315
|
return this.makeHandle(declaration, { sourceDir }, targetDir);
|
|
2250
2316
|
}
|
|
@@ -2253,18 +2319,58 @@ var LocalConnector = class extends AbstractConnector {
|
|
|
2253
2319
|
}
|
|
2254
2320
|
async _sync(handle, _options) {
|
|
2255
2321
|
this.log.debug("sync start");
|
|
2256
|
-
const
|
|
2257
|
-
|
|
2322
|
+
const state = handle.state;
|
|
2323
|
+
if (state.fleetManaged) {
|
|
2324
|
+
this.log.debug("sync skipped \u2014 fleet-managed");
|
|
2325
|
+
return { filesWritten: 0, filesDeleted: 0, bytesTransferred: 0 };
|
|
2326
|
+
}
|
|
2327
|
+
const src = resolve(state.sourceDir);
|
|
2258
2328
|
const tgt = resolve(handle.mountPath);
|
|
2259
2329
|
if (src === tgt || tgt.startsWith(`${src}/`)) {
|
|
2260
2330
|
this.log.debug("sync ok (no-op: source equals target)");
|
|
2261
2331
|
return { filesWritten: 0, filesDeleted: 0, bytesTransferred: 0 };
|
|
2262
2332
|
}
|
|
2263
|
-
|
|
2264
|
-
|
|
2333
|
+
await withFsDeadline(`mkdir ${tgt}`, () => mkdir(tgt, { recursive: true }));
|
|
2334
|
+
await this.copyTree(src, tgt);
|
|
2265
2335
|
this.log.debug("sync ok");
|
|
2266
2336
|
return { filesWritten: 0, filesDeleted: 0, bytesTransferred: 0 };
|
|
2267
2337
|
}
|
|
2338
|
+
/**
|
|
2339
|
+
* Fail with the historical message when the source directory is missing,
|
|
2340
|
+
* while letting a wedged-mount deadline surface as itself.
|
|
2341
|
+
*
|
|
2342
|
+
* The old `existsSync` probe could not tell those apart — and on a hung
|
|
2343
|
+
* mount it never returned at all.
|
|
2344
|
+
*/
|
|
2345
|
+
async assertSourceExists(sourceDir) {
|
|
2346
|
+
try {
|
|
2347
|
+
await withFsDeadline(`stat ${sourceDir}`, () => stat(sourceDir));
|
|
2348
|
+
} catch (err) {
|
|
2349
|
+
if (err instanceof FsDeadlineError) {
|
|
2350
|
+
this.log.error("connect failed: source path unreadable (deadline)", err, { sourceDir });
|
|
2351
|
+
throw err;
|
|
2352
|
+
}
|
|
2353
|
+
this.log.error("connect failed: source path does not exist", void 0, { sourceDir });
|
|
2354
|
+
throw new Error(`Local source path does not exist: ${sourceDir}`);
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
/**
|
|
2358
|
+
* Recursively copy `src` into `tgt`, skipping the copy when the two overlap.
|
|
2359
|
+
*
|
|
2360
|
+
* The string-overlap guard is a second line of defence behind the
|
|
2361
|
+
* fleet-managed refusal in `connect`: it is a *textual* comparison, so a
|
|
2362
|
+
* source that differs textually while overlapping physically (symlink, bind
|
|
2363
|
+
* mount, `..` segments already normalised away) still slips past it. It stays
|
|
2364
|
+
* because it is free and catches the common container layout.
|
|
2365
|
+
*/
|
|
2366
|
+
async copyTree(src, tgt) {
|
|
2367
|
+
if (src === tgt || tgt.startsWith(`${src}/`)) return;
|
|
2368
|
+
await withFsDeadline(
|
|
2369
|
+
`cp -r ${src} -> ${tgt}`,
|
|
2370
|
+
() => cp(src, tgt, { recursive: true }),
|
|
2371
|
+
fsDeadlineMs() * COPY_DEADLINE_FACTOR
|
|
2372
|
+
);
|
|
2373
|
+
}
|
|
2268
2374
|
watch(handle, callback, options) {
|
|
2269
2375
|
let fsWatcher = null;
|
|
2270
2376
|
let closed = false;
|
|
@@ -3373,6 +3479,7 @@ function createConnector12() {
|
|
|
3373
3479
|
return new PostgresConnector();
|
|
3374
3480
|
}
|
|
3375
3481
|
var s3Pkg = "@aws-sdk/client-s3";
|
|
3482
|
+
var DOWNLOAD_DEADLINE_FACTOR = 20;
|
|
3376
3483
|
var S3Connector = class extends AbstractConnector {
|
|
3377
3484
|
name = "s3";
|
|
3378
3485
|
/** Optional SDK module override — used in tests to avoid importing the real AWS SDK. */
|
|
@@ -3420,7 +3527,7 @@ var S3Connector = class extends AbstractConnector {
|
|
|
3420
3527
|
}
|
|
3421
3528
|
const client = new S3Client(clientConfig);
|
|
3422
3529
|
const state = { client, bucket, prefix, region };
|
|
3423
|
-
|
|
3530
|
+
await withFsDeadline(`mkdir ${targetDir}`, () => mkdir(targetDir, { recursive: true }));
|
|
3424
3531
|
try {
|
|
3425
3532
|
const result = await this.downloadAll(state, targetDir);
|
|
3426
3533
|
this.log.info("mount ok", {
|
|
@@ -3451,6 +3558,28 @@ var S3Connector = class extends AbstractConnector {
|
|
|
3451
3558
|
throw err;
|
|
3452
3559
|
}
|
|
3453
3560
|
}
|
|
3561
|
+
/**
|
|
3562
|
+
* Fetch one object's bytes, or `null` when it yields none.
|
|
3563
|
+
*
|
|
3564
|
+
* S3-side failures are contained here — a single `GetObject` miss is
|
|
3565
|
+
* survivable and must not abort the whole sync. Local filesystem failures are
|
|
3566
|
+
* deliberately *not* in scope: see the write path in {@link downloadAll}.
|
|
3567
|
+
*/
|
|
3568
|
+
async fetchObject(s3Mod, state, key) {
|
|
3569
|
+
try {
|
|
3570
|
+
const resp = await state.client.send(
|
|
3571
|
+
new s3Mod.GetObjectCommand({ Bucket: state.bucket, Key: key })
|
|
3572
|
+
);
|
|
3573
|
+
const bytes = await resp.Body?.transformToByteArray();
|
|
3574
|
+
return bytes == null ? null : Buffer.from(bytes);
|
|
3575
|
+
} catch (err) {
|
|
3576
|
+
this.log.warn("object download failed", {
|
|
3577
|
+
key,
|
|
3578
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3579
|
+
});
|
|
3580
|
+
return null;
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3454
3583
|
async downloadAll(state, targetDir) {
|
|
3455
3584
|
const s3Mod = await this._loadSdk();
|
|
3456
3585
|
const { client, bucket, prefix } = state;
|
|
@@ -3474,23 +3603,32 @@ var S3Connector = class extends AbstractConnector {
|
|
|
3474
3603
|
} while (continuationToken);
|
|
3475
3604
|
let filesWritten = 0;
|
|
3476
3605
|
let bytesTransferred = 0;
|
|
3606
|
+
const budgetMs = fsDeadlineMs() * DOWNLOAD_DEADLINE_FACTOR;
|
|
3607
|
+
const deadlineAt = Date.now() + budgetMs;
|
|
3608
|
+
const created = /* @__PURE__ */ new Set();
|
|
3477
3609
|
for (const { key, relPath } of entries) {
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
});
|
|
3610
|
+
if (deadlineAt - Date.now() <= 0) {
|
|
3611
|
+
throw new FsDeadlineError(`downloadAll ${targetDir}`, budgetMs);
|
|
3612
|
+
}
|
|
3613
|
+
const body = await this.fetchObject(s3Mod, state, key);
|
|
3614
|
+
if (body == null) continue;
|
|
3615
|
+
const localPath = join(targetDir, relPath);
|
|
3616
|
+
const parent = dirname(localPath);
|
|
3617
|
+
if (!created.has(parent)) {
|
|
3618
|
+
await withFsDeadline(
|
|
3619
|
+
`mkdir ${parent}`,
|
|
3620
|
+
() => mkdir(parent, { recursive: true }),
|
|
3621
|
+
deadlineAt - Date.now()
|
|
3622
|
+
);
|
|
3623
|
+
created.add(parent);
|
|
3493
3624
|
}
|
|
3625
|
+
await withFsDeadline(
|
|
3626
|
+
`writeFile ${localPath}`,
|
|
3627
|
+
() => writeFile(localPath, body),
|
|
3628
|
+
deadlineAt - Date.now()
|
|
3629
|
+
);
|
|
3630
|
+
filesWritten++;
|
|
3631
|
+
bytesTransferred += body.byteLength;
|
|
3494
3632
|
}
|
|
3495
3633
|
return { filesWritten, filesDeleted: 0, bytesTransferred };
|
|
3496
3634
|
}
|
|
@@ -3583,14 +3721,21 @@ var SQLiteConnector = class extends AbstractConnector {
|
|
|
3583
3721
|
let db;
|
|
3584
3722
|
if (dbPath === ":memory:") {
|
|
3585
3723
|
db = new SQL.Database();
|
|
3586
|
-
} else if (existsSync(dbPath)) {
|
|
3587
|
-
const buffer = readFileSync(dbPath);
|
|
3588
|
-
db = new SQL.Database(buffer);
|
|
3589
|
-
} else if (!isReadonly) {
|
|
3590
|
-
db = new SQL.Database();
|
|
3591
3724
|
} else {
|
|
3592
|
-
|
|
3593
|
-
|
|
3725
|
+
let buffer;
|
|
3726
|
+
try {
|
|
3727
|
+
buffer = await withFsDeadline(`readFile ${dbPath}`, () => readFile(dbPath));
|
|
3728
|
+
} catch (err) {
|
|
3729
|
+
if (err.code !== "ENOENT") {
|
|
3730
|
+
this.log.error("connect failed: db path unreadable", err, { dbPath });
|
|
3731
|
+
throw err;
|
|
3732
|
+
}
|
|
3733
|
+
if (isReadonly) {
|
|
3734
|
+
this.log.error("connect failed: db file not found", void 0, { dbPath });
|
|
3735
|
+
throw new Error(`SQLite database not found: ${dbPath}`);
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
db = buffer ? new SQL.Database(buffer) : new SQL.Database();
|
|
3594
3739
|
}
|
|
3595
3740
|
this.log.info("connect ok", { dbPath, durationMs: Date.now() - started });
|
|
3596
3741
|
if (!isReadonly && dbPath !== ":memory:") {
|
|
@@ -3605,7 +3750,7 @@ var SQLiteConnector = class extends AbstractConnector {
|
|
|
3605
3750
|
this.log.info("disconnect");
|
|
3606
3751
|
const { db, dbPath, readonly: isReadonly } = handle.state;
|
|
3607
3752
|
if (!isReadonly && dbPath !== ":memory:") {
|
|
3608
|
-
this.saveToDisk(db, dbPath);
|
|
3753
|
+
await this.saveToDisk(db, dbPath);
|
|
3609
3754
|
}
|
|
3610
3755
|
db.close();
|
|
3611
3756
|
handle.status = "disconnected";
|
|
@@ -3613,13 +3758,18 @@ var SQLiteConnector = class extends AbstractConnector {
|
|
|
3613
3758
|
db(handle) {
|
|
3614
3759
|
return handle.state.db;
|
|
3615
3760
|
}
|
|
3616
|
-
/** sql.js operates in-memory — flush to disk explicitly.
|
|
3617
|
-
|
|
3761
|
+
/** sql.js operates in-memory — flush to disk explicitly. Best-effort, but no
|
|
3762
|
+
* longer silent: a dropped flush on a wedged mount is lost data, so it warns. */
|
|
3763
|
+
async saveToDisk(db, dbPath) {
|
|
3618
3764
|
try {
|
|
3619
3765
|
const data = db.export();
|
|
3620
3766
|
const buffer = Buffer.from(data);
|
|
3621
|
-
|
|
3622
|
-
} catch {
|
|
3767
|
+
await withFsDeadline(`writeFile ${dbPath}`, () => writeFile(dbPath, buffer));
|
|
3768
|
+
} catch (err) {
|
|
3769
|
+
this.log.warn("db flush failed \u2014 changes not persisted", {
|
|
3770
|
+
dbPath,
|
|
3771
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3772
|
+
});
|
|
3623
3773
|
}
|
|
3624
3774
|
}
|
|
3625
3775
|
/** Run a query that returns rows. sql.js uses stmt.getAsObject() pattern. */
|
|
@@ -3790,7 +3940,7 @@ var SQLiteConnector = class extends AbstractConnector {
|
|
|
3790
3940
|
if (!sql) return "Error: sql argument is required";
|
|
3791
3941
|
const changes = this.runStmt(db, sql);
|
|
3792
3942
|
if (!state.readonly && state.dbPath !== ":memory:") {
|
|
3793
|
-
this.saveToDisk(db, state.dbPath);
|
|
3943
|
+
await this.saveToDisk(db, state.dbPath);
|
|
3794
3944
|
}
|
|
3795
3945
|
return JSON.stringify({ changes });
|
|
3796
3946
|
}
|
|
@@ -3821,7 +3971,7 @@ var StaticServerConnector = class extends AbstractConnector {
|
|
|
3821
3971
|
const worktreeDir = String(declaration.options?.worktree_dir ?? DEFAULT_WORKTREE_DIR);
|
|
3822
3972
|
let repoRoot = null;
|
|
3823
3973
|
try {
|
|
3824
|
-
repoRoot = findGitRoot(process.cwd());
|
|
3974
|
+
repoRoot = await findGitRoot(process.cwd());
|
|
3825
3975
|
} catch {
|
|
3826
3976
|
}
|
|
3827
3977
|
return this.makeHandle(declaration, {
|
|
@@ -3945,7 +4095,10 @@ var StaticServerConnector = class extends AbstractConnector {
|
|
|
3945
4095
|
}
|
|
3946
4096
|
const serveDir = dir;
|
|
3947
4097
|
const server = createServer((req, res) => {
|
|
3948
|
-
serveStaticFile(serveDir, req.url ?? "/", res)
|
|
4098
|
+
void serveStaticFile(serveDir, req.url ?? "/", res).catch(() => {
|
|
4099
|
+
if (!res.headersSent) res.writeHead(500, { "content-type": "text/plain" });
|
|
4100
|
+
res.end();
|
|
4101
|
+
});
|
|
3949
4102
|
});
|
|
3950
4103
|
server.listen(port);
|
|
3951
4104
|
state.instances.set(label, {
|
|
@@ -4014,7 +4167,14 @@ var StaticServerConnector = class extends AbstractConnector {
|
|
|
4014
4167
|
};
|
|
4015
4168
|
}
|
|
4016
4169
|
};
|
|
4017
|
-
function
|
|
4170
|
+
async function statOrNull(filePath) {
|
|
4171
|
+
try {
|
|
4172
|
+
return await withFsDeadline(`stat ${filePath}`, () => stat(filePath));
|
|
4173
|
+
} catch {
|
|
4174
|
+
return void 0;
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
async function serveStaticFile(rootDir, reqUrl, res) {
|
|
4018
4178
|
const root = resolve(rootDir);
|
|
4019
4179
|
const pathname = decodeURIComponent(new URL(reqUrl, "http://localhost").pathname);
|
|
4020
4180
|
let filePath = resolve(root, `.${pathname}`);
|
|
@@ -4023,10 +4183,18 @@ function serveStaticFile(rootDir, reqUrl, res) {
|
|
|
4023
4183
|
res.end("Forbidden");
|
|
4024
4184
|
return;
|
|
4025
4185
|
}
|
|
4026
|
-
|
|
4186
|
+
let stats;
|
|
4187
|
+
if (pathname.endsWith("/")) {
|
|
4027
4188
|
filePath = join(filePath, "index.html");
|
|
4189
|
+
stats = await statOrNull(filePath);
|
|
4190
|
+
} else {
|
|
4191
|
+
stats = await statOrNull(filePath);
|
|
4192
|
+
if (stats?.isDirectory()) {
|
|
4193
|
+
filePath = join(filePath, "index.html");
|
|
4194
|
+
stats = await statOrNull(filePath);
|
|
4195
|
+
}
|
|
4028
4196
|
}
|
|
4029
|
-
if (!
|
|
4197
|
+
if (!stats?.isFile()) {
|
|
4030
4198
|
res.writeHead(404, { "content-type": "text/plain" });
|
|
4031
4199
|
res.end("Not Found");
|
|
4032
4200
|
return;
|
|
@@ -4361,8 +4529,13 @@ var XStateConnector = class extends AbstractConnector {
|
|
|
4361
4529
|
let definition = declaration.options?.machine;
|
|
4362
4530
|
if (!definition && declaration.options?.definitionPath) {
|
|
4363
4531
|
const defPath = String(declaration.options.definitionPath);
|
|
4364
|
-
|
|
4365
|
-
|
|
4532
|
+
let raw;
|
|
4533
|
+
try {
|
|
4534
|
+
raw = await withFsDeadline(`readFile ${defPath}`, () => readFile(defPath, "utf-8"));
|
|
4535
|
+
} catch (err) {
|
|
4536
|
+
if (err instanceof FsDeadlineError) throw err;
|
|
4537
|
+
throw new Error(`Machine definition not found: ${defPath}`);
|
|
4538
|
+
}
|
|
4366
4539
|
if (defPath.endsWith(".json")) {
|
|
4367
4540
|
definition = JSON.parse(raw);
|
|
4368
4541
|
} else {
|
|
@@ -5317,7 +5490,7 @@ var ConnectorManager = class {
|
|
|
5317
5490
|
if (connector.filesystem != null) {
|
|
5318
5491
|
const absPath = this.resolveMountTarget(declaration);
|
|
5319
5492
|
this.reserveMountTarget(declaration.id, absPath);
|
|
5320
|
-
|
|
5493
|
+
await withFsDeadline(`mkdir ${absPath}`, () => mkdir(absPath, { recursive: true }));
|
|
5321
5494
|
ctx.mountTarget = absPath;
|
|
5322
5495
|
}
|
|
5323
5496
|
return ctx;
|
|
@@ -5370,8 +5543,18 @@ var ConnectorManager = class {
|
|
|
5370
5543
|
*/
|
|
5371
5544
|
async connectAll(declarations, options) {
|
|
5372
5545
|
this.mgrLog.info("connectAll start", { count: declarations.length });
|
|
5373
|
-
|
|
5374
|
-
|
|
5546
|
+
const claimed = [];
|
|
5547
|
+
try {
|
|
5548
|
+
for (const decl of declarations) {
|
|
5549
|
+
if (decl.mount == null) continue;
|
|
5550
|
+
const absPath = this.resolveMountTarget(decl);
|
|
5551
|
+
const isNew = !this.mountTargets.has(absPath);
|
|
5552
|
+
this.reserveMountTarget(decl.id, absPath);
|
|
5553
|
+
if (isNew) claimed.push(absPath);
|
|
5554
|
+
}
|
|
5555
|
+
} catch (err) {
|
|
5556
|
+
for (const path of claimed) this.mountTargets.delete(path);
|
|
5557
|
+
throw err;
|
|
5375
5558
|
}
|
|
5376
5559
|
const results = [];
|
|
5377
5560
|
for (const decl of declarations) {
|
|
@@ -5447,6 +5630,7 @@ var ConnectorManager = class {
|
|
|
5447
5630
|
access: decl.access
|
|
5448
5631
|
};
|
|
5449
5632
|
} catch (err) {
|
|
5633
|
+
if (!this.active.has(decl.id)) this.releaseMountTarget(decl.id);
|
|
5450
5634
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5451
5635
|
this.mgrLog.error("connect failed", err, { id: decl.id, driver: decl.driver });
|
|
5452
5636
|
this.opts.onStatusChange?.({
|
|
@@ -5514,8 +5698,8 @@ var ConnectorManager = class {
|
|
|
5514
5698
|
instance: declaration.id
|
|
5515
5699
|
});
|
|
5516
5700
|
connector.setLogger?.(connectorLog);
|
|
5517
|
-
const ctx = await this.buildConnectContext(declaration, connector);
|
|
5518
5701
|
try {
|
|
5702
|
+
const ctx = await this.buildConnectContext(declaration, connector);
|
|
5519
5703
|
const handle = await this.withSpan(
|
|
5520
5704
|
"connector.connect",
|
|
5521
5705
|
{
|
|
@@ -6796,11 +6980,15 @@ var DEFAULT_IGNORED = [
|
|
|
6796
6980
|
(p) => p.endsWith("~")
|
|
6797
6981
|
];
|
|
6798
6982
|
var DEFAULT_DEBOUNCE_MS = 150;
|
|
6799
|
-
function parseGitignore(rootDir) {
|
|
6983
|
+
async function parseGitignore(rootDir) {
|
|
6800
6984
|
const gitignorePath = join(rootDir, ".gitignore");
|
|
6801
|
-
|
|
6985
|
+
const content = await tryWithFsDeadline(
|
|
6986
|
+
`read ${gitignorePath}`,
|
|
6987
|
+
() => readFile(gitignorePath, "utf-8"),
|
|
6988
|
+
null
|
|
6989
|
+
);
|
|
6990
|
+
if (content === null) return [];
|
|
6802
6991
|
try {
|
|
6803
|
-
const content = readFileSync(gitignorePath, "utf-8");
|
|
6804
6992
|
const matchers = [];
|
|
6805
6993
|
for (const raw of content.split("\n")) {
|
|
6806
6994
|
const line = raw.trim();
|
|
@@ -6834,7 +7022,7 @@ var CHOKIDAR_EVENT_MAP = {
|
|
|
6834
7022
|
};
|
|
6835
7023
|
async function createFsWatcher(rootDir, callback, options) {
|
|
6836
7024
|
const log = createLogger({ kind: "connector", subkind: "watcher", instance: rootDir });
|
|
6837
|
-
const gitignorePatterns = parseGitignore(rootDir);
|
|
7025
|
+
const gitignorePatterns = await parseGitignore(rootDir);
|
|
6838
7026
|
const optionsIgnored = (options?.ignored ?? []).map(
|
|
6839
7027
|
(entry) => typeof entry === "string" ? globToMatcher(entry) : entry
|
|
6840
7028
|
);
|
|
@@ -6865,6 +7053,7 @@ async function createFsWatcher(rootDir, callback, options) {
|
|
|
6865
7053
|
close: () => watcher.close()
|
|
6866
7054
|
};
|
|
6867
7055
|
}
|
|
7056
|
+
var execFileAsync3 = promisify(execFile);
|
|
6868
7057
|
var WorktreeRegistryImpl = class {
|
|
6869
7058
|
entries = /* @__PURE__ */ new Map();
|
|
6870
7059
|
register(path, owner) {
|
|
@@ -6889,27 +7078,37 @@ var WorktreeRegistryImpl = class {
|
|
|
6889
7078
|
}
|
|
6890
7079
|
};
|
|
6891
7080
|
var worktreeRegistry = new WorktreeRegistryImpl();
|
|
6892
|
-
|
|
6893
|
-
|
|
7081
|
+
var GIT_QUERY_TIMEOUT_MS = 15e3;
|
|
7082
|
+
var GIT_WORKTREE_TIMEOUT_MS = 12e4;
|
|
7083
|
+
async function git2(args, cwd, timeoutMs) {
|
|
7084
|
+
const { stdout } = await execFileAsync3("git", args, {
|
|
7085
|
+
cwd,
|
|
7086
|
+
encoding: "utf-8",
|
|
7087
|
+
timeout: timeoutMs,
|
|
7088
|
+
killSignal: "SIGKILL"
|
|
7089
|
+
});
|
|
7090
|
+
return stdout.trim();
|
|
6894
7091
|
}
|
|
6895
|
-
function resolveRef(repoRoot, ref) {
|
|
6896
|
-
return git2(
|
|
7092
|
+
async function resolveRef(repoRoot, ref) {
|
|
7093
|
+
return git2(["rev-parse", "--verify", ref], repoRoot, GIT_QUERY_TIMEOUT_MS);
|
|
6897
7094
|
}
|
|
6898
|
-
function findGitRoot(fromDir) {
|
|
6899
|
-
return git2("rev-parse --show-toplevel", fromDir);
|
|
7095
|
+
async function findGitRoot(fromDir) {
|
|
7096
|
+
return git2(["rev-parse", "--show-toplevel"], fromDir, GIT_QUERY_TIMEOUT_MS);
|
|
6900
7097
|
}
|
|
6901
7098
|
async function createWorktree(opts) {
|
|
6902
|
-
const sha = resolveRef(opts.repoRoot, opts.ref);
|
|
7099
|
+
const sha = await resolveRef(opts.repoRoot, opts.ref);
|
|
6903
7100
|
const label = opts.label ?? sha.slice(0, 8);
|
|
6904
7101
|
const wtPath = resolve(opts.baseDir, label);
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
}
|
|
6908
|
-
git2(`worktree add "${wtPath}" ${sha} --detach`, opts.repoRoot);
|
|
7102
|
+
await withFsDeadline(`mkdir ${opts.baseDir}`, () => mkdir(opts.baseDir, { recursive: true }));
|
|
7103
|
+
await git2(["worktree", "add", wtPath, sha, "--detach"], opts.repoRoot, GIT_WORKTREE_TIMEOUT_MS);
|
|
6909
7104
|
worktreeRegistry.register(wtPath, opts.owner);
|
|
6910
7105
|
let branch;
|
|
6911
7106
|
try {
|
|
6912
|
-
const refName = git2(
|
|
7107
|
+
const refName = await git2(
|
|
7108
|
+
["rev-parse", "--abbrev-ref", opts.ref],
|
|
7109
|
+
opts.repoRoot,
|
|
7110
|
+
GIT_QUERY_TIMEOUT_MS
|
|
7111
|
+
);
|
|
6913
7112
|
if (refName !== "HEAD" && refName !== sha) branch = refName;
|
|
6914
7113
|
} catch {
|
|
6915
7114
|
}
|
|
@@ -6924,15 +7123,19 @@ async function createWorktree(opts) {
|
|
|
6924
7123
|
throw new Error(`worktree in use by: ${remaining.join(", ")}`);
|
|
6925
7124
|
}
|
|
6926
7125
|
try {
|
|
6927
|
-
git2(
|
|
7126
|
+
await git2(
|
|
7127
|
+
["worktree", "remove", wtPath, "--force"],
|
|
7128
|
+
opts.repoRoot,
|
|
7129
|
+
GIT_WORKTREE_TIMEOUT_MS
|
|
7130
|
+
);
|
|
6928
7131
|
} catch {
|
|
6929
7132
|
}
|
|
6930
|
-
git2("worktree prune", opts.repoRoot);
|
|
7133
|
+
await git2(["worktree", "prune"], opts.repoRoot, GIT_WORKTREE_TIMEOUT_MS);
|
|
6931
7134
|
}
|
|
6932
7135
|
};
|
|
6933
7136
|
}
|
|
6934
7137
|
async function listWorktrees(repoRoot) {
|
|
6935
|
-
const raw = git2("worktree list --porcelain", repoRoot);
|
|
7138
|
+
const raw = await git2(["worktree", "list", "--porcelain"], repoRoot, GIT_QUERY_TIMEOUT_MS);
|
|
6936
7139
|
const trees = [];
|
|
6937
7140
|
let current = {};
|
|
6938
7141
|
for (const line of raw.split("\n")) {
|
|
@@ -7907,5 +8110,5 @@ function createConnector() {
|
|
|
7907
8110
|
}
|
|
7908
8111
|
|
|
7909
8112
|
export { AbstractConnector, BUILTIN_CONNECTOR_CATALOG, BoxConnector, ConnectorFieldMissingError, ConnectorManager, ConnectorStartupError, DeployConnector, DevServerConnector, FlowAdapter, GitConnector, GmailConnector, GoogleDriveConnector, LocalConnector, LogBuffer, ManagedGitconfigCollisionError, MattermostConnector, MemoryConnector, MinIOConnector, PortPool, PostgresConnector, S3Connector, SQLiteConnector, SharePointConnector, StaticServerConnector, TunnelConnector, WebDAVConnector, XStateConnector, XStateStoreConnector, __test, atomicReplaceCredential, buildConnectorPromptSection, buildSdkConnectorTools, buildSdkFlowTools, createConnector, createConnector10, createConnector11, createConnector12, createConnector13, createConnector14, createConnector15, createConnector16, createConnector17, createConnector18, createConnector19, createConnector2, createConnector20, createConnector3, createConnector4, createConnector5, createConnector6, createConnector7, createConnector8, createConnector9, createFsWatcher, createWorktree, defaultSpawn, ensureDirMode, ensureFleetMounted, findGitRoot, findMissingPackages, getConnector, installNpmPackages, isFleetManaged, isPackageResolvable, listConnectors, listWorktrees, readGitSyncStatus, registerBuiltinConnectors, removeMountBlock, renderCredentialHelperScript, tryGetConnector, worktreeRegistry, writeHelperScript, writeMountBlock };
|
|
7910
|
-
//# sourceMappingURL=chunk-
|
|
7911
|
-
//# sourceMappingURL=chunk-
|
|
8113
|
+
//# sourceMappingURL=chunk-HOL5KD7U.js.map
|
|
8114
|
+
//# sourceMappingURL=chunk-HOL5KD7U.js.map
|