Git - more git blame code cleanup (#234739)

* Cleanup code

* Fix multi-file diff editor uri/title
This commit is contained in:
Ladislau Szomoru
2024-11-27 11:14:46 +01:00
committed by GitHub
parent ce446a0855
commit 2b1cfedf1e
6 changed files with 68 additions and 66 deletions

View File

@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { DecorationOptions, l10n, Position, Range, TextEditor, TextEditorChange, TextEditorDecorationType, TextEditorChangeKind, ThemeColor, Uri, window, workspace, EventEmitter, ConfigurationChangeEvent, StatusBarItem, StatusBarAlignment, Command, MarkdownString } from 'vscode';
import { DecorationOptions, l10n, Position, Range, TextEditor, TextEditorChange, TextEditorDecorationType, TextEditorChangeKind, ThemeColor, Uri, window, workspace, EventEmitter, ConfigurationChangeEvent, StatusBarItem, StatusBarAlignment, Command, MarkdownString, TextEditorDiffInformation } from 'vscode';
import { Model } from './model';
import { dispose, fromNow, IDisposable } from './util';
import { Repository } from './repository';
@@ -63,22 +63,6 @@ type BlameInformationTemplateTokens = {
readonly authorDateAgo: string;
};
function formatBlameInformation(template: string, blameInformation: BlameInformation): string {
const templateTokens = {
hash: blameInformation.hash,
hashShort: blameInformation.hash.substring(0, 8),
subject: blameInformation.subject ?? '',
authorName: blameInformation.authorName ?? '',
authorEmail: blameInformation.authorEmail ?? '',
authorDate: new Date(blameInformation.authorDate ?? new Date()).toLocaleString(),
authorDateAgo: fromNow(blameInformation.authorDate ?? new Date(), true, true)
} satisfies BlameInformationTemplateTokens;
return template.replace(/\$\{(.+?)\}/g, (_, token) => {
return token in templateTokens ? templateTokens[token as keyof BlameInformationTemplateTokens] : `\${${token}}`;
});
}
interface RepositoryBlameInformation {
/**
* Track the current HEAD of the repository so that we can clear cache entries
@@ -182,6 +166,22 @@ export class GitBlameController {
this._updateTextEditorBlameInformation(window.activeTextEditor);
}
formatBlameInformationMessage(template: string, blameInformation: BlameInformation): string {
const templateTokens = {
hash: blameInformation.hash,
hashShort: blameInformation.hash.substring(0, 8),
subject: blameInformation.subject ?? '',
authorName: blameInformation.authorName ?? '',
authorEmail: blameInformation.authorEmail ?? '',
authorDate: new Date(blameInformation.authorDate ?? new Date()).toLocaleString(),
authorDateAgo: fromNow(blameInformation.authorDate ?? new Date(), true, true)
} satisfies BlameInformationTemplateTokens;
return template.replace(/\$\{(.+?)\}/g, (_, token) => {
return token in templateTokens ? templateTokens[token as keyof BlameInformationTemplateTokens] : `\${${token}}`;
});
}
getBlameInformationHover(documentUri: Uri, blameInformation: BlameInformation | string): MarkdownString {
if (typeof blameInformation === 'string') {
return new MarkdownString(blameInformation, true);
@@ -270,6 +270,10 @@ export class GitBlameController {
return blameInformation;
}
private _findDiffInformation(textEditor: TextEditor, ref: string): TextEditorDiffInformation | undefined {
return textEditor.diffInformation?.find(diff => diff.original && isGitUri(diff.original) && fromGitUri(diff.original).ref === ref);
}
@throttle
private async _updateTextEditorBlameInformation(textEditor: TextEditor | undefined): Promise<void> {
if (!textEditor?.diffInformation || textEditor !== window.activeTextEditor) {
@@ -297,9 +301,7 @@ export class GitBlameController {
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');
const diffInformationWorkingTreeAndIndex = this._findDiffInformation(textEditor, 'HEAD');
// Working tree + index diff information is present and it is stale
if (diffInformationWorkingTreeAndIndex && diffInformationWorkingTreeAndIndex.isStale) {
@@ -313,9 +315,7 @@ export class GitBlameController {
}
} else {
// Working tree diff information
const diffInformationWorkingTree = textEditor.diffInformation
.filter(diff => diff.original && isGitUri(diff.original))
.find(diff => fromGitUri(diff.original!).ref === '');
const diffInformationWorkingTree = this._findDiffInformation(textEditor, '');
// Working tree diff information is not present or it is stale
if (!diffInformationWorkingTree || diffInformationWorkingTree.isStale) {
@@ -323,9 +323,7 @@ export class GitBlameController {
}
// Working tree + index diff information
const diffInformationWorkingTreeAndIndex = textEditor.diffInformation
.filter(diff => diff.original && isGitUri(diff.original))
.find(diff => fromGitUri(diff.original!).ref === 'HEAD');
const diffInformationWorkingTreeAndIndex = this._findDiffInformation(textEditor, 'HEAD');
// Working tree + index diff information is present and it is stale
if (diffInformationWorkingTreeAndIndex && diffInformationWorkingTreeAndIndex.isStale) {
@@ -469,7 +467,7 @@ class GitBlameEditorDecoration {
const decorations = blameInformation.map(blame => {
const contentText = typeof blame.blameInformation === 'string'
? blame.blameInformation
: formatBlameInformation(template, blame.blameInformation);
: this._controller.formatBlameInformationMessage(template, blame.blameInformation);
const hoverMessage = this._controller.getBlameInformationHover(textEditor.document.uri, blame.blameInformation);
return this._createDecoration(blame.lineNumber, contentText, hoverMessage);
@@ -575,7 +573,7 @@ class GitBlameStatusBarItem {
this._statusBarItem.tooltip = this._controller.getBlameInformationHover(textEditor.document.uri, blameInformation[0].blameInformation);
this._statusBarItem.command = undefined;
} else {
this._statusBarItem.text = formatBlameInformation(template, blameInformation[0].blameInformation);
this._statusBarItem.text = this._controller.formatBlameInformationMessage(template, blameInformation[0].blameInformation);
this._statusBarItem.tooltip = this._controller.getBlameInformationHover(textEditor.document.uri, blameInformation[0].blameInformation);
this._statusBarItem.command = {
title: l10n.t('View Commit'),

View File

@@ -14,7 +14,7 @@ import { Model } from './model';
import { GitResourceGroup, Repository, Resource, ResourceGroupType } from './repository';
import { DiffEditorSelectionHunkToolbarContext, applyLineChanges, getModifiedRange, intersectDiffWithRange, invertLineChange, toLineRanges } from './staging';
import { fromGitUri, toGitUri, isGitUri, toMergeUris, toMultiFileDiffEditorUris } from './uri';
import { dispose, grep, isDefined, isDescendant, pathEquals, relativePath } from './util';
import { dispose, grep, isDefined, isDescendant, pathEquals, relativePath, truncate } from './util';
import { GitTimelineItem } from './timelineProvider';
import { ApiRepository } from './api/api1';
import { getRemoteSourceActions, pickRemoteSource } from './remoteSource';
@@ -3981,8 +3981,8 @@ export class CommandCenter {
const commitParentId = commit.parents.length > 0 ? commit.parents[0] : `${commit.hash}^`;
const changes = await repository.diffBetween(commitParentId, commit.hash);
const title = `${item.shortRef} - ${commit.message}`;
const multiDiffSourceUri = toGitUri(Uri.file(repository.root), commit.hash, { scheme: 'git-commit' });
const title = `${item.shortRef} - ${truncate(commit.message)}`;
const multiDiffSourceUri = Uri.from({ scheme: 'scm-history-item', path: `${repository.root}/${commitParentId}..${commit.hash}` });
const resources: { originalUri: Uri | undefined; modifiedUri: Uri | undefined }[] = [];
for (const change of changes) {
@@ -4243,14 +4243,14 @@ export class CommandCenter {
// TODO@lszomoru - handle the case when historyItem2 is the first commit in the repository
if (!historyItem2) {
const commit = await repository.getCommit(historyItem1.id);
title = `${historyItem1.id.substring(0, 8)} - ${commit.message}`;
title = `${historyItem1.id.substring(0, 8)} - ${truncate(commit.message)}`;
historyItemParentId = historyItem1.parentIds.length > 0 ? historyItem1.parentIds[0] : `${historyItem1.id}^`;
} else {
title = l10n.t('All Changes ({0} ↔ {1})', historyItem2.id.substring(0, 8), historyItem1.id.substring(0, 8));
historyItemParentId = historyItem2.parentIds.length > 0 ? historyItem2.parentIds[0] : `${historyItem2.id}^`;
}
const multiDiffSourceUri = toGitUri(Uri.file(repository.root), `${historyItemParentId}..${historyItem1.id}`, { scheme: 'git-commit', });
const multiDiffSourceUri = Uri.from({ scheme: 'scm-history-item', path: `${repository.root}/${historyItemParentId}..${historyItem1.id}` });
await this._viewChanges(repository, historyItem1.id, historyItemParentId, multiDiffSourceUri, title);
}
@@ -4302,10 +4302,10 @@ export class CommandCenter {
}
const commit = await repository.getCommit(historyItemId);
const title = `${historyItemId.substring(0, 8)} - ${commit.message}`;
const title = `${historyItemId.substring(0, 8)} - ${truncate(commit.message)}`;
const historyItemParentId = commit.parents.length > 0 ? commit.parents[0] : `${historyItemId}^`;
const multiDiffSourceUri = toGitUri(Uri.file(repository.root), `${historyItemParentId}..${historyItemId}`, { scheme: 'git-commit', });
const multiDiffSourceUri = Uri.from({ scheme: 'scm-history-item', path: `${repository.root}/${historyItemParentId}..${historyItemId}` });
const changes = await repository.diffBetween(historyItemParentId, historyItemId);
const resources = changes.map(c => toMultiFileDiffEditorUris(c, historyItemParentId, historyItemId));

View File

@@ -288,6 +288,10 @@ export function detectUnicodeEncoding(buffer: Buffer): Encoding | null {
return null;
}
export function truncate(value: string, maxLength = 20): string {
return value.length <= maxLength ? value : `${value.substring(0, maxLength)}\u2026`;
}
function normalizePath(path: string): string {
// Windows & Mac are currently being handled
// as case insensitive file systems in VS Code.