Skip to content

Commit b9a1429

Browse files
committed
fix(diff): use standard git: scheme so markdown diff tools work (#51)
Diff editors opened from Git Graph+ used a custom `git-graph-plus:` URI scheme served by our own content provider. Markdown-diff tooling — VS Code's "Reopen editor with…" and extensions like mddiff — only recognise the built-in `git:` scheme, so they couldn't resolve the comparison. Build diff URIs in the exact format the built-in Git extension uses (`git:` scheme, `{ path, ref }` query) and let its content provider serve the blobs. Remove the now-unused GitContentProvider and its registration.
1 parent b6513aa commit b9a1429

5 files changed

Lines changed: 30 additions & 192 deletions

File tree

src/__tests__/extension.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ vi.mock('../panels/MainPanel', () => ({
5959
static onRepoChange: unknown = null;
6060
},
6161
}));
62-
vi.mock('../services/git-content-provider', () => ({ GitContentProvider: class {} }));
6362
vi.mock('../git/git-service', () => ({ GitService: class { setExtraEnv() {} setDefaultTimeout() {} get rootPath() { return '/repo'; } worktreeList() { return Promise.resolve(H.worktreeList); } } }));
6463
vi.mock('../services/file-watcher', () => ({ FileWatcher: class { enabled = true; suppress() {} dispose() {} } }));
6564
const viewStub = () => ({ ViewProvider: undefined });

src/extension.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import * as path from 'path';
33
import { existsSync } from 'fs';
44
import { setGitBinaryPath } from './git/git-binary';
55
import { MainPanel } from './panels/MainPanel';
6-
import { GitContentProvider } from './services/git-content-provider';
76
import { GitService } from './git/git-service';
87
import { FileWatcher } from './services/file-watcher';
98
import { BranchesViewProvider } from './views/branches-view';
@@ -112,12 +111,6 @@ export function activate(context: vscode.ExtensionContext) {
112111
}),
113112
);
114113

115-
// --- Content Provider for diff URIs ---
116-
const contentProvider = new GitContentProvider();
117-
context.subscriptions.push(
118-
vscode.workspace.registerTextDocumentContentProvider('git-graph-plus', contentProvider)
119-
);
120-
121114
// --- Tree View Providers ---
122115
const branchesProvider = new BranchesViewProvider(activeGitService);
123116
const remotesProvider = new RemotesViewProvider(activeGitService);

src/panels/MainPanel.ts

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,27 @@ export class MainPanel {
15991599
}
16001600
}
16011601

