mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-02-12 11:08:34 -05:00
Compare commits
10 Commits
v5.1.0
...
v5.1.1-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a10376385a | ||
|
|
41d25803d8 | ||
|
|
3802b43027 | ||
|
|
04ea3b7971 | ||
|
|
6d7f44e091 | ||
|
|
3a1caa2e0d | ||
|
|
3f7058bd48 | ||
|
|
71d17bcc2f | ||
|
|
a69afdb6ef | ||
|
|
26c6346b84 |
16
CHANGELOG.md
16
CHANGELOG.md
@@ -4,6 +4,22 @@ 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/).
|
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [5.1.1-beta]
|
||||||
|
### Added
|
||||||
|
- Adds new `Changed Files` node to the `Repository Status` node of the `GitLens` custom view's `Repository View` (enabled via `"gitlens.insiders": true`) -- closes [#139](https://github.com/eamodio/vscode-gitlens/issues/139)
|
||||||
|
- Provides a file-based view of all the changed files in the working tree and/or files in commits that haven't yet been pushed upstream
|
||||||
|
- Adds `gitlens.gitExplorer.enabled` setting to specify whether or not to show the `GitLens` custom view - closes [#144](https://github.com/eamodio/vscode-gitlens/issues/144)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Chnages the default of the `gitlens.gitExplorer.commitFormat` setting to add parentheses around the commit id
|
||||||
|
- Removes many menu items from `editor/title` & `editor/title/context` by default -- can be re-enabled via the `gitlens.advanced.menus` setting
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixes an issue when running `Open File in Remote` with a multi-line selection wasn't properly opening the selection in GitLab -- thanks to [PR #145](https://github.com/eamodio/vscode-gitlens/pull/145) by Amanda Cameron ([@AmandaCameron](https://github.com/AmandaCameron))!
|
||||||
|
- Fixes an issue where the `gitlens.advanced.menus` setting wasn't controlling all the menu items properly
|
||||||
|
|
||||||
## [5.1.0] - 2017-09-15
|
## [5.1.0] - 2017-09-15
|
||||||
### Added
|
### Added
|
||||||
- Adds full (multi-line) commit message to the `details` hover annotations -- closes [#116](https://github.com/eamodio/vscode-gitlens/issues/116)
|
- Adds full (multi-line) commit message to the `details` hover annotations -- closes [#116](https://github.com/eamodio/vscode-gitlens/issues/116)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
||||||
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
||||||
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
||||||
[](https://join.slack.com/t/vscode-gitlens/shared_invite/MjIxOTgxNDE3NzM0LTE1MDE2Nzk1MTgtMjkwMmZjMzcxNQ)
|
[](https://join.slack.com/t/vscode-dev-community/shared_invite/enQtMjIxOTgxNDE3NzM0LWU5M2ZiZDU1YjBlMzdlZjA2YjBjYzRhYTM5NTgzMTAxMjdiNWU0ZmQzYWI3MWU5N2Q1YjBiYmQ4MzY0NDE1MzY)
|
||||||
|
|
||||||
# GitLens
|
# GitLens
|
||||||
|
|
||||||
@@ -350,6 +350,7 @@ GitLens is highly customizable and provides many configuration settings to allow
|
|||||||
|
|
||||||
|Name | Description
|
|Name | Description
|
||||||
|-----|------------
|
|-----|------------
|
||||||
|
|`gitlens.gitExplorer.enabled`|Specifies whether or not to show the `GitLens` custom view"
|
||||||
|`gitlens.gitExplorer.view`|Specifies the starting view (mode) of the `GitLens` custom view<br />`history` - shows the commit history of the active file<br />`repository` - shows a repository explorer"
|
|`gitlens.gitExplorer.view`|Specifies the starting view (mode) of the `GitLens` custom view<br />`history` - shows the commit history of the active file<br />`repository` - shows a repository explorer"
|
||||||
|`gitlens.gitExplorer.showTrackingBranch`|Specifies whether or not to show the tracking branch when displaying local branches in the `GitLens` custom view"
|
|`gitlens.gitExplorer.showTrackingBranch`|Specifies whether or not to show the tracking branch when displaying local branches in the `GitLens` custom view"
|
||||||
|`gitlens.gitExplorer.commitFormat`|Specifies the format of committed changes in the `GitLens` custom view<br />Available tokens<br /> ${id} - commit id<br /> ${author} - commit author<br /> ${message} - commit message<br /> ${ago} - relative commit date (e.g. 1 day ago)<br /> ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)<br /> ${authorAgo} - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|
|`gitlens.gitExplorer.commitFormat`|Specifies the format of committed changes in the `GitLens` custom view<br />Available tokens<br /> ${id} - commit id<br /> ${author} - commit author<br /> ${message} - commit message<br /> ${ago} - relative commit date (e.g. 1 day ago)<br /> ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)<br /> ${authorAgo} - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|
||||||
@@ -422,6 +423,7 @@ GitLens is highly customizable and provides many configuration settings to allow
|
|||||||
|
|
||||||
A big thanks to the people that have contributed to this project:
|
A big thanks to the people that have contributed to this project:
|
||||||
|
|
||||||
|
- Amanda Cameron ([@AmandaCameron](https://github.com/AmandaCameron)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=AmandaCameron))
|
||||||
- Peng Lyu ([@rebornix](https://github.com/rebornix)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=rebornix))
|
- Peng Lyu ([@rebornix](https://github.com/rebornix)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=rebornix))
|
||||||
- Aurelio Ogliari ([@nobitagit](https://github.com/nobitagit)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=nobitagit)
|
- Aurelio Ogliari ([@nobitagit](https://github.com/nobitagit)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=nobitagit)
|
||||||
- Johannes Rieken ([@jrieken](https://github.com/jrieken)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=jrieken))
|
- Johannes Rieken ([@jrieken](https://github.com/jrieken)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=jrieken))
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gitlens",
|
"name": "gitlens",
|
||||||
"version": "5.1.0",
|
"version": "5.1.1-beta",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
82
package.json
82
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gitlens",
|
"name": "gitlens",
|
||||||
"version": "5.1.0",
|
"version": "5.1.1-beta",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Eric Amodio",
|
"name": "Eric Amodio",
|
||||||
"email": "eamodio@gmail.com"
|
"email": "eamodio@gmail.com"
|
||||||
@@ -15,8 +15,8 @@
|
|||||||
"badges": [
|
"badges": [
|
||||||
{
|
{
|
||||||
"url": "https://img.shields.io/badge/chat-on%20slack-brightgreen.svg",
|
"url": "https://img.shields.io/badge/chat-on%20slack-brightgreen.svg",
|
||||||
"href": "https://join.slack.com/t/vscode-gitlens/shared_invite/MjIxOTgxNDE3NzM0LTE1MDE2Nzk1MTgtMjkwMmZjMzcxNQ",
|
"href": "https://join.slack.com/t/vscode-dev-community/shared_invite/enQtMjIxOTgxNDE3NzM0LWU5M2ZiZDU1YjBlMzdlZjA2YjBjYzRhYTM5NTgzMTAxMjdiNWU0ZmQzYWI3MWU5N2Q1YjBiYmQ4MzY0NDE1MzY",
|
||||||
"description": "Chat at https://vscode-gitlens.slack.com/"
|
"description": "Chat at https://vscode-dev-community.slack.com/"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
@@ -415,7 +415,7 @@
|
|||||||
},
|
},
|
||||||
"gitlens.gitExplorer.commitFormat": {
|
"gitlens.gitExplorer.commitFormat": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "${message} \u00a0\u2022\u00a0 ${authorAgo} \u00a0\u2022\u00a0 ${id}",
|
"default": "${message} \u00a0\u2022\u00a0 ${authorAgo} \u00a0 (${id})",
|
||||||
"description": "Specifies the format of committed changes in the `GitLens` custom view\nAvailable tokens\n ${id} - commit id\n ${author} - commit author\n ${message} - commit message\n ${ago} - relative commit date (e.g. 1 day ago)\n ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)\n ${authorAgo} - commit author, relative commit date\nSee https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting"
|
"description": "Specifies the format of committed changes in the `GitLens` custom view\nAvailable tokens\n ${id} - commit id\n ${author} - commit author\n ${message} - commit message\n ${ago} - relative commit date (e.g. 1 day ago)\n ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)\n ${authorAgo} - commit author, relative commit date\nSee https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting"
|
||||||
},
|
},
|
||||||
"gitlens.gitExplorer.commitFileFormat": {
|
"gitlens.gitExplorer.commitFileFormat": {
|
||||||
@@ -423,6 +423,11 @@
|
|||||||
"default": "${filePath}",
|
"default": "${filePath}",
|
||||||
"description": "Specifies the format of a committed file in the `GitLens` custom view\nAvailable tokens\n ${file} - file name\n ${filePath} - file name and path\n ${path} - file path"
|
"description": "Specifies the format of a committed file in the `GitLens` custom view\nAvailable tokens\n ${file} - file name\n ${filePath} - file name and path\n ${path} - file path"
|
||||||
},
|
},
|
||||||
|
"gitlens.gitExplorer.enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Specifies whether or not to show the `GitLens` custom view"
|
||||||
|
},
|
||||||
"gitlens.gitExplorer.showTrackingBranch": {
|
"gitlens.gitExplorer.showTrackingBranch": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true,
|
"default": true,
|
||||||
@@ -646,16 +651,16 @@
|
|||||||
},
|
},
|
||||||
"editorTitle": {
|
"editorTitle": {
|
||||||
"blame": true,
|
"blame": true,
|
||||||
"fileDiff": true,
|
"fileDiff": false,
|
||||||
"history": true,
|
"history": false,
|
||||||
"remote": true,
|
"remote": false,
|
||||||
"status": true
|
"status": false
|
||||||
},
|
},
|
||||||
"editorTitleContext": {
|
"editorTitleContext": {
|
||||||
"blame": true,
|
"blame": false,
|
||||||
"fileDiff": true,
|
"fileDiff": false,
|
||||||
"history": true,
|
"history": false,
|
||||||
"remote": true
|
"remote": false
|
||||||
},
|
},
|
||||||
"explorerContext": {
|
"explorerContext": {
|
||||||
"fileDiff": true,
|
"fileDiff": true,
|
||||||
@@ -1397,12 +1402,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "gitlens.openFileInRemote",
|
"command": "gitlens.openFileInRemote",
|
||||||
"when": "gitlens:enabled && gitlens:hasRemotes && config.gitlens.advanced.menus.editorTitleContext.remote",
|
"when": "gitlens:enabled && gitlens:hasRemotes && config.gitlens.advanced.menus.editorTitle.remote",
|
||||||
"group": "1_gitlens"
|
"group": "1_gitlens"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "gitlens.openRepoInRemote",
|
"command": "gitlens.openRepoInRemote",
|
||||||
"when": "gitlens:enabled && gitlens:hasRemotes && config.gitlens.advanced.menus.editorTitleContext.remote",
|
"when": "gitlens:enabled && gitlens:hasRemotes && config.gitlens.advanced.menus.editorTitle.remote",
|
||||||
"group": "1_gitlens"
|
"group": "1_gitlens"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1737,9 +1742,54 @@
|
|||||||
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:status",
|
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:status",
|
||||||
"group": "1_gitlens@1"
|
"group": "1_gitlens@1"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.gitExplorer.openChanges",
|
||||||
|
"when": "view == gitlens.gitExplorer && viewItem == gitlens:status-file",
|
||||||
|
"group": "1_gitlens@1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.gitExplorer.openChangesWithWorking",
|
||||||
|
"when": "view == gitlens.gitExplorer && viewItem == gitlens:status-file",
|
||||||
|
"group": "1_gitlens@2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.gitExplorer.openFile",
|
||||||
|
"when": "view == gitlens.gitExplorer && viewItem == gitlens:status-file",
|
||||||
|
"group": "2_gitlens@1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.gitExplorer.openFileRevision",
|
||||||
|
"when": "view == gitlens.gitExplorer && viewItem == gitlens:status-file",
|
||||||
|
"group": "2_gitlens@2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.openFileInRemote",
|
||||||
|
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:status-file",
|
||||||
|
"group": "3_gitlens@1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.showQuickFileHistory",
|
||||||
|
"when": "view == gitlens.gitExplorer && viewItem == gitlens:status-file && gitlens:gitExplorer:view == repository",
|
||||||
|
"group": "5_gitlens@1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.showQuickCommitFileDetails",
|
||||||
|
"when": "view == gitlens.gitExplorer && viewItem == gitlens:status-file",
|
||||||
|
"group": "5_gitlens@2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.gitExplorer.openFile",
|
||||||
|
"when": "view == gitlens.gitExplorer && viewItem == gitlens:status-file-commits",
|
||||||
|
"group": "1_gitlens@1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.openFileInRemote",
|
||||||
|
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:status-file-commits",
|
||||||
|
"group": "1_gitlens@2"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "gitlens.gitExplorer.refresh",
|
"command": "gitlens.gitExplorer.refresh",
|
||||||
"when": "view == gitlens.gitExplorer && viewItem != gitlens:commit-file && viewItem != gitlens:stash-file",
|
"when": "view == gitlens.gitExplorer && viewItem != gitlens:commit-file && viewItem != gitlens:stash-file && viewItem != gitlens:status-file",
|
||||||
"group": "9_gitlens@1"
|
"group": "9_gitlens@1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1841,7 +1891,7 @@
|
|||||||
{
|
{
|
||||||
"id": "gitlens.gitExplorer",
|
"id": "gitlens.gitExplorer",
|
||||||
"name": "GitLens",
|
"name": "GitLens",
|
||||||
"when": "gitlens:enabled"
|
"when": "gitlens:enabled && config.gitlens.gitExplorer.enabled"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,6 +317,7 @@ export interface IConfig {
|
|||||||
defaultDateFormat: string | null;
|
defaultDateFormat: string | null;
|
||||||
|
|
||||||
gitExplorer: {
|
gitExplorer: {
|
||||||
|
enabled: boolean;
|
||||||
view: GitExplorerView;
|
view: GitExplorerView;
|
||||||
showTrackingBranch: boolean;
|
showTrackingBranch: boolean;
|
||||||
commitFormat: string;
|
commitFormat: string;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export class CommitFormatter extends Formatter<GitCommit, ICommitFormatOptions>
|
|||||||
}
|
}
|
||||||
|
|
||||||
get id() {
|
get id() {
|
||||||
return this._item.shortSha;
|
return this._item.isUncommitted ? 'index' : this._item.shortSha;
|
||||||
}
|
}
|
||||||
|
|
||||||
get message() {
|
get message() {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import { GitHubService } from './github';
|
import { Range } from 'vscode';
|
||||||
|
import { RemoteProvider } from './provider';
|
||||||
|
|
||||||
export class GitLabService extends GitHubService {
|
export class GitLabService extends RemoteProvider {
|
||||||
|
|
||||||
constructor(public domain: string, public path: string, public custom: boolean = false) {
|
constructor(public domain: string, public path: string, public custom: boolean = false) {
|
||||||
super(domain, path);
|
super(domain, path);
|
||||||
@@ -10,4 +11,32 @@ export class GitLabService extends GitHubService {
|
|||||||
get name() {
|
get name() {
|
||||||
return this.formatName('GitLab');
|
return this.formatName('GitLab');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected getUrlForBranches(): string {
|
||||||
|
return `${this.baseUrl}/branches`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getUrlForBranch(branch: string): string {
|
||||||
|
return `${this.baseUrl}/commits/${branch}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getUrlForCommit(sha: string): string {
|
||||||
|
return `${this.baseUrl}/commit/${sha}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getUrlForFile(fileName: string, branch?: string, sha?: string, range?: Range): string {
|
||||||
|
let line = '';
|
||||||
|
if (range) {
|
||||||
|
if (range.start.line === range.end.line) {
|
||||||
|
line = `#L${range.start.line}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
line = `#L${range.start.line}-${range.end.line}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sha) return `${this.baseUrl}/blob/${sha}/${fileName}${line}`;
|
||||||
|
if (branch) return `${this.baseUrl}/blob/${branch}/${fileName}${line}`;
|
||||||
|
return `${this.baseUrl}?path=${fileName}${line}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -74,6 +74,7 @@ export const RepoChangedReasons = {
|
|||||||
export class GitService extends Disposable {
|
export class GitService extends Disposable {
|
||||||
|
|
||||||
static fakeSha = 'ffffffffffffffffffffffffffffffffffffffff';
|
static fakeSha = 'ffffffffffffffffffffffffffffffffffffffff';
|
||||||
|
static uncommittedSha = '0000000000000000000000000000000000000000';
|
||||||
|
|
||||||
private _onDidBlameFail = new EventEmitter<string>();
|
private _onDidBlameFail = new EventEmitter<string>();
|
||||||
get onDidBlameFail(): Event<string> {
|
get onDidBlameFail(): Event<string> {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
export namespace Arrays {
|
export namespace Arrays {
|
||||||
export function groupBy<T>(array: T[], accessor: (item: T) => any): T[] {
|
export function groupBy<T>(array: T[], accessor: (item: T) => string): { [key: string]: T[] } {
|
||||||
return array.reduce((previous, current) => {
|
return array.reduce((previous, current) => {
|
||||||
const value = accessor(current);
|
const value = accessor(current);
|
||||||
previous[value] = previous[value] || [];
|
previous[value] = previous[value] || [];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Iterables } from '../system';
|
|||||||
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
||||||
import { CommitNode } from './commitNode';
|
import { CommitNode } from './commitNode';
|
||||||
import { GlyphChars } from '../constants';
|
import { GlyphChars } from '../constants';
|
||||||
import { ExplorerNode, ResourceType, ShowAllCommitsNode } from './explorerNode';
|
import { ExplorerNode, ResourceType, ShowAllNode } from './explorerNode';
|
||||||
import { GitBranch, GitService, GitUri } from '../gitService';
|
import { GitBranch, GitService, GitUri } from '../gitService';
|
||||||
|
|
||||||
export class BranchHistoryNode extends ExplorerNode {
|
export class BranchHistoryNode extends ExplorerNode {
|
||||||
@@ -12,7 +12,12 @@ export class BranchHistoryNode extends ExplorerNode {
|
|||||||
|
|
||||||
maxCount: number | undefined = undefined;
|
maxCount: number | undefined = undefined;
|
||||||
|
|
||||||
constructor(public readonly branch: GitBranch, uri: GitUri, private readonly template: string, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
public readonly branch: GitBranch,
|
||||||
|
uri: GitUri,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(uri);
|
super(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,10 +25,11 @@ export class BranchHistoryNode extends ExplorerNode {
|
|||||||
const log = await this.git.getLogForRepo(this.uri.repoPath!, this.branch.name, this.maxCount);
|
const log = await this.git.getLogForRepo(this.uri.repoPath!, this.branch.name, this.maxCount);
|
||||||
if (log === undefined) return [];
|
if (log === undefined) return [];
|
||||||
|
|
||||||
const children = Iterables.map(log.commits.values(), c => new CommitNode(c, this.template, this.context, this.git, this.branch));
|
const children: (CommitNode | ShowAllNode)[] = [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.context, this.git, this.branch))];
|
||||||
if (!log.truncated) return [...children];
|
if (log.truncated) {
|
||||||
|
children.push(new ShowAllNode('Show All Commits', this, this.context));
|
||||||
return [...children, new ShowAllCommitsNode(this, this.context)];
|
}
|
||||||
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTreeItem(): Promise<TreeItem> {
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ export class BranchesNode extends ExplorerNode {
|
|||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:branches';
|
readonly resourceType: ResourceType = 'gitlens:branches';
|
||||||
|
|
||||||
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
uri: GitUri,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(uri);
|
super(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,7 +22,7 @@ export class BranchesNode extends ExplorerNode {
|
|||||||
if (branches === undefined) return [];
|
if (branches === undefined) return [];
|
||||||
|
|
||||||
branches.sort((a, b) => (a.current ? -1 : 1) - (b.current ? -1 : 1) || a.name.localeCompare(b.name));
|
branches.sort((a, b) => (a.current ? -1 : 1) - (b.current ? -1 : 1) || a.name.localeCompare(b.name));
|
||||||
return [...Iterables.filterMap(branches, b => b.remote ? undefined : new BranchHistoryNode(b, this.uri, this.git.config.gitExplorer.commitFormat, this.context, this.git))];
|
return [...Iterables.filterMap(branches, b => b.remote ? undefined : new BranchHistoryNode(b, this.uri, this.context, this.git))];
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTreeItem(): Promise<TreeItem> {
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
|
|||||||
@@ -2,19 +2,36 @@
|
|||||||
import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
||||||
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
||||||
import { ExplorerNode, ResourceType } from './explorerNode';
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
import { getGitStatusIcon, GitBranch, GitCommit, GitService, GitUri, IGitStatusFile, StatusFileFormatter } from '../gitService';
|
import { CommitFormatter, getGitStatusIcon, GitBranch, GitCommit, GitService, GitUri, ICommitFormatOptions, IGitStatusFile, StatusFileFormatter } from '../gitService';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export enum CommitFileNodeDisplayAs {
|
||||||
|
CommitLabel = 1 << 0,
|
||||||
|
CommitIcon = 1 << 1,
|
||||||
|
FileLabel = 1 << 2,
|
||||||
|
StatusIcon = 1 << 3,
|
||||||
|
|
||||||
|
Commit = CommitLabel | CommitIcon,
|
||||||
|
File = FileLabel | StatusIcon
|
||||||
|
}
|
||||||
|
|
||||||
export class CommitFileNode extends ExplorerNode {
|
export class CommitFileNode extends ExplorerNode {
|
||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:commit-file';
|
readonly resourceType: ResourceType = 'gitlens:commit-file';
|
||||||
|
|
||||||
constructor(public readonly status: IGitStatusFile, public commit: GitCommit, protected readonly context: ExtensionContext, protected readonly git: GitService, public readonly branch?: GitBranch) {
|
constructor(
|
||||||
|
public readonly status: IGitStatusFile,
|
||||||
|
public commit: GitCommit,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService,
|
||||||
|
private displayAs: CommitFileNodeDisplayAs = CommitFileNodeDisplayAs.Commit,
|
||||||
|
public readonly branch?: GitBranch
|
||||||
|
) {
|
||||||
super(new GitUri(Uri.file(path.resolve(commit.repoPath, status.fileName)), { repoPath: commit.repoPath, fileName: status.fileName, sha: commit.sha }));
|
super(new GitUri(Uri.file(path.resolve(commit.repoPath, status.fileName)), { repoPath: commit.repoPath, fileName: status.fileName, sha: commit.sha }));
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
return Promise.resolve([]);
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTreeItem(): Promise<TreeItem> {
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
@@ -25,10 +42,20 @@ export class CommitFileNode extends ExplorerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const item = new TreeItem(StatusFileFormatter.fromTemplate(this.git.config.gitExplorer.commitFileFormat, this.status), TreeItemCollapsibleState.None);
|
const label = (this.displayAs & CommitFileNodeDisplayAs.CommitLabel)
|
||||||
|
? CommitFormatter.fromTemplate(this.getCommitTemplate(), this.commit, {
|
||||||
|
truncateMessageAtNewLine: true,
|
||||||
|
dataFormat: this.git.config.defaultDateFormat
|
||||||
|
} as ICommitFormatOptions)
|
||||||
|
: StatusFileFormatter.fromTemplate(this.getCommitFileTemplate(), this.status);
|
||||||
|
|
||||||
|
const item = new TreeItem(label, TreeItemCollapsibleState.None);
|
||||||
item.contextValue = this.resourceType;
|
item.contextValue = this.resourceType;
|
||||||
|
|
||||||
const icon = getGitStatusIcon(this.status.status);
|
const icon = (this.displayAs & CommitFileNodeDisplayAs.CommitIcon)
|
||||||
|
? 'icon-commit.svg'
|
||||||
|
: getGitStatusIcon(this.status.status);
|
||||||
|
|
||||||
item.iconPath = {
|
item.iconPath = {
|
||||||
dark: this.context.asAbsolutePath(path.join('images', 'dark', icon)),
|
dark: this.context.asAbsolutePath(path.join('images', 'dark', icon)),
|
||||||
light: this.context.asAbsolutePath(path.join('images', 'light', icon))
|
light: this.context.asAbsolutePath(path.join('images', 'light', icon))
|
||||||
@@ -39,6 +66,14 @@ export class CommitFileNode extends ExplorerNode {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected getCommitTemplate() {
|
||||||
|
return this.git.config.gitExplorer.commitFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getCommitFileTemplate() {
|
||||||
|
return this.git.config.gitExplorer.commitFileFormat;
|
||||||
|
}
|
||||||
|
|
||||||
getCommand(): Command | undefined {
|
getCommand(): Command | undefined {
|
||||||
return {
|
return {
|
||||||
title: 'Compare File with Previous Revision',
|
title: 'Compare File with Previous Revision',
|
||||||
|
|||||||
@@ -2,58 +2,44 @@
|
|||||||
import { Iterables } from '../system';
|
import { Iterables } from '../system';
|
||||||
import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
||||||
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
||||||
import { CommitFileNode } from './commitFileNode';
|
import { CommitFileNode, CommitFileNodeDisplayAs } from './commitFileNode';
|
||||||
import { ExplorerNode, ResourceType } from './explorerNode';
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
import { CommitFormatter, getGitStatusIcon, GitBranch, GitLogCommit, GitService, GitUri, ICommitFormatOptions } from '../gitService';
|
import { CommitFormatter, GitBranch, GitLogCommit, GitService, GitUri, ICommitFormatOptions } from '../gitService';
|
||||||
import * as path from 'path';
|
|
||||||
|
|
||||||
export class CommitNode extends ExplorerNode {
|
export class CommitNode extends ExplorerNode {
|
||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:commit';
|
readonly resourceType: ResourceType = 'gitlens:commit';
|
||||||
|
|
||||||
constructor(public readonly commit: GitLogCommit, private readonly template: string, protected readonly context: ExtensionContext, protected readonly git: GitService, public readonly branch?: GitBranch) {
|
constructor(
|
||||||
|
public readonly commit: GitLogCommit,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService,
|
||||||
|
public readonly branch?: GitBranch
|
||||||
|
) {
|
||||||
super(new GitUri(commit.uri, commit));
|
super(new GitUri(commit.uri, commit));
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
if (this.commit.type === 'file') Promise.resolve([]);
|
|
||||||
|
|
||||||
const log = await this.git.getLogForRepo(this.commit.repoPath, this.commit.sha, 1);
|
const log = await this.git.getLogForRepo(this.commit.repoPath, this.commit.sha, 1);
|
||||||
if (log === undefined) return [];
|
if (log === undefined) return [];
|
||||||
|
|
||||||
const commit = Iterables.first(log.commits.values());
|
const commit = Iterables.first(log.commits.values());
|
||||||
if (commit === undefined) return [];
|
if (commit === undefined) return [];
|
||||||
|
|
||||||
return [...Iterables.map(commit.fileStatuses, s => new CommitFileNode(s, commit, this.context, this.git, this.branch))];
|
return [...Iterables.map(commit.fileStatuses, s => new CommitFileNode(s, commit, this.context, this.git, CommitFileNodeDisplayAs.File, this.branch))];
|
||||||
}
|
}
|
||||||
|
|
||||||
getTreeItem(): TreeItem {
|
getTreeItem(): TreeItem {
|
||||||
const item = new TreeItem(CommitFormatter.fromTemplate(this.template, this.commit, {
|
const item = new TreeItem(CommitFormatter.fromTemplate(this.git.config.gitExplorer.commitFormat, this.commit, {
|
||||||
truncateMessageAtNewLine: true,
|
truncateMessageAtNewLine: true,
|
||||||
dataFormat: this.git.config.defaultDateFormat
|
dataFormat: this.git.config.defaultDateFormat
|
||||||
} as ICommitFormatOptions));
|
} as ICommitFormatOptions), TreeItemCollapsibleState.Collapsed);
|
||||||
|
|
||||||
if (this.commit.type === 'file') {
|
item.contextValue = this.resourceType;
|
||||||
item.collapsibleState = TreeItemCollapsibleState.None;
|
item.iconPath = {
|
||||||
item.command = this.getCommand();
|
dark: this.context.asAbsolutePath('images/dark/icon-commit.svg'),
|
||||||
const resourceType: ResourceType = 'gitlens:commit-file';
|
light: this.context.asAbsolutePath('images/light/icon-commit.svg')
|
||||||
item.contextValue = resourceType;
|
};
|
||||||
|
|
||||||
const icon = getGitStatusIcon(this.commit.status!);
|
|
||||||
item.iconPath = {
|
|
||||||
dark: this.context.asAbsolutePath(path.join('images', 'dark', icon)),
|
|
||||||
light: this.context.asAbsolutePath(path.join('images', 'light', icon))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
item.collapsibleState = TreeItemCollapsibleState.Collapsed;
|
|
||||||
item.contextValue = this.resourceType;
|
|
||||||
|
|
||||||
item.iconPath = {
|
|
||||||
dark: this.context.asAbsolutePath('images/dark/icon-commit.svg'),
|
|
||||||
light: this.context.asAbsolutePath('images/light/icon-commit.svg')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ export declare type ResourceType =
|
|||||||
'gitlens:stash-file' |
|
'gitlens:stash-file' |
|
||||||
'gitlens:stashes' |
|
'gitlens:stashes' |
|
||||||
'gitlens:status' |
|
'gitlens:status' |
|
||||||
|
'gitlens:status-file' |
|
||||||
|
'gitlens:status-files' |
|
||||||
|
'gitlens:status-file-commits' |
|
||||||
'gitlens:status-upstream';
|
'gitlens:status-upstream';
|
||||||
|
|
||||||
export abstract class ExplorerNode {
|
export abstract class ExplorerNode {
|
||||||
@@ -88,11 +91,11 @@ export class PagerNode extends ExplorerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ShowAllCommitsNode extends PagerNode {
|
export class ShowAllNode extends PagerNode {
|
||||||
|
|
||||||
args: RefreshNodeCommandArgs = { maxCount: 0 };
|
args: RefreshNodeCommandArgs = { maxCount: 0 };
|
||||||
|
|
||||||
constructor(node: ExplorerNode, context: ExtensionContext) {
|
constructor(message: string, node: ExplorerNode, context: ExtensionContext) {
|
||||||
super(`Show All Commits ${GlyphChars.Space}${GlyphChars.Dash}${GlyphChars.Space} this may take a while`, node, context);
|
super(`${message} ${GlyphChars.Space}${GlyphChars.Dash}${GlyphChars.Space} this may take a while`, node, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,8 +10,10 @@ export * from './historyNode';
|
|||||||
export * from './remoteNode';
|
export * from './remoteNode';
|
||||||
export * from './remotesNode';
|
export * from './remotesNode';
|
||||||
export * from './repositoryNode';
|
export * from './repositoryNode';
|
||||||
|
export * from './stashesNode';
|
||||||
export * from './stashFileNode';
|
export * from './stashFileNode';
|
||||||
export * from './stashNode';
|
export * from './stashNode';
|
||||||
export * from './stashesNode';
|
export * from './statusFileCommitsNode';
|
||||||
|
export * from './statusFilesNode';
|
||||||
export * from './statusNode';
|
export * from './statusNode';
|
||||||
export * from './statusUpstreamNode';
|
export * from './statusUpstreamNode';
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import { Iterables } from '../system';
|
import { Iterables } from '../system';
|
||||||
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
||||||
import { CommitNode } from './commitNode';
|
import { CommitFileNode, CommitFileNodeDisplayAs } from './commitFileNode';
|
||||||
import { ExplorerNode, MessageNode, ResourceType } from './explorerNode';
|
import { ExplorerNode, MessageNode, ResourceType } from './explorerNode';
|
||||||
import { GitService, GitUri } from '../gitService';
|
import { GitService, GitUri } from '../gitService';
|
||||||
|
|
||||||
@@ -9,15 +9,19 @@ export class FileHistoryNode extends ExplorerNode {
|
|||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:file-history';
|
readonly resourceType: ResourceType = 'gitlens:file-history';
|
||||||
|
|
||||||
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
uri: GitUri,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(uri);
|
super(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
const log = await this.git.getLogForFile(this.uri.repoPath, this.uri.fsPath, this.uri.sha);
|
const log = await this.git.getLogForFile(this.uri.repoPath, this.uri.fsPath, this.uri.sha);
|
||||||
if (log === undefined) return [new MessageNode('No file history')];
|
if (log === undefined) return [new MessageNode('No file history')];
|
||||||
|
|
||||||
return [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.git.config.gitExplorer.commitFormat, this.context, this.git))];
|
return [...Iterables.map(log.commits.values(), c => new CommitFileNode(c.fileStatuses[0], c, this.context, this.git, CommitFileNodeDisplayAs.CommitLabel | CommitFileNodeDisplayAs.StatusIcon))];
|
||||||
}
|
}
|
||||||
|
|
||||||
getTreeItem(): TreeItem {
|
getTreeItem(): TreeItem {
|
||||||
|
|||||||
@@ -8,9 +8,13 @@ export class HistoryNode extends ExplorerNode {
|
|||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:history';
|
readonly resourceType: ResourceType = 'gitlens:history';
|
||||||
|
|
||||||
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
uri: GitUri,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(uri);
|
super(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
return [new FileHistoryNode(this.uri, this.context, this.git)];
|
return [new FileHistoryNode(this.uri, this.context, this.git)];
|
||||||
|
|||||||
@@ -10,7 +10,12 @@ export class RemoteNode extends ExplorerNode {
|
|||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:remote';
|
readonly resourceType: ResourceType = 'gitlens:remote';
|
||||||
|
|
||||||
constructor(public readonly remote: GitRemote, uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
public readonly remote: GitRemote,
|
||||||
|
uri: GitUri,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(uri);
|
super(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +24,7 @@ export class RemoteNode extends ExplorerNode {
|
|||||||
if (branches === undefined) return [];
|
if (branches === undefined) return [];
|
||||||
|
|
||||||
branches.sort((a, b) => a.name.localeCompare(b.name));
|
branches.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
return [...Iterables.filterMap(branches, b => !b.remote || !b.name.startsWith(this.remote.name) ? undefined : new BranchHistoryNode(b, this.uri, this.git.config.gitExplorer.commitFormat, this.context, this.git))];
|
return [...Iterables.filterMap(branches, b => !b.remote || !b.name.startsWith(this.remote.name) ? undefined : new BranchHistoryNode(b, this.uri, this.context, this.git))];
|
||||||
}
|
}
|
||||||
|
|
||||||
getTreeItem(): TreeItem {
|
getTreeItem(): TreeItem {
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ export class RemotesNode extends ExplorerNode {
|
|||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:remotes';
|
readonly resourceType: ResourceType = 'gitlens:remotes';
|
||||||
|
|
||||||
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
uri: GitUri,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(uri);
|
super(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,13 @@ export class RepositoryNode extends ExplorerNode {
|
|||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:repository';
|
readonly resourceType: ResourceType = 'gitlens:repository';
|
||||||
|
|
||||||
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
uri: GitUri,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(uri);
|
super(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -2,13 +2,26 @@
|
|||||||
import { ExtensionContext } from 'vscode';
|
import { ExtensionContext } from 'vscode';
|
||||||
import { ResourceType } from './explorerNode';
|
import { ResourceType } from './explorerNode';
|
||||||
import { GitService, GitStashCommit, IGitStatusFile } from '../gitService';
|
import { GitService, GitStashCommit, IGitStatusFile } from '../gitService';
|
||||||
import { CommitFileNode } from './commitFileNode';
|
import { CommitFileNode, CommitFileNodeDisplayAs } from './commitFileNode';
|
||||||
|
|
||||||
export class StashFileNode extends CommitFileNode {
|
export class StashFileNode extends CommitFileNode {
|
||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:stash-file';
|
readonly resourceType: ResourceType = 'gitlens:stash-file';
|
||||||
|
|
||||||
constructor(readonly status: IGitStatusFile, readonly commit: GitStashCommit, readonly context: ExtensionContext, readonly git: GitService) {
|
constructor(
|
||||||
super(status, commit, context, git);
|
readonly status: IGitStatusFile,
|
||||||
|
readonly commit: GitStashCommit,
|
||||||
|
readonly context: ExtensionContext,
|
||||||
|
readonly git: GitService
|
||||||
|
) {
|
||||||
|
super(status, commit, context, git, CommitFileNodeDisplayAs.File);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getCommitTemplate() {
|
||||||
|
return this.git.config.gitExplorer.stashFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getCommitFileTemplate() {
|
||||||
|
return this.git.config.gitExplorer.stashFileFormat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,11 @@ export class StashNode extends ExplorerNode {
|
|||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:stash';
|
readonly resourceType: ResourceType = 'gitlens:stash';
|
||||||
|
|
||||||
constructor(public readonly commit: GitStashCommit, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
public readonly commit: GitStashCommit,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(new GitUri(commit.uri, commit));
|
super(new GitUri(commit.uri, commit));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +31,7 @@ export class StashNode extends ExplorerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve(statuses.map(s => new StashFileNode(s, this.commit, this.context, this.git)));
|
return statuses.map(s => new StashFileNode(s, this.commit, this.context, this.git));
|
||||||
}
|
}
|
||||||
|
|
||||||
getTreeItem(): TreeItem {
|
getTreeItem(): TreeItem {
|
||||||
|
|||||||
@@ -9,9 +9,13 @@ export class StashesNode extends ExplorerNode {
|
|||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:stashes';
|
readonly resourceType: ResourceType = 'gitlens:stashes';
|
||||||
|
|
||||||
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
uri: GitUri,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(uri);
|
super(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
const stash = await this.git.getStashList(this.uri.repoPath!);
|
const stash = await this.git.getStashList(this.uri.repoPath!);
|
||||||
|
|||||||
68
src/views/statusFileCommitsNode.ts
Normal file
68
src/views/statusFileCommitsNode.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
'use strict';
|
||||||
|
import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
||||||
|
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
||||||
|
import { CommitFileNode, CommitFileNodeDisplayAs } from './commitFileNode';
|
||||||
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
|
import { getGitStatusIcon, GitBranch, GitLogCommit, GitService, GitUri, IGitStatusFile, StatusFileFormatter } from '../gitService';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export class StatusFileCommitsNode extends ExplorerNode {
|
||||||
|
|
||||||
|
readonly resourceType: ResourceType = 'gitlens:status-file-commits';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
repoPath: string,
|
||||||
|
public readonly status: IGitStatusFile,
|
||||||
|
public commits: GitLogCommit[],
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService,
|
||||||
|
public readonly branch?: GitBranch
|
||||||
|
) {
|
||||||
|
super(new GitUri(Uri.file(path.resolve(repoPath, status.fileName)), { repoPath: repoPath, fileName: status.fileName, sha: 'HEAD' }));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
|
return this.commits.map(c => new CommitFileNode(this.status, c, this.context, this.git, CommitFileNodeDisplayAs.Commit, this.branch));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
|
const item = new TreeItem(StatusFileFormatter.fromTemplate(this.git.config.gitExplorer.commitFileFormat, this.status), TreeItemCollapsibleState.Collapsed);
|
||||||
|
item.contextValue = this.resourceType;
|
||||||
|
|
||||||
|
const icon = getGitStatusIcon(this.status.status);
|
||||||
|
item.iconPath = {
|
||||||
|
dark: this.context.asAbsolutePath(path.join('images', 'dark', icon)),
|
||||||
|
light: this.context.asAbsolutePath(path.join('images', 'light', icon))
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.commits.length === 1 && this.commits[0].isUncommitted) {
|
||||||
|
item.collapsibleState = TreeItemCollapsibleState.None;
|
||||||
|
item.contextValue = 'gitlens:status-file' as ResourceType;
|
||||||
|
item.command = this.getCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
get commit() {
|
||||||
|
return this.commits[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
getCommand(): Command | undefined {
|
||||||
|
return {
|
||||||
|
title: 'Compare File with Previous Revision',
|
||||||
|
command: Commands.DiffWithPrevious,
|
||||||
|
arguments: [
|
||||||
|
GitUri.fromFileStatus(this.status, this.uri.repoPath!),
|
||||||
|
{
|
||||||
|
commit: this.commit,
|
||||||
|
line: 0,
|
||||||
|
showOptions: {
|
||||||
|
preserveFocus: true,
|
||||||
|
preview: true
|
||||||
|
}
|
||||||
|
} as DiffWithPreviousCommandArgs
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
70
src/views/statusFilesNode.ts
Normal file
70
src/views/statusFilesNode.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
'use strict';
|
||||||
|
import { Arrays, Iterables, Objects } from '../system';
|
||||||
|
import { ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
||||||
|
import { ExplorerNode, ResourceType, ShowAllNode } from './explorerNode';
|
||||||
|
import { GitBranch, GitLog, GitLogCommit, GitService, GitStatus, GitUri, IGitStatusFile } from '../gitService';
|
||||||
|
import { StatusFileCommitsNode } from './statusFileCommitsNode';
|
||||||
|
|
||||||
|
interface IGitStatusFileWithCommit extends IGitStatusFile {
|
||||||
|
commit: GitLogCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StatusFilesNode extends ExplorerNode {
|
||||||
|
|
||||||
|
readonly resourceType: ResourceType = 'gitlens:status-files';
|
||||||
|
|
||||||
|
maxCount: number | undefined = undefined;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public readonly status: GitStatus,
|
||||||
|
public readonly range: string | undefined,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService,
|
||||||
|
public readonly branch?: GitBranch
|
||||||
|
) {
|
||||||
|
super(new GitUri(Uri.file(status.repoPath), { repoPath: status.repoPath, fileName: status.repoPath }));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
|
let statuses: IGitStatusFileWithCommit[];
|
||||||
|
let log: GitLog | undefined;
|
||||||
|
if (this.range !== undefined) {
|
||||||
|
log = await this.git.getLogForRepo(this.status.repoPath, this.range, this.maxCount);
|
||||||
|
if (log === undefined) return [];
|
||||||
|
|
||||||
|
statuses = Array.from(Iterables.flatMap(log.commits.values(), c => {
|
||||||
|
return c.fileStatuses.map(s => {
|
||||||
|
return { ...s, commit: c } as IGitStatusFileWithCommit;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
statuses = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.status.files.length !== 0) {
|
||||||
|
statuses.splice(0, 0, ...this.status.files.map(s => {
|
||||||
|
return { ...s, commit: new GitLogCommit('file', this.status.repoPath, GitService.uncommittedSha, s.fileName, 'You', new Date(), '', s.status, [s], s.originalFileName, 'HEAD', s.fileName) } as IGitStatusFileWithCommit;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
statuses.sort((a, b) => b.commit.date.getTime() - a.commit.date.getTime());
|
||||||
|
|
||||||
|
const groups = Arrays.groupBy(statuses, s => s.fileName);
|
||||||
|
|
||||||
|
const children: (StatusFileCommitsNode | ShowAllNode)[] = [
|
||||||
|
...Iterables.map(Objects.values<IGitStatusFileWithCommit[]>(groups),
|
||||||
|
statuses => new StatusFileCommitsNode(this.uri.repoPath!, statuses[statuses.length - 1], statuses.map(s => s.commit), this.context, this.git, this.branch))
|
||||||
|
];
|
||||||
|
|
||||||
|
if (log !== undefined && log.truncated) {
|
||||||
|
children.push(new ShowAllNode('Show All Changes', this, this.context));
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
|
const item = new TreeItem(`Changed Files`, TreeItemCollapsibleState.Collapsed);
|
||||||
|
item.contextValue = this.resourceType;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,40 @@
|
|||||||
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
||||||
import { ExplorerNode, ResourceType } from './explorerNode';
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
import { GitService, GitUri } from '../gitService';
|
import { GitService, GitUri } from '../gitService';
|
||||||
|
import { StatusFilesNode } from './statusFilesNode';
|
||||||
import { StatusUpstreamNode } from './statusUpstreamNode';
|
import { StatusUpstreamNode } from './statusUpstreamNode';
|
||||||
|
|
||||||
export class StatusNode extends ExplorerNode {
|
export class StatusNode extends ExplorerNode {
|
||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:status';
|
readonly resourceType: ResourceType = 'gitlens:status';
|
||||||
|
|
||||||
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
uri: GitUri,
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(uri);
|
super(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
const status = await this.git.getStatusForRepo(this.uri.repoPath!);
|
const status = await this.git.getStatusForRepo(this.uri.repoPath!);
|
||||||
if (status === undefined) return [];
|
if (status === undefined) return [];
|
||||||
|
|
||||||
const children = [];
|
const children: ExplorerNode[] = [];
|
||||||
|
|
||||||
if (status.state.behind) {
|
if (status.state.behind) {
|
||||||
children.push(new StatusUpstreamNode(status, 'behind', this.git.config.gitExplorer.commitFormat, this.context, this.git));
|
children.push(new StatusUpstreamNode(status, 'behind', this.context, this.git));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.state.ahead) {
|
if (status.state.ahead) {
|
||||||
children.push(new StatusUpstreamNode(status, 'ahead', this.git.config.gitExplorer.commitFormat, this.context, this.git));
|
children.push(new StatusUpstreamNode(status, 'ahead', this.context, this.git));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.files.length !== 0 || status.state.ahead && this.git.config.insiders) {
|
||||||
|
const range = status.state.ahead
|
||||||
|
? `${status.upstream}..${status.branch}`
|
||||||
|
: undefined;
|
||||||
|
children.splice(0, 0, new StatusFilesNode(status, range, this.context, this.git));
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
@@ -57,6 +69,10 @@ export class StatusNode extends ExplorerNode {
|
|||||||
label = `${status.branch} is up-to-date`;
|
label = `${status.branch} is up-to-date`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.git.config.insiders) {
|
||||||
|
hasChildren = hasChildren || status.files.length !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
const item = new TreeItem(label, hasChildren ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None);
|
const item = new TreeItem(label, hasChildren ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None);
|
||||||
item.contextValue = this.resourceType;
|
item.contextValue = this.resourceType;
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import { Iterables } from '../system';
|
import { Iterables } from '../system';
|
||||||
import { ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
import { ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
||||||
|
import { CommitNode } from './commitNode';
|
||||||
import { ExplorerNode, ResourceType } from './explorerNode';
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
import { GitService, GitStatus, GitUri } from '../gitService';
|
import { GitService, GitStatus, GitUri } from '../gitService';
|
||||||
import { CommitNode } from './commitNode';
|
|
||||||
|
|
||||||
export class StatusUpstreamNode extends ExplorerNode {
|
export class StatusUpstreamNode extends ExplorerNode {
|
||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:status-upstream';
|
readonly resourceType: ResourceType = 'gitlens:status-upstream';
|
||||||
|
|
||||||
constructor(public readonly status: GitStatus, public readonly direction: 'ahead' | 'behind', private readonly template: string, protected readonly context: ExtensionContext, protected readonly git: GitService) {
|
constructor(
|
||||||
|
public readonly status: GitStatus,
|
||||||
|
public readonly direction: 'ahead' | 'behind',
|
||||||
|
protected readonly context: ExtensionContext,
|
||||||
|
protected readonly git: GitService
|
||||||
|
) {
|
||||||
super(new GitUri(Uri.file(status.repoPath), { repoPath: status.repoPath, fileName: status.repoPath }));
|
super(new GitUri(Uri.file(status.repoPath), { repoPath: status.repoPath, fileName: status.repoPath }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,10 +22,11 @@ export class StatusUpstreamNode extends ExplorerNode {
|
|||||||
const range = this.direction === 'ahead'
|
const range = this.direction === 'ahead'
|
||||||
? `${this.status.upstream}..${this.status.branch}`
|
? `${this.status.upstream}..${this.status.branch}`
|
||||||
: `${this.status.branch}..${this.status.upstream}`;
|
: `${this.status.branch}..${this.status.upstream}`;
|
||||||
|
|
||||||
let log = await this.git.getLogForRepo(this.uri.repoPath!, range, 0);
|
let log = await this.git.getLogForRepo(this.uri.repoPath!, range, 0);
|
||||||
if (log === undefined) return [];
|
if (log === undefined) return [];
|
||||||
|
|
||||||
if (this.direction !== 'ahead') return [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.template, this.context, this.git))];
|
if (this.direction !== 'ahead') return [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.context, this.git))];
|
||||||
|
|
||||||
// Since the last commit when we are looking 'ahead' can have no previous (because of the range given) -- look it up
|
// Since the last commit when we are looking 'ahead' can have no previous (because of the range given) -- look it up
|
||||||
const commits = Array.from(log.commits.values());
|
const commits = Array.from(log.commits.values());
|
||||||
@@ -32,8 +38,8 @@ export class StatusUpstreamNode extends ExplorerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...Iterables.map(commits, c => new CommitNode(c, this.template, this.context, this.git))];
|
return [...Iterables.map(commits, c => new CommitNode(c, this.context, this.git))];
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTreeItem(): Promise<TreeItem> {
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
const label = this.direction === 'ahead'
|
const label = this.direction === 'ahead'
|
||||||
|
|||||||
Reference in New Issue
Block a user