diff --git a/src/extension.ts b/src/extension.ts index 9d921a0..faeec88 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -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); diff --git a/src/gitIntegration.ts b/src/gitIntegration.ts index d5b012e..e0884ad 100644 --- a/src/gitIntegration.ts +++ b/src/gitIntegration.ts @@ -29,6 +29,71 @@ try { } const execAsync = promisify(exec); +const nbdimeWarningShownRoots = new Set(); + +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 { + 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 { + 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, '/');