sync-worktrees 3.6.0 → 3.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +60 -42
- package/dist/index.js.map +2 -2
- package/dist/mcp-server.js +148 -123
- package/dist/mcp-server.js.map +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2756,10 +2756,11 @@ var WorktreeStatusService = class {
|
|
|
2756
2756
|
const reasons = [];
|
|
2757
2757
|
if (!isClean) reasons.push("uncommitted changes");
|
|
2758
2758
|
if (hasUnpushedCommits) reasons.push("unpushed commits");
|
|
2759
|
+
if (hasStashedChanges) reasons.push("stashed changes");
|
|
2759
2760
|
if (hasOperationInProgress) reasons.push("operation in progress");
|
|
2760
2761
|
if (hasModifiedSubmodules) reasons.push("modified submodules");
|
|
2761
2762
|
if (upstreamGone) reasons.push("upstream gone");
|
|
2762
|
-
const canRemove = isClean && !hasUnpushedCommits && !hasOperationInProgress && !hasModifiedSubmodules;
|
|
2763
|
+
const canRemove = isClean && !hasUnpushedCommits && !hasStashedChanges && !hasOperationInProgress && !hasModifiedSubmodules;
|
|
2763
2764
|
const details = includeDetails ? this.buildStatusDetails(snap) : void 0;
|
|
2764
2765
|
return {
|
|
2765
2766
|
isClean,
|
|
@@ -3808,7 +3809,7 @@ var GitService = class {
|
|
|
3808
3809
|
const bareGit = this.getCachedGit(this.bareRepoPath);
|
|
3809
3810
|
const checkRef = async (ref) => {
|
|
3810
3811
|
try {
|
|
3811
|
-
await bareGit.raw(["show-ref", "--verify",
|
|
3812
|
+
await bareGit.raw(["show-ref", "--verify", ref]);
|
|
3812
3813
|
return true;
|
|
3813
3814
|
} catch {
|
|
3814
3815
|
return false;
|
|
@@ -3825,10 +3826,22 @@ var GitService = class {
|
|
|
3825
3826
|
const branches = await bareGit.branch();
|
|
3826
3827
|
return branches.all;
|
|
3827
3828
|
}
|
|
3829
|
+
async resolveCreateBranchBaseRef(bareGit, baseBranch) {
|
|
3830
|
+
const candidates = baseBranch.startsWith(GIT_CONSTANTS.REMOTE_PREFIX) || baseBranch.startsWith("refs/") ? [baseBranch] : [`${GIT_CONSTANTS.REMOTE_PREFIX}${baseBranch}`, baseBranch];
|
|
3831
|
+
for (const candidate of candidates) {
|
|
3832
|
+
try {
|
|
3833
|
+
await bareGit.revparse(["--verify", candidate]);
|
|
3834
|
+
return candidate;
|
|
3835
|
+
} catch {
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3838
|
+
return candidates[0];
|
|
3839
|
+
}
|
|
3828
3840
|
async createBranch(branchName, baseBranch) {
|
|
3829
3841
|
const bareGit = this.getCachedGit(this.bareRepoPath);
|
|
3830
|
-
await
|
|
3831
|
-
|
|
3842
|
+
const baseRef = await this.resolveCreateBranchBaseRef(bareGit, baseBranch);
|
|
3843
|
+
await bareGit.raw(["branch", branchName, baseRef]);
|
|
3844
|
+
this.logger.info(`Created branch '${branchName}' from '${baseRef}'`);
|
|
3832
3845
|
}
|
|
3833
3846
|
async pushBranch(branchName) {
|
|
3834
3847
|
const bareGit = this.getCachedGit(this.bareRepoPath);
|
|
@@ -3940,17 +3953,9 @@ var WorktreeSyncService = class {
|
|
|
3940
3953
|
this.progressListeners.add(listener);
|
|
3941
3954
|
return () => this.progressListeners.delete(listener);
|
|
3942
3955
|
}
|
|
3943
|
-
|
|
3944
|
-
for (const listener of this.progressListeners) {
|
|
3945
|
-
try {
|
|
3946
|
-
listener(event);
|
|
3947
|
-
} catch {
|
|
3948
|
-
}
|
|
3949
|
-
}
|
|
3950
|
-
}
|
|
3951
|
-
async sync() {
|
|
3956
|
+
async runExclusiveRepoOperation(operation) {
|
|
3952
3957
|
if (this.syncInProgress) {
|
|
3953
|
-
this.logger.warn("\u26A0\uFE0F
|
|
3958
|
+
this.logger.warn("\u26A0\uFE0F Another repository operation is already in progress, skipping...");
|
|
3954
3959
|
return { started: false, reason: "in_progress" };
|
|
3955
3960
|
}
|
|
3956
3961
|
const release = await this.acquireBareLock();
|
|
@@ -3959,36 +3964,55 @@ var WorktreeSyncService = class {
|
|
|
3959
3964
|
return { started: false, reason: "locked" };
|
|
3960
3965
|
}
|
|
3961
3966
|
this.syncInProgress = true;
|
|
3962
|
-
this.logger.info(`[${(/* @__PURE__ */ new Date()).toISOString()}] Starting worktree synchronization...`);
|
|
3963
|
-
const totalTimer = new Timer();
|
|
3964
|
-
const phaseTimer = new PhaseTimer();
|
|
3965
|
-
const syncContext = { lfsSkipEnabled: false };
|
|
3966
|
-
const retryOptions = this.createRetryOptions(syncContext);
|
|
3967
3967
|
try {
|
|
3968
|
-
|
|
3969
|
-
} catch (error) {
|
|
3970
|
-
this.logger.error("\n\u274C Error during worktree synchronization after all retry attempts:", error);
|
|
3971
|
-
throw error;
|
|
3968
|
+
return { started: true, value: await operation() };
|
|
3972
3969
|
} finally {
|
|
3973
|
-
if (syncContext.lfsSkipEnabled && !this.config.skipLfs) {
|
|
3974
|
-
this.gitService.setLfsSkipEnabled(false);
|
|
3975
|
-
}
|
|
3976
3970
|
this.syncInProgress = false;
|
|
3977
3971
|
try {
|
|
3978
3972
|
await release();
|
|
3979
3973
|
} catch (releaseError) {
|
|
3980
3974
|
this.logger.warn(`Failed to release sync lock: ${getErrorMessage(releaseError)}`);
|
|
3981
3975
|
}
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
emitProgress(event) {
|
|
3979
|
+
for (const listener of this.progressListeners) {
|
|
3980
|
+
try {
|
|
3981
|
+
listener(event);
|
|
3982
|
+
} catch {
|
|
3989
3983
|
}
|
|
3990
3984
|
}
|
|
3991
|
-
|
|
3985
|
+
}
|
|
3986
|
+
async sync() {
|
|
3987
|
+
const result = await this.runExclusiveRepoOperation(async () => {
|
|
3988
|
+
if (!this.isInitialized()) {
|
|
3989
|
+
await this.initialize();
|
|
3990
|
+
}
|
|
3991
|
+
this.logger.info(`[${(/* @__PURE__ */ new Date()).toISOString()}] Starting worktree synchronization...`);
|
|
3992
|
+
const totalTimer = new Timer();
|
|
3993
|
+
const phaseTimer = new PhaseTimer();
|
|
3994
|
+
const syncContext = { lfsSkipEnabled: false };
|
|
3995
|
+
const retryOptions = this.createRetryOptions(syncContext);
|
|
3996
|
+
try {
|
|
3997
|
+
await retry(() => this.runSyncAttempt(phaseTimer, syncContext), retryOptions);
|
|
3998
|
+
} catch (error) {
|
|
3999
|
+
this.logger.error("\n\u274C Error during worktree synchronization after all retry attempts:", error);
|
|
4000
|
+
throw error;
|
|
4001
|
+
} finally {
|
|
4002
|
+
if (syncContext.lfsSkipEnabled && !this.config.skipLfs) {
|
|
4003
|
+
this.gitService.setLfsSkipEnabled(false);
|
|
4004
|
+
}
|
|
4005
|
+
this.logger.info(`[${(/* @__PURE__ */ new Date()).toISOString()}] Synchronization finished.
|
|
4006
|
+
`);
|
|
4007
|
+
if (this.config.debug) {
|
|
4008
|
+
const totalDuration = totalTimer.stop();
|
|
4009
|
+
const phaseResults = phaseTimer.getResults();
|
|
4010
|
+
const repoName = this.config.name;
|
|
4011
|
+
this.logger.table(formatTimingTable(totalDuration, phaseResults, repoName));
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
});
|
|
4015
|
+
return result.started ? { started: true } : result;
|
|
3992
4016
|
}
|
|
3993
4017
|
async acquireBareLock() {
|
|
3994
4018
|
if (process.env.NODE_ENV === ENV_CONSTANTS.NODE_ENV_TEST) {
|
|
@@ -4000,15 +4024,9 @@ var WorktreeSyncService = class {
|
|
|
4000
4024
|
};
|
|
4001
4025
|
}
|
|
4002
4026
|
const barePath = this.gitService.getBareRepoPath();
|
|
4003
|
-
|
|
4004
|
-
try {
|
|
4005
|
-
await fs6.access(lockTarget);
|
|
4006
|
-
} catch {
|
|
4007
|
-
return async () => {
|
|
4008
|
-
};
|
|
4009
|
-
}
|
|
4027
|
+
await fs6.mkdir(barePath, { recursive: true });
|
|
4010
4028
|
try {
|
|
4011
|
-
const release = await lockfile.lock(
|
|
4029
|
+
const release = await lockfile.lock(barePath, {
|
|
4012
4030
|
stale: DEFAULT_CONFIG.LOCK_STALE_MS,
|
|
4013
4031
|
update: DEFAULT_CONFIG.LOCK_UPDATE_MS,
|
|
4014
4032
|
retries: 0,
|