Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ function registerGitStateWatchers(context: vscode.ExtensionContext): void {
export function activate(context: vscode.ExtensionContext) {
console.log('MergeNB extension is now active');
const isTestMode = process.env.MERGENB_TEST_MODE === 'true';
void gitIntegration.ensureSupportedMergeTool().catch((error) => {
console.error('[MergeNB] Unsupported merge tool configuration detected:', error);
});

resolver = new NotebookConflictResolver(context.extensionUri);

Expand Down
65 changes: 65 additions & 0 deletions src/gitIntegration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,71 @@ try {
}

const execAsync = promisify(exec);
const nbdimeWarningShownRoots = new Set<string>();

export class UnsupportedMergeToolError extends Error {
constructor(public readonly gitRoot: string, public readonly mergeTool: string) {
super(`[MergeNB] Unsupported Git merge tool configured: merge.tool=${mergeTool}`);
this.name = 'UnsupportedMergeToolError';
}
}

function getNbdimeDisableCommands(): string[] {
return [
'# MergeNB detected merge.tool=nbdime (unsupported in the same merge flow)',
'# Review the commands below, then press Enter to run the selected ones.',
'git config --unset merge.tool',
'git config --global --unset merge.tool',
'git config --remove-section mergetool.nbdime || true',
'git config --global --remove-section mergetool.nbdime || true',
'# Optional: uninstall nbdime if you no longer use it (interactive prompt expected)',
'python -m pip uninstall nbdime'
];
}

async function showUnsupportedMergeToolGuidance(error: UnsupportedMergeToolError): Promise<void> {
if (!vscode || nbdimeWarningShownRoots.has(error.gitRoot)) {
return;
}

nbdimeWarningShownRoots.add(error.gitRoot);
const terminalChoice = 'Show terminal fix commands';
const selection = await vscode.window.showErrorMessage(
`MergeNB cannot run while Git merge.tool is set to "${error.mergeTool}" in this repo. Disable nbdime merge tool and retry.`,
terminalChoice
);

if (selection === terminalChoice) {
const terminal = vscode.window.createTerminal('MergeNB nbdime fix');
terminal.show(true);
terminal.sendText(getNbdimeDisableCommands().join('\n'), false);
}
}

export async function ensureSupportedMergeTool(gitRootOrPath?: string): Promise<void> {
let gitRoot = gitRootOrPath;
if (!gitRoot && vscode?.workspace?.workspaceFolders?.[0]?.uri?.fsPath) {
gitRoot = vscode.workspace.workspaceFolders[0].uri.fsPath;
}
if (!gitRoot) {
return;
}

try {
const { stdout } = await execAsync('git config --get merge.tool', { cwd: gitRoot });
const mergeTool = stdout.trim().toLowerCase();
if (mergeTool === 'nbdime') {
const error = new UnsupportedMergeToolError(gitRoot, mergeTool);
await showUnsupportedMergeToolGuidance(error);
throw error;
}
} catch (error) {
if (error instanceof UnsupportedMergeToolError) {
throw error;
}
// `git config --get merge.tool` exits with code 1 when unset; ignore to keep default flow.
}
}

function toGitPath(filePath: string): string {
const converted = filePath.replace(/\\/g, '/');
Expand Down