8 Commits

Author SHA1 Message Date
Eric Amodio
0160e064be Preps v4.1-beta.2 2017-06-12 12:13:48 -04:00
Eric Amodio
76961d6697 Fixes #33 - escape commit message 2017-06-12 12:13:48 -04:00
Eric Amodio
cc827f4711 Adds more notes on copy commands 2017-06-12 12:13:48 -04:00
Eric Amodio
6f3441a9e7 Adds default date format 2017-06-12 12:13:48 -04:00
Eric Amodio
64ae82075e Cleans up some duplicate code 2017-06-12 12:13:48 -04:00
Eric Amodio
5624567daa Fixes regression with code lens 2017-06-12 12:13:48 -04:00
Eric Amodio
c1c65127b7 Fixes extra newline in multiline commit messages 2017-06-11 17:56:07 -04:00
Eric Amodio
ce98f02706 Adds details hover to recent changes annotations 2017-06-11 17:43:53 -04:00
17 changed files with 181 additions and 59 deletions

View File

@@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
## [4.1.0-beta] - 2017-06-10
## [4.1.0-beta.2] - 2017-06-12
### Added
- Adds all-new recent changes annotations of the whole-file - annotates and highlights all of lines changed in the most recent commit
- Can customize the [layout](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#file-recent-changes-annotation-settings), as well as the [theme](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#theme-settings)
@@ -12,9 +12,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Improves performance
- Optimized git output parsing to increase speed and reduce memory usage
- Defers diff chunk parsing until it is actually required
- Adds `gitlens.defaultDateFormat` setting to specify how all absolute dates will be formatted by default
### Fixed
- Fixes excessive memory usage when parsing diffs
- Fixes extra newline in multiline commit messages
- Fixes (again) [#33](https://github.com/eamodio/vscode-gitlens/issues/33) - Commit messages can causes markdown formatting in hovers
## [4.0.1] - 2017-06-09
### Fixed

View File

@@ -20,8 +20,8 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
![Line Blame Annotation](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotation.png)
- Contains the author, date, and message of the line's most recent commit, by [default](#line-blame-annotation-settings)
- Also adds a `details` hover annotation to the current line annotation which provides more commit details ([optional](#line-blame-annotation-settings), on by default)
- Also adds a `changes` (diff) hover annotation to the current line annotation which provides **instant** access to the line's previous version ([optional](#line-blame-annotation-settings), on by default)
- Adds a `details` hover annotation to the current line annotation, which provides more commit details ([optional](#line-blame-annotation-settings), on by default)
- Adds a `changes` (diff) hover annotation to the current line annotation, which provides **instant** access to the line's previous version ([optional](#line-blame-annotation-settings), on by default)
![Line Blame Annotations](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotations.png)
@@ -30,7 +30,9 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
![File Blame Annotation](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-file-blame-annotations.png)
- Choose between `gutter` (default) and `hover` [annotation styles](#file-blame-annotation-settings)
- Contains the commit message and date, by [default](#file-blame-annotation-settings)
- Also adds a `details` hover annotation to the line's annotation which provides more commit details ([optional](#file-blame-annotation-settings), on by default)
- Adds a `details` hover annotation to the line's annotation, which provides more commit details ([optional](#file-blame-annotation-settings), on by default)
- Adds a `heatmap` (age) indicator to the gutter annotations (on right edge by [default](#file-blame-annotation-settings)), which provides an easy, at-a-glance way to tell the age of a line ([optional](#file-blame-annotation-settings), on by default)
- Indicator ranges from bright yellow (newer) to dark brown (older)
- Adds [customizable](#status-bar-settings) **blame information** about the current line to the **status bar** ([optional](#status-bar-settings), on by default)
@@ -57,7 +59,8 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
- Adds on-demand, [customizable](#file-recent-changes-annotation-settings) and [themeable](#theme-settings), **recent changes annotations** of the whole file
- Highlights all of lines changed in the most recent commit
- Also adds a `changes` (diff) hover annotation to the current line annotation which provides **instant** access to the line's previous version ([optional](#file-recent-changes-annotation-settings), on by default)
- Adds a `details` hover annotation to each line, which provides more commit details ([optional](#file-blame-annotation-settings), on by default)
- Adds a `changes` (diff) hover annotation to each line, which provides **instant** access to the line's previous version ([optional](#file-recent-changes-annotation-settings), on by default)
- Adds `Toggle Recent File Changes Annotations` command (`gitlens.toggleFileRecentChanges`) to toggle the recent changes annotations on and off
@@ -192,9 +195,9 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
### And More
- Adds a `Copy Commit ID to Clipboard` command (`gitlens.copyShaToClipboard`) to copy the commit id (sha) of the active line to the clipboard
- Adds a `Copy Commit ID to Clipboard` command (`gitlens.copyShaToClipboard`) to copy the commit id (sha) of the active line to the clipboard or from the most recent commit to the current branch, if there is no active editor
- Adds a `Copy Commit Message to Clipboard` command (`gitlens.copyMessageToClipboard`) to copy the commit message of the active line to the clipboard
- Adds a `Copy Commit Message to Clipboard` command (`gitlens.copyMessageToClipboard`) to copy the commit message of the active line to the clipboard or from the most recent commit to the current branch, if there is no active editor
- Adds a `Open Changed Files` command (`gitlens.openChangedFiles`) to open any files with working tree changes
@@ -216,6 +219,7 @@ GitLens is highly customizable and provides many configuration settings to allow
|Name | Description
|-----|------------
|`gitlens.defaultDateFormat`|Specifies how all absolute dates will be formatted by default\nSee https://momentjs.com/docs/#/displaying/format/ for valid formats
|`gitlens.insiders`|Opts into the insiders channel -- provides access to upcoming features
|`gitlens.outputLevel`|Specifies how much (if any) output will be sent to the GitLens output channel
@@ -257,7 +261,8 @@ GitLens is highly customizable and provides many configuration settings to allow
|Name | Description
|-----|------------
|`gitlens.recentChanges.file.lineHighlight.locations`|Specifies where the highlights of the recently changed lines will be shown<br />`gutter` - adds a gutter glyph<br />`line` - adds a full-line highlight background color<br />`overviewRuler` - adds a decoration to the overviewRuler (scroll bar)
|`gitlens.annotations.file.recentChanges.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotations
|`gitlens.annotations.file.recentChanges.hover.details`|Specifies whether or not to provide a commit details hover annotation
|`gitlens.annotations.file.recentChanges.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation
|`gitlens.annotations.file.recentChanges.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
### Code Lens Settings

View File

@@ -1,6 +1,6 @@
{
"name": "gitlens",
"version": "4.1.0-beta",
"version": "4.1.0-beta.2",
"author": {
"name": "Eric Amodio",
"email": "eamodio@gmail.com"
@@ -122,10 +122,15 @@
"default": true,
"description": "Specifies whether or not to trigger hover annotations over the whole line"
},
"gitlens.annotations.file.recentChanges.hover.details": {
"type": "boolean",
"default": true,
"description": "Specifies whether or not to provide a commit details hover annotation"
},
"gitlens.annotations.file.recentChanges.hover.changes": {
"type": "boolean",
"default": true,
"description": "Specifies whether or not to provide a changes (diff) hover annotations"
"description": "Specifies whether or not to provide a changes (diff) hover annotation"
},
"gitlens.annotations.file.recentChanges.hover.wholeLine": {
"type": "boolean",
@@ -397,6 +402,11 @@
"default": false,
"description": "Specifies whether or not to show debug information in code lens"
},
"gitlens.defaultDateFormat": {
"type": "string",
"default": null,
"description": "Specifies how all absolute dates will be formatted by default\nSee https://momentjs.com/docs/#/displaying/format/ for valid formats"
},
"gitlens.statusBar.enabled": {
"type": "boolean",
"default": true,

View File

@@ -59,8 +59,8 @@ export class Annotations {
} as DecorationOptions;
}
static detailsHover(commit: GitCommit): DecorationOptions {
const message = CommitFormatter.toHoverAnnotation(commit);
static detailsHover(commit: GitCommit, dateFormat: string | null): DecorationOptions {
const message = CommitFormatter.toHoverAnnotation(commit, dateFormat);
return {
hoverMessage: message
} as DecorationOptions;
@@ -127,9 +127,9 @@ export class Annotations {
} as IRenderOptions;
}
static hover(commit: GitCommit, renderOptions: IRenderOptions, heatmap: boolean): DecorationOptions {
static hover(commit: GitCommit, renderOptions: IRenderOptions, heatmap: boolean, dateFormat: string | null): DecorationOptions {
return {
hoverMessage: CommitFormatter.toHoverAnnotation(commit),
hoverMessage: CommitFormatter.toHoverAnnotation(commit, dateFormat),
renderOptions: heatmap ? { before: { ...renderOptions.before } } : undefined
} as DecorationOptions;
}

View File

@@ -25,7 +25,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
}, {} as { [token: string]: ICommitFormatOptions });
const options: ICommitFormatOptions = {
dateFormat: cfg.dateFormat,
dateFormat: cfg.dateFormat === null ? this._config.defaultDateFormat : cfg.dateFormat,
tokenOptions: tokenOptions
};
@@ -33,6 +33,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
const offset = this.uri.offset;
let previousLine: string | undefined = undefined;
const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap);
const dateFormat = this._config.defaultDateFormat;
const decorations: DecorationOptions[] = [];
@@ -58,7 +59,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
decorations.push(gutter);
if (cfg.hover.details) {
const details = Annotations.detailsHover(commit);
const details = Annotations.detailsHover(commit, dateFormat);
details.range = cfg.hover.wholeLine
? this.editor.document.validateRange(new Range(line, 0, line, endOfLineIndex))
: gutter.range;

View File

@@ -18,6 +18,7 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
const now = moment();
const offset = this.uri.offset;
const renderOptions = Annotations.hoverRenderOptions(this._config.theme, cfg.heatmap);
const dateFormat = this._config.defaultDateFormat;
const decorations: DecorationOptions[] = [];
@@ -27,7 +28,7 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
const line = l.line + offset;
const hover = Annotations.hover(commit, renderOptions, cfg.heatmap.enabled);
const hover = Annotations.hover(commit, renderOptions, cfg.heatmap.enabled, dateFormat);
const endIndex = cfg.wholeLine ? endOfLineIndex : this.editor.document.lineAt(line).firstNonWhitespaceCharacterIndex;
hover.range = this.editor.document.validateRange(new Range(line, 0, line, endIndex));

View File

@@ -21,6 +21,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
if (diff === undefined) return false;
const cfg = this._config.annotations.file.recentChanges;
const dateFormat = this._config.defaultDateFormat;
const decorators: DecorationOptions[] = [];
@@ -34,15 +35,27 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
if (change.state === 'unchanged') continue;
let endingIndex = 0;
if (cfg.hover.details || cfg.hover.changes) {
endingIndex = cfg.hover.wholeLine ? endOfLineIndex : this.editor.document.lineAt(count).firstNonWhitespaceCharacterIndex;
}
const range = this.editor.document.validateRange(new Range(new Position(count, 0), new Position(count, endingIndex)));
if (cfg.hover.details) {
decorators.push({
hoverMessage: CommitFormatter.toHoverAnnotation(commit, dateFormat),
range: range
} as DecorationOptions);
}
let message: string | undefined = undefined;
if (cfg.hover.changes) {
message = CommitFormatter.toHoverDiff(commit, chunk.previous[count], change);
endingIndex = cfg.hover.wholeLine ? endOfLineIndex : this.editor.document.lineAt(count).firstNonWhitespaceCharacterIndex;
}
decorators.push({
hoverMessage: message,
range: this.editor.document.validateRange(new Range(new Position(count, 0), new Position(count, endingIndex)))
range: range
} as DecorationOptions);
}
}

View File

@@ -21,16 +21,16 @@ export * from './commands/openInRemote';
export * from './commands/openRepoInRemote';
export * from './commands/resetSuppressedWarnings';
export * from './commands/showBlameHistory';
export * from './commands/showCommitSearch';
export * from './commands/showFileBlame';
export * from './commands/showFileHistory';
export * from './commands/showLastQuickPick';
export * from './commands/showLineBlame';
export * from './commands/showQuickBranchHistory';
export * from './commands/showQuickCommitDetails';
export * from './commands/showQuickCommitFileDetails';
export * from './commands/showCommitSearch';
export * from './commands/showQuickFileHistory';
export * from './commands/showQuickBranchHistory';
export * from './commands/showQuickCurrentBranchHistory';
export * from './commands/showQuickFileHistory';
export * from './commands/showQuickRepoStatus';
export * from './commands/showQuickStashList';
export * from './commands/stashApply';

View File

@@ -216,7 +216,7 @@ export interface IConfig {
file: {
gutter: {
format: string;
dateFormat: string;
dateFormat: string | null;
compact: boolean;
heatmap: {
enabled: boolean;
@@ -237,6 +237,7 @@ export interface IConfig {
recentChanges: {
hover: {
details: boolean;
changes: boolean;
wholeLine: boolean;
};
@@ -251,7 +252,7 @@ export interface IConfig {
trailing: {
format: string;
dateFormat: string;
dateFormat: string | null;
hover: {
changes: boolean;
details: boolean;
@@ -300,12 +301,14 @@ export interface IConfig {
debug: boolean;
};
defaultDateFormat: string | null;
statusBar: {
enabled: boolean;
alignment: 'left' | 'right';
command: StatusBarCommand;
format: string;
dateFormat: string;
dateFormat: string | null;
};
strings: {

View File

@@ -291,7 +291,7 @@ export class CurrentLineController extends Disposable {
showDetailsInStartingWhitespace = true;
}
const decoration = Annotations.trailing(commit, cfgAnnotations.format, cfgAnnotations.dateFormat, this._config.theme);
const decoration = Annotations.trailing(commit, cfgAnnotations.format, cfgAnnotations.dateFormat === null ? this._config.defaultDateFormat : cfgAnnotations.dateFormat, this._config.theme);
decoration.range = editor.document.validateRange(new Range(line, endOfLineIndex, line, endOfLineIndex));
decorationOptions.push(decoration);
@@ -361,6 +361,16 @@ export class CurrentLineController extends Disposable {
}
case FileAnnotationType.RecentChanges: {
const cfgChanges = this._config.annotations.file.recentChanges.hover;
if (cfgChanges.details) {
if (cfgChanges.wholeLine) {
// Avoid double annotations if we are showing the whole-file hover blame annotations
showDetails = false;
}
else {
showDetailsInStartingWhitespace = false;
}
}
if (cfgChanges.changes) {
if (cfgChanges.wholeLine) {
// Avoid double annotations if we are showing the whole-file hover blame annotations
@@ -385,7 +395,7 @@ export class CurrentLineController extends Disposable {
// I have no idea why I need this protection -- but it happens
if (editor.document === undefined) return;
const decoration = Annotations.detailsHover(logCommit || commit);
const decoration = Annotations.detailsHover(logCommit || commit, this._config.defaultDateFormat);
decoration.range = editor.document.validateRange(new Range(line, showDetailsStartIndex, line, endOfLineIndex));
decorationOptions.push(decoration);
@@ -419,7 +429,7 @@ export class CurrentLineController extends Disposable {
const cfg = this._config.statusBar;
if (!cfg.enabled || this._statusBarItem === undefined) return;
this._statusBarItem.text = `$(git-commit) ${CommitFormatter.fromTemplate(cfg.format, commit, cfg.dateFormat)}`;
this._statusBarItem.text = `$(git-commit) ${CommitFormatter.fromTemplate(cfg.format, commit, cfg.dateFormat === null ? this._config.defaultDateFormat : cfg.dateFormat)}`;
switch (cfg.command) {
case StatusBarCommand.BlameAnnotate:

View File

@@ -21,8 +21,8 @@ import { CodeLensLocations, IConfig, LineHighlightLocations } from './configurat
import { ApplicationInsightsKey, ExtensionKey, QualifiedExtensionId, WorkspaceState } from './constants';
import { CurrentLineController, LineAnnotationType } from './currentLineController';
import { GitContentProvider } from './gitContentProvider';
import { GitContextTracker, GitService } from './gitService';
import { GitRevisionCodeLensProvider } from './gitRevisionCodeLensProvider';
import { GitContextTracker, GitService } from './gitService';
import { Logger } from './logger';
import { Messages, SuppressedKeys } from './messages';
import { Telemetry } from './telemetry';
@@ -270,6 +270,8 @@ async function notifyOnNewGitLensVersion(context: ExtensionContext, version: str
const [major, minor] = version.split('.');
const [prevMajor, prevMinor] = previousVersion.split('.');
if (major === prevMajor && minor === prevMinor) return;
// Don't notify on downgrades
if (major < prevMajor || (major === prevMajor && minor < prevMinor)) return;
await Messages.showUpdateMessage(version);
}

View File

@@ -4,6 +4,9 @@ import { GitCommit } from '../models/commit';
import { GitDiffLine } from '../models/diff';
import * as moment from 'moment';
const escapeMarkdownRegEx = /[`\>\#\*\_\-\+\.]/g;
// const sampleMarkdown = '## message `not code` *not important* _no underline_ \n> don\'t quote me \n- don\'t list me \n+ don\'t list me \n1. don\'t list me \nnot h1 \n=== \nnot h2 \n---\n***\n---\n___';
export interface ICommitFormatOptions {
dateFormat?: string | null;
tokenOptions?: {
@@ -17,9 +20,18 @@ export interface ICommitFormatOptions {
export class CommitFormatter {
private _commit: GitCommit;
private _options: ICommitFormatOptions;
constructor(private commit: GitCommit, options?: ICommitFormatOptions) {
constructor(commit: GitCommit, options?: ICommitFormatOptions) {
this.reset(commit, options);
}
reset(commit: GitCommit, options?: ICommitFormatOptions) {
this._commit = commit;
if (options === undefined && this._options !== undefined) return;
options = options || {};
if (options.tokenOptions == null) {
options.tokenOptions = {};
@@ -33,31 +45,31 @@ export class CommitFormatter {
}
get ago() {
const ago = moment(this.commit.date).fromNow();
const ago = moment(this._commit.date).fromNow();
return this._padOrTruncate(ago, this._options.tokenOptions!.ago);
}
get author() {
const author = this.commit.author;
const author = this._commit.author;
return this._padOrTruncate(author, this._options.tokenOptions!.author);
}
get authorAgo() {
const authorAgo = `${this.commit.author}, ${moment(this.commit.date).fromNow()}`;
const authorAgo = `${this._commit.author}, ${moment(this._commit.date).fromNow()}`;
return this._padOrTruncate(authorAgo, this._options.tokenOptions!.authorAgo);
}
get date() {
const date = moment(this.commit.date).format(this._options.dateFormat!);
const date = moment(this._commit.date).format(this._options.dateFormat!);
return this._padOrTruncate(date, this._options.tokenOptions!.date);
}
get id() {
return this.commit.shortSha;
return this._commit.shortSha;
}
get message() {
const message = this.commit.isUncommitted ? 'Uncommitted change' : this.commit.message;
const message = this._commit.isUncommitted ? 'Uncommitted change' : this._commit.message;
return this._padOrTruncate(message, this._options.tokenOptions!.message);
}
@@ -113,6 +125,18 @@ export class CommitFormatter {
return s;
}
private static _formatter: CommitFormatter | undefined = undefined;
static fromCommit(commit: GitCommit, options?: ICommitFormatOptions): CommitFormatter {
if (CommitFormatter._formatter === undefined) {
CommitFormatter._formatter = new CommitFormatter(commit, options);
}
else {
CommitFormatter._formatter.reset(commit, options);
}
return CommitFormatter._formatter;
}
static fromTemplate(template: string, commit: GitCommit, dateFormat: string | null): string;
static fromTemplate(template: string, commit: GitCommit, options?: ICommitFormatOptions): string;
static fromTemplate(template: string, commit: GitCommit, dateFormatOrOptions?: string | null | ICommitFormatOptions): string;
@@ -137,8 +161,22 @@ export class CommitFormatter {
return Strings.interpolate(template, new CommitFormatter(commit, options));
}
static toHoverAnnotation(commit: GitCommit, dateFormat: string = 'MMMM Do, YYYY h:MMa'): string | string[] {
const message = commit.isUncommitted ? '' : `\n\n> ${commit.message.replace(/\n/g, '\n>\n> ')}`;
static toHoverAnnotation(commit: GitCommit, dateFormat: string | null): string | string[] {
if (dateFormat === null) {
dateFormat = 'MMMM Do, YYYY h:MMa';
}
let message = '';
if (!commit.isUncommitted) {
message = commit.message
// Escape markdown
.replace(escapeMarkdownRegEx, '\\$&')
// Escape markdown header (since the above regex won't match it)
.replace(/^===/gm, '\u200b===')
// Keep under the same block-quote
.replace(/\n/g, ' \n');
message = `\n\n> ${message}`;
}
return `\`${commit.shortSha}\` &nbsp; __${commit.author}__, ${moment(commit.date).fromNow()} &nbsp; _(${moment(commit.date).format(dateFormat)})_${message}`;
}

View File

@@ -102,6 +102,28 @@ export class GitUri extends Uri {
const uri = Uri.file(path.resolve(repoPath, original ? status.originalFileName || status.fileName : status.fileName));
return new GitUri(uri, repoPathOrCommit);
}
static getDirectory(fileName: string): string {
const directory: string | undefined = GitService.normalizePath(path.dirname(fileName));
return (!directory || directory === '.') ? '' : directory;
}
static getFormattedPath(fileNameOrUri: string | Uri, separator: string = ' \u00a0\u2022\u00a0 '): string {
let fileName: string;
if (fileNameOrUri instanceof Uri) {
if (fileNameOrUri instanceof GitUri) return fileNameOrUri.getFormattedPath(separator);
fileName = fileNameOrUri.fsPath;
}
else {
fileName = fileNameOrUri;
}
const directory = GitUri.getDirectory(fileName);
return !directory
? path.basename(fileName)
: `${path.basename(fileName)}${separator}${directory}`;
}
}
export interface IGitCommitInfo {

View File

@@ -1,5 +1,6 @@
'use strict';
import { Uri } from 'vscode';
import { GitUri } from '../gitUri';
import * as path from 'path';
export interface GitStatus {
@@ -32,6 +33,14 @@ export class GitStatusFile implements IGitStatusFile {
this.originalFileName = originalFileName;
}
getFormattedDirectory(includeOriginal: boolean = false): string {
return GitStatusFile.getFormattedDirectory(this, includeOriginal);
}
getFormattedPath(separator: string = ' \u00a0\u2022\u00a0 '): string {
return GitUri.getFormattedPath(this.fileName, separator);
}
getIcon() {
return getGitStatusIcon(this.status);
}
@@ -39,6 +48,13 @@ export class GitStatusFile implements IGitStatusFile {
get Uri(): Uri {
return Uri.file(path.resolve(this.repoPath, this.fileName));
}
static getFormattedDirectory(status: IGitStatusFile, includeOriginal: boolean = false): string {
const directory = GitUri.getDirectory(status.fileName);
return (includeOriginal && status.status === 'R' && status.originalFileName)
? `${directory} \u00a0\u2190\u00a0 ${status.originalFileName}`
: directory;
}
}
const statusOcticonsMap = {

View File

@@ -73,7 +73,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
let blame: GitBlame | undefined;
if (languageLocations.locations.length === 1 && languageLocations.locations.includes(CodeLensLocations.Document)) {
blame = await blamePromise;
if (blame === undefined || !blame.lines.length) return lenses;
if (blame === undefined || blame.lines.length === 0) return lenses;
}
else {
const values = await Promise.all([
@@ -82,7 +82,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
]);
blame = values[0] as GitBlame;
if (blame === undefined || !blame.lines.length) return lenses;
if (blame === undefined || blame.lines.length === 0) return lenses;
const symbols = values[1] as SymbolInformation[];
Logger.log('GitCodeLensProvider.provideCodeLenses:', `${symbols.length} symbol(s) found`);

View File

@@ -486,7 +486,7 @@ export class GitService extends Disposable {
const authors: Map<string, GitAuthor> = new Map();
const commits: Map<string, GitBlameCommit> = new Map();
for (const c of blame.commits.values()) {
if (!shas.has(c.sha)) return;
if (!shas.has(c.sha)) continue;
const commit = new GitBlameCommit(c.repoPath, c.sha, c.fileName, c.author, c.date, c.message,
c.lines.filter(l => l.line >= range.start.line && l.line <= range.end.line), c.originalFileName, c.previousSha, c.previousFileName);
@@ -521,13 +521,14 @@ export class GitService extends Disposable {
if (blame === undefined) return undefined;
const commitCount = blame.commits.size;
const dateFormat = this.config.defaultDateFormat === null ? 'MMMM Do, YYYY h:MMa' : this.config.defaultDateFormat;
const locations: Location[] = [];
Iterables.forEach(blame.commits.values(), (c, i) => {
if (c.isUncommitted) return;
const decoration = `\u2937 ${c.author}, ${moment(c.date).format('MMMM Do, YYYY h:MMa')}`;
const uri = GitService.toReferenceGitContentUri(c, i + 1, commitCount, c.originalFileName, decoration);
const decoration = `\u2937 ${c.author}, ${moment(c.date).format(dateFormat)}`;
const uri = GitService.toReferenceGitContentUri(c, i + 1, commitCount, c.originalFileName, decoration, dateFormat);
locations.push(new Location(uri, new Position(0, 0)));
if (c.sha === selectedSha) {
locations.push(new Location(uri, new Position((line || 0) + 1, 0)));
@@ -858,13 +859,14 @@ export class GitService extends Disposable {
if (log === undefined) return undefined;
const commitCount = log.commits.size;
const dateFormat = this.config.defaultDateFormat === null ? 'MMMM Do, YYYY h:MMa' : this.config.defaultDateFormat;
const locations: Location[] = [];
Iterables.forEach(log.commits.values(), (c, i) => {
if (c.isUncommitted) return;
const decoration = `\u2937 ${c.author}, ${moment(c.date).format('MMMM Do, YYYY h:MMa')}`;
const uri = GitService.toReferenceGitContentUri(c, i + 1, commitCount, c.originalFileName, decoration);
const decoration = `\u2937 ${c.author}, ${moment(c.date).format(dateFormat)}`;
const uri = GitService.toReferenceGitContentUri(c, i + 1, commitCount, c.originalFileName, decoration, dateFormat);
locations.push(new Location(uri, new Position(0, 0)));
if (c.sha === selectedSha) {
locations.push(new Location(uri, new Position((line || 0) + 1, 0)));
@@ -1086,11 +1088,11 @@ export class GitService extends Disposable {
return Uri.parse(`${DocumentSchemes.GitLensGit}:${path.basename(fileName!, extension)}:${shortSha}${extension}?${JSON.stringify(data)}`);
}
static toReferenceGitContentUri(commit: GitCommit, index: number, commitCount: number, originalFileName?: string, decoration?: string): Uri {
return GitService._toReferenceGitContentUri(commit, DocumentSchemes.GitLensGit, commitCount, GitService._toGitUriData(commit, index, originalFileName, decoration));
static toReferenceGitContentUri(commit: GitCommit, index: number, commitCount: number, originalFileName: string | undefined, decoration: string, dateFormat: string | null): Uri {
return GitService._toReferenceGitContentUri(commit, DocumentSchemes.GitLensGit, commitCount, GitService._toGitUriData(commit, index, originalFileName, decoration), dateFormat);
}
private static _toReferenceGitContentUri(commit: GitCommit, scheme: DocumentSchemes, commitCount: number, data: IGitUriData) {
private static _toReferenceGitContentUri(commit: GitCommit, scheme: DocumentSchemes, commitCount: number, data: IGitUriData, dateFormat: string | null) {
const pad = (n: number) => ('0000000' + n).slice(-('' + commitCount).length);
const ext = path.extname(data.fileName);
const uriPath = `${path.relative(commit.repoPath, data.fileName.slice(0, -ext.length))}/${commit.shortSha}${ext}`;
@@ -1100,8 +1102,12 @@ export class GitService extends Disposable {
message = message.substring(0, 49) + '\u2026';
}
if (dateFormat === null) {
dateFormat = 'MMMM Do, YYYY h:MMa';
}
// NOTE: Need to specify an index here, since I can't control the sort order -- just alphabetic or by file location
return Uri.parse(`${scheme}:${pad(data.index || 0)} \u2022 ${encodeURIComponent(message)} \u2022 ${moment(commit.date).format('MMM D, YYYY hh:MMa')} \u2022 ${encodeURIComponent(uriPath)}?${JSON.stringify(data)}`);
return Uri.parse(`${scheme}:${pad(data.index || 0)} \u2022 ${encodeURIComponent(message)} \u2022 ${moment(commit.date).format(dateFormat)} \u2022 ${encodeURIComponent(uriPath)}?${JSON.stringify(data)}`);
}
private static _toGitUriData<T extends IGitUriData>(commit: IGitUriData, index?: number, originalFileName?: string, decoration?: string): T {

View File

@@ -3,7 +3,7 @@ import { Arrays, Iterables } from '../system';
import { commands, QuickPickOptions, TextDocumentShowOptions, Uri, window } from 'vscode';
import { Commands, CopyMessageToClipboardCommandArgs, CopyShaToClipboardCommandArgs, DiffDirectoryCommandCommandArgs, DiffWithPreviousCommandArgs, Keyboard, KeyNoopCommand, Keys, ShowQuickCommitDetailsCommandArgs, StashApplyCommandArgs, StashDeleteCommandArgs } from '../commands';
import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, KeyCommandQuickPickItem, OpenFileCommandQuickPickItem, OpenFilesCommandQuickPickItem, QuickPickItem } from './common';
import { getGitStatusIcon, GitCommit, GitLog, GitLogCommit, GitService, GitStashCommit, GitStatusFileStatus, GitUri, IGitCommitInfo, IGitStatusFile, RemoteResource } from '../gitService';
import { getGitStatusIcon, GitCommit, GitLog, GitLogCommit, GitService, GitStashCommit, GitStatusFile, GitStatusFileStatus, GitUri, IGitCommitInfo, IGitStatusFile, RemoteResource } from '../gitService';
import { OpenRemotesCommandQuickPickItem } from './remotes';
import * as moment from 'moment';
import * as path from 'path';
@@ -19,15 +19,7 @@ export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickI
constructor(commit: GitCommit, status: IGitStatusFile) {
const icon = getGitStatusIcon(status.status);
let directory: string | undefined = GitService.normalizePath(path.dirname(status.fileName));
if (!directory || directory === '.') {
directory = '';
}
const description = (status.status === 'R' && status.originalFileName)
? `${directory} \u00a0\u2190\u00a0 ${status.originalFileName}`
: directory;
const description = GitStatusFile.getFormattedDirectory(status, true);
let sha;
let shortSha;