sync-worktrees 4.1.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/components/App.d.ts.map +1 -1
- package/dist/components/BranchCreationWizard.d.ts.map +1 -1
- package/dist/components/OpenEditorWizard.d.ts.map +1 -1
- package/dist/components/StatusBar.d.ts +1 -0
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/WorktreeStatusView.d.ts.map +1 -1
- package/dist/index.js +156 -69
- package/dist/index.js.map +4 -4
- package/dist/mcp-server.js +61 -32
- package/dist/mcp-server.js.map +4 -4
- package/dist/services/InteractiveUIService.d.ts.map +1 -1
- package/dist/services/worktree-sync.service.d.ts +5 -2
- package/dist/services/worktree-sync.service.d.ts.map +1 -1
- package/package.json +28 -27
package/README.md
CHANGED
|
@@ -31,6 +31,8 @@ The default — **worktree mode** — gives every remote branch its own director
|
|
|
31
31
|
- Fetches latest changes (no merge — your local work stays untouched).
|
|
32
32
|
- Removes directories for branches deleted upstream (preserves dirty trees and unpushed commits).
|
|
33
33
|
|
|
34
|
+
The bare repository is not an extra object store layered on top — it is the single Git database every worktree attaches to natively, so branches share history for free (no `--reference`, no alternates). The bare layout exists only so that no branch is a privileged "main" checkout: every branch, the default included, is a peer directory.
|
|
35
|
+
|
|
34
36
|
Smallest config that produces this:
|
|
35
37
|
|
|
36
38
|
```javascript
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BranchCreationWizard.d.ts","sourceRoot":"","sources":["../../src/components/BranchCreationWizard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAOjF,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACzD,uBAAuB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACnD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,mBAAmB,EAAE,CACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,KACf,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAC1B,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAK,IAAI,CAAC;CACZ;AAED,QAAA,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,
|
|
1
|
+
{"version":3,"file":"BranchCreationWizard.d.ts","sourceRoot":"","sources":["../../src/components/BranchCreationWizard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAOjF,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACzD,uBAAuB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACnD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,mBAAmB,EAAE,CACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,KACf,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAC1B,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAK,IAAI,CAAC;CACZ;AAED,QAAA,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA0e7D,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenEditorWizard.d.ts","sourceRoot":"","sources":["../../src/components/OpenEditorWizard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAKjF,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACzF,oBAAoB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrF,sBAAsB,EAAE,CACtB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,KACf;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,
|
|
1
|
+
{"version":3,"file":"OpenEditorWizard.d.ts","sourceRoot":"","sources":["../../src/components/OpenEditorWizard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAKjF,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACzF,oBAAoB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrF,sBAAsB,EAAE,CACtB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,KACf;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAuUrD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -3,6 +3,7 @@ import type { AppSyncProgress } from "../utils/app-events";
|
|
|
3
3
|
export interface StatusBarProps {
|
|
4
4
|
status: "idle" | "syncing";
|
|
5
5
|
syncProgressEntries?: AppSyncProgress[];
|
|
6
|
+
activeOps?: string[];
|
|
6
7
|
maxProgressLines?: number;
|
|
7
8
|
repositoryCount: number;
|
|
8
9
|
lastSyncTime: Date | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../src/components/StatusBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,mBAAmB,CAAC,EAAE,eAAe,EAAE,CAAC;IACxC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,QAAA,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,
|
|
1
|
+
{"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../src/components/StatusBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,mBAAmB,CAAC,EAAE,eAAe,EAAE,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,QAAA,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAgHvC,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorktreeStatusView.d.ts","sourceRoot":"","sources":["../../src/components/WorktreeStatusView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAIjF,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAGlB,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAIpC,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC,wBAAwB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC5E,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACzE,6BAA6B,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACpF,uBAAuB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA2GD,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,
|
|
1
|
+
{"version":3,"file":"WorktreeStatusView.d.ts","sourceRoot":"","sources":["../../src/components/WorktreeStatusView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAIjF,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAGlB,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAIpC,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC,wBAAwB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC5E,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACzE,6BAA6B,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACpF,uBAAuB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA2GD,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAqiBzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { realpathSync as realpathSync2 } from "fs";
|
|
5
5
|
import * as path17 from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
|
-
import
|
|
7
|
+
import pLimit4 from "p-limit";
|
|
8
8
|
|
|
9
9
|
// src/constants.ts
|
|
10
10
|
var GIT_CONSTANTS = {
|
|
@@ -141,6 +141,8 @@ var SyncWorktreesError = class extends Error {
|
|
|
141
141
|
Caused by: ${cause.stack}`;
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
+
code;
|
|
145
|
+
cause;
|
|
144
146
|
};
|
|
145
147
|
var GitError = class extends SyncWorktreesError {
|
|
146
148
|
constructor(message, code, cause) {
|
|
@@ -163,6 +165,8 @@ var WorktreeNotCleanError = class extends WorktreeError {
|
|
|
163
165
|
this.path = path18;
|
|
164
166
|
this.reasons = reasons;
|
|
165
167
|
}
|
|
168
|
+
path;
|
|
169
|
+
reasons;
|
|
166
170
|
};
|
|
167
171
|
var ConfigError = class extends SyncWorktreesError {
|
|
168
172
|
constructor(message, code, cause) {
|
|
@@ -175,18 +179,22 @@ var ConfigValidationError = class extends ConfigError {
|
|
|
175
179
|
this.field = field;
|
|
176
180
|
this.reason = reason;
|
|
177
181
|
}
|
|
182
|
+
field;
|
|
183
|
+
reason;
|
|
178
184
|
};
|
|
179
185
|
var ConfigFileNotFoundError = class extends ConfigError {
|
|
180
186
|
constructor(configPath) {
|
|
181
187
|
super(`Config file not found: ${configPath}`, "FILE_NOT_FOUND");
|
|
182
188
|
this.configPath = configPath;
|
|
183
189
|
}
|
|
190
|
+
configPath;
|
|
184
191
|
};
|
|
185
192
|
var ConfigFileExistsError = class extends ConfigError {
|
|
186
193
|
constructor(configPath) {
|
|
187
194
|
super(`Config file already exists: ${configPath}`, "FILE_EXISTS");
|
|
188
195
|
this.configPath = configPath;
|
|
189
196
|
}
|
|
197
|
+
configPath;
|
|
190
198
|
};
|
|
191
199
|
|
|
192
200
|
// src/services/config-loader.service.ts
|
|
@@ -814,13 +822,13 @@ import React8 from "react";
|
|
|
814
822
|
import * as path14 from "path";
|
|
815
823
|
import { render } from "ink";
|
|
816
824
|
import * as cron2 from "node-cron";
|
|
817
|
-
import
|
|
825
|
+
import pLimit3 from "p-limit";
|
|
818
826
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
819
827
|
import { existsSync as existsSync2 } from "fs";
|
|
820
828
|
|
|
821
829
|
// src/components/App.tsx
|
|
822
830
|
import React7, { useState as useState6, useEffect as useEffect6, useCallback as useCallback4, useRef as useRef5 } from "react";
|
|
823
|
-
import { Box as Box7, useInput as useInput6,
|
|
831
|
+
import { Box as Box7, useInput as useInput6, useWindowSize } from "ink";
|
|
824
832
|
|
|
825
833
|
// src/components/StatusBar.tsx
|
|
826
834
|
import React, { useState, useEffect } from "react";
|
|
@@ -829,6 +837,7 @@ import { CronExpressionParser } from "cron-parser";
|
|
|
829
837
|
var StatusBar = ({
|
|
830
838
|
status,
|
|
831
839
|
syncProgressEntries = [],
|
|
840
|
+
activeOps = [],
|
|
832
841
|
maxProgressLines = 2,
|
|
833
842
|
repositoryCount,
|
|
834
843
|
lastSyncTime,
|
|
@@ -864,17 +873,14 @@ var StatusBar = ({
|
|
|
864
873
|
const getStatusIcon = () => {
|
|
865
874
|
return status === "syncing" ? "\u27F3" : "\u2713";
|
|
866
875
|
};
|
|
867
|
-
const formatProgress = (syncProgress) => {
|
|
868
|
-
const percent = syncProgress.progress === void 0 || syncProgress.message.includes(`${syncProgress.progress}%`) ? "" : ` ${syncProgress.progress}%`;
|
|
869
|
-
return `[${syncProgress.repo}] ${syncProgress.message}${percent}`;
|
|
870
|
-
};
|
|
876
|
+
const formatProgress = (syncProgress) => `[${syncProgress.repo}] ${syncProgress.message}`;
|
|
871
877
|
const progressLineCount = Math.max(1, maxProgressLines);
|
|
872
878
|
const visibleProgress = syncProgressEntries.slice(-progressLineCount);
|
|
873
879
|
return /* @__PURE__ */ React.createElement(Box, { borderStyle: "single", paddingX: 1 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between" }, /* @__PURE__ */ React.createElement(Text, { bold: true }, getStatusIcon(), " Status:", " ", /* @__PURE__ */ React.createElement(Text, { color: getStatusColor() }, status === "syncing" ? "Syncing..." : "Running")), /* @__PURE__ */ React.createElement(Text, null, "Repositories: ", /* @__PURE__ */ React.createElement(Text, { bold: true, color: "cyan" }, repositoryCount))), /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between" }, /* @__PURE__ */ React.createElement(Text, null, "Last Sync: ", /* @__PURE__ */ React.createElement(Text, { color: "gray" }, formatTime(lastSyncTime))), cronSchedule && /* @__PURE__ */ React.createElement(Text, null, "Next Sync: ", /* @__PURE__ */ React.createElement(Text, { color: "gray" }, formatTime(nextSyncTime)))), status === "syncing" && Array.from({ length: progressLineCount }).map((_, index) => {
|
|
874
880
|
const entry = visibleProgress[index];
|
|
875
881
|
const message = entry ? formatProgress(entry) : index === 0 ? "waiting for progress events" : "";
|
|
876
882
|
return /* @__PURE__ */ React.createElement(Box, { key: index }, /* @__PURE__ */ React.createElement(Text, { wrap: "truncate" }, message ? "Progress: " : " ", message && /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, message)));
|
|
877
|
-
}), /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between" }, /* @__PURE__ */ React.createElement(Text, null, "Disk Space: ", /* @__PURE__ */ React.createElement(Text, { color: "magenta" }, diskSpaceUsed || "Calculating...")), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "s"), "ync", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "c"), "reate", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "o"), "pen", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "w"), "tree", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "r"), "eload", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "?"), "help", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "q"), "uit"))));
|
|
883
|
+
}), activeOps.map((label, index) => /* @__PURE__ */ React.createElement(Box, { key: `op-${index}` }, /* @__PURE__ */ React.createElement(Text, { wrap: "truncate" }, /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "\u23F3 "), /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, label)))), /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between" }, /* @__PURE__ */ React.createElement(Text, null, "Disk Space: ", /* @__PURE__ */ React.createElement(Text, { color: "magenta" }, diskSpaceUsed || "Calculating...")), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "s"), "ync", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "c"), "reate", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "o"), "pen", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "w"), "tree", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "r"), "eload", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "?"), "help", " ", /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "q"), "uit"))));
|
|
878
884
|
};
|
|
879
885
|
var StatusBar_default = StatusBar;
|
|
880
886
|
|
|
@@ -893,7 +899,7 @@ var HelpModal_default = HelpModal;
|
|
|
893
899
|
|
|
894
900
|
// src/components/BranchCreationWizard.tsx
|
|
895
901
|
import React3, { useState as useState2, useEffect as useEffect2, useCallback, useMemo, useRef } from "react";
|
|
896
|
-
import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
|
|
902
|
+
import { Box as Box3, Text as Text3, useInput as useInput2, usePaste } from "ink";
|
|
897
903
|
|
|
898
904
|
// src/utils/git-validation.ts
|
|
899
905
|
function isValidGitBranchName(name) {
|
|
@@ -1159,6 +1165,17 @@ var BranchCreationWizard = ({
|
|
|
1159
1165
|
onComplete(result?.success ?? false);
|
|
1160
1166
|
}
|
|
1161
1167
|
});
|
|
1168
|
+
usePaste((text) => {
|
|
1169
|
+
if (step === "SELECT_PROJECT") {
|
|
1170
|
+
setProjectFilter((prev) => prev + text);
|
|
1171
|
+
setSelectedProjectIndex(0);
|
|
1172
|
+
} else if (step === "SELECT_BRANCH") {
|
|
1173
|
+
setBranchFilter((prev) => prev + text);
|
|
1174
|
+
setSelectedBranchIndex(0);
|
|
1175
|
+
} else if (step === "ENTER_NAME") {
|
|
1176
|
+
setBranchName((prev) => prev + text.replace(/[^a-zA-Z0-9/._-]/g, ""));
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1162
1179
|
const getStepNumber = () => {
|
|
1163
1180
|
if (repositories.length === 1) {
|
|
1164
1181
|
if (step === "SELECT_BRANCH") return 1;
|
|
@@ -1252,7 +1269,7 @@ var BranchCreationWizard_default = BranchCreationWizard;
|
|
|
1252
1269
|
|
|
1253
1270
|
// src/components/OpenEditorWizard.tsx
|
|
1254
1271
|
import React4, { useState as useState3, useEffect as useEffect3, useMemo as useMemo2, useCallback as useCallback2, useRef as useRef2 } from "react";
|
|
1255
|
-
import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
|
|
1272
|
+
import { Box as Box4, Text as Text4, useInput as useInput3, usePaste as usePaste2 } from "ink";
|
|
1256
1273
|
var OpenEditorWizard = ({
|
|
1257
1274
|
repositories,
|
|
1258
1275
|
getWorktreesForRepo,
|
|
@@ -1370,6 +1387,15 @@ var OpenEditorWizard = ({
|
|
|
1370
1387
|
onClose();
|
|
1371
1388
|
}
|
|
1372
1389
|
});
|
|
1390
|
+
usePaste2((text) => {
|
|
1391
|
+
if (step === "SELECT_PROJECT") {
|
|
1392
|
+
setProjectFilter((prev) => prev + text);
|
|
1393
|
+
setSelectedProjectIndex(0);
|
|
1394
|
+
} else if (step === "SELECT_WORKTREE") {
|
|
1395
|
+
setWorktreeFilter((prev) => prev + text);
|
|
1396
|
+
setSelectedWorktreeIndex(0);
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1373
1399
|
const getStepNumber = () => {
|
|
1374
1400
|
if (repositories.length === 1) {
|
|
1375
1401
|
return 1;
|
|
@@ -1441,7 +1467,7 @@ var OpenEditorWizard_default = OpenEditorWizard;
|
|
|
1441
1467
|
|
|
1442
1468
|
// src/components/WorktreeStatusView.tsx
|
|
1443
1469
|
import React5, { useState as useState4, useEffect as useEffect4, useMemo as useMemo3, useCallback as useCallback3, useRef as useRef3 } from "react";
|
|
1444
|
-
import { Box as Box5, Text as Text5, useInput as useInput4 } from "ink";
|
|
1470
|
+
import { Box as Box5, Text as Text5, useInput as useInput4, usePaste as usePaste3 } from "ink";
|
|
1445
1471
|
|
|
1446
1472
|
// src/utils/lfs-error.ts
|
|
1447
1473
|
function getErrorMessage(error) {
|
|
@@ -1747,6 +1773,17 @@ var WorktreeStatusView = ({
|
|
|
1747
1773
|
onClose();
|
|
1748
1774
|
}
|
|
1749
1775
|
});
|
|
1776
|
+
usePaste3((text) => {
|
|
1777
|
+
if (confirmDelete !== null) return;
|
|
1778
|
+
if (step === "SELECT_PROJECT") {
|
|
1779
|
+
setProjectFilter((prev) => prev + text);
|
|
1780
|
+
setSelectedProjectIndex(0);
|
|
1781
|
+
} else if (step === "VIEW_STATUS" && !loading) {
|
|
1782
|
+
setEntryFilter((prev) => prev + text);
|
|
1783
|
+
setSelectedEntryIndex(0);
|
|
1784
|
+
setExpandedEntry(null);
|
|
1785
|
+
}
|
|
1786
|
+
});
|
|
1750
1787
|
const getStepNumber = () => {
|
|
1751
1788
|
if (repositories.length === 1) return 1;
|
|
1752
1789
|
return step === "SELECT_PROJECT" ? 1 : 2;
|
|
@@ -1971,13 +2008,15 @@ var App = ({
|
|
|
1971
2008
|
const [showOpenEditorWizard, setShowOpenEditorWizard] = useState6(false);
|
|
1972
2009
|
const [showWorktreeStatus, setShowWorktreeStatus] = useState6(false);
|
|
1973
2010
|
const [status, setStatus] = useState6("idle");
|
|
2011
|
+
const [activeOps, setActiveOps] = useState6([]);
|
|
2012
|
+
const opIdRef = useRef5(0);
|
|
1974
2013
|
const [syncProgressEntries, setSyncProgressEntries] = useState6([]);
|
|
1975
2014
|
const [lastSyncTime, setLastSyncTime] = useState6(null);
|
|
1976
2015
|
const [diskSpaceUsed, setDiskSpaceUsed] = useState6(null);
|
|
1977
2016
|
const [logs, setLogs] = useState6([]);
|
|
1978
2017
|
const [repoCount, setRepoCount] = useState6(repositoryCount);
|
|
1979
2018
|
const [schedule2, setSchedule] = useState6(cronSchedule);
|
|
1980
|
-
const {
|
|
2019
|
+
const { rows } = useWindowSize();
|
|
1981
2020
|
const addLog = useCallback4((message, level = "info") => {
|
|
1982
2021
|
setLogs((prev) => {
|
|
1983
2022
|
const newLogs = [
|
|
@@ -2011,11 +2050,11 @@ var App = ({
|
|
|
2011
2050
|
onQuit().catch((err) => console.error("Quit failed:", err));
|
|
2012
2051
|
} else if (input2 === "?" || input2 === "h") {
|
|
2013
2052
|
setShowHelp(true);
|
|
2014
|
-
} else if (input2 === "c"
|
|
2053
|
+
} else if (input2 === "c") {
|
|
2015
2054
|
setShowBranchWizard(true);
|
|
2016
|
-
} else if (input2 === "o"
|
|
2055
|
+
} else if (input2 === "o") {
|
|
2017
2056
|
setShowOpenEditorWizard(true);
|
|
2018
|
-
} else if (input2 === "w" &&
|
|
2057
|
+
} else if (input2 === "w" && getWorktreeStatusForRepo) {
|
|
2019
2058
|
setShowWorktreeStatus(true);
|
|
2020
2059
|
} else if (input2 === "s" && status !== "syncing") {
|
|
2021
2060
|
setStatus("syncing");
|
|
@@ -2092,8 +2131,8 @@ var App = ({
|
|
|
2092
2131
|
};
|
|
2093
2132
|
}, []);
|
|
2094
2133
|
const progressLineCount = status === "syncing" ? Math.max(1, maxProgressLines) : 0;
|
|
2095
|
-
const statusBarHeight = 5 + progressLineCount;
|
|
2096
|
-
const terminalRows =
|
|
2134
|
+
const statusBarHeight = 5 + progressLineCount + activeOps.length;
|
|
2135
|
+
const terminalRows = rows ?? 24;
|
|
2097
2136
|
const logPanelHeight = Math.max(5, terminalRows - statusBarHeight);
|
|
2098
2137
|
const showModal = showHelp || showBranchWizard || showOpenEditorWizard || showWorktreeStatus;
|
|
2099
2138
|
return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", minHeight: terminalRows }, !showModal && /* @__PURE__ */ React7.createElement(LogPanel_default, { logs, height: logPanelHeight, isActive: !showModal }), showHelp && /* @__PURE__ */ React7.createElement(HelpModal_default, { onClose: () => setShowHelp(false) }), showBranchWizard && /* @__PURE__ */ React7.createElement(
|
|
@@ -2106,7 +2145,8 @@ var App = ({
|
|
|
2106
2145
|
createAndPushBranch,
|
|
2107
2146
|
onClose: () => setShowBranchWizard(false),
|
|
2108
2147
|
onBranchCreated: (context) => {
|
|
2109
|
-
|
|
2148
|
+
const opId = ++opIdRef.current;
|
|
2149
|
+
setActiveOps((prev) => [...prev, { id: opId, label: `Creating worktree ${context.newBranch}` }]);
|
|
2110
2150
|
(async () => {
|
|
2111
2151
|
try {
|
|
2112
2152
|
await createWorktreeForBranch(context.repoIndex, context.newBranch);
|
|
@@ -2135,7 +2175,7 @@ var App = ({
|
|
|
2135
2175
|
level: "error"
|
|
2136
2176
|
});
|
|
2137
2177
|
} finally {
|
|
2138
|
-
|
|
2178
|
+
setActiveOps((prev) => prev.filter((op) => op.id !== opId));
|
|
2139
2179
|
}
|
|
2140
2180
|
})().catch((err) => console.error("Branch creation unhandled error:", err));
|
|
2141
2181
|
},
|
|
@@ -2167,6 +2207,7 @@ var App = ({
|
|
|
2167
2207
|
{
|
|
2168
2208
|
status,
|
|
2169
2209
|
syncProgressEntries,
|
|
2210
|
+
activeOps: activeOps.map((op) => op.label),
|
|
2170
2211
|
maxProgressLines,
|
|
2171
2212
|
repositoryCount: repoCount,
|
|
2172
2213
|
lastSyncTime,
|
|
@@ -2177,6 +2218,9 @@ var App = ({
|
|
|
2177
2218
|
};
|
|
2178
2219
|
var App_default = App;
|
|
2179
2220
|
|
|
2221
|
+
// src/services/worktree-sync.service.ts
|
|
2222
|
+
import pLimit2 from "p-limit";
|
|
2223
|
+
|
|
2180
2224
|
// src/utils/retry.ts
|
|
2181
2225
|
var DEFAULT_OPTIONS = {
|
|
2182
2226
|
maxAttempts: "unlimited",
|
|
@@ -2577,6 +2621,7 @@ var SyncOutcomeAccumulator = class {
|
|
|
2577
2621
|
constructor(options) {
|
|
2578
2622
|
this.options = options;
|
|
2579
2623
|
}
|
|
2624
|
+
options;
|
|
2580
2625
|
counts = cloneCounts(EMPTY_COUNTS);
|
|
2581
2626
|
actions = [];
|
|
2582
2627
|
add(action) {
|
|
@@ -2653,6 +2698,9 @@ var CloneSyncService = class {
|
|
|
2653
2698
|
this.progressEmitter = options.progressEmitter;
|
|
2654
2699
|
this.onSkip = options.onSkip;
|
|
2655
2700
|
}
|
|
2701
|
+
config;
|
|
2702
|
+
gitService;
|
|
2703
|
+
logger;
|
|
2656
2704
|
initialized = false;
|
|
2657
2705
|
resolvedBranch = null;
|
|
2658
2706
|
branchCreatedActions;
|
|
@@ -3758,6 +3806,7 @@ var WorktreeStatusService = class {
|
|
|
3758
3806
|
this.config = config;
|
|
3759
3807
|
this.logger = logger ?? Logger.createDefault();
|
|
3760
3808
|
}
|
|
3809
|
+
config;
|
|
3761
3810
|
gitInstances = /* @__PURE__ */ new Map();
|
|
3762
3811
|
logger;
|
|
3763
3812
|
async checkWorktreeStatus(worktreePath) {
|
|
@@ -4116,6 +4165,8 @@ var GitService = class {
|
|
|
4116
4165
|
this.statusService = new WorktreeStatusService({ skipLfs: this.config.skipLfs }, this.logger);
|
|
4117
4166
|
this.sparseCheckoutService = new SparseCheckoutService(this.logger);
|
|
4118
4167
|
}
|
|
4168
|
+
config;
|
|
4169
|
+
progressEmitter;
|
|
4119
4170
|
git = null;
|
|
4120
4171
|
bareRepoPath;
|
|
4121
4172
|
mainWorktreePath;
|
|
@@ -5010,6 +5061,9 @@ var RepoOperationLock = class {
|
|
|
5010
5061
|
this.gitService = gitService;
|
|
5011
5062
|
this.logger = logger;
|
|
5012
5063
|
}
|
|
5064
|
+
config;
|
|
5065
|
+
gitService;
|
|
5066
|
+
logger;
|
|
5013
5067
|
updateLogger(logger) {
|
|
5014
5068
|
this.logger = logger;
|
|
5015
5069
|
}
|
|
@@ -5071,6 +5125,9 @@ var SyncRetryPolicy = class {
|
|
|
5071
5125
|
this.gitService = gitService;
|
|
5072
5126
|
this.logger = logger;
|
|
5073
5127
|
}
|
|
5128
|
+
config;
|
|
5129
|
+
gitService;
|
|
5130
|
+
logger;
|
|
5074
5131
|
updateLogger(logger) {
|
|
5075
5132
|
this.logger = logger;
|
|
5076
5133
|
}
|
|
@@ -5291,6 +5348,10 @@ var WorktreeModeSyncRunner = class {
|
|
|
5291
5348
|
this.logger = logger;
|
|
5292
5349
|
this.progressEmitter = progressEmitter;
|
|
5293
5350
|
}
|
|
5351
|
+
config;
|
|
5352
|
+
gitService;
|
|
5353
|
+
logger;
|
|
5354
|
+
progressEmitter;
|
|
5294
5355
|
pathResolution = new PathResolutionService();
|
|
5295
5356
|
updateLogger(logger) {
|
|
5296
5357
|
this.logger = logger;
|
|
@@ -5989,10 +6050,15 @@ var WorktreeSyncService = class {
|
|
|
5989
6050
|
});
|
|
5990
6051
|
}
|
|
5991
6052
|
}
|
|
6053
|
+
config;
|
|
5992
6054
|
gitService;
|
|
5993
6055
|
cloneSyncService = null;
|
|
5994
6056
|
logger;
|
|
5995
|
-
|
|
6057
|
+
// In-process FIFO serializer for all bare-repo-mutating operations (sync, init,
|
|
6058
|
+
// interactive create). One per repo. wait:true callers queue behind an in-flight op;
|
|
6059
|
+
// wait:false callers fail fast. The cross-process file lock (RepoOperationLock) is
|
|
6060
|
+
// acquired inside the mutex body for multi-process safety.
|
|
6061
|
+
repoMutex = pLimit2(1);
|
|
5996
6062
|
progressEmitter = new ProgressEmitter();
|
|
5997
6063
|
repoOperationLock;
|
|
5998
6064
|
retryPolicy;
|
|
@@ -6044,7 +6110,7 @@ var WorktreeSyncService = class {
|
|
|
6044
6110
|
return this.gitService.isInitialized();
|
|
6045
6111
|
}
|
|
6046
6112
|
isSyncInProgress() {
|
|
6047
|
-
return this.
|
|
6113
|
+
return this.repoMutex.activeCount + this.repoMutex.pendingCount > 0;
|
|
6048
6114
|
}
|
|
6049
6115
|
getGitService() {
|
|
6050
6116
|
return this.gitService;
|
|
@@ -6060,34 +6126,31 @@ var WorktreeSyncService = class {
|
|
|
6060
6126
|
onProgress(listener) {
|
|
6061
6127
|
return this.progressEmitter.onProgress(listener);
|
|
6062
6128
|
}
|
|
6063
|
-
async runExclusiveRepoOperation(operation) {
|
|
6064
|
-
if (this.
|
|
6129
|
+
async runExclusiveRepoOperation(operation, options = {}) {
|
|
6130
|
+
if (!options.wait && this.repoMutex.activeCount + this.repoMutex.pendingCount > 0) {
|
|
6065
6131
|
this.logger.warn("\u26A0\uFE0F Another repository operation is already in progress, skipping...");
|
|
6066
6132
|
return { started: false, reason: "in_progress" };
|
|
6067
6133
|
}
|
|
6068
|
-
this.
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
throw error;
|
|
6075
|
-
}
|
|
6076
|
-
if (release === null) {
|
|
6077
|
-
this.syncInProgress = false;
|
|
6078
|
-
this.logger.warn("\u26A0\uFE0F Another process holds the sync lock for this repo, skipping...");
|
|
6079
|
-
return { started: false, reason: "locked" };
|
|
6080
|
-
}
|
|
6081
|
-
try {
|
|
6082
|
-
return { started: true, value: await operation() };
|
|
6083
|
-
} finally {
|
|
6134
|
+
return this.repoMutex(async () => {
|
|
6135
|
+
const release = await this.repoOperationLock.acquire();
|
|
6136
|
+
if (release === null) {
|
|
6137
|
+
this.logger.warn("\u26A0\uFE0F Another process holds the sync lock for this repo, skipping...");
|
|
6138
|
+
return { started: false, reason: "locked" };
|
|
6139
|
+
}
|
|
6084
6140
|
try {
|
|
6085
|
-
await
|
|
6086
|
-
}
|
|
6087
|
-
|
|
6141
|
+
return { started: true, value: await operation() };
|
|
6142
|
+
} finally {
|
|
6143
|
+
try {
|
|
6144
|
+
await release();
|
|
6145
|
+
} catch (releaseError) {
|
|
6146
|
+
this.logger.warn(`Failed to release sync lock: ${getErrorMessage(releaseError)}`);
|
|
6147
|
+
}
|
|
6088
6148
|
}
|
|
6089
|
-
|
|
6090
|
-
|
|
6149
|
+
});
|
|
6150
|
+
}
|
|
6151
|
+
// Interactive variant: queues behind any in-flight sync/op instead of failing fast.
|
|
6152
|
+
async runQueuedRepoOperation(operation) {
|
|
6153
|
+
return this.runExclusiveRepoOperation(operation, { wait: true });
|
|
6091
6154
|
}
|
|
6092
6155
|
emitProgress(event) {
|
|
6093
6156
|
this.progressEmitter.emit(event);
|
|
@@ -6393,7 +6456,7 @@ var InteractiveUIService = class {
|
|
|
6393
6456
|
this.cronSchedule = cronSchedule;
|
|
6394
6457
|
this.repositoryCount = syncServices.length;
|
|
6395
6458
|
this.maxProgressLines = Math.max(1, maxParallel ?? DEFAULT_CONFIG.PARALLELISM.MAX_REPOSITORIES);
|
|
6396
|
-
this.limit =
|
|
6459
|
+
this.limit = pLimit3(this.maxProgressLines);
|
|
6397
6460
|
this.startBufferFlushCheck();
|
|
6398
6461
|
this.renderUI();
|
|
6399
6462
|
this.subscribeToServiceProgress();
|
|
@@ -6526,7 +6589,11 @@ var InteractiveUIService = class {
|
|
|
6526
6589
|
createWorktreeForBranch: (repoIndex, branchName) => this.createWorktreeForBranch(repoIndex, branchName),
|
|
6527
6590
|
executeOnBranchCreatedHooks: (repoIndex, context) => this.executeOnBranchCreatedHooks(repoIndex, context)
|
|
6528
6591
|
}
|
|
6529
|
-
)
|
|
6592
|
+
),
|
|
6593
|
+
{
|
|
6594
|
+
alternateScreen: true,
|
|
6595
|
+
incrementalRendering: true
|
|
6596
|
+
}
|
|
6530
6597
|
);
|
|
6531
6598
|
}
|
|
6532
6599
|
async handleManualSync() {
|
|
@@ -6721,11 +6788,12 @@ var InteractiveUIService = class {
|
|
|
6721
6788
|
}
|
|
6722
6789
|
const sizeBytes = bareSizeBytes + worktreeSizeBytes;
|
|
6723
6790
|
const failedAllPaths = errors.length === sizeTargets.length;
|
|
6791
|
+
const partialFailure = errors.length > 0 && !failedAllPaths;
|
|
6724
6792
|
return {
|
|
6725
6793
|
repoIndex,
|
|
6726
6794
|
repoName,
|
|
6727
6795
|
sizeBytes: failedAllPaths ? null : sizeBytes,
|
|
6728
|
-
sizeFormatted: failedAllPaths ? "N/A" : formatBytes(sizeBytes),
|
|
6796
|
+
sizeFormatted: failedAllPaths ? "N/A" : partialFailure ? `\u2265${formatBytes(sizeBytes)}` : formatBytes(sizeBytes),
|
|
6729
6797
|
bareSizeBytes,
|
|
6730
6798
|
worktreeSizeBytes,
|
|
6731
6799
|
error: errors.length > 0 ? errors.join("; ") : void 0
|
|
@@ -6755,11 +6823,15 @@ var InteractiveUIService = class {
|
|
|
6755
6823
|
throw new Error(`Invalid repository index: ${repoIndex}`);
|
|
6756
6824
|
}
|
|
6757
6825
|
const service = this.syncServices[repoIndex];
|
|
6758
|
-
|
|
6759
|
-
|
|
6826
|
+
const result = await service.runQueuedRepoOperation(async () => {
|
|
6827
|
+
if (!service.isInitialized()) {
|
|
6828
|
+
await service.initializeUnlocked();
|
|
6829
|
+
}
|
|
6830
|
+
await service.getGitService().fetchAll();
|
|
6831
|
+
});
|
|
6832
|
+
if (!result.started) {
|
|
6833
|
+
throw new Error("Another process holds the repository lock; fetch skipped. Try again.");
|
|
6760
6834
|
}
|
|
6761
|
-
const gitService = service.getGitService();
|
|
6762
|
-
await gitService.fetchAll();
|
|
6763
6835
|
}
|
|
6764
6836
|
async createAndPushBranch(repoIndex, baseBranch, branchName) {
|
|
6765
6837
|
if (repoIndex < 0 || repoIndex >= this.syncServices.length) {
|
|
@@ -6767,25 +6839,35 @@ var InteractiveUIService = class {
|
|
|
6767
6839
|
}
|
|
6768
6840
|
const service = this.syncServices[repoIndex];
|
|
6769
6841
|
const gitService = service.getGitService();
|
|
6770
|
-
const
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6842
|
+
const result = await service.runQueuedRepoOperation(async () => {
|
|
6843
|
+
const maxAttempts = 10;
|
|
6844
|
+
let finalName = branchName;
|
|
6845
|
+
let suffix = 0;
|
|
6846
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
6847
|
+
try {
|
|
6848
|
+
await gitService.createBranch(finalName, baseBranch);
|
|
6849
|
+
await gitService.pushBranch(finalName);
|
|
6850
|
+
return { success: true, finalName };
|
|
6851
|
+
} catch (error) {
|
|
6852
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
6853
|
+
if (errorMessage.includes("already exists")) {
|
|
6854
|
+
suffix++;
|
|
6855
|
+
finalName = `${branchName}-${suffix}`;
|
|
6856
|
+
continue;
|
|
6857
|
+
}
|
|
6858
|
+
return { success: false, finalName: branchName, error: errorMessage };
|
|
6784
6859
|
}
|
|
6785
|
-
return { success: false, finalName: branchName, error: errorMessage };
|
|
6786
6860
|
}
|
|
6861
|
+
return { success: false, finalName: branchName, error: `Failed to create branch after ${maxAttempts} attempts` };
|
|
6862
|
+
});
|
|
6863
|
+
if (!result.started) {
|
|
6864
|
+
return {
|
|
6865
|
+
success: false,
|
|
6866
|
+
finalName: branchName,
|
|
6867
|
+
error: "Another process holds the repository lock; branch not created. Try again."
|
|
6868
|
+
};
|
|
6787
6869
|
}
|
|
6788
|
-
return
|
|
6870
|
+
return result.value;
|
|
6789
6871
|
}
|
|
6790
6872
|
async getWorktreesForRepo(repoIndex) {
|
|
6791
6873
|
if (repoIndex < 0 || repoIndex >= this.syncServices.length) {
|
|
@@ -6887,7 +6969,12 @@ var InteractiveUIService = class {
|
|
|
6887
6969
|
const gitService = service.getGitService();
|
|
6888
6970
|
const worktreeDir = service.config.worktreeDir;
|
|
6889
6971
|
const worktreePath = this.pathResolution.getBranchWorktreePath(worktreeDir, branchName);
|
|
6890
|
-
await
|
|
6972
|
+
const result = await service.runQueuedRepoOperation(async () => {
|
|
6973
|
+
await gitService.addWorktree(branchName, worktreePath);
|
|
6974
|
+
});
|
|
6975
|
+
if (!result.started) {
|
|
6976
|
+
throw new Error("Another process holds the repository lock; worktree not created. Try again.");
|
|
6977
|
+
}
|
|
6891
6978
|
}
|
|
6892
6979
|
openEditorInWorktree(worktreePath) {
|
|
6893
6980
|
const editor = process.env.EDITOR || process.env.VISUAL || "code";
|
|
@@ -7465,7 +7552,7 @@ async function runMultipleRepositories(configFile, repositories, configPath) {
|
|
|
7465
7552
|
const globalLogger = Logger.createDefault();
|
|
7466
7553
|
const runOnce = configFile.defaults?.runOnce ?? false;
|
|
7467
7554
|
const maxParallel = configFile.parallelism?.maxRepositories ?? configFile.defaults?.parallelism?.maxRepositories ?? DEFAULT_CONFIG.PARALLELISM.MAX_REPOSITORIES;
|
|
7468
|
-
const limit =
|
|
7555
|
+
const limit = pLimit4(maxParallel);
|
|
7469
7556
|
if (runOnce) {
|
|
7470
7557
|
globalLogger.info(`
|
|
7471
7558
|
\u{1F504} Syncing ${repositories.length} repositories...`);
|