Skip to content

Commit bf66dd3

Browse files
Copilotalexr00
andcommitted
Fix webworker build: move child_process usage to env/node module
Move git worktree operations (child_process/util) into dedicated env/node/gitWorktree.ts and env/browser/gitWorktree.ts modules, following the existing env pattern. The webpack alias ensures the browser/no-op version is used for the webworker target. Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
1 parent 0998558 commit bf66dd3

File tree

4 files changed

+67
-38
lines changed

4 files changed

+67
-38
lines changed

src/env/browser/gitWorktree.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
export async function getWorktreeForBranch(_branchName: string, _repositoryRootFsPath: string): Promise<string | undefined> {
7+
return undefined;
8+
}
9+
10+
export async function removeWorktree(_worktreePath: string, _repositoryRootFsPath: string): Promise<void> {
11+
// Worktrees are not supported in browser environments
12+
}

src/env/node/gitWorktree.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { execFile } from 'child_process';
7+
import * as nodePath from 'path';
8+
import { promisify } from 'util';
9+
import * as vscode from 'vscode';
10+
11+
const execFileAsync = promisify(execFile);
12+
13+
export async function getWorktreeForBranch(branchName: string, repositoryRootFsPath: string): Promise<string | undefined> {
14+
const gitPath = vscode.workspace.getConfiguration('git').get<string>('path') || 'git';
15+
const { stdout } = await execFileAsync(gitPath, ['worktree', 'list', '--porcelain'], {
16+
cwd: repositoryRootFsPath,
17+
});
18+
19+
const worktrees = stdout.split('\n\n');
20+
for (const entry of worktrees) {
21+
const lines = entry.trim().split('\n');
22+
let worktreePath: string | undefined;
23+
let branch: string | undefined;
24+
for (const line of lines) {
25+
if (line.startsWith('worktree ')) {
26+
worktreePath = line.substring('worktree '.length);
27+
} else if (line.startsWith('branch ')) {
28+
branch = line.substring('branch '.length);
29+
// branch line is like "branch refs/heads/branchName"
30+
const prefix = 'refs/heads/';
31+
if (branch.startsWith(prefix)) {
32+
branch = branch.substring(prefix.length);
33+
}
34+
}
35+
}
36+
if (branch === branchName && worktreePath) {
37+
// Don't return the main worktree (the repository root itself)
38+
if (nodePath.resolve(worktreePath) !== nodePath.resolve(repositoryRootFsPath)) {
39+
return worktreePath;
40+
}
41+
}
42+
}
43+
return undefined;
44+
}
45+
46+
export async function removeWorktree(worktreePath: string, repositoryRootFsPath: string): Promise<void> {
47+
const gitPath = vscode.workspace.getConfiguration('git').get<string>('path') || 'git';
48+
await execFileAsync(gitPath, ['worktree', 'remove', worktreePath], {
49+
cwd: repositoryRootFsPath,
50+
});
51+
}

src/github/folderRepositoryManager.ts

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { execFile } from 'child_process';
76
import * as nodePath from 'path';
8-
import { promisify } from 'util';
97
import { bulkhead } from 'cockatiel';
108
import * as vscode from 'vscode';
119
import { OctokitCommon } from './common';
@@ -62,6 +60,7 @@ import { EventType } from '../common/timelineEvent';
6260
import { Schemes } from '../common/uri';
6361
import { AsyncPredicate, batchPromiseAll, compareIgnoreCase, formatError, Predicate } from '../common/utils';
6462
import { PULL_REQUEST_OVERVIEW_VIEW_TYPE } from '../common/webview';
63+
import { getWorktreeForBranch as envGetWorktreeForBranch, removeWorktree as envRemoveWorktree } from '../env/node/gitWorktree';
6564
import { BRANCHES_ASSOCIATED_WITH_PRS, LAST_USED_EMAIL, NEVER_SHOW_PULL_NOTIFICATION, REPO_KEYS, ReposState } from '../extensionState';
6665
import { git } from '../gitProviders/gitCommands';
6766
import { IThemeWatcher } from '../themeWatcher';
@@ -2454,37 +2453,7 @@ export class FolderRepositoryManager extends Disposable {
24542453

24552454
async getWorktreeForBranch(branchName: string): Promise<string | undefined> {
24562455
try {
2457-
const execFileAsync = promisify(execFile);
2458-
const gitPath = vscode.workspace.getConfiguration('git').get<string>('path') || 'git';
2459-
const { stdout } = await execFileAsync(gitPath, ['worktree', 'list', '--porcelain'], {
2460-
cwd: this.repository.rootUri.fsPath,
2461-
});
2462-
2463-
const worktrees = stdout.split('\n\n');
2464-
for (const entry of worktrees) {
2465-
const lines = entry.trim().split('\n');
2466-
let worktreePath: string | undefined;
2467-
let branch: string | undefined;
2468-
for (const line of lines) {
2469-
if (line.startsWith('worktree ')) {
2470-
worktreePath = line.substring('worktree '.length);
2471-
} else if (line.startsWith('branch ')) {
2472-
branch = line.substring('branch '.length);
2473-
// branch line is like "branch refs/heads/branchName"
2474-
const prefix = 'refs/heads/';
2475-
if (branch.startsWith(prefix)) {
2476-
branch = branch.substring(prefix.length);
2477-
}
2478-
}
2479-
}
2480-
if (branch === branchName && worktreePath) {
2481-
// Don't return the main worktree (the repository root itself)
2482-
const repoRoot = this.repository.rootUri.fsPath;
2483-
if (nodePath.resolve(worktreePath) !== nodePath.resolve(repoRoot)) {
2484-
return worktreePath;
2485-
}
2486-
}
2487-
}
2456+
return await envGetWorktreeForBranch(branchName, this.repository.rootUri.fsPath);
24882457
} catch (e) {
24892458
Logger.error(`Failed to get worktree for branch ${branchName}: ${e}`, this.id);
24902459
}
@@ -2493,11 +2462,7 @@ export class FolderRepositoryManager extends Disposable {
24932462

24942463
async removeWorktree(worktreePath: string): Promise<void> {
24952464
try {
2496-
const execFileAsync = promisify(execFile);
2497-
const gitPath = vscode.workspace.getConfiguration('git').get<string>('path') || 'git';
2498-
await execFileAsync(gitPath, ['worktree', 'remove', worktreePath], {
2499-
cwd: this.repository.rootUri.fsPath,
2500-
});
2465+
await envRemoveWorktree(worktreePath, this.repository.rootUri.fsPath);
25012466
} catch (e) {
25022467
Logger.error(`Failed to remove worktree ${worktreePath}: ${e}`, this.id);
25032468
throw e;

webpack.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ async function getExtensionConfig(target, mode, env) {
349349
'../env/node/net': path.resolve(__dirname, 'src', 'env', 'browser', 'net'),
350350
'../env/node/ssh': path.resolve(__dirname, 'src', 'env', 'browser', 'ssh'),
351351
'../../env/node/ssh': path.resolve(__dirname, 'src', 'env', 'browser', 'ssh'),
352+
'../env/node/gitWorktree': path.resolve(__dirname, 'src', 'env', 'browser', 'gitWorktree'),
352353
'./env/node/gitProviders/api': path.resolve(
353354
__dirname,
354355
'src',

0 commit comments

Comments
 (0)