mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-01-13 17:23:11 -05:00
Adds new gitlens.showQuickFileHistory command
Adds new gitlens.showQuickRepoHistory command Adds gitlens.showQuickFileHistory option to the settings Removes git.viewFileHistory option Changes the gitlens.statusBar.command settings default to gitlens.showQuickFileHistory
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,6 +1,18 @@
|
||||
---
|
||||
## Release Notes
|
||||
|
||||
### 1.1.0
|
||||
|
||||
- Adds new `gitlens.showQuickFileHistory` command to show the file history in a quick-pick list (palette)
|
||||
- Adds new `gitlens.showQuickRepoHistory` command to show the repository history in a quick-pick list (palette)
|
||||
- Adds `gitlens.showQuickFileHistory` option to the `gitlens.codeLens.recentChange.command`, `gitlens.codeLens.authors.command`, and `gitlens.statusBar.command` settings
|
||||
- Removes `git.viewFileHistory` option from the `gitlens.codeLens.recentChange.command`, `gitlens.codeLens.authors.command`, and `gitlens.statusBar.command` settings
|
||||
- Changes the `gitlens.statusBar.command` settings default to `gitlens.showQuickFileHistory` instead of `gitlens.toggleBlame`
|
||||
|
||||
### 1.0.2
|
||||
|
||||
- Fixes [#16](https://github.com/eamodio/vscode-gitlens/issues/16) - incorrect 'Unable to find Git' message
|
||||
|
||||
### 1.0.0
|
||||
|
||||
- Adds support for git history (log)!
|
||||
|
||||
10
README.md
10
README.md
@@ -22,10 +22,6 @@ Provides Git CodeLens information (most recent commit, # of authors), on-demand
|
||||
|
||||

|
||||
|
||||
## Requirements
|
||||
|
||||
Must be using Git.
|
||||
|
||||
## Extension Settings
|
||||
|
||||
|Name | Description
|
||||
@@ -39,13 +35,13 @@ Must be using Git.
|
||||
|`gitlens.codeLens.locationCustomSymbols`|Specifies the set of document symbols to render active document CodeLens on. Must be a member of `SymbolKind`
|
||||
|`gitlens.codeLens.languageLocations`|Specifies where CodeLens will be rendered in the active document for the specified languages
|
||||
|`gitlens.codeLens.recentChange.enabled`|Specifies whether the recent change CodeLens is shown
|
||||
|`gitlens.codeLens.recentChange.command`|Specifies the command executed when the recent change CodeLens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `git.viewFileHistory` - opens a file history picker, which requires the Git History (git log) extension
|
||||
|`gitlens.codeLens.recentChange.command`|Specifies the command executed when the recent change CodeLens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `gitlens.showQuickFileHistory` - shows a file history picker
|
||||
|`gitlens.codeLens.authors.enabled`|Specifies whether the authors CodeLens is shown
|
||||
|`gitlens.codeLens.authors.command`|Specifies the command executed when the authors CodeLens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `git.viewFileHistory` - opens a file history picker, which requires the Git History (git log) extension
|
||||
|`gitlens.codeLens.authors.command`|Specifies the command executed when the authors CodeLens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `gitlens.showQuickFileHistory` - shows a file history picker
|
||||
|`gitlens.menus.fileDiff.enabled`|Specifies whether file-based diff commands will be added to the context menus
|
||||
|`gitlens.menus.lineDiff.enabled`|Specifies whether line-based diff commands will be added to the context menus
|
||||
|`gitlens.statusBar.enabled`|Specifies whether blame information is shown in the status bar
|
||||
|`gitlens.statusBar.command`|"Specifies the command executed when the blame status bar item is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `git.viewFileHistory` - opens a file history picker, which requires the Git History (git log) extension"
|
||||
|`gitlens.statusBar.command`|"Specifies the command executed when the blame status bar item is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `gitlens.showQuickFileHistory` - shows a file history picker
|
||||
|
||||
## Known Issues
|
||||
|
||||
|
||||
77
package.json
77
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gitlens",
|
||||
"version": "1.0.2",
|
||||
"version": "1.1.0",
|
||||
"author": {
|
||||
"name": "Eric Amodio",
|
||||
"email": "eamodio@gmail.com"
|
||||
@@ -162,9 +162,9 @@
|
||||
"gitlens.showBlameHistory",
|
||||
"gitlens.showFileHistory",
|
||||
"gitlens.diffWithPrevious",
|
||||
"git.viewFileHistory"
|
||||
"gitlens.showQuickFileHistory"
|
||||
],
|
||||
"description": "Specifies the command executed when the recent change CodeLens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `git.viewFileHistory` - opens a file history picker, which requires the Git History (git log) extension"
|
||||
"description": "Specifies the command executed when the recent change CodeLens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `gitlens.showQuickFileHistory` - shows a file history picker"
|
||||
},
|
||||
"gitlens.codeLens.authors.enabled": {
|
||||
"type": "boolean",
|
||||
@@ -179,9 +179,9 @@
|
||||
"gitlens.showBlameHistory",
|
||||
"gitlens.showFileHistory",
|
||||
"gitlens.diffWithPrevious",
|
||||
"git.viewFileHistory"
|
||||
"gitlens.showQuickFileHistory"
|
||||
],
|
||||
"description": "Specifies the command executed when the authors CodeLens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `git.viewFileHistory` - opens a file history picker, which requires the Git History (git log) extension"
|
||||
"description": "Specifies the command executed when the authors CodeLens is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `gitlens.showQuickFileHistory` - shows a file history picker"
|
||||
},
|
||||
"gitlens.statusBar.enabled": {
|
||||
"type": "boolean",
|
||||
@@ -190,16 +190,16 @@
|
||||
},
|
||||
"gitlens.statusBar.command": {
|
||||
"type": "string",
|
||||
"default": "gitlens.toggleBlame",
|
||||
"default": "gitlens.showQuickFileHistory",
|
||||
"enum": [
|
||||
"gitlens.toggleBlame",
|
||||
"gitlens.showBlameHistory",
|
||||
"gitlens.showFileHistory",
|
||||
"gitlens.diffWithPrevious",
|
||||
"gitlens.toggleCodeLens",
|
||||
"git.viewFileHistory"
|
||||
"gitlens.showQuickFileHistory"
|
||||
],
|
||||
"description": "Specifies the command executed when the blame status bar item is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `git.viewFileHistory` - opens a file history picker, which requires the Git History (git log) extension"
|
||||
"description": "Specifies the command executed when the blame status bar item is clicked. `gitlens.toggleBlame` - toggles blame annotations. `gitlens.showBlameHistory` - opens the blame history explorer. `gitlens.showFileHistory` - opens the file history explorer. `gitlens.diffWithPrevious` - compares the current checked-in file with the previous commit. `gitlens.showQuickFileHistory` - shows a file history picker"
|
||||
},
|
||||
"gitlens.menus.fileDiff.enabled": {
|
||||
"type": "boolean",
|
||||
@@ -281,58 +281,83 @@
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showBlameHistory",
|
||||
"title": "Open Git Blame History",
|
||||
"title": "Open Git Blame History Explorer",
|
||||
"category": "GitLens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showFileHistory",
|
||||
"title": "Open Git File History",
|
||||
"title": "Open File History Explorer",
|
||||
"category": "GitLens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickFileHistory",
|
||||
"title": "Show File History",
|
||||
"category": "GitLens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickRepoHistory",
|
||||
"title": "Show Repository History",
|
||||
"category": "GitLens"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
"explorer/context": [
|
||||
{
|
||||
"command": "gitlens.showQuickFileHistory",
|
||||
"when": "config.git.enabled",
|
||||
"group": "2_gitlens-file@1.0"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithPrevious",
|
||||
"alt": "gitlens.diffWithWorking",
|
||||
"when": "config.gitlens.menus.fileDiff.enabled && config.git.enabled",
|
||||
"group": "2_gitlens-file"
|
||||
"group": "2_gitlens-file@1.1"
|
||||
}
|
||||
],
|
||||
"editor/title": [
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "editorTextFocus && config.git.enabled",
|
||||
"group": "2_gitlens-blame"
|
||||
"group": "2_gitlens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickFileHistory",
|
||||
"when": "editorTextFocus && config.git.enabled",
|
||||
"group": "3_gitlens"
|
||||
}
|
||||
],
|
||||
"editor/context": [
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "editorTextFocus && config.git.enabled",
|
||||
"group": "2_gitlens"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.showQuickFileHistory",
|
||||
"when": "config.git.enabled",
|
||||
"group": "3_gitlens@1.0"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithWorking",
|
||||
"when": "editorTextFocus && config.gitlens.menus.lineDiff.enabled && config.git.enabled",
|
||||
"group": "3_gitlens-line@1.0"
|
||||
"group": "3_gitlens@1.1"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffLineWithPrevious",
|
||||
"when": "editorTextFocus && config.gitlens.menus.lineDiff.enabled && config.git.enabled",
|
||||
"group": "3_gitlens-line@1.1"
|
||||
"group": "3_gitlens@1.2"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithWorking",
|
||||
"alt": "gitlens.diffLineWithWorking",
|
||||
"when": "editorTextFocus && config.gitlens.menus.fileDiff.enabled && config.git.enabled",
|
||||
"group": "3_gitlens-file@1.0"
|
||||
"group": "3_gitlens@1.3"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.diffWithPrevious",
|
||||
"alt": "gitlens.diffLineWithPrevious",
|
||||
"when": "editorTextFocus && config.gitlens.menus.fileDiff.enabled && config.git.enabled",
|
||||
"group": "3_gitlens-file@1.1"
|
||||
},
|
||||
{
|
||||
"command": "gitlens.toggleBlame",
|
||||
"when": "editorTextFocus && config.git.enabled",
|
||||
"group": "2_gitlens-blame"
|
||||
"group": "3_gitlens@1.4"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -360,16 +385,16 @@
|
||||
"lodash.escaperegexp": "^4.1.2",
|
||||
"lodash.isequal": "^4.4.0",
|
||||
"lodash.once": "^4.1.1",
|
||||
"moment": "^2.16.0",
|
||||
"moment": "^2.17.0",
|
||||
"spawn-rx": "^2.0.6",
|
||||
"tmp": "^0.0.30"
|
||||
"tmp": "^0.0.31"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^3.1.2",
|
||||
"tslint": "^3.15.1",
|
||||
"typescript": "^2.0.9",
|
||||
"tslint": "^4.0.1",
|
||||
"typescript": "^2.0.10",
|
||||
"vscode": "^1.0.3",
|
||||
"@types/node": "^6.0.48",
|
||||
"@types/node": "^6.0.50",
|
||||
"@types/mocha": "^2.2.33",
|
||||
"@types/tmp": "^0.0.31"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Objects } from './system';
|
||||
import { Disposable, ExtensionContext, StatusBarAlignment, StatusBarItem, TextDocument, TextEditor, TextEditorSelectionChangeEvent, window, workspace } from 'vscode';
|
||||
import { TextDocumentComparer } from './comparers';
|
||||
import { IConfig, StatusBarCommand } from './configuration';
|
||||
import { WorkspaceState } from './constants';
|
||||
import GitProvider, { GitCommit, GitUri, IGitBlame } from './gitProvider';
|
||||
import * as moment from 'moment';
|
||||
|
||||
@@ -17,7 +16,7 @@ export default class BlameStatusBarController extends Disposable {
|
||||
private _uri: GitUri;
|
||||
private _useCaching: boolean;
|
||||
|
||||
constructor(private context: ExtensionContext, private git: GitProvider) {
|
||||
constructor(context: ExtensionContext, private git: GitProvider) {
|
||||
super(() => this.dispose());
|
||||
|
||||
this._onConfigure();
|
||||
@@ -50,11 +49,6 @@ export default class BlameStatusBarController extends Disposable {
|
||||
config.statusBar.command = StatusBarCommand.BlameAnnotate;
|
||||
}
|
||||
break;
|
||||
case StatusBarCommand.GitViewHistory:
|
||||
if (!this.context.workspaceState.get(WorkspaceState.HasGitHistoryExtension, false)) {
|
||||
config.statusBar.command = StatusBarCommand.ShowBlameHistory;
|
||||
}
|
||||
break;
|
||||
}
|
||||
this._statusBarItem.command = config.statusBar.command;
|
||||
|
||||
@@ -156,7 +150,7 @@ export default class BlameStatusBarController extends Disposable {
|
||||
case StatusBarCommand.ToggleCodeLens:
|
||||
this._statusBarItem.tooltip = 'Toggle Blame CodeLens';
|
||||
break;
|
||||
case StatusBarCommand.GitViewHistory:
|
||||
case StatusBarCommand.ShowQuickFileHistory:
|
||||
this._statusBarItem.tooltip = 'View Git File History';
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ export default class ShowFileHistoryCommand extends EditorCommand {
|
||||
|
||||
try {
|
||||
const locations = await this.git.getLogLocations(gitUri.fsPath, gitUri.sha, gitUri.repoPath, sha, line);
|
||||
if (!locations) return window.showWarningMessage(`Unable to show history. File is probably not under source control`);
|
||||
if (!locations) return window.showWarningMessage(`Unable to show file history. File is probably not under source control`);
|
||||
|
||||
return commands.executeCommand(BuiltInCommands.ShowReferences, uri, position, locations);
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error('[GitLens.ShowFileHistoryCommand]', 'getLogLocations', ex);
|
||||
return window.showErrorMessage(`Unable to show history. See output channel for more details`);
|
||||
return window.showErrorMessage(`Unable to show file history. See output channel for more details`);
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/commands/showQuickFileHistory.ts
Normal file
54
src/commands/showQuickFileHistory.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
import { Iterables } from '../system';
|
||||
import { commands, QuickPickItem, QuickPickOptions, TextEditor, TextEditorEdit, Uri, window } from 'vscode';
|
||||
import { EditorCommand } from './commands';
|
||||
import { Commands } from '../constants';
|
||||
import GitProvider, { GitCommit, GitUri } from '../gitProvider';
|
||||
import { Logger } from '../logger';
|
||||
import * as moment from 'moment';
|
||||
|
||||
class CommitQuickPickItem implements QuickPickItem {
|
||||
label: string;
|
||||
description: string;
|
||||
detail: string;
|
||||
|
||||
constructor(public commit: GitCommit) {
|
||||
this.label = `${commit.author}, ${moment(commit.date).fromNow()}`;
|
||||
this.description = `\u2022 ${commit.sha}`;
|
||||
this.detail = commit.message;
|
||||
}
|
||||
}
|
||||
|
||||
export default class ShowQuickFileHistoryCommand extends EditorCommand {
|
||||
constructor(private git: GitProvider) {
|
||||
super(Commands.ShowQuickFileHistory);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
|
||||
const gitUri = GitUri.fromUri(uri);
|
||||
|
||||
try {
|
||||
const log = await this.git.getLogForFile(gitUri.fsPath, gitUri.sha, gitUri.repoPath);
|
||||
if (!log) return window.showWarningMessage(`Unable to show file history. File is probably not under source control`);
|
||||
|
||||
const items = Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c));
|
||||
const commitPick = await window.showQuickPick(Array.from(items), <QuickPickOptions>{
|
||||
matchOnDescription: true,
|
||||
matchOnDetail: true
|
||||
});
|
||||
|
||||
if (commitPick) {
|
||||
return commands.executeCommand(Commands.DiffWithWorking, commitPick.commit.uri, commitPick.commit);
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error('[GitLens.ShowQuickFileHistoryCommand]', 'getLogLocations', ex);
|
||||
return window.showErrorMessage(`Unable to show file history. See output channel for more details`);
|
||||
}
|
||||
}
|
||||
}
|
||||
84
src/commands/showQuickRepoHistory.ts
Normal file
84
src/commands/showQuickRepoHistory.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
'use strict';
|
||||
import { Iterables } from '../system';
|
||||
import { commands, QuickPickItem, QuickPickOptions, TextEditor, TextEditorEdit, Uri, window } from 'vscode';
|
||||
import { EditorCommand } from './commands';
|
||||
import { Commands } from '../constants';
|
||||
import GitProvider, { GitCommit, GitUri } from '../gitProvider';
|
||||
import { Logger } from '../logger';
|
||||
import * as moment from 'moment';
|
||||
import * as path from 'path';
|
||||
|
||||
class CommitQuickPickItem implements QuickPickItem {
|
||||
label: string;
|
||||
description: string;
|
||||
detail: string;
|
||||
|
||||
constructor(public commit: GitCommit) {
|
||||
this.label = `${commit.author}, ${moment(commit.date).fromNow()}`;
|
||||
this.description = `\u2022 ${commit.sha} \u2014 ${commit.fileName}`;
|
||||
this.detail = commit.message;
|
||||
}
|
||||
}
|
||||
|
||||
class FileQuickPickItem implements QuickPickItem {
|
||||
label: string;
|
||||
description: string;
|
||||
detail: string;
|
||||
uri: GitUri;
|
||||
|
||||
constructor(commit: GitCommit, public fileName: string) {
|
||||
this.label = fileName;
|
||||
this.uri = GitUri.fromUri(Uri.file(path.resolve(commit.repoPath, fileName)));
|
||||
}
|
||||
}
|
||||
|
||||
export default class ShowQuickRepoHistoryCommand extends EditorCommand {
|
||||
constructor(private git: GitProvider) {
|
||||
super(Commands.ShowQuickRepoHistory);
|
||||
}
|
||||
|
||||
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri) {
|
||||
if (!(uri instanceof Uri)) {
|
||||
if (!editor.document) return undefined;
|
||||
uri = editor.document.uri;
|
||||
}
|
||||
|
||||
const gitUri = GitUri.fromUri(uri);
|
||||
|
||||
let repoPath = gitUri.repoPath;
|
||||
try {
|
||||
if (!repoPath) {
|
||||
repoPath = await this.git.getRepoPathFromFile(gitUri.fsPath);
|
||||
}
|
||||
|
||||
if (!repoPath) return window.showWarningMessage(`Unable to show repository history`);
|
||||
|
||||
const log = await this.git.getLogForRepo(repoPath);
|
||||
if (!log) return window.showWarningMessage(`Unable to show repository history`);
|
||||
|
||||
const items = Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c));
|
||||
const commitPick = await window.showQuickPick(Array.from(items), <QuickPickOptions>{
|
||||
matchOnDescription: true,
|
||||
matchOnDetail: true
|
||||
});
|
||||
|
||||
if (commitPick) {
|
||||
const items = commitPick.commit.fileName.split(', ').map(f => new FileQuickPickItem(commitPick.commit, f));
|
||||
const filePick = await window.showQuickPick(items, <QuickPickOptions>{
|
||||
matchOnDescription: true,
|
||||
matchOnDetail: true,
|
||||
placeHolder: `${commitPick.commit.author}, ${moment(commitPick.commit.date).fromNow()} \u2022 ${commitPick.commit.sha}`
|
||||
});
|
||||
|
||||
if (filePick) {
|
||||
const commit = new GitCommit(commitPick.commit.repoPath, commitPick.commit.sha, filePick.fileName, commitPick.commit.author, commitPick.commit.date, commitPick.commit.message, undefined, undefined, commitPick.commit.previousSha);
|
||||
commands.executeCommand(Commands.DiffWithWorking, filePick.uri, commit);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
Logger.error('[GitLens.ShowQuickRepoHistoryCommand]', 'getLogLocations', ex);
|
||||
return window.showErrorMessage(`Unable to show repository history. See output channel for more details`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,13 @@ export interface IBlameConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export type CodeLensCommand = 'gitlens.toggleBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' | 'gitlens.diffWithPrevious' | 'git.viewFileHistory';
|
||||
export type CodeLensCommand = 'gitlens.toggleBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' | 'gitlens.diffWithPrevious' | 'gitlens.showQuickFileHistory';
|
||||
export const CodeLensCommand = {
|
||||
BlameAnnotate: Commands.ToggleBlame as CodeLensCommand,
|
||||
ShowBlameHistory: Commands.ShowBlameHistory as CodeLensCommand,
|
||||
ShowFileHistory: Commands.ShowFileHistory as CodeLensCommand,
|
||||
DiffWithPrevious: Commands.DiffWithPrevious as CodeLensCommand,
|
||||
GitViewHistory: 'git.viewFileHistory' as CodeLensCommand
|
||||
ShowQuickFileHistory: Commands.ShowQuickFileHistory as CodeLensCommand
|
||||
};
|
||||
|
||||
export type CodeLensLocation = 'all' | 'document+containers' | 'document' | 'custom' | 'none';
|
||||
@@ -61,14 +61,14 @@ export interface ICodeLensesConfig {
|
||||
authors: ICodeLensConfig;
|
||||
}
|
||||
|
||||
export type StatusBarCommand = 'gitlens.toggleBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' | 'gitlens.toggleCodeLens' | 'gitlens.diffWithPrevious' | 'git.viewFileHistory';
|
||||
export type StatusBarCommand = 'gitlens.toggleBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' | 'gitlens.toggleCodeLens' | 'gitlens.diffWithPrevious' | 'gitlens.showQuickFileHistory';
|
||||
export const StatusBarCommand = {
|
||||
BlameAnnotate: Commands.ToggleBlame as StatusBarCommand,
|
||||
ShowBlameHistory: Commands.ShowBlameHistory as StatusBarCommand,
|
||||
ShowFileHistory: Commands.ShowFileHistory as CodeLensCommand,
|
||||
DiffWithPrevious: Commands.DiffWithPrevious as StatusBarCommand,
|
||||
ToggleCodeLens: Commands.ToggleCodeLens as StatusBarCommand,
|
||||
GitViewHistory: 'git.viewFileHistory' as StatusBarCommand
|
||||
ShowQuickFileHistory: Commands.ShowQuickFileHistory as StatusBarCommand
|
||||
};
|
||||
|
||||
export interface IStatusBarConfig {
|
||||
|
||||
@@ -14,7 +14,7 @@ export const BuiltInCommands = {
|
||||
ToggleRenderWhitespace: 'editor.action.toggleRenderWhitespace' as BuiltInCommands
|
||||
};
|
||||
|
||||
export type Commands = 'gitlens.diffWithPrevious' | 'gitlens.diffLineWithPrevious' | 'gitlens.diffWithWorking' | 'gitlens.diffLineWithWorking' | 'gitlens.showBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' | 'gitlens.toggleBlame' | 'gitlens.toggleCodeLens';
|
||||
export type Commands = 'gitlens.diffWithPrevious' | 'gitlens.diffLineWithPrevious' | 'gitlens.diffWithWorking' | 'gitlens.diffLineWithWorking' | 'gitlens.showBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' | 'gitlens.showQuickFileHistory' | 'gitlens.showQuickRepoHistory' | 'gitlens.toggleBlame' | 'gitlens.toggleCodeLens';
|
||||
export const Commands = {
|
||||
DiffWithPrevious: 'gitlens.diffWithPrevious' as Commands,
|
||||
DiffLineWithPrevious: 'gitlens.diffLineWithPrevious' as Commands,
|
||||
@@ -23,6 +23,8 @@ export const Commands = {
|
||||
ShowBlame: 'gitlens.showBlame' as Commands,
|
||||
ShowBlameHistory: 'gitlens.showBlameHistory' as Commands,
|
||||
ShowFileHistory: 'gitlens.showFileHistory' as Commands,
|
||||
ShowQuickFileHistory: 'gitlens.showQuickFileHistory' as Commands,
|
||||
ShowQuickRepoHistory: 'gitlens.showQuickRepoHistory' as Commands,
|
||||
ToggleBlame: 'gitlens.toggleBlame' as Commands,
|
||||
ToggleCodeLens: 'gitlens.toggleCodeLens' as Commands
|
||||
};
|
||||
@@ -33,8 +35,7 @@ export const DocumentSchemes = {
|
||||
Git: 'git' as DocumentSchemes
|
||||
};
|
||||
|
||||
export type WorkspaceState = 'hasGitHistoryExtension' | 'repoPath';
|
||||
export type WorkspaceState = 'repoPath';
|
||||
export const WorkspaceState = {
|
||||
HasGitHistoryExtension: 'hasGitHistoryExtension' as WorkspaceState,
|
||||
RepoPath: 'repoPath' as WorkspaceState
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
import { ExtensionContext, extensions, languages, window, workspace } from 'vscode';
|
||||
import { ExtensionContext, languages, window, workspace } from 'vscode';
|
||||
import BlameAnnotationController from './blameAnnotationController';
|
||||
import BlameStatusBarController from './blameStatusBarController';
|
||||
import DiffLineWithPreviousCommand from './commands/diffLineWithPrevious';
|
||||
@@ -9,6 +9,8 @@ import DiffWithWorkingCommand from './commands/diffWithWorking';
|
||||
import ShowBlameCommand from './commands/showBlame';
|
||||
import ShowBlameHistoryCommand from './commands/showBlameHistory';
|
||||
import ShowFileHistoryCommand from './commands/showFileHistory';
|
||||
import ShowQuickFileHistoryCommand from './commands/showQuickFileHistory';
|
||||
import ShowQuickRepoHistoryCommand from './commands/showQuickRepoHistory';
|
||||
import ToggleBlameCommand from './commands/toggleBlame';
|
||||
import ToggleCodeLensCommand from './commands/toggleCodeLens';
|
||||
import { IAdvancedConfig } from './configuration';
|
||||
@@ -45,7 +47,6 @@ export async function activate(context: ExtensionContext) {
|
||||
}
|
||||
|
||||
context.workspaceState.update(WorkspaceState.RepoPath, repoPath);
|
||||
context.workspaceState.update(WorkspaceState.HasGitHistoryExtension, extensions.getExtension('donjayamanne.githistory') !== undefined);
|
||||
|
||||
const git = new GitProvider(context);
|
||||
context.subscriptions.push(git);
|
||||
@@ -68,6 +69,8 @@ export async function activate(context: ExtensionContext) {
|
||||
context.subscriptions.push(new ToggleBlameCommand(annotationController));
|
||||
context.subscriptions.push(new ShowBlameHistoryCommand(git));
|
||||
context.subscriptions.push(new ShowFileHistoryCommand(git));
|
||||
context.subscriptions.push(new ShowQuickFileHistoryCommand(git));
|
||||
context.subscriptions.push(new ShowQuickRepoHistoryCommand(git));
|
||||
context.subscriptions.push(new ToggleCodeLensCommand(git));
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,13 @@ interface ILogEntry {
|
||||
committerDate?: string;
|
||||
|
||||
fileName?: string;
|
||||
fileNames?: string[];
|
||||
|
||||
summary?: string;
|
||||
}
|
||||
|
||||
export class GitLogParserEnricher implements IGitEnricher<IGitLog> {
|
||||
private _parseEntries(data: string): ILogEntry[] {
|
||||
private _parseEntries(data: string, isRepoPath: boolean): ILogEntry[] {
|
||||
if (!data) return undefined;
|
||||
|
||||
const lines = data.split('\n');
|
||||
@@ -65,14 +66,34 @@ export class GitLogParserEnricher implements IGitEnricher<IGitLog> {
|
||||
break;
|
||||
|
||||
case 'filename':
|
||||
position += 2;
|
||||
lineParts = lines[position].split(' ');
|
||||
if (lineParts.length === 1) {
|
||||
entry.fileName = lineParts[0];
|
||||
if (isRepoPath) {
|
||||
position++;
|
||||
while (++position < lines.length) {
|
||||
lineParts = lines[position].split(' ');
|
||||
if (/^[a-f0-9]{40}$/.test(lineParts[0])) {
|
||||
position--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (entry.fileNames == null) {
|
||||
entry.fileNames = [lineParts[0]];
|
||||
}
|
||||
else {
|
||||
entry.fileNames.push(lineParts[0]);
|
||||
}
|
||||
}
|
||||
entry.fileName = entry.fileNames.join(', ');
|
||||
}
|
||||
else {
|
||||
entry.fileName = lineParts[3].substring(2);
|
||||
position += 4;
|
||||
position += 2;
|
||||
lineParts = lines[position].split(' ');
|
||||
if (lineParts.length === 1) {
|
||||
entry.fileName = lineParts[0];
|
||||
}
|
||||
else {
|
||||
entry.fileName = lineParts[3].substring(2);
|
||||
position += 4;
|
||||
}
|
||||
}
|
||||
|
||||
entries.push(entry);
|
||||
@@ -87,8 +108,9 @@ export class GitLogParserEnricher implements IGitEnricher<IGitLog> {
|
||||
return entries;
|
||||
}
|
||||
|
||||
enrich(data: string, fileName: string): IGitLog {
|
||||
const entries = this._parseEntries(data);
|
||||
enrich(data: string, fileNameOrRepoPath: string): IGitLog {
|
||||
const isRepoPath = !path.extname(fileNameOrRepoPath);
|
||||
const entries = this._parseEntries(data, isRepoPath);
|
||||
if (!entries) return undefined;
|
||||
|
||||
const authors: Map<string, IGitAuthor> = new Map();
|
||||
@@ -98,13 +120,22 @@ export class GitLogParserEnricher implements IGitEnricher<IGitLog> {
|
||||
let relativeFileName: string;
|
||||
let recentCommit: GitCommit;
|
||||
|
||||
if (isRepoPath) {
|
||||
repoPath = fileNameOrRepoPath;
|
||||
}
|
||||
|
||||
for (let i = 0, len = entries.length; i < len; i++) {
|
||||
const entry = entries[i];
|
||||
|
||||
if (i === 0) {
|
||||
// Try to get the repoPath from the most recent commit
|
||||
repoPath = fileName.replace(`/${entry.fileName}`, '');
|
||||
relativeFileName = path.relative(repoPath, fileName).replace(/\\/g, '/');
|
||||
if (i === 0 || isRepoPath) {
|
||||
if (isRepoPath) {
|
||||
relativeFileName = entry.fileName;
|
||||
}
|
||||
else {
|
||||
// Try to get the repoPath from the most recent commit
|
||||
repoPath = fileNameOrRepoPath.replace(`/${entry.fileName}`, '');
|
||||
relativeFileName = path.relative(repoPath, fileNameOrRepoPath).replace(/\\/g, '/');
|
||||
}
|
||||
}
|
||||
|
||||
let commit = commits.get(entry.sha);
|
||||
@@ -129,7 +160,9 @@ export class GitLogParserEnricher implements IGitEnricher<IGitLog> {
|
||||
|
||||
if (recentCommit) {
|
||||
recentCommit.previousSha = commit.sha;
|
||||
recentCommit.previousFileName = commit.originalFileName || commit.fileName;
|
||||
if (!isRepoPath) {
|
||||
recentCommit.previousFileName = commit.originalFileName || commit.fileName;
|
||||
}
|
||||
}
|
||||
recentCommit = commit;
|
||||
}
|
||||
|
||||
@@ -89,6 +89,12 @@ export default class Git {
|
||||
return gitCommand(root, 'log', `--follow`, `--name-only`, `--no-merges`, `--date=iso8601-strict`, `--format=%H -%nauthor %an%nauthor-date %ai%ncommitter %cn%ncommitter-date %ci%nsummary %s%nfilename ?`, file);
|
||||
}
|
||||
|
||||
static logMostRecent(fileName: string, repoPath?: string) {
|
||||
const [file, root]: [string, string] = Git.splitPath(Git.normalizePath(fileName, repoPath));
|
||||
|
||||
return gitCommand(root, 'log', `-n1`, `--follow`, `--name-only`, `--no-merges`, `--date=iso8601-strict`, `--format=%H -%nauthor %an%nauthor-date %ai%ncommitter %cn%ncommitter-date %ci%nsummary %s%nfilename ?`, file);
|
||||
}
|
||||
|
||||
static logRange(fileName: string, start: number, end: number, sha?: string, repoPath?: string) {
|
||||
const [file, root]: [string, string] = Git.splitPath(Git.normalizePath(fileName), repoPath);
|
||||
|
||||
@@ -98,6 +104,10 @@ export default class Git {
|
||||
return gitCommand(root, 'log', `--name-only`, `--no-merges`, `--date=iso8601-strict`, `--format=%H -%nauthor %an%nauthor-date %ai%ncommitter %cn%ncommitter-date %ci%nsummary %s%nfilename ?`, `-L ${start},${end}:${file}`);
|
||||
}
|
||||
|
||||
static logRepo(repoPath: string) {
|
||||
return gitCommand(repoPath, 'log', `--name-only`, `--no-merges`, `--date=iso8601-strict`, `--format=%H -%nauthor %an%nauthor-date %ai%ncommitter %cn%ncommitter-date %ci%nsummary %s%nfilename ?`);
|
||||
}
|
||||
|
||||
static getVersionedFile(fileName: string, repoPath: string, sha: string) {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
Git.getVersionedFileText(fileName, repoPath, sha).then(data => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
import { Functions, Iterables, Strings } from './system';
|
||||
import { CancellationToken, CodeLens, CodeLensProvider, commands, DocumentSelector, ExtensionContext, Position, Range, SymbolInformation, SymbolKind, TextDocument, Uri, workspace } from 'vscode';
|
||||
import { BuiltInCommands, Commands, DocumentSchemes, WorkspaceState } from './constants';
|
||||
import { BuiltInCommands, Commands, DocumentSchemes } from './constants';
|
||||
import { CodeLensCommand, CodeLensLocation, IConfig, ICodeLensLanguageLocation } from './configuration';
|
||||
import GitProvider, { GitCommit, GitUri, IGitBlame, IGitBlameLines } from './gitProvider';
|
||||
import * as moment from 'moment';
|
||||
@@ -30,11 +30,9 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
static selector: DocumentSelector = { scheme: DocumentSchemes.File };
|
||||
|
||||
private _config: IConfig;
|
||||
private _hasGitHistoryExtension: boolean;
|
||||
|
||||
constructor(context: ExtensionContext, private git: GitProvider) {
|
||||
this._config = workspace.getConfiguration('').get<IConfig>('gitlens');
|
||||
this._hasGitHistoryExtension = context.workspaceState.get(WorkspaceState.HasGitHistoryExtension, false);
|
||||
}
|
||||
|
||||
async provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
|
||||
@@ -197,7 +195,7 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
case CodeLensCommand.ShowBlameHistory: return this._applyShowBlameHistoryCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
|
||||
case CodeLensCommand.ShowFileHistory: return this._applyShowFileHistoryCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
|
||||
case CodeLensCommand.DiffWithPrevious: return this._applyDiffWithPreviousCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
|
||||
case CodeLensCommand.GitViewHistory: return this._applyGitHistoryCommand<GitRecentChangeCodeLens>(title, lens, blame);
|
||||
case CodeLensCommand.ShowQuickFileHistory: return this._applyShowQuickFileHistoryCommand<GitRecentChangeCodeLens>(title, lens, blame);
|
||||
default: return lens;
|
||||
}
|
||||
}
|
||||
@@ -212,7 +210,7 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
case CodeLensCommand.ShowBlameHistory: return this._applyShowBlameHistoryCommand<GitAuthorsCodeLens>(title, lens, blame);
|
||||
case CodeLensCommand.ShowFileHistory: return this._applyShowFileHistoryCommand<GitAuthorsCodeLens>(title, lens, blame);
|
||||
case CodeLensCommand.DiffWithPrevious: return this._applyDiffWithPreviousCommand<GitAuthorsCodeLens>(title, lens, blame);
|
||||
case CodeLensCommand.GitViewHistory: return this._applyGitHistoryCommand<GitAuthorsCodeLens>(title, lens, blame);
|
||||
case CodeLensCommand.ShowQuickFileHistory: return this._applyShowQuickFileHistoryCommand<GitAuthorsCodeLens>(title, lens, blame);
|
||||
default: return lens;
|
||||
}
|
||||
}
|
||||
@@ -280,12 +278,10 @@ export default class GitCodeLensProvider implements CodeLensProvider {
|
||||
return lens;
|
||||
}
|
||||
|
||||
_applyGitHistoryCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: IGitBlameLines): T {
|
||||
if (!this._hasGitHistoryExtension) return this._applyShowFileHistoryCommand(title, lens, blame);
|
||||
|
||||
_applyShowQuickFileHistoryCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: IGitBlameLines): T {
|
||||
lens.command = {
|
||||
title: title,
|
||||
command: CodeLensCommand.GitViewHistory,
|
||||
command: CodeLensCommand.ShowQuickFileHistory,
|
||||
arguments: [Uri.file(lens.uri.fsPath)]
|
||||
};
|
||||
return lens;
|
||||
|
||||
@@ -167,6 +167,11 @@ export default class GitProvider extends Disposable {
|
||||
return Git.repoPath(cwd);
|
||||
}
|
||||
|
||||
async getRepoPathFromFile(fileName: string): Promise<string | undefined> {
|
||||
const log = await this.getMostRecentLogForFile(fileName);
|
||||
return log && log.repoPath;
|
||||
}
|
||||
|
||||
getBlameForFile(fileName: string, sha?: string, repoPath?: string): Promise<IGitBlame | undefined> {
|
||||
Logger.log(`getBlameForFile('${fileName}', ${sha}, ${repoPath})`);
|
||||
fileName = Git.normalizePath(fileName);
|
||||
@@ -342,6 +347,30 @@ export default class GitProvider extends Disposable {
|
||||
return locations;
|
||||
}
|
||||
|
||||
async getLogForRepo(repoPath: string): Promise<IGitLog | undefined> {
|
||||
Logger.log(`getLogForRepo('${repoPath}')`);
|
||||
try {
|
||||
const data = await Git.logRepo(repoPath);
|
||||
return new GitLogParserEnricher().enrich(data, repoPath);
|
||||
}
|
||||
catch (ex) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async getMostRecentLogForFile(fileName: string): Promise<IGitLog | undefined> {
|
||||
Logger.log(`getMostRecentLogForFile('${fileName}')`);
|
||||
fileName = Git.normalizePath(fileName);
|
||||
|
||||
try {
|
||||
const data = await Git.logMostRecent(fileName);
|
||||
return new GitLogParserEnricher().enrich(data, fileName);
|
||||
}
|
||||
catch (ex) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
getLogForFile(fileName: string, sha?: string, repoPath?: string, range?: Range): Promise<IGitLog | undefined> {
|
||||
Logger.log(`getLogForFile('${fileName}', ${sha}, ${repoPath}, ${range && `[${range.start.line}, ${range.end.line}]`})`);
|
||||
fileName = Git.normalizePath(fileName);
|
||||
@@ -371,7 +400,7 @@ export default class GitProvider extends Disposable {
|
||||
: Git.log(fileName, sha, repoPath))
|
||||
.then(data => new GitLogParserEnricher().enrich(data, fileName))
|
||||
.catch(ex => {
|
||||
// Trap and cache expected blame errors
|
||||
// Trap and cache expected log errors
|
||||
if (useCaching) {
|
||||
const msg = ex && ex.toString();
|
||||
Logger.log(`Replace log cache with empty promise for '${cacheKey}'`);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
"no-internal-module": true,
|
||||
"no-reference": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-unreachable": true,
|
||||
"no-unsafe-finally": true,
|
||||
"no-unused-expression": false,
|
||||
"no-unused-new": true,
|
||||
|
||||
Reference in New Issue
Block a user