浏览代码

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
main
Eric Amodio 8 年前
父节点
当前提交
d3ffabd76b
共有 15 个文件被更改,包括 313 次插入77 次删除
  1. +12
    -0
      CHANGELOG.md
  2. +3
    -7
      README.md
  3. +51
    -26
      package.json
  4. +2
    -8
      src/blameStatusBarController.ts
  5. +2
    -2
      src/commands/showFileHistory.ts
  6. +54
    -0
      src/commands/showQuickFileHistory.ts
  7. +84
    -0
      src/commands/showQuickRepoHistory.ts
  8. +4
    -4
      src/configuration.ts
  9. +4
    -3
      src/constants.ts
  10. +5
    -2
      src/extension.ts
  11. +47
    -14
      src/git/enrichers/logParserEnricher.ts
  12. +10
    -0
      src/git/git.ts
  13. +5
    -9
      src/gitCodeLensProvider.ts
  14. +30
    -1
      src/gitProvider.ts
  15. +0
    -1
      tslint.json

+ 12
- 0
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)!

+ 3
- 7
README.md 查看文件

@ -22,10 +22,6 @@ Provides Git CodeLens information (most recent commit, # of authors), on-demand
![GitLens preview](https://raw.githubusercontent.com/eamodio/vscode-git-codelens/master/images/preview-gitlens.gif)
## 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

+ 51
- 26
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"
},

+ 2
- 8
src/blameStatusBarController.ts 查看文件

@ -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;
}

+ 2
- 2
src/commands/showFileHistory.ts 查看文件

@ -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
- 0
src/commands/showQuickFileHistory.ts 查看文件

@ -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
- 0
src/commands/showQuickRepoHistory.ts 查看文件

@ -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`);
}
}
}

+ 4
- 4
src/configuration.ts 查看文件

@ -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 {

+ 4
- 3
src/constants.ts 查看文件

@ -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
};

+ 5
- 2
src/extension.ts 查看文件

@ -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));
}

+ 47
- 14
src/git/enrichers/logParserEnricher.ts 查看文件

@ -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 {
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 {
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 {
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 {
if (recentCommit) {
recentCommit.previousSha = commit.sha;
recentCommit.previousFileName = commit.originalFileName || commit.fileName;
if (!isRepoPath) {
recentCommit.previousFileName = commit.originalFileName || commit.fileName;
}
}
recentCommit = commit;
}

+ 10
- 0
src/git/git.ts 查看文件

@ -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 => {

+ 5
- 9
src/gitCodeLensProvider.ts 查看文件

@ -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;

+ 30
- 1
src/gitProvider.ts 查看文件

@ -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}'`);

+ 0
- 1
tslint.json 查看文件

@ -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,

正在加载...
取消
保存