mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-28 12:33:35 +01:00
Git - add git blame decoration to diff editors (#234714)
* Initial implementation * Manually fix the merge * WIP - saving my work * Made good progress, saving my work * Remove debug statement
This commit is contained in:
@@ -281,33 +281,78 @@ export class GitBlameController {
|
||||
return;
|
||||
}
|
||||
|
||||
// Working tree diff information
|
||||
const diffInformationWorkingTree = textEditor.diffInformation
|
||||
.filter(diff => diff.original && isGitUri(diff.original))
|
||||
.find(diff => fromGitUri(diff.original!).ref !== 'HEAD');
|
||||
let allChanges: readonly TextEditorChange[];
|
||||
let workingTreeChanges: readonly TextEditorChange[];
|
||||
let workingTreeAndIndexChanges: readonly TextEditorChange[] | undefined;
|
||||
|
||||
// Working tree + index diff information
|
||||
const diffInformationWorkingTreeAndIndex = textEditor.diffInformation
|
||||
.filter(diff => diff.original && isGitUri(diff.original))
|
||||
.find(diff => fromGitUri(diff.original!).ref === 'HEAD');
|
||||
if (isGitUri(textEditor.document.uri)) {
|
||||
const { ref } = fromGitUri(textEditor.document.uri);
|
||||
|
||||
// Working tree diff information is not present or it is stale
|
||||
if (!diffInformationWorkingTree || diffInformationWorkingTree.isStale) {
|
||||
return;
|
||||
// For the following scenarios we can discard the diff information
|
||||
// 1) Commit - Resource in the multi-file diff editor when viewing the details of a commit.
|
||||
// 2) HEAD - Resource on the left-hand side of the diff editor when viewing a resource from the index.
|
||||
// 3) ~ - Resource on the left-hand side of the diff editor when viewing a resource from the working tree.
|
||||
if (/^[0-9a-f]{40}$/i.test(ref) || ref === 'HEAD' || ref === '~') {
|
||||
workingTreeChanges = allChanges = [];
|
||||
workingTreeAndIndexChanges = undefined;
|
||||
} else if (ref === '') {
|
||||
// Resource on the right-hand side of the diff editor when viewing a resource from the index.
|
||||
const diffInformationWorkingTreeAndIndex = textEditor.diffInformation
|
||||
.filter(diff => diff.original && isGitUri(diff.original))
|
||||
.find(diff => fromGitUri(diff.original!).ref === 'HEAD');
|
||||
|
||||
// Working tree + index diff information is present and it is stale
|
||||
if (diffInformationWorkingTreeAndIndex && diffInformationWorkingTreeAndIndex.isStale) {
|
||||
return;
|
||||
}
|
||||
|
||||
workingTreeChanges = [];
|
||||
workingTreeAndIndexChanges = allChanges = diffInformationWorkingTreeAndIndex?.changes ?? [];
|
||||
} else {
|
||||
throw new Error(`Unexpected ref: ${ref}`);
|
||||
}
|
||||
} else {
|
||||
// Working tree diff information
|
||||
const diffInformationWorkingTree = textEditor.diffInformation
|
||||
.filter(diff => diff.original && isGitUri(diff.original))
|
||||
.find(diff => fromGitUri(diff.original!).ref === '');
|
||||
|
||||
// Working tree diff information is not present or it is stale
|
||||
if (!diffInformationWorkingTree || diffInformationWorkingTree.isStale) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Working tree + index diff information
|
||||
const diffInformationWorkingTreeAndIndex = textEditor.diffInformation
|
||||
.filter(diff => diff.original && isGitUri(diff.original))
|
||||
.find(diff => fromGitUri(diff.original!).ref === 'HEAD');
|
||||
|
||||
// Working tree + index diff information is present and it is stale
|
||||
if (diffInformationWorkingTreeAndIndex && diffInformationWorkingTreeAndIndex.isStale) {
|
||||
return;
|
||||
}
|
||||
|
||||
workingTreeChanges = diffInformationWorkingTree.changes;
|
||||
workingTreeAndIndexChanges = diffInformationWorkingTreeAndIndex?.changes;
|
||||
|
||||
// For staged resources, we provide an additional "original resource" so that the editor
|
||||
// diff information contains both the changes that are in the working tree and the changes
|
||||
// that are in the working tree + index.
|
||||
allChanges = workingTreeAndIndexChanges ?? workingTreeChanges;
|
||||
}
|
||||
|
||||
// Working tree + index diff information is present and it is stale
|
||||
if (diffInformationWorkingTreeAndIndex && diffInformationWorkingTreeAndIndex.isStale) {
|
||||
return;
|
||||
let commit: string;
|
||||
if (!isGitUri(textEditor.document.uri)) {
|
||||
// Resource with the `file` scheme
|
||||
commit = repository.HEAD.commit;
|
||||
} else {
|
||||
// Resource with the `git` scheme
|
||||
const { ref } = fromGitUri(textEditor.document.uri);
|
||||
commit = /^[0-9a-f]{40}$/i.test(ref) ? ref : repository.HEAD.commit;
|
||||
}
|
||||
|
||||
// For staged resources, we provide an additional "original resource" so that core can
|
||||
// compute the diff information that contains the changes from the working tree and the
|
||||
// index.
|
||||
const diffInformation = diffInformationWorkingTreeAndIndex ?? diffInformationWorkingTree;
|
||||
|
||||
// Git blame information
|
||||
const resourceBlameInformation = await this._getBlameInformation(textEditor.document.uri, repository.HEAD.commit);
|
||||
const resourceBlameInformation = await this._getBlameInformation(textEditor.document.uri, commit);
|
||||
if (!resourceBlameInformation) {
|
||||
return;
|
||||
}
|
||||
@@ -315,19 +360,19 @@ export class GitBlameController {
|
||||
const lineBlameInformation: LineBlameInformation[] = [];
|
||||
for (const lineNumber of textEditor.selections.map(s => s.active.line)) {
|
||||
// Check if the line is contained in the working tree diff information
|
||||
if (lineRangesContainLine(diffInformationWorkingTree.changes, lineNumber + 1)) {
|
||||
if (lineRangesContainLine(workingTreeChanges, lineNumber + 1)) {
|
||||
lineBlameInformation.push({ lineNumber, blameInformation: l10n.t('Not Committed Yet') });
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the line is contained in the working tree + index diff information
|
||||
if (lineRangesContainLine(diffInformationWorkingTreeAndIndex?.changes ?? [], lineNumber + 1)) {
|
||||
if (lineRangesContainLine(workingTreeAndIndexChanges ?? [], lineNumber + 1)) {
|
||||
lineBlameInformation.push({ lineNumber, blameInformation: l10n.t('Not Committed Yet (Staged)') });
|
||||
continue;
|
||||
}
|
||||
|
||||
// Map the line number to the git blame ranges using the diff information
|
||||
const lineNumberWithDiff = mapModifiedLineNumberToOriginalLineNumber(lineNumber + 1, diffInformation.changes);
|
||||
const lineNumberWithDiff = mapModifiedLineNumberToOriginalLineNumber(lineNumber + 1, allChanges);
|
||||
const blameInformation = resourceBlameInformation.find(blameInformation => {
|
||||
return blameInformation.ranges.find(range => {
|
||||
return lineNumberWithDiff >= range.startLineNumber && lineNumberWithDiff <= range.endLineNumber;
|
||||
@@ -407,9 +452,15 @@ class GitBlameEditorDecoration {
|
||||
editor.setDecorations(this._decorationType, []);
|
||||
}
|
||||
|
||||
// Only support resources with `file` and `git` schemes
|
||||
if (textEditor.document.uri.scheme !== 'file' && !isGitUri(textEditor.document.uri)) {
|
||||
textEditor.setDecorations(this._decorationType, []);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get blame information
|
||||
const blameInformation = this._controller.textEditorBlameInformation.get(textEditor);
|
||||
if (!blameInformation || textEditor.document.uri.scheme !== 'file') {
|
||||
if (!blameInformation) {
|
||||
textEditor.setDecorations(this._decorationType, []);
|
||||
return;
|
||||
}
|
||||
@@ -507,8 +558,14 @@ class GitBlameStatusBarItem {
|
||||
this._disposables.push(this._statusBarItem);
|
||||
}
|
||||
|
||||
// Only support resources with `file` and `git` schemes
|
||||
if (textEditor.document.uri.scheme !== 'file' && !isGitUri(textEditor.document.uri)) {
|
||||
this._statusBarItem.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
const blameInformation = this._controller.textEditorBlameInformation.get(textEditor);
|
||||
if (!blameInformation || blameInformation.length === 0 || textEditor.document.uri.scheme !== 'file') {
|
||||
if (!blameInformation || blameInformation.length === 0) {
|
||||
this._statusBarItem.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user