1602+
/**
1603+
* Builds a `git:`-scheme URI in the exact format VS Code's built-in Git
1604+
* extension understands (mirrors its internal `toGitUri`). Using the standard
1605+
* scheme — rather than our own provider — lets the built-in content provider
1606+
* serve the blob and, crucially, lets markdown-diff tooling recognise the
1607+
* comparison: "Reopen editor with…" and extensions like `mddiff` only handle
1608+
* the `git:` scheme. (#51)
1609+
*
1610+
* ref conventions match the built-in extension: '' → index (stage 0),
1611+
* 'HEAD'/<sha>/<sha>~1 → that revision (`git show <ref>:<path>`). The query
1612+
* `path` is the absolute fsPath; the URI path keeps the file extension so the
1613+
* editor still infers the language.
1614+
*/
1615+
private toGitUri(fullPath: string, ref: string): vscode.Uri {
1616+
const fileUri = vscode.Uri.file(fullPath);
1617+
return fileUri.with({
1618+
scheme: 'git',
1619+
query: JSON.stringify({ path: fileUri.fsPath, ref }),
1620+
});
1621+
}
1622+
16021623
private async openDiffInEditor(
16031624
file: string,
16041625
staged?: boolean,
@@ -1613,51 +1634,35 @@ export class MainPanel {
16131634
if (commitHash) {
16141635
// Commit diff: parent vs commit
16151636
const parentRef = commitHash + '~1';
1616-
const leftUri = vscode.Uri.parse(`git-graph-plus://show/${parentRef}/${file}`).with({
1617-
query: JSON.stringify({ ref: parentRef, path: file, repoPath: this.repoPath }),
1618-
});
1619-
const rightUri = vscode.Uri.parse(`git-graph-plus://show/${commitHash}/${file}`).with({
1620-
query: JSON.stringify({ ref: commitHash, path: file, repoPath: this.repoPath }),
1621-
});
1637+
const leftUri = this.toGitUri(fullPath, parentRef);
1638+
const rightUri = this.toGitUri(fullPath, commitHash);
16221639
const title = `${file} (${commitHash.substring(0, 7)})`;
16231640
await vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title);
16241641
} else if (staged) {
16251642
// Staged diff: HEAD vs index
1626-
const headUri = vscode.Uri.parse(`git-graph-plus://show/HEAD/${file}`).with({
1627-
query: JSON.stringify({ ref: 'HEAD', path: file, repoPath: this.repoPath }),
1628-
});
1629-
const indexUri = vscode.Uri.parse(`git-graph-plus://show/:0/${file}`).with({
1630-
query: JSON.stringify({ ref: ':0', path: file, repoPath: this.repoPath }),
1631-
});
1643+
const headUri = this.toGitUri(fullPath, 'HEAD');
1644+
const indexUri = this.toGitUri(fullPath, '');
16321645
await vscode.commands.executeCommand('vscode.diff', headUri, indexUri, `${file} (Staged)`);
16331646
} else {
16341647
// Unstaged diff: index vs working tree
1635-
const indexUri = vscode.Uri.parse(`git-graph-plus://show/:0/${file}`).with({
1636-
query: JSON.stringify({ ref: ':0', path: file, repoPath: this.repoPath }),
1637-
});
1648+
const indexUri = this.toGitUri(fullPath, '');
16381649
await vscode.commands.executeCommand('vscode.diff', indexUri, fileUri, `${file} (Working Tree)`);
16391650
}
16401651
}
16411652

16421653
private async openCompareDiffInEditor(file: string, ref1: string, ref2: string): Promise<void> {
16431654
// Same validation as openDiffInEditor — the path must stay inside the repo
1644-
// before being embedded in the diff editor and our content-provider URI.
1655+
// before being embedded in the diff editor and the content-provider URI.
16451656
const fullPath = this.resolveRepoRelativePath(file, 'openCompareDiff');
16461657
// ref1 = 'working' means compare ref2 against working tree
16471658
if (ref1 === 'working' || ref2 === 'working') {
16481659
const commitRef = ref1 === 'working' ? ref2 : ref1;
1649-
const commitUri = vscode.Uri.parse(`git-graph-plus://show/${commitRef}/${file}`).with({
1650-
query: JSON.stringify({ ref: commitRef, path: file, repoPath: this.repoPath }),
1651-
});
1660+
const commitUri = this.toGitUri(fullPath, commitRef);
16521661
const fileUri = vscode.Uri.file(fullPath);
16531662
await vscode.commands.executeCommand('vscode.diff', commitUri, fileUri, `${file} (${commitRef.substring(0, 7)} ↔ Working Tree)`);
16541663
} else {
1655-
const leftUri = vscode.Uri.parse(`git-graph-plus://show/${ref1}/${file}`).with({
1656-
query: JSON.stringify({ ref: ref1, path: file, repoPath: this.repoPath }),
1657-
});
1658-
const rightUri = vscode.Uri.parse(`git-graph-plus://show/${ref2}/${file}`).with({
1659-
query: JSON.stringify({ ref: ref2, path: file, repoPath: this.repoPath }),
1660-
});
1664+
const leftUri = this.toGitUri(fullPath, ref1);
1665+
const rightUri = this.toGitUri(fullPath, ref2);
16611666
const label1 = ref1.length > 10 ? ref1.substring(0, 7) : ref1;
16621667
const label2 = ref2.length > 10 ? ref2.substring(0, 7) : ref2;
16631668
await vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, `${file} (${label1}${label2})`);

src/services/__tests__/git-content-provider.test.ts

Lines changed: 0 additions & 99 deletions
This file was deleted.

src/services/git-content-provider.ts

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)