163 Commits

Author SHA1 Message Date
Eric Amodio
11eacb27a1 Preps v5.0.0 2017-09-12 19:06:15 -04:00
Eric Amodio
543d39246f Closes #138 - adds ignore whitespace setting 2017-09-12 17:46:22 -04:00
Eric Amodio
6837414f22 Adds more details to remotes in custom view 2017-09-12 15:48:36 -04:00
Eric Amodio
ea6fdbaaf2 Adds groupBy function 2017-09-12 15:47:57 -04:00
Eric Amodio
ccc29e3dfc Reworks remote parsing
Combines same url into same remote
Adds a change event for custom remote providers
Adds a repo change event for custom remote providers
2017-09-12 15:46:44 -04:00
Eric Amodio
48814d4213 Changes show all commits icon 2017-09-12 13:02:04 -04:00
Eric Amodio
c3dd83cf3c Updates documention with remotes exanple 2017-09-12 11:56:17 -04:00
Eric Amodio
77482f4930 Adds openChangedFileChanges to custom view
Adds openChangedFileChangesWithWorking to custom view
Removes unneeded context checks from custom view commands
2017-09-12 11:11:03 -04:00
Eric Amodio
503b2a3785 Fixes issue where the revision wasn't properly opened
Adds ability to provide a branch to open file in remote
2017-09-12 10:38:51 -04:00
Eric Amodio
9464f7e79f Preps v5.0.0-beta.2 2017-09-11 23:51:27 -04:00
Eric Amodio
77ae37c54c Adds rudimentary "paging" to custom view branch history 2017-09-11 23:47:51 -04:00
Eric Amodio
e20ec552b7 Removes branches remote commands if no remotes
Removes branch remote commands if not tracked
2017-09-11 23:41:47 -04:00
Eric Amodio
f911447c5e Formats svg like other icons 2017-09-11 23:38:47 -04:00
Eric Amodio
38c44c808d Fixes double getRemotes call 2017-09-11 21:32:52 -04:00
Eric Amodio
655afb358e Fixes double hovers on blank lines 2017-09-11 21:32:52 -04:00
Eric Amodio
21e0963600 Adds bitbucket server support 2017-09-11 21:32:40 -04:00
Eric Amodio
62580da702 Preps v5.0.0-beta 2017-09-11 03:02:56 -04:00
Eric Amodio
6b97c107eb Updates dependencies 2017-09-11 02:27:49 -04:00
Eric Amodio
92b57580b8 Fixes #120 - Adds custom remotes support 2017-09-11 02:09:32 -04:00
Eric Amodio
e400f27c84 Adds refs changes into repo watcher
Catches branch & remote changes
2017-09-11 00:50:40 -04:00
Eric Amodio
4221e06ae3 Removes history limit for custom view 2017-09-11 00:41:32 -04:00
Eric Amodio
a2dc65c044 Adds message truncation at newline 2017-09-11 00:41:11 -04:00
Eric Amodio
4102bdd471 Reworks git command error handling
Switches to use the new diffWith command
2017-09-11 00:39:52 -04:00
Eric Amodio
d420d82ab2 Removes unneeded shortSha parameter 2017-09-11 00:36:38 -04:00
Eric Amodio
260874fa1d Adds better filename sanitization 2017-09-10 17:44:26 -04:00
Eric Amodio
9d83fbcacb Switches to use the new diffWith command 2017-09-09 15:48:44 -04:00
Eric Amodio
a50f04c569 Adds commands to hover links 2017-09-09 01:57:12 -04:00
Eric Amodio
df0599a832 Adds shortenSha method 2017-09-09 00:43:20 -04:00
Eric Amodio
f05d236e79 Updates dependencies
Updates to latest vscode engine
2017-09-08 18:47:25 -04:00
Eric Amodio
1b7610857a Fixes issue where repo change wasn't fired in some cases
Consolidates repo watching into a single watcher
Adds debounce to repo changes in the custom view
2017-09-08 18:02:43 -04:00
Eric Amodio
04d2c00ebf Fixes issue with branch name truncations (rebase) 2017-09-08 17:03:21 -04:00
Eric Amodio
ece34dba32 Cleans up some command overrides 2017-09-05 21:30:07 -04:00
Eric Amodio
68fcbf713d Fixes regression with not opening line in remote 2017-09-05 21:29:22 -04:00
Eric Amodio
e192c547b1 Fixes #130 - Stops repeated welcome for some users
No idea why the version check fails, but hopefully this will help
2017-09-04 03:30:19 -04:00
Eric Amodio
3835193118 Updates images 2017-09-04 03:05:26 -04:00
Eric Amodio
d161084ccd Fixes issue with stashing untracked files 2017-09-04 03:04:05 -04:00
Eric Amodio
b9c4468cf7 Updates changelog 2017-09-04 01:46:29 -04:00
Eric Amodio
4bacb6fbff Hides remote menus if there are no remotes 2017-09-04 01:46:28 -04:00
Eric Amodio
c98755cc87 Adds refresh of custom view on settings change 2017-09-04 01:46:28 -04:00
Eric Amodio
6d759daaad Avoids remote disambiguation quick pick 2017-09-04 01:46:28 -04:00
Eric Amodio
5a42ce4ed4 Adds remote tracking branch to custom view
Adds setting to show remote tracking branch in custom view
2017-09-04 01:46:28 -04:00
Eric Amodio
a5af318269 Adds message in custom view if no remotes 2017-09-04 01:46:28 -04:00
Eric Amodio
5a2bd02402 Reworks branch parsing to include tracking info
Reworks current branch retrieval for better performance
2017-09-04 01:46:21 -04:00
Eric Amodio
2bba14260f Adds Open Branches in Remote command to the Remote custom view items
Adds Open Repository in Remote command to the Remote custom view items
2017-09-03 16:33:52 -04:00
Eric Amodio
22378d5f25 Updates changelog and readme 2017-09-03 16:03:33 -04:00
Eric Amodio
d1d1db18e2 Changes the icon of the File History custom view items
Provides more information rather than just a commit icon
2017-09-03 15:49:50 -04:00
Eric Amodio
3dab90709b Adds Open File command to History custom view item
Adds Open File in Remote command to History custom view item
2017-09-03 15:44:18 -04:00
Eric Amodio
f58d085352 Adds Open Branches in Remote command
Adds Open Branches in Remote command to the Branches custom view item
Adds Open Repository in Remote command to the Repository Status custom view item
2017-09-03 15:37:52 -04:00
Eric Amodio
a77bb36ee3 Preps v5.0.0-alpha.2 2017-09-03 13:47:13 -04:00
Eric Amodio
5cc9365fa1 Adds more info to the status nodes 2017-09-03 13:40:46 -04:00
Eric Amodio
a587108cab Adds Stash Changes command to the Stashes custom view item 2017-09-03 13:29:33 -04:00
Eric Amodio
1b4350e476 Removes Stash Unstaged Changes option
Changes Stash Changes icon to a +
2017-09-03 13:23:17 -04:00
Eric Amodio
586785cfb8 Changes stashes icon to match custom view 2017-09-03 13:22:40 -04:00
Eric Amodio
04df931902 Adds Refresh command to most custom view items
Updates custom view when repo changes (brute force for now)
2017-09-03 12:59:16 -04:00
Eric Amodio
d31eb25451 Adds Apply Changes command to custom view files
Adds Stash Changes command to SCM view items
2017-09-03 12:58:05 -04:00
Eric Amodio
35b16a78ba Adds status indicator to repo icon 2017-09-03 00:25:01 -04:00
Eric Amodio
825b9661fb Preps v5.0.0-alpha
Updates dependencies
2017-09-02 01:53:04 -04:00
Eric Amodio
9782a81e46 Adds new GitLens custom view 2017-09-02 01:43:08 -04:00
Eric Amodio
ed58dc3b49 Preps v4.5.0-beta 2017-08-30 12:25:51 -04:00
Eric Amodio
480dcb95fb Adds a file history explorer view 2017-08-30 12:25:07 -04:00
Eric Amodio
ef41176ea7 Defaults stashes format to ${filePath}
Adds message when there are no stashes
Cleans up the stash explorer
2017-08-30 12:25:07 -04:00
Eric Amodio
bcd83566a1 Reworks ExplorerNode base class
Adds TextExplorerNode for messages
2017-08-30 12:25:07 -04:00
Eric Amodio
ca089777db Adds ${filePath} support to status file formatting 2017-08-30 12:25:07 -04:00
Eric Amodio
a255eea949 Splits code lens out of GitService 2017-08-30 12:25:07 -04:00
Eric Amodio
1ffb42a090 Updates dependencies 2017-08-30 12:25:07 -04:00
Eric Amodio
bc2f1b192a Preps v4.4.3 2017-08-30 12:19:57 -04:00
Eric Amodio
7d99624068 Adds more logging to track down #130 2017-08-30 12:19:33 -04:00
Eric Amodio
c258d04381 Fixes #135 - Full-width chars break gutter annotations (really) 2017-08-30 11:46:41 -04:00
Eric Amodio
4c4926c8b5 Preps v4.4.2 2017-08-29 22:48:59 -04:00
Eric Amodio
6255b26fd2 Fixes #135 - Full-width chars break gutter annotations 2017-08-29 22:47:12 -04:00
Eric Amodio
4db2b116c2 Preps v4.4.1 2017-08-23 21:01:16 -04:00
Eric Amodio
b40579f4b2 Updates dependencies 2017-08-23 21:01:01 -04:00
Eric Amodio
15c981ba06 Fixes #114 - Stylus file jumpiness 2017-08-23 21:00:29 -04:00
Eric Amodio
c2f78a7242 Preps v4.4.0 2017-08-18 11:58:23 -04:00
Eric Amodio
d3013a03d4 Preps v4.4.0-beta 2017-08-17 03:30:28 -04:00
Eric Amodio
323148d9ab Disables whitespace toggling by default 2017-08-17 03:24:09 -04:00
Eric Amodio
03fefaad3b Disables current line blame annotations when debugging 2017-08-17 03:22:07 -04:00
Eric Amodio
f11c00ceda Changes the annotation line separator rendering 2017-08-17 02:23:35 -04:00
Eric Amodio
0e338308c6 Fixes jumpiness when opening a diff 2017-08-17 01:18:00 -04:00
Eric Amodio
e39bd5dad3 Removes setting & command to show/hide stashes view 2017-08-16 23:33:27 -04:00
Eric Amodio
00cdd2e375 Adds "on" state to file annotation command
Adds "progress" state to file annotation command
2017-08-15 01:35:50 -04:00
Eric Amodio
787e0e6aa1 Updates dependencies 2017-08-14 20:52:45 -04:00
Eric Amodio
46554e93f3 Changes gitter to slack 2017-08-02 10:51:23 -04:00
Eric Amodio
4160234962 Add slack chat badge 2017-08-02 10:49:55 -04:00
Eric Amodio
0bd31099ce Keeps the hover info in the whitespace area at the start of the current line 2017-07-28 22:00:01 -04:00
Eric Amodio
a272f8f6a4 Preps v4.3.3 2017-07-28 17:37:08 -04:00
Eric Amodio
e10d7eb648 Increases performance of blame annotations
especially for larger file
2017-07-28 17:09:34 -04:00
Eric Amodio
9d9c3181f7 Fixes #107 - Double-byte characters break blame layout 2017-07-27 00:56:33 -04:00
Eric Amodio
68a42fd0c7 Adds progress indicator for long annotation operations 2017-07-26 23:26:07 -04:00
Eric Amodio
28db0bf2f5 Updates to v2.0 task schema 2017-07-26 23:25:32 -04:00
Eric Amodio
5f85388db7 Preps v4.3.2
Fixes #118 - stopped working on latest insiders build
2017-07-20 22:37:51 +02:00
Eric Amodio
4d167c3cdd Fixes lint issues 2017-07-20 22:19:58 +02:00
Eric Amodio
4826e99986 Updates dependencies 2017-07-20 22:14:13 +02:00
Johannes Rieken
459a8dce1d mixin state of super type
As discussed, this should be ok for Insiders and Stable and accommodate for our URI changes.
2017-07-20 21:54:37 +02:00
Eric Amodio
2650a84105 Preps v4.3.1 2017-07-03 09:50:31 -04:00
Eric Amodio
a2cd57cf95 Fixes #108 - hides stash explorer by default
Adds stash explorer toggle command
2017-07-03 09:50:12 -04:00
Eric Amodio
62a148c156 Adds rebornix thank you 2017-07-03 02:33:37 -04:00
Eric Amodio
be682c5def Preps v4.3.0 2017-07-03 02:30:06 -04:00
Eric Amodio
12d310bdf1 Adds git stashes screenshot 2017-07-03 02:23:13 -04:00
Eric Amodio
af4f433972 Adds stash commands similar to SCM 2017-07-03 02:00:15 -04:00
Eric Amodio
52275215fe Adds content uri from GitUri 2017-07-03 01:59:02 -04:00
Eric Amodio
71edb1b99a Stops error message with stash apply conflict 2017-07-03 01:57:26 -04:00
Eric Amodio
7f3fdb48fd Removes insiders flag from stash view 2017-07-02 23:16:55 -04:00
Eric Amodio
81a9092455 Removes stash list in explorer command
Rename Show File History in Explorer back to Open File History Explorer
Removes the git explorer view (for now)
2017-07-02 23:12:01 -04:00
Eric Amodio
d288985c26 Adapts stash commands to new structure for views
Adds onDidChangeRepo event to GitService
Refreshes stash view when repo changes
2017-07-02 22:34:55 -04:00
rebornix
b81d873a34 WIP of Stash Explorer commands
# Conflicts:
#	src/commands/stashApply.ts
2017-07-02 22:34:05 -04:00
Eric Amodio
c96a659e9e Fixes uris on nodes 2017-07-02 22:34:05 -04:00
Eric Amodio
d193676502 Adds status icons to explorer views
Adds templating support to explorer views
2017-07-02 22:33:56 -04:00
Eric Amodio
6410a274d5 Renames explorer views
Adds refresh commands for explorer views
Adds context menu commands to both explorer views
2017-07-02 22:33:09 -04:00
Eric Amodio
272bb4db45 Sets line to avoid diff jumping 2017-07-02 22:33:09 -04:00
Eric Amodio
7fbee675f0 Spits branch and status nodes into separate files
Removes status node for now
2017-07-02 22:33:09 -04:00
Eric Amodio
bc21272409 Defers command construction until later
Gets a properly constructed commit to improve performance of opening the diff
2017-07-02 22:32:59 -04:00
Eric Amodio
da450a614d Renames explorerNodes 2017-07-02 22:32:05 -04:00
rebornix
0e4664bab1 Rename Stash Explorer 2017-07-02 22:32:04 -04:00
rebornix
1b4800571d extract stash explorer 2017-07-02 22:32:04 -04:00
Eric Amodio
c812a56eac Adds an experimental custom view (wip) 2017-07-02 22:31:04 -04:00
Eric Amodio
3081632815 Updates dependencies (typescript)
Fixes newly detected typescript errors
2017-07-02 22:23:54 -04:00
Eric Amodio
3d32d86998 Renames onDidBlameabilityChange for consistency 2017-06-29 01:41:10 -04:00
Eric Amodio
0a9559f5a5 Reworks commanding structure for less redundancy
Adds command args copying when needed
2017-06-28 01:06:20 -04:00
Eric Amodio
8693c87523 Updates dependencies 2017-06-27 18:34:28 -04:00
Eric Amodio
54c077eb8d Switches to png icon 2017-06-27 01:45:13 -04:00
Eric Amodio
ee124b5325 Preps v4.2.0 2017-06-27 01:34:00 -04:00
Eric Amodio
63a0646c8f Adds commands to the SCM menus 2017-06-27 01:34:00 -04:00
Eric Amodio
cb360c5a3d Renames Compare File with... command 2017-06-27 01:34:00 -04:00
Eric Amodio
3bf5f23c66 Adds diffWithRevision command 2017-06-27 01:34:00 -04:00
Eric Amodio
1751987868 Reworks more commands deal with context 2017-06-27 01:33:59 -04:00
Eric Amodio
9179b70875 Avoids re-setting the line if it is already set 2017-06-27 01:33:59 -04:00
Eric Amodio
93ea2c7145 Fixes another infinite loop in close command 2017-06-27 01:33:59 -04:00
Eric Amodio
f9275a8e1a Reworks command structure with context 2017-06-27 01:33:59 -04:00
Eric Amodio
ceb9c5e126 Removes "Line" from some command titles 2017-06-27 01:33:53 -04:00
Eric Amodio
e42af14b11 Adds status formatter 2017-06-26 23:54:50 -04:00
Eric Amodio
bcfa2cb4d7 Renames icon references to octicon 2017-06-26 23:53:18 -04:00
Eric Amodio
16963ee054 Fixes typo 2017-06-26 23:48:44 -04:00
Eric Amodio
db1bdaa778 Updates excludes 2017-06-26 23:47:31 -04:00
Eric Amodio
ccac13088c Fixes #103 - toggled line annotation state is sometimes forgotten
Often happened when also toggling file annotations
2017-06-26 23:37:16 -04:00
Eric Amodio
899a69357c Fixes a few spelling errors
Adds a better description to blame.line.enabled to be clearer about its behavior
Adds a better description to codeLens.enabled to be clearer about its behavior
2017-06-26 22:49:23 -04:00
Eric Amodio
c78c3c7525 Preps v4.1.4 2017-06-25 13:26:33 -04:00
Eric Amodio
1cbf0b2c73 Updates dependencies 2017-06-25 13:26:33 -04:00
Eric Amodio
191a158b3b Optimizes diff with previous command 2017-06-25 13:26:33 -04:00
Eric Amodio
f553980146 Attempts to fix #99
undo/redo spawns too many git processes
2017-06-25 13:26:19 -04:00
Eric Amodio
a306ba2b98 Stops trying to set the line if we don't have one 2017-06-25 00:29:11 -04:00
Eric Amodio
1cdd94cb46 Adds a with method to commit 2017-06-24 17:54:19 -04:00
Eric Amodio
12caa017a9 Fixes issues with changes showing wrong diff
Refactors diff parsing
2017-06-24 17:52:52 -04:00
Eric Amodio
ad790b274b Preps v4.1.3 2017-06-20 01:30:05 -04:00
Eric Amodio
55ef004332 Fixes changes hover not showing the correct diff when showing recent changes annotations 2017-06-19 23:23:20 -04:00
Eric Amodio
329d5a496d Preps v4.1.2 2017-06-15 23:54:43 -04:00
Eric Amodio
6b4642d8c8 Fixes #96 - stops opening external diff if configured 2017-06-15 23:44:41 -04:00
Eric Amodio
45aa9b17ac Changes to use enum for glyphs 2017-06-13 22:34:51 -04:00
Eric Amodio
9b908e27ba Preps v4.1.1 2017-06-13 03:21:49 -04:00
Eric Amodio
0eb6026a82 Fixes missing icons 2017-06-13 03:18:14 -04:00
Eric Amodio
5823457ea0 Removes invalid signature 2017-06-13 03:15:15 -04:00
Eric Amodio
64b929fd5b Preps v4.1.0 2017-06-13 01:33:23 -04:00
Eric Amodio
a618b7efe6 Adds ability to esc out of file annotations 2017-06-13 01:31:13 -04:00
Eric Amodio
a2903ce4a9 Refactors formatters
Moves annotation messages from formatter to annotations
Moves icons into dark/light folders
2017-06-13 00:14:10 -04:00
Eric Amodio
12debe583c Cleans up more duplicate code 2017-06-12 12:25:35 -04:00
Eric Amodio
0160e064be Preps v4.1-beta.2 2017-06-12 12:13:48 -04:00
Eric Amodio
76961d6697 Fixes #33 - escape commit message 2017-06-12 12:13:48 -04:00
Eric Amodio
cc827f4711 Adds more notes on copy commands 2017-06-12 12:13:48 -04:00
Eric Amodio
6f3441a9e7 Adds default date format 2017-06-12 12:13:48 -04:00
Eric Amodio
64ae82075e Cleans up some duplicate code 2017-06-12 12:13:48 -04:00
Eric Amodio
5624567daa Fixes regression with code lens 2017-06-12 12:13:48 -04:00
Eric Amodio
c1c65127b7 Fixes extra newline in multiline commit messages 2017-06-11 17:56:07 -04:00
Eric Amodio
ce98f02706 Adds details hover to recent changes annotations 2017-06-11 17:43:53 -04:00
188 changed files with 7474 additions and 2886 deletions

View File

@@ -1,13 +1,13 @@
{ {
"editor.insertSpaces": true, "editor.insertSpaces": true,
"files.exclude": { "files.exclude": {
"node_modules": true, "**/node_modules": true,
"out": true "**/out": true
}, },
"files.trimTrailingWhitespace": true, "files.trimTrailingWhitespace": true,
"search.exclude": { "search.exclude": {
"node_modules": true, "**/node_modules": true,
"out": true "**/out": true
}, },
"javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
"typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version

25
.vscode/tasks.json vendored
View File

@@ -9,13 +9,18 @@
// A task runner that calls a custom npm script that compiles the extension. // A task runner that calls a custom npm script that compiles the extension.
{ {
"version": "2.0.0", "version": "2.0.0",
"showOutput": "silent", "presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"tasks": [ "tasks": [
{ {
"taskName": "compile", "label": "compile",
"command": "npm run compile --silent", "type": "npm",
"isBuildCommand": true, "script": "compile",
"isShellCommand": true, "group": "build",
"problemMatcher": [ "problemMatcher": [
"$tsc", "$tsc",
{ {
@@ -25,19 +30,17 @@
] ]
}, },
{ {
"taskName": "lint", "type": "npm",
"command": "npm run lint --silent", "script": "lint",
"isShellCommand": true,
"problemMatcher": { "problemMatcher": {
"base": "$tslint5", "base": "$tslint5",
"fileLocation": "relative" "fileLocation": "relative"
} }
}, },
{ {
"taskName": "watch", "type": "npm",
"command": "npm run watch --silent", "script": "watch",
"isBackground": true, "isBackground": true,
"isShellCommand": true,
"problemMatcher": "$tsc-watch" "problemMatcher": "$tsc-watch"
} }
] ]

View File

@@ -1,4 +1,6 @@
!images/*.svg !images/dark/**
!images/light/**
!images/gitlens-icon.png
images/** images/**
.vscode/** .vscode/**
.vscode-test/** .vscode-test/**

View File

@@ -4,17 +4,231 @@ 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/).
## [4.1.0-beta] - 2017-06-10 ## [5.0.0] - 2017-09-12
### Added
- Adds an all-new `GitLens` custom view to the Explorer activity
- `Repository View` - provides a full repository explorer
![GitLens Repository view](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-git-custom-view-repository.png)
- `Repository Status` node — provides the status of the repository
- Provides the name of the current branch, its upstream tracking branch (if available), and its upstream status (if available)
- Provides indicator dots on the repository icon which denote the following:
- `None` - up-to-date with the upstream
- `Green` - ahead of the upstream
- `Red` - behind the upstream
- `Yellow` - both ahead of and behind the upstream
- Provides additional nodes, if the current branch is not synchronized with the upstream, to quickly see and explore the specific commits ahead and/or behind the upstream
- Provides a context menu with `Open Repository in Remote`, and `Refresh` commands
- `Branches` node — provides a list of the local branches
- Indicates which branch is the current branch and optionally shows the remote tracking branch
- Expand each branch to easily see its revision (commit) history
- Expand each revision (commit) to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu on each changed file with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, `Show File History`, and `Show Commit File Details` commands
- Provides a context menu on each revision (commit) with `Open Commit in Remote`, `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit ID to Clipboard`, `Copy Commit Message to Clipboard`, `Show Commit Details`, and `Refresh` commands
- Provides a context menu on each branch with `Open Branch in Remote`, and `Refresh` commands
- Provides a context menu with `Open Branches in Remote`, and `Refresh` commands
- `Remotes` node — provides a list of remotes
- Indicates the direction of the remote (fetch, push, both), remote service (if applicable), and repository path
- Expand each remote to see its list of branches
- Expand each branch to easily see its revision (commit) history
- Expand each revision (commit) to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu on each changed file with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, and `Show Commit File Details` commands
- Provides a context menu on each revision (commit) with `Open Commit in Remote`, `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit ID to Clipboard`, `Copy Commit Message to Clipboard`,`Show Commit Details`, and `Refresh` commands
- Provides a context menu on each remote with `Open Branches in Remote`, `Open Repository in Remote`, and `Refresh` commands
- Provides a context menu with a `Refresh` command
- `Stashes` node — provides a list of stashed changes
- Expand each stash to quickly see the set of files stashed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu with `Stash Changes`, and `Refresh` commands
- Provides a context menu on each stash with `Apply Stashed Changes` (confirmation required), `Delete Stashed Changes` (confirmation required), `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit Message to Clipboard`, and `Refresh` commands
- Provides a context menu on each stashed file with `Apply Changes`, `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, and `Show File History` commands
- `History View` - provides the revision history of the active file
![GitLens History view](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-git-custom-view-history.png)
- Automatically updates to track the active editor
- Provides a context menu with `Open File`, `Open File in Remote`, and `Refresh` commands
- Provides a context menu on each revision (commit) with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, and `Show Commit File Details` commands
- Quickly switch between views using the `Switch to Repository View` or `Switch to History View` commands
- Provides toolbar commands to `Search Commits`, `Switch to Repository View` or `Switch to History View`, and `Refresh`
- Adds all-new interactivity to the hover annotations
![Hover Annotations](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotations.png)
- Adds the following command-links to the `details` hover annotation
- Clicking the commit id will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds the following command-links to the `changes` hover annotation
- Clicking on `Changes` will run the `Compare File Revisions` command (`gitlens.diffWith`)
- Clicking the current and previous commit ids will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds support for remote services with custom domains -- closes [#120](https://github.com/eamodio/vscode-gitlens/issues/120)
- Adds support for the Bitbucket Server (previously called Stash) remote service -- closes [#120](https://github.com/eamodio/vscode-gitlens/issues/120)
- Adds `gitlens.blame.ignoreWhitespace` setting to specify whether or not to ignore whitespace when comparing revisions during blame operations -- closes [#138](https://github.com/eamodio/vscode-gitlens/issues/138)
- Adds `Compare File Revisions` command (`gitlens.diffWith`) - compares the specified file revisions
- Adds `Open Branches in Remote` command (`gitlens.openBranchesInRemote`) - opens the branches in the supported remote service
- Adds `Stash Changes` command (`gitlens.stashSave`) to the source control group context menu -- can now stash a group of files
- Adds `Stash Changes` command (`gitlens.stashSave`) to the source control resource context menu -- can now stash individual files (works with multi-select too!)
- Adds `gitlens.gitExplorer.view` setting to specify the starting view (mode) of the `GitLens` custom view
- Adds `gitlens.gitExplorer.showTrackingBranch` setting to specify whether or not to show the tracking branch when displaying local branches in the `GitLens` custom view
- Adds `gitlens.gitExplorer.commitFormat` setting to specify the format of committed changes in the `GitLens` custom view
- Adds `gitlens.gitExplorer.commitFileFormat` setting to specify the format of a committed file in the `GitLens` custom view
- Adds `gitlens.gitExplorer.stashFormat` setting to specify the format of stashed changes in the `GitLens` custom view
- Adds `gitlens.gitExplorer.stashFileFormat` setting to specify the format of a stashed file in the `GitLens` custom view
- Adds `${filePath}` token to file formatting settings
### Changed
- Changes `Show Stashed Changes` option icon in repository status quick pick menu to match the `GitLens` custom view
- Changes `Stash Changes` option icon in stashed changes quick pick menu to a plus (+)
- Renames `Compare File with Previous` command (`gitlens.diffWithPrevious`) to `Compare File with Previous Revision`
- Renames `Compare File with Next Commit` command (`gitlens.diffWithNext`) to `Compare File with Next Revision`
- Renames `Compare File with Working Tree` command (`gitlens.diffWithWorking`) to `Compare File with Working Revision`
- Renames `Compare Line Commit with Previous` command (`gitlens.diffLineWithPrevious`) to `Compare Line Revision with Previous`
- Renames `Compare Line Commit with Working Tree` command (`gitlens.diffLineWithWorking`) to `Compare Line Revision with Working`
### Removed
- Removes `Git Stashes` custom view view - as it's functionality has been folded into the new `GitLens` custom view
- Removes `gitlens.stashExplorer.stashFormat` setting
- Removes `gitlens.stashExplorer.stashFileFormat` setting
- Removes `Stash Unstaged Changes` option from stashed changes quick pick menu -- didn't work as intended
- Removes the seeding of the commit search command from the clipboard
### Fixed
- Fixes an issue where double hover annotations could be shown on blank lines
- Fixes an issue where remote branches couldn't be opened properly in their remote service
- Fixes [#130](https://github.com/eamodio/vscode-gitlens/issues/130) - First-run "Thank you for choosing GitLens! [...]" info message shown on every start up
- Fixes an issue where sometimes diffs (via branch name) wouldn't open properly
- Fixes an issue where remotes are queried more than once on startup
## [4.4.3] - 2017-08-30
## Fixed
- Fixes [#135](https://github.com/eamodio/vscode-gitlens/issues/135) - Full-width characters break gutter annotations (really this time)
## [4.4.2] - 2017-08-29
## Fixed
- Fixes [#135](https://github.com/eamodio/vscode-gitlens/issues/135) - Full-width characters break gutter annotations
## [4.4.1] - 2017-08-23
## Fixed
- Fixes [#114](https://github.com/eamodio/vscode-gitlens/issues/114) - Stylus files makes code lens freak out
## [4.4.0] - 2017-08-18
## Added
- Adds a progress indicator to the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) icon -- pulses while annotations are computed
- Adds an active state to the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) icon -- turns orange while the annotations are visible
- Adds automatic disabling of the current line blame annotations when starting a debug session and will restore them when the debug session ends -- can still be manually toggled via the `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`)
## Changed
- Changes chat links from Gitter to [Slack](https://join.slack.com/t/vscode-gitlens/shared_invite/MjIxOTgxNDE3NzM0LTE1MDE2Nzk1MTgtMjkwMmZjMzcxNQ)
- Changes the look of the line separators on the gutter blame annotations
- Changes the `gitlens.advanced.toggleWhitespace.enabled` configuration setting to default to `false` -- thanks to the awesome work in vscode by Alexandru Dima ([@alexandrudima](https://github.com/alexandrudima)) this is no longer required!
## Removed
- Removes unneeded `gitlens.stashExplorer.enabled` configuration setting since users can add or remove custom views natively now
- Removes unneeded `Toggle Git Stashes Explorer` command (`gitlens.stashExplorer.toggle`) since users can add or remove custom views natively now
- Removes the `gitlens.theme.annotations.file.hover.separateLines` configuration setting
## Fixed
- Fixes jumpiness when opening a diff to a certain line
## [4.3.3] - 2017-07-28
## Added
- Adds progress indicator for when computing annotations takes a while
## Changed
- Optimizes performance of the providing blame annotations, especially for large files (saw a 3.5x improvement on some files)
## Fixed
- Fixes [#107](https://github.com/eamodio/vscode-gitlens/issues/107) - Double-byte characters break blame layout (still requires proper font support)
## [4.3.2] - 2017-07-20
## Fixed
- Fixes [#118](https://github.com/eamodio/vscode-gitlens/issues/118) - GitLens stopped working on latest insiders build -- thanks to [PR #121](https://github.com/eamodio/vscode-gitlens/pull/121) by Johannes Rieken ([@jrieken](https://github.com/jrieken))
## [4.3.1] - 2017-07-03
## Added
- Adds `gitlens.stashExplorer.enabled` setting to specify whether or not to show the `Git Stashes` custom view
- Adds `Toggle Git Stashes Explorer` command (`gitlens.stashExplorer.toggle`) - toggles the `Git Stashes` custom view on and off
## Changed
- Hides the `Git Stashes` custom view by default
## Fixed
- Fixes [#108](https://github.com/eamodio/vscode-gitlens/issues/108) - Option to remove stash explorer from the main explorer?
## [4.3.0] - 2017-07-03
## Added
- Adds `Git Stashes` custom view to the Explorer activity
- Shows all of the stashed changes in the repository
- Provides toolbar buttons to `Stash Changes` and `Refresh`
- Provides a context menu with `Apply Stashed Changes` and `Delete Stashed Changes` commands - both require a confirmation
- Expand each stash to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu with `Open Changes`, `Open File`, `Open Stashed File`, `Open File in Remote`, and `Compare File with Working Tree` commands
## [4.2.0] - 2017-06-27
## Added
- Adds `Compare File with Revision...` command (`gitlens.diffWithRevision`) - compares the active file with the selected revision of the same file
- Adds `Open Changed Files` command (`gitlens.openChangedFiles`) to the source control group context menu
- Adds `Close Unchanged Files` command (`gitlens.closeUnchangedFiles`) to the source control group context menu
- Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the source control resource context menu
- Adds `Compare File with Revision...` command (`gitlens.diffWithRevision`) to the source control resource context menu
- Adds `Show File History` command (`gitlens.showQuickFileHistory`) to the source control resource context menu
## Changed
- Renames `Compare File with...` command to `Compare File with Branch...`
- Renames `Open Line Commit in Remote` command to `Open Commit in Remote`
- Renames `Show Line Commit Details` command to `Show Commit File Details`
- Updates the description of `gitlens.blame.line.enabled` to be clearer about its behavior
- Updates the description of `gitlens.codeLens.enabled` to be clearer about its behavior
### Fixed
- Fixes [#103](https://github.com/eamodio/vscode-gitlens/issues/103) - Toggle file blame annotations disables line blame annotations if line blame annotations are off by default
- Fixes another infinite loop in the `Close Unchanged Files` command
## [4.1.4] - 2017-06-25
## Changed
- Optimizes performance of the `Compare with Previous` commands - also avoids trying to focus a line if we don't have one
### Fixed
- Fixes `changes` (diff) hover not showing the correct previous line (for real this time)
- Attempts to fix [#99](https://github.com/eamodio/vscode-gitlens/issues/99) - undo/redo spawns too many git processes
## [4.1.3] - 2017-06-20
### Fixed
- Fixes `changes` (diff) hover not showing the correct previous line when showing recent changes annotations of the whole-file
## [4.1.2] - 2017-06-15
### Fixed
- Fixes [#96](https://github.com/eamodio/vscode-gitlens/issues/96) - External diff command can be unintentionally triggered
## [4.1.1] - 2017-06-13
### Added
- Adds an `alt` command to the `Toggle File Blame Annotations` command button, which when you hold down `alt` and click it will execute the `Toggle Recent File Changes Annotations` command instead
### Fixed
- Fixes missing `Toggle File Blame Annotations` command icon
## [4.1.0] - 2017-06-13
### Added ### Added
- Adds all-new recent changes annotations of the whole-file - annotates and highlights all of lines changed in the most recent commit - Adds all-new recent changes annotations of the whole-file - annotates and highlights all of lines changed in the most recent commit
- Can customize the [layout](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#file-recent-changes-annotation-settings), as well as the [theme](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#theme-settings) - Can customize the [layout](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#file-recent-changes-annotation-settings), as well as the [theme](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens#theme-settings)
- Adds `Toggle Recent File Changes Annotations` command (`gitlens.toggleFileRecentChanges`) - toggles the recent changes annotations on and off - Adds `Toggle Recent File Changes Annotations` command (`gitlens.toggleFileRecentChanges`) - toggles the recent changes annotations on and off
- Adds ability to press `Escape` to quickly toggle any whole-file annotations off
- Improves performance - Improves performance
- Optimized git output parsing to increase speed and reduce memory usage - Optimized git output parsing to increase speed and dramatically reduce memory usage
- Defers diff chunk parsing until it is actually required - Defers diff chunk parsing until it is actually required
- Adds `gitlens.defaultDateFormat` setting to specify how all absolute dates will be formatted by default
### Fixed ### Fixed
- Fixes excessive memory usage when parsing diffs - Fixes excessive memory usage when parsing diffs
- Fixes extra newline in multi-line commit messages
- Fixes (again) [#33](https://github.com/eamodio/vscode-gitlens/issues/33) - Commit messages can causes markdown formatting in hovers
## [4.0.1] - 2017-06-09 ## [4.0.1] - 2017-06-09
### Fixed ### Fixed
@@ -97,7 +311,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
### Added ### Added
- Improves performance - Improves performance
- Reduces the number of git calls on known "untrackables" - Reduces the number of git calls on known "untrackables"
- Caches many more git commands to reduce git command roundtrips and parsing - Caches many more git commands to reduce git command round-trips and parsing
- Increases the debounce (delay) on cursor movement to reduce lag when navigating around a file - Increases the debounce (delay) on cursor movement to reduce lag when navigating around a file
- Adds diff information (the line's previous version) into the active line hover when the current line is uncommitted - Adds diff information (the line's previous version) into the active line hover when the current line is uncommitted
- Adds `gitlens.statusBar.alignment` settings to control the alignment of the status bar -- thanks to [PR #72](https://github.com/eamodio/vscode-gitlens/pull/72) by Zack Schuster ([@zackschuster](https://github.com/zackschuster))! - Adds `gitlens.statusBar.alignment` settings to control the alignment of the status bar -- thanks to [PR #72](https://github.com/eamodio/vscode-gitlens/pull/72) by Zack Schuster ([@zackschuster](https://github.com/zackschuster))!
@@ -288,7 +502,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
### Fixed ### Fixed
- Fixes issue with `gitlens.diffWithPrevious` command execution via code lens when the code lens was not at the document/file level - Fixes issue with `gitlens.diffWithPrevious` command execution via code lens when the code lens was not at the document/file level
- Fixes issue where full shas were displayed on the file/blame history explorers - Fixes issue where full shas were displayed on the file/blame history explorers
- Fixes [#30](https://github.com/eamodio/vscode-gitlens/issues/30) - Diff with Working Tree fails from repo/commit quickpick list if file was renamed (and the commit was before the rename) - Fixes [#30](https://github.com/eamodio/vscode-gitlens/issues/30) - Diff with Working Tree fails from repo/commit quick pick list if file was renamed (and the commit was before the rename)
- Fixes various other quick pick menu command issues when a file was renamed - Fixes various other quick pick menu command issues when a file was renamed
- Fixes various issues when caching is disabled - Fixes various issues when caching is disabled
- Fixes issues with parsing commits history - Fixes issues with parsing commits history
@@ -391,7 +605,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [2.9.0] ## [2.9.0]
### Changed ### Changed
- To accomodate the realization that blame information is invalid when a file has unsaved changes, the following behavior changes have been made - To accommodate the realization that blame information is invalid when a file has unsaved changes, the following behavior changes have been made
- Status bar blame information will hide - Status bar blame information will hide
- Code lens change to a `Cannot determine...` message and become unclickable - Code lens change to a `Cannot determine...` message and become unclickable
- Many menu choices and commands will hide - Many menu choices and commands will hide
@@ -429,7 +643,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
### Fixed ### Fixed
- Fixes [#34](https://github.com/eamodio/vscode-gitlens/issues/34) - Open file should open the selected version of the file - Fixes [#34](https://github.com/eamodio/vscode-gitlens/issues/34) - Open file should open the selected version of the file
- Fixes some issue where some editors opened by the quickpick would not be opened in preview tabs - Fixes some issue where some editors opened by the quick pick would not be opened in preview tabs
- Fixes issue where copy to clipboard commands would fail if there was no active editor - Fixes issue where copy to clipboard commands would fail if there was no active editor
- Fixes issue where active line annotations would show for opened versioned files - Fixes issue where active line annotations would show for opened versioned files
- Fixes issue where code lens compare commands on opened versioned files would fail - Fixes issue where code lens compare commands on opened versioned files would fail

159
README.md
View File

@@ -1,11 +1,11 @@
[![](https://vsmarketplacebadge.apphb.com/version/eamodio.gitlens.svg)](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) [![](https://vsmarketplacebadge.apphb.com/version/eamodio.gitlens.svg)](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
[![](https://vsmarketplacebadge.apphb.com/installs/eamodio.gitlens.svg)](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) [![](https://vsmarketplacebadge.apphb.com/installs/eamodio.gitlens.svg)](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
[![](https://vsmarketplacebadge.apphb.com/rating/eamodio.gitlens.svg)](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) [![](https://vsmarketplacebadge.apphb.com/rating/eamodio.gitlens.svg)](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
[![Chat at https://gitter.im/vscode-gitlens/Lobby](https://badges.gitter.im/vscode-gitlens/Lobby.svg)](https://gitter.im/vscode-gitlens/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Chat at https://vscode-gitlens.slack.com/](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/chat-badge.png)](https://join.slack.com/t/vscode-gitlens/shared_invite/MjIxOTgxNDE3NzM0LTE1MDE2Nzk1MTgtMjkwMmZjMzcxNQ)
# GitLens # GitLens
GitLens **supercharges** the built-in Visual Studio Code Git capabilities. It helps you to **visualize code authorship** at a glance via Git blame annotations and code lens, **seamlessly navigate and explore** the history of a file or branch, **gain valuable insights** via powerful comparision commands, and so much more. GitLens **supercharges** the built-in Visual Studio Code Git capabilities. It helps you to **visualize code authorship** at a glance via Git blame annotations and code lens, **seamlessly navigate and explore** the history of a file or branch, **gain valuable insights** via powerful comparison commands, and so much more.
GitLens provides an unobtrusive blame annotation at the end of the current line, a status bar item showing the commit information (author and date, by default) of the current line, code lens showing the most recent commit and # of authors of the file and/or code block, and many commands for exploring commits and histories, comparing and navigating revisions, stash access, repository status, and more. GitLens is also [highly customizable](#extension-settings) to meet your specific needs — find code lens intrusive or the current line blame annotation distracting — no problem, it is easy to [turn them off or change how they behave](#extension-settings). GitLens provides an unobtrusive blame annotation at the end of the current line, a status bar item showing the commit information (author and date, by default) of the current line, code lens showing the most recent commit and # of authors of the file and/or code block, and many commands for exploring commits and histories, comparing and navigating revisions, stash access, repository status, and more. GitLens is also [highly customizable](#extension-settings) to meet your specific needs — find code lens intrusive or the current line blame annotation distracting — no problem, it is easy to [turn them off or change how they behave](#extension-settings).
@@ -20,8 +20,11 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
![Line Blame Annotation](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotation.png) ![Line Blame Annotation](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotation.png)
- Contains the author, date, and message of the line's most recent commit, by [default](#line-blame-annotation-settings) - Contains the author, date, and message of the line's most recent commit, by [default](#line-blame-annotation-settings)
- Also adds a `details` hover annotation to the current line annotation which provides more commit details ([optional](#line-blame-annotation-settings), on by default) - Adds a `details` hover annotation to the current line annotation, which provides more commit details ([optional](#line-blame-annotation-settings), on by default)
- Also adds a `changes` (diff) hover annotation to the current line annotation which provides **instant** access to the line's previous version ([optional](#line-blame-annotation-settings), on by default) - Clicking the commit id will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds a `changes` (diff) hover annotation to the current line annotation, which provides **instant** access to the line's previous version ([optional](#line-blame-annotation-settings), on by default)
- Clicking on `Changes` will run the `Compare File Revisions` command (`gitlens.diffWith`)
- Clicking the current and previous commit ids will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
![Line Blame Annotations](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotations.png) ![Line Blame Annotations](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-line-blame-annotations.png)
@@ -30,7 +33,11 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
![File Blame Annotation](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-file-blame-annotations.png) ![File Blame Annotation](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-file-blame-annotations.png)
- Choose between `gutter` (default) and `hover` [annotation styles](#file-blame-annotation-settings) - Choose between `gutter` (default) and `hover` [annotation styles](#file-blame-annotation-settings)
- Contains the commit message and date, by [default](#file-blame-annotation-settings) - Contains the commit message and date, by [default](#file-blame-annotation-settings)
- Also adds a `details` hover annotation to the line's annotation which provides more commit details ([optional](#file-blame-annotation-settings), on by default) - Adds a `details` hover annotation to the line's annotation, which provides more commit details ([optional](#file-blame-annotation-settings), on by default)
- Clicking the commit id will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds a `heatmap` (age) indicator to the gutter annotations (on right edge by [default](#file-blame-annotation-settings)), which provides an easy, at-a-glance way to tell the age of a line ([optional](#file-blame-annotation-settings), on by default)
- Indicator ranges from bright yellow (newer) to dark brown (older)
- Press `Escape` to quickly toggle the annotations off
- Adds [customizable](#status-bar-settings) **blame information** about the current line to the **status bar** ([optional](#status-bar-settings), on by default) - Adds [customizable](#status-bar-settings) **blame information** about the current line to the **status bar** ([optional](#status-bar-settings), on by default)
@@ -57,7 +64,12 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
- Adds on-demand, [customizable](#file-recent-changes-annotation-settings) and [themeable](#theme-settings), **recent changes annotations** of the whole file - Adds on-demand, [customizable](#file-recent-changes-annotation-settings) and [themeable](#theme-settings), **recent changes annotations** of the whole file
- Highlights all of lines changed in the most recent commit - Highlights all of lines changed in the most recent commit
- Also adds a `changes` (diff) hover annotation to the current line annotation which provides **instant** access to the line's previous version ([optional](#file-recent-changes-annotation-settings), on by default) - Adds a `details` hover annotation to each line, which provides more commit details ([optional](#file-blame-annotation-settings), on by default)
- Clicking the commit id will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Adds a `changes` (diff) hover annotation to each line, which provides **instant** access to the line's previous version ([optional](#file-recent-changes-annotation-settings), on by default)
- Clicking on `Changes` will run the `Compare File Revisions` command (`gitlens.diffWith`)
- Clicking the current and previous commit ids will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
- Press `Escape` to quickly toggle the annotations off
- Adds `Toggle Recent File Changes Annotations` command (`gitlens.toggleFileRecentChanges`) to toggle the recent changes annotations on and off - Adds `Toggle Recent File Changes Annotations` command (`gitlens.toggleFileRecentChanges`) to toggle the recent changes annotations on and off
@@ -84,31 +96,88 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
### Powerful Comparison Tools ### Powerful Comparison Tools
- Effortlessly navigate between comparisions via the `alt+,` and `alt+.` shortcut keys to go back and forth through a file's revisions - Effortlessly navigate between comparisons via the `alt+,` and `alt+.` shortcut keys to go back and forth through a file's revisions
- Provides easy access to the following comparison commands via the `Command Palette` as well as in context via the many provided quick pick menus - Provides easy access to the following comparison commands via the `Command Palette` as well as in context via the many provided quick pick menus
- Adds a `Directory Compare` command (`gitlens.diffDirectory`) to open the configured Git difftool to compare directories between branches - Adds a `Directory Compare` command (`gitlens.diffDirectory`) to open the configured Git difftool to compare directories between branches
- Adds a `Compare File with...` command (`gitlens.diffWithBranch`) to compare the active file with the same file on the selected branch - Adds a `Compare File with Branch...` command (`gitlens.diffWithBranch`) to compare the active file with the same file on the selected branch
- Adds a `Compare File with Next Commit` command (`gitlens.diffWithNext`) with a shortcut of `alt+.` to compare the active file/diff with the next commit revision - Adds a `Compare File with Next Revision` command (`gitlens.diffWithNext`) with a shortcut of `alt+.` to compare the active file/diff with the next commit revision
- Adds a `Compare File with Previous` command (`gitlens.diffWithPrevious`) with a shortcut of `alt+,` to compare the active file/diff with the previous commit revision - Adds a `Compare File with Previous Revision` command (`gitlens.diffWithPrevious`) with a shortcut of `alt+,` to compare the active file/diff with the previous commit revision
- Adds a `Compare Line Commit with Previous` command (`gitlens.diffLineWithPrevious`) with a shortcut of `shift+alt+,` to compare the active file/diff with the previous line commit revision - Adds a `Compare Line Revision with Previous` command (`gitlens.diffLineWithPrevious`) with a shortcut of `shift+alt+,` to compare the active file/diff with the previous line commit revision
- Adds a `Compare File with Working Tree` command (`gitlens.diffWithWorking`) with a shortcut of `shift+alt+w` to compare the most recent commit revision of the active file/diff with the working tree - Adds a `Compare File with Revision...` command (`gitlens.diffWithRevision`) to compare the active file with the selected revision of the same file
- Adds a `Compare Line Commit with Working Tree` command (`gitlens.diffLineWithWorking`) with a shortcut of `alt+w` to compare the commit revision of the active line with the working tree - Adds a `Compare File with Working Revision` command (`gitlens.diffWithWorking`) with a shortcut of `shift+alt+w` to compare the most recent commit revision of the active file/diff with the working tree
- Adds a `Compare Line Revision with Working` command (`gitlens.diffLineWithWorking`) with a shortcut of `alt+w` to compare the commit revision of the active line with the working tree
### Navigate and Explore ### Navigate and Explore
- Adds a [customizable](#gitlens-custom-view-settings) `GitLens` custom view to the Explorer activity
- `Repository View` - provides a full repository explorer
![GitLens Repository view](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-git-custom-view-repository.png)
- `Repository Status` node — provides the status of the repository
- Provides the name of the current branch, its upstream tracking branch (if available), and its upstream status (if available)
- Provides indicator dots on the repository icon which denote the following:
- `None` - up-to-date with the upstream
- `Green` - ahead of the upstream
- `Red` - behind the upstream
- `Yellow` - both ahead of and behind the upstream
- Provides additional nodes, if the current branch is not synchronized with the upstream, to quickly see and explore the specific commits ahead and/or behind the upstream
- Provides a context menu with `Open Repository in Remote`, and `Refresh` commands
- `Branches` node — provides a list of the local branches
- Indicates which branch is the current branch and [optionally](#gitlens-custom-view-settings) shows the remote tracking branch
- Expand each branch to easily see its revision (commit) history
- Expand each revision (commit) to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu on each changed file with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, and `Show Commit File Details` commands
- Provides a context menu on each revision (commit) with `Open Commit in Remote`, `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit ID to Clipboard`, `Copy Commit Message to Clipboard`, `Show Commit Details`, and `Refresh` commands
- Provides a context menu on each branch with `Open Branch in Remote`, and `Refresh` commands
- Provides a context menu with `Open Branches in Remote`, and `Refresh` commands
- `Remotes` node — provides a list of remotes
- Indicates the direction of the remote (fetch, push, both), remote service (if applicable), and repository path
- Expand each remote to see its list of branches
- Expand each branch to easily see its revision (commit) history
- Expand each revision (commit) to quickly see the set of files changed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu on each changed file with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, `Show File History`, and `Show Commit File Details` commands
- Provides a context menu on each revision (commit) with `Open Commit in Remote`, `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit ID to Clipboard`, `Copy Commit Message to Clipboard`,`Show Commit Details`, and `Refresh` commands
- Provides a context menu on each remote with `Open Branches in Remote`, `Open Repository in Remote`, and `Refresh` commands
- Provides a context menu with a `Refresh` command
- `Stashes` node — provides a list of stashed changes
- Expand each stash to quickly see the set of files stashed, complete with status indicators for adds, changes, renames, and deletes
- Provides a context menu with `Stash Changes`, and `Refresh` commands
- Provides a context menu on each stash with `Apply Stashed Changes` (confirmation required), `Delete Stashed Changes` (confirmation required), `Open All Changes`, `Open All Changes with Working Tree`, `Open Files`, `Open Revisions`, `Copy Commit Message to Clipboard`, and `Refresh` commands
- Provides a context menu on each stashed file with `Apply Changes`, `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, and `Show File History` commands
- `History View` - provides the revision history of the active file
![GitLens History view](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-git-custom-view-history.png)
- Automatically updates to track the active editor
- Provides a context menu with `Open File`, `Open File in Remote`, and `Refresh` commands
- Provides a context menu on each revision (commit) with `Open Changes`, `Open Changes with Working Tree`, `Open File`, `Open Revision`, `Open File in Remote`, `Open Revision in Remote`, `Apply Changes`, and `Show Commit File Details` commands
- Quickly switch between views using the `Switch to Repository View` or `Switch to History View` commands
- Provides toolbar commands to `Search Commits`, `Switch to Repository View` or `Switch to History View`, and `Refresh`
- Adds a `Search Commits` command (`gitlens.showCommitSearch`) with a shortcut of `alt+/` to search for commits by message, author, file(s), or commit id - Adds a `Search Commits` command (`gitlens.showCommitSearch`) with a shortcut of `alt+/` to search for commits by message, author, file(s), or commit id
- Adds commands to open files, commits, branches, and the repository in the supported remote services, currently **BitBucket, GitHub, GitLab, and Visual Studio Team Services** — only available if a Git upstream service is configured in the repository - Adds commands to open files, commits, branches, and the repository in the supported remote services, currently **BitBucket, GitHub, GitLab, and Visual Studio Team Services** — only available if a Git upstream service is configured in the repository
- Also supports [remote services with custom domains](#custom-remotes-settings), such as **BitBucket, Bitbucket Server (previously called Stash), GitHub, GitHub Enterprise, GitLab**
- `Open Branches in Remote` command (`gitlens.openBranchesInRemote`) — opens the branches in the supported remote service
- `Open Branch in Remote` command (`gitlens.openBranchInRemote`) — opens the current branch commits in the supported remote service - `Open Branch in Remote` command (`gitlens.openBranchInRemote`) — opens the current branch commits in the supported remote service
- `Open Line Commit in Remote` command (`gitlens.openCommitInRemote`) — opens the commit revision of the active line in the supported remote service - `Open Commit in Remote` command (`gitlens.openCommitInRemote`) — opens the commit revision of the active line in the supported remote service
- `Open File in Remote` command (`gitlens.openFileInRemote`) — opens the active file/revision in the supported remote service - `Open File in Remote` command (`gitlens.openFileInRemote`) — opens the active file/revision in the supported remote service
- `Open Repository in Remote` command (`gitlens.openRepoInRemote`) — opens the repository in the supported remote service - `Open Repository in Remote` command (`gitlens.openRepoInRemote`) — opens the repository in the supported remote service
@@ -139,12 +208,11 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
- Provides entries to `Copy to Clipboard`, `Directory Compare`, `Open Changed Files`, `Open File in <remote-service>` when available, and more - Provides entries to `Copy to Clipboard`, `Directory Compare`, `Open Changed Files`, `Open File in <remote-service>` when available, and more
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available - Navigate back to the previous quick pick menu via `alt+left arrow`, if available
- Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set - Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set
- Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the current revision of the while leaving the quick pick menu open - Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the comparison of the current revision with the previous one
- NOTE: Once [vscode issue #10568](https://github.com/Microsoft/vscode/issues/10568) is resolved this will change to preview the comparison of the current revision with the previous one
- Adds a `Show Line Commit Details` command (`gitlens.showQuickCommitFileDetails`) with a shortcut of `alt+c` to show a **file commit details quick pick menu** of the most recent commit of the active file - Adds a `Show Commit File Details` command (`gitlens.showQuickCommitFileDetails`) with a shortcut of `alt+c` to show a **file commit details quick pick menu** of the most recent commit of the active file
![Line Commit Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-commit-file-details.png) ![Commit File Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-commit-file-details.png)
- Provides entries to `Show Commit Details`, `Show File History`, `Compare File with...`, `Copy to Clipboard`, `Open File`, `Open File in <remote-service>` when available, and more - Provides entries to `Show Commit Details`, `Show File History`, `Compare File with...`, `Copy to Clipboard`, `Open File`, `Open File in <remote-service>` when available, and more
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available - Navigate back to the previous quick pick menu via `alt+left arrow`, if available
@@ -155,13 +223,12 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
![Repository Status Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-repo-status.png) ![Repository Status Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-repo-status.png)
- Quickly see upstream status (if an Git upstream is configured) — complete with ahead and behind information - Quickly see upstream status (if an Git upstream is configured) — complete with ahead and behind information
- If you are ahead of the upstream, an entry will be shown with the number of commits ahead. Chosing it will show a limited **branch history quick pick menu** containing just the commits ahead of the upstream - If you are ahead of the upstream, an entry will be shown with the number of commits ahead. Choosing it will show a limited **branch history quick pick menu** containing just the commits ahead of the upstream
- If you are behind the upstream, an entry will be shown with the number of commits behind. Chosing it will show a limited **branch history quick pick menu** containing just the commits behind the upstream - If you are behind the upstream, an entry will be shown with the number of commits behind. Choosing it will show a limited **branch history quick pick menu** containing just the commits behind the upstream
- Quickly see all working changes, both staged and unstaged, complete with status indicators for adds, changes, renames, and deletes - Quickly see all working changes, both staged and unstaged, complete with status indicators for adds, changes, renames, and deletes
- Provides entries to `Show Stashed Changes`, `Open Changed Files`, and `Close Unchanged Files` - Provides entries to `Show Stashed Changes`, `Open Changed Files`, and `Close Unchanged Files`
- Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set - Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set
- Use the `alt+right arrow` shortcut on a file entry in the `Staged Files` or `Unstaged Files` sections to preview the working file while leaving the quick pick menu open - Use the `alt+right arrow` shortcut on a file entry in the `Staged Files` or `Unstaged Files` sections to preview the comparison of the working file with the previous revision
- NOTE: Once [vscode issue #10568](https://github.com/Microsoft/vscode/issues/10568) is resolved this will change to preview the comparison of the working file with the previous revision
- Adds a `Show Stashed Changes` command (`gitlens.showQuickStashList`) to show a **stashed changes quick pick menu** for exploring your repository stash history - Adds a `Show Stashed Changes` command (`gitlens.showQuickStashList`) to show a **stashed changes quick pick menu** for exploring your repository stash history
@@ -170,7 +237,7 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
- Provides entries to `Stash Changes` - Provides entries to `Stash Changes`
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available - Navigate back to the previous quick pick menu via `alt+left arrow`, if available
- Chosing a stash entry shows a **stash details quick pick menu** which is very similar to the **commit details quick pick menu** above - Choosing a stash entry shows a **stash details quick pick menu** which is very similar to the **commit details quick pick menu** above
![Stash Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-stash-details.png) ![Stash Details Quick Pick Menu](https://raw.githubusercontent.com/eamodio/vscode-gitlens/master/images/screenshot-stash-details.png)
@@ -179,8 +246,7 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
- Provides entries to `Apply Stashed Changes` and `Delete Stashed Changes` — both require a confirmation - Provides entries to `Apply Stashed Changes` and `Delete Stashed Changes` — both require a confirmation
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available - Navigate back to the previous quick pick menu via `alt+left arrow`, if available
- Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set - Use the `alt+right arrow` shortcut on an entry to execute it without closing the quick pick menu, if possible — commands that open windows outside of VS Code will still close the quick pick menu unless [`"gitlens.advanced.quickPick.closeOnFocusOut": false`](#extension-settings) is set
- Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the current revision of the while leaving the quick pick menu open - Use the `alt+right arrow` shortcut on a file entry in the `Changed Files` section to preview the comparison of the current revision with the previous one
- NOTE: Once [vscode issue #10568](https://github.com/Microsoft/vscode/issues/10568) is resolved this will change to preview the comparison of the current revision with the previous one
- Adds a `Show Last Opened Quick Pick` command (`gitlens.showLastQuickPick`) with a shortcut of `alt+-` to quickly get back to where you were when the last GitLens quick pick menu closed - Adds a `Show Last Opened Quick Pick` command (`gitlens.showLastQuickPick`) with a shortcut of `alt+-` to quickly get back to where you were when the last GitLens quick pick menu closed
@@ -192,9 +258,9 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
### And More ### And More
- Adds a `Copy Commit ID to Clipboard` command (`gitlens.copyShaToClipboard`) to copy the commit id (sha) of the active line to the clipboard - Adds a `Copy Commit ID to Clipboard` command (`gitlens.copyShaToClipboard`) to copy the commit id (sha) of the active line to the clipboard or from the most recent commit to the current branch, if there is no active editor
- Adds a `Copy Commit Message to Clipboard` command (`gitlens.copyMessageToClipboard`) to copy the commit message of the active line to the clipboard - Adds a `Copy Commit Message to Clipboard` command (`gitlens.copyMessageToClipboard`) to copy the commit message of the active line to the clipboard or from the most recent commit to the current branch, if there is no active editor
- Adds a `Open Changed Files` command (`gitlens.openChangedFiles`) to open any files with working tree changes - Adds a `Open Changed Files` command (`gitlens.openChangedFiles`) to open any files with working tree changes
@@ -203,6 +269,7 @@ GitLens provides an unobtrusive blame annotation at the end of the current line,
- Adds a `Apply Stashed Changes` command (`gitlens.stashApply`) to chose a stash entry to apply to the working tree from a quick pick menu - Adds a `Apply Stashed Changes` command (`gitlens.stashApply`) to chose a stash entry to apply to the working tree from a quick pick menu
- Adds a `Stash Changes` command (`gitlens.stashSave`) to save any working tree changes to the stash — can optionally provide a stash message - Adds a `Stash Changes` command (`gitlens.stashSave`) to save any working tree changes to the stash — can optionally provide a stash message
- Also adds the command to the Source Control items context menu to stash an individual or group of files, works with multi-select too!
## Insiders ## Insiders
@@ -216,10 +283,15 @@ GitLens is highly customizable and provides many configuration settings to allow
|Name | Description |Name | Description
|-----|------------ |-----|------------
|`gitlens.defaultDateFormat`|Specifies how all absolute dates will be formatted by default\nSee https://momentjs.com/docs/#/displaying/format/ for valid formats
|`gitlens.insiders`|Opts into the insiders channel -- provides access to upcoming features |`gitlens.insiders`|Opts into the insiders channel -- provides access to upcoming features
|`gitlens.outputLevel`|Specifies how much (if any) output will be sent to the GitLens output channel |`gitlens.outputLevel`|Specifies how much (if any) output will be sent to the GitLens output channel
### Blame Annotation Settings ### Blame Settings
|Name | Description
|-----|------------
|`gitlens.blame.ignoreWhitespace`|Specifies whether or not to ignore whitespace when comparing revisions during blame operations
#### File Blame Annotation Settings #### File Blame Annotation Settings
@@ -242,7 +314,7 @@ GitLens is highly customizable and provides many configuration settings to allow
|Name | Description |Name | Description
|-----|------------ |-----|------------
|`gitlens.blame.line.enabled`|Specifies whether or not to provide a blame annotation for the current line |`gitlens.blame.line.enabled`|Specifies whether or not to provide a blame annotation for the current line, by default<br />Use the `gitlens.toggleLineBlame` command to toggle the annotations on and off for the current session
|`gitlens.blame.line.annotationType`|Specifies the type of blame annotations that will be shown for the current line<br />`trailing` - adds an annotation to the end of the current line<br />`hover` - shows annotations when hovering over the current line |`gitlens.blame.line.annotationType`|Specifies the type of blame annotations that will be shown for the current line<br />`trailing` - adds an annotation to the end of the current line<br />`hover` - shows annotations when hovering over the current line
|`gitlens.annotations.line.trailing.format`|Specifies the format of the trailing blame annotations<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.annotations.line.trailing.dateFormat`)<br />`${authorAgo}` - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting |`gitlens.annotations.line.trailing.format`|Specifies the format of the trailing blame annotations<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.annotations.line.trailing.dateFormat`)<br />`${authorAgo}` - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|`gitlens.annotations.line.trailing.dateFormat`|Specifies how to format absolute dates (using the `${date}` token) in trailing blame annotations<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats |`gitlens.annotations.line.trailing.dateFormat`|Specifies how to format absolute dates (using the `${date}` token) in trailing blame annotations<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
@@ -257,14 +329,15 @@ GitLens is highly customizable and provides many configuration settings to allow
|Name | Description |Name | Description
|-----|------------ |-----|------------
|`gitlens.recentChanges.file.lineHighlight.locations`|Specifies where the highlights of the recently changed lines will be shown<br />`gutter` - adds a gutter glyph<br />`line` - adds a full-line highlight background color<br />`overviewRuler` - adds a decoration to the overviewRuler (scroll bar) |`gitlens.recentChanges.file.lineHighlight.locations`|Specifies where the highlights of the recently changed lines will be shown<br />`gutter` - adds a gutter glyph<br />`line` - adds a full-line highlight background color<br />`overviewRuler` - adds a decoration to the overviewRuler (scroll bar)
|`gitlens.annotations.file.recentChanges.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotations |`gitlens.annotations.file.recentChanges.hover.details`|Specifies whether or not to provide a commit details hover annotation
|`gitlens.annotations.file.recentChanges.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation
|`gitlens.annotations.file.recentChanges.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line |`gitlens.annotations.file.recentChanges.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
### Code Lens Settings ### Code Lens Settings
|Name | Description |Name | Description
|-----|------------ |-----|------------
|`gitlens.codeLens.enabled`|Specifies whether or not to provide any Git code lens |`gitlens.codeLens.enabled`|Specifies whether or not to provide any Git code lens, by default<br />Use the `gitlens.toggleCodeLens` command to toggle the Git code lens on and off for the current session
|`gitlens.codeLens.recentChange.enabled`|Specifies whether or not to show a `recent change` code lens showing the author and date of the most recent commit for the file or code block |`gitlens.codeLens.recentChange.enabled`|Specifies whether or not to show a `recent change` code lens showing the author and date of the most recent commit for the file or code block
|`gitlens.codeLens.recentChange.command`|Specifies the command to be executed when the `recent change` code lens is clicked<br />`gitlens.toggleFileBlame` - toggles file blame annotations<br />`gitlens.showBlameHistory` - opens the blame history explorer<br />`gitlens.showFileHistory` - opens the file history explorer<br />`gitlens.diffWithPrevious` - compares the current committed file with the previous commit<br />`gitlens.showQuickCommitDetails` - shows a commit details quick pick<br />`gitlens.showQuickCommitFileDetails` - shows a commit file details quick pick<br />`gitlens.showQuickFileHistory` - shows a file history quick pick<br />`gitlens.showQuickRepoHistory` - shows a branch history quick pick |`gitlens.codeLens.recentChange.command`|Specifies the command to be executed when the `recent change` code lens is clicked<br />`gitlens.toggleFileBlame` - toggles file blame annotations<br />`gitlens.showBlameHistory` - opens the blame history explorer<br />`gitlens.showFileHistory` - opens the file history explorer<br />`gitlens.diffWithPrevious` - compares the current committed file with the previous commit<br />`gitlens.showQuickCommitDetails` - shows a commit details quick pick<br />`gitlens.showQuickCommitFileDetails` - shows a commit file details quick pick<br />`gitlens.showQuickFileHistory` - shows a file history quick pick<br />`gitlens.showQuickRepoHistory` - shows a branch history quick pick
|`gitlens.codeLens.authors.enabled`|Specifies whether or not to show an `authors` code lens showing number of authors of the file or code block and the most prominent author (if there is more than one) |`gitlens.codeLens.authors.enabled`|Specifies whether or not to show an `authors` code lens showing number of authors of the file or code block and the most prominent author (if there is more than one)
@@ -273,6 +346,23 @@ GitLens is highly customizable and provides many configuration settings to allow
|`gitlens.codeLens.customLocationSymbols`|Specifies the set of document symbols where Git code lens will be shown in the document |`gitlens.codeLens.customLocationSymbols`|Specifies the set of document symbols where Git code lens will be shown in the document
|`gitlens.codeLens.perLanguageLocations`|Specifies where Git code lens will be shown in the document for the specified languages |`gitlens.codeLens.perLanguageLocations`|Specifies where Git code lens will be shown in the document for the specified languages
### GitLens Custom View Settings
|Name | Description
|-----|------------
|`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.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.commitFileFormat`|Specifies the format of a committed file in the `GitLens` custom view<br />Available tokens<br /> ${file} - file name<br /> ${filePath} - file name and path<br /> ${path} - file path
|`gitlens.gitExplorer.stashFormat`|Specifies the format of stashed 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.stashFileFormat`|Specifies the format of a stashed file in the `GitLens` custom view<br />Available tokens<br /> ${file} - file name<br /> ${filePath} - file name and path<br /> ${path} - file path
### Custom Remotes Settings
|Name | Description
|-----|------------
|`gitlens.remotes`|Specifies any custom domains for remote (code-hosting) services<br />Example: ```"gitlens.remotes": [{ "domain": "git.corporate-url.com", "type": "GitHub" }]```
### Status Bar Settings ### Status Bar Settings
|Name | Description |Name | Description
@@ -295,14 +385,13 @@ GitLens is highly customizable and provides many configuration settings to allow
|Name | Description |Name | Description
|-----|------------ |-----|------------
|`gitlens.theme.annotations.file.gutter.separateLines`|Specifies whether or not gutter blame annotations will be separated by a small gap |`gitlens.theme.annotations.file.gutter.separateLines`|Specifies whether or not gutter blame annotations will have line separators
|`gitlens.theme.annotations.file.gutter.dark.backgroundColor`|Specifies the dark theme background color of the gutter blame annotations |`gitlens.theme.annotations.file.gutter.dark.backgroundColor`|Specifies the dark theme background color of the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.light.backgroundColor`|Specifies the light theme background color of the gutter blame annotations |`gitlens.theme.annotations.file.gutter.light.backgroundColor`|Specifies the light theme background color of the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.dark.foregroundColor`|Specifies the dark theme foreground color of the gutter blame annotations |`gitlens.theme.annotations.file.gutter.dark.foregroundColor`|Specifies the dark theme foreground color of the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.light.foregroundColor`|Specifies the light theme foreground color of the gutter blame annotations |`gitlens.theme.annotations.file.gutter.light.foregroundColor`|Specifies the light theme foreground color of the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.dark.uncommittedForegroundColor`|Specifies the dark theme foreground color of an uncommitted line in the gutter blame annotations |`gitlens.theme.annotations.file.gutter.dark.uncommittedForegroundColor`|Specifies the dark theme foreground color of an uncommitted line in the gutter blame annotations
|`gitlens.theme.annotations.file.gutter.light.uncommittedForegroundColor`|Specifies the light theme foreground color of an uncommitted line in the gutter blame annotations |`gitlens.theme.annotations.file.gutter.light.uncommittedForegroundColor`|Specifies the light theme foreground color of an uncommitted line in the gutter blame annotations
|`gitlens.theme.annotations.file.hover.separateLines`|Specifies whether or not hover blame annotations will be separated by a small gap (if heatmap is enabled)
|`gitlens.theme.annotations.line.trailing.dark.backgroundColor`|Specifies the dark theme background color of the trailing blame annotation |`gitlens.theme.annotations.line.trailing.dark.backgroundColor`|Specifies the dark theme background color of the trailing blame annotation
|`gitlens.theme.annotations.line.trailing.light.backgroundColor`|Specifies the light theme background color of the trailing blame annotation |`gitlens.theme.annotations.line.trailing.light.backgroundColor`|Specifies the light theme background color of the trailing blame annotation
|`gitlens.theme.annotations.line.trailing.dark.foregroundColor`|Specifies the dark theme foreground color of the trailing blame annotation |`gitlens.theme.annotations.line.trailing.dark.foregroundColor`|Specifies the dark theme foreground color of the trailing blame annotation
@@ -316,7 +405,6 @@ GitLens is highly customizable and provides many configuration settings to allow
|Name | Description |Name | Description
|-----|------------ |-----|------------
|`gitlens.advanced.toggleWhitespace.enabled`|Specifies whether or not to toggle whitespace off then showing blame annotations (*may* be required by certain fonts/themes)
|`gitlens.advanced.telemetry.enabled`|Specifies whether or not to enable GitLens telemetry (even if enabled still abides by the overall `telemetry.enableTelemetry` setting |`gitlens.advanced.telemetry.enabled`|Specifies whether or not to enable GitLens telemetry (even if enabled still abides by the overall `telemetry.enableTelemetry` setting
|`gitlens.advanced.menus`|Specifies which commands will be added to which menus |`gitlens.advanced.menus`|Specifies which commands will be added to which menus
|`gitlens.advanced.caching.enabled`|Specifies whether git output will be cached |`gitlens.advanced.caching.enabled`|Specifies whether git output will be cached
@@ -329,11 +417,12 @@ GitLens is highly customizable and provides many configuration settings to allow
## Known Issues ## Known Issues
- If the `Copy to * clipboard` commands don't work on Linux -- `xclip` needs to be installed. You can install it via `sudo apt-get install xclip` - If the `Copy to * clipboard` commands don't work on Linux -- `xclip` needs to be installed. You can install it via `sudo apt-get install xclip`
- Visible whitespace causes issues ([vscode issue #11485](https://github.com/Microsoft/vscode/issues/11485)) with the `expanded` and `compact` blame annotation styles when using a non-monospace font -- set `"gitlens.advanced.toggleWhitespace.enabled": true` if you are using a non-monospace font
## Contributors ## Contributors
A big thanks to the people that have contributed to this project: A big thanks to the people that have contributed to this project:
- 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))
- Zack Schuster ([@zackschuster](https://github.com/zackschuster)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=zackschuster) - Zack Schuster ([@zackschuster](https://github.com/zackschuster)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=zackschuster)

BIN
images/chat-badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

88
images/chat-badge.svg Normal file
View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="92" height="20" xml:space="preserve">
<style type="text/css">
.white{fill:#FFF;}
.shadow{fill:#2e840e;}
</style>
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="a">
<rect width="92" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#a)">
<path fill="#555" d="M0 0h34v20H0z"/>
<path fill="#4c1" d="M34 0h58v20H34z"/>
<path fill="url(#b)" d="M0 0h92v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="17" y="15" fill="#010101" fill-opacity=".3">chat</text>
<text x="17" y="14">chat</text>
<g transform="scale(0.1) translate(340, -21)">
<path class="shadow" d="M263.5,105.5c3.9,1.7,4.2,3,1.1,8.8c-3.1,6-3.9,6.3-7.7,4.8c-4.8-2.1-11-3.6-15-3.6c-6.5,0-10.9,2.3-10.9,5.9
c0,11.7,37.4,5.4,37.4,30.4c0,12.6-10.8,21-27,21c-8.5,0-19-2.8-26.3-6.5c-3.6-1.8-3.8-2.9-0.7-8.9c2.7-5.3,3.6-5.8,7.5-4.2
c6.2,2.7,14,4.8,19.3,4.8c6,0,9.9-2.4,9.9-6c0-11.4-38.1-6-38.1-30.2c0-12.9,10.7-21.5,26.8-21.5
C247.4,100.2,256.9,102.5,263.5,105.5z"/>
<path class="shadow" d="M293.7,75.8V169c0,1.4-1.5,2.9-3.6,2.9h-9.8c-2.1,0-3.6-1.5-3.6-2.9V75.8c0-4.6,1.3-5,8.5-5
C293.4,70.7,293.7,71.3,293.7,75.8z"/>
<path class="shadow" d="M363.4,128.2v40.1c0,2.1-1.5,3.6-3.6,3.6h-9.7c-2.2,0-3.8-1.6-3.6-3.8l0.1-4.3c-5.3,5.8-12.8,8.9-20.3,8.9
c-14.6,0-24.4-8.5-24.4-21.1c0-13.4,11.1-22.5,27.7-22.5c6.3,0,12.1,1.1,16.8,3.1v-4.6c0-7.4-5.8-11.8-15.7-11.8
c-4.6,0-10.3,1.8-14.8,4.5c-3.5,2-4.3,1.8-8.1-3.8c-3.7-5.6-3.6-6.7,0-9c6.8-4.4,16.1-7.2,24.6-7.2
C351.4,100.2,363.4,110.6,363.4,128.2z M318.2,151.4c0,4.8,4,8,10.2,8c7.4,0,14.1-3.6,18-9.6v-6.3c-3.9-1.5-8.7-2.3-12.9-2.3
C324.3,141.2,318.2,145.5,318.2,151.4z"/>
<path class="shadow" d="M429.9,105.6c3.6,2.1,3.7,3.2-0.2,9.2c-3.7,5.7-4.3,6-8.2,4c-3-1.6-7.7-2.9-11.7-2.9
c-12.3,0-20.5,8.1-20.5,20.3c0,12.7,8.2,21.2,20.5,21.2c4.3,0,9.6-1.6,13.1-3.6c3.6-2.1,4.3-1.9,8.1,3.6c3.4,5.1,3.3,6.3,0.3,8.5
c-5.5,3.8-14.1,6.7-21.7,6.7c-22.7,0-37.9-14.6-37.9-36.4c0-21.7,15.2-36.1,38.1-36.1C416.6,100.2,424.8,102.6,429.9,105.6z"/>
<path class="shadow" d="M504.1,163.1c2.8,3.6,1.7,4.9-5.4,7.5c-7.2,2.6-8.2,2.5-10.8-0.9l-20.3-27.1l-9.1,8.8V169
c0,1.4-1.5,2.9-3.6,2.9H445c-2.1,0-3.6-1.5-3.6-2.9V75.8c0-4.6,1.3-5,8.5-5c8.2,0,8.5,0.6,8.5,5v53l27.8-26.7
c3.1-2.9,4.8-2.7,10.2,0.9c6,3.9,6.5,5,3.6,7.8L479.3,131L504.1,163.1z"/>
</g>
<g transform="scale(0.1) translate(340, -21)">
<rect x="115.9" y="126.3" transform="matrix(0.9482 -0.3176 0.3176 0.9482 -36.3582 46.5843)" class="shadow" width="17.6" height="17"/>
<g>
<rect x="115.9" y="126.3" transform="matrix(0.9482 -0.3176 0.3176 0.9482 -36.3582 46.5843)" class="shadow" width="17.6" height="17"/>
<path class="shadow" d="M182,117.5c-12.9-43-31.5-53-74.5-40.1s-53,31.5-40.1,74.5s31.5,53,74.5,40.1S194.9,160.5,182,117.5z
M160.3,145.4l-8.1,2.7l2.8,8.4c1.1,3.4-0.7,7.1-4.1,8.2c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4l-2.8-8.4l-16.7,5.6
l2.8,8.4c1.1,3.4-0.7,7.1-4.1,8.2c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4l-2.8-8.4l-8.1,2.7c-0.7,0.2-1.5,0.4-2.2,0.3
c-2.6-0.1-5.1-1.8-6-4.4c-1.1-3.4,0.7-7.1,4.1-8.2l8.1-2.7l-5.4-16.1l-8.1,2.7c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4
c-1.1-3.4,0.7-7.1,4.1-8.2l8.1-2.7l-2.8-8.4c-1.1-3.4,0.7-7.1,4.1-8.2s7.1,0.7,8.2,4.1l2.8,8.4l16.7-5.6l-2.8-8.4
c-1.1-3.4,0.7-7.1,4.1-8.2s7.1,0.7,8.2,4.1l2.8,8.4l8.1-2.7c3.4-1.1,7.1,0.7,8.2,4.1c1.1,3.4-0.7,7.1-4.1,8.2l-8.1,2.7l5.4,16.1
l8.1-2.7c3.4-1.1,7.1,0.7,8.2,4.1C165.5,140.6,163.7,144.3,160.3,145.4z"/>
</g>
</g>
<g transform="scale(0.1) translate(340, -31)">
<path class="white" d="M263.5,105.5c3.9,1.7,4.2,3,1.1,8.8c-3.1,6-3.9,6.3-7.7,4.8c-4.8-2.1-11-3.6-15-3.6c-6.5,0-10.9,2.3-10.9,5.9
c0,11.7,37.4,5.4,37.4,30.4c0,12.6-10.8,21-27,21c-8.5,0-19-2.8-26.3-6.5c-3.6-1.8-3.8-2.9-0.7-8.9c2.7-5.3,3.6-5.8,7.5-4.2
c6.2,2.7,14,4.8,19.3,4.8c6,0,9.9-2.4,9.9-6c0-11.4-38.1-6-38.1-30.2c0-12.9,10.7-21.5,26.8-21.5
C247.4,100.2,256.9,102.5,263.5,105.5z"/>
<path class="white" d="M293.7,75.8V169c0,1.4-1.5,2.9-3.6,2.9h-9.8c-2.1,0-3.6-1.5-3.6-2.9V75.8c0-4.6,1.3-5,8.5-5
C293.4,70.7,293.7,71.3,293.7,75.8z"/>
<path class="white" d="M363.4,128.2v40.1c0,2.1-1.5,3.6-3.6,3.6h-9.7c-2.2,0-3.8-1.6-3.6-3.8l0.1-4.3c-5.3,5.8-12.8,8.9-20.3,8.9
c-14.6,0-24.4-8.5-24.4-21.1c0-13.4,11.1-22.5,27.7-22.5c6.3,0,12.1,1.1,16.8,3.1v-4.6c0-7.4-5.8-11.8-15.7-11.8
c-4.6,0-10.3,1.8-14.8,4.5c-3.5,2-4.3,1.8-8.1-3.8c-3.7-5.6-3.6-6.7,0-9c6.8-4.4,16.1-7.2,24.6-7.2
C351.4,100.2,363.4,110.6,363.4,128.2z M318.2,151.4c0,4.8,4,8,10.2,8c7.4,0,14.1-3.6,18-9.6v-6.3c-3.9-1.5-8.7-2.3-12.9-2.3
C324.3,141.2,318.2,145.5,318.2,151.4z"/>
<path class="white" d="M429.9,105.6c3.6,2.1,3.7,3.2-0.2,9.2c-3.7,5.7-4.3,6-8.2,4c-3-1.6-7.7-2.9-11.7-2.9
c-12.3,0-20.5,8.1-20.5,20.3c0,12.7,8.2,21.2,20.5,21.2c4.3,0,9.6-1.6,13.1-3.6c3.6-2.1,4.3-1.9,8.1,3.6c3.4,5.1,3.3,6.3,0.3,8.5
c-5.5,3.8-14.1,6.7-21.7,6.7c-22.7,0-37.9-14.6-37.9-36.4c0-21.7,15.2-36.1,38.1-36.1C416.6,100.2,424.8,102.6,429.9,105.6z"/>
<path class="white" d="M504.1,163.1c2.8,3.6,1.7,4.9-5.4,7.5c-7.2,2.6-8.2,2.5-10.8-0.9l-20.3-27.1l-9.1,8.8V169
c0,1.4-1.5,2.9-3.6,2.9H445c-2.1,0-3.6-1.5-3.6-2.9V75.8c0-4.6,1.3-5,8.5-5c8.2,0,8.5,0.6,8.5,5v53l27.8-26.7
c3.1-2.9,4.8-2.7,10.2,0.9c6,3.9,6.5,5,3.6,7.8L479.3,131L504.1,163.1z"/>
</g>
<g transform="scale(0.1) translate(340, -31)">
<rect x="115.9" y="126.3" transform="matrix(0.9482 -0.3176 0.3176 0.9482 -36.3582 46.5843)" class="white" width="17.6" height="17"/>
<g>
<rect x="115.9" y="126.3" transform="matrix(0.9482 -0.3176 0.3176 0.9482 -36.3582 46.5843)" class="white" width="17.6" height="17"/>
<path class="white" d="M182,117.5c-12.9-43-31.5-53-74.5-40.1s-53,31.5-40.1,74.5s31.5,53,74.5,40.1S194.9,160.5,182,117.5z
M160.3,145.4l-8.1,2.7l2.8,8.4c1.1,3.4-0.7,7.1-4.1,8.2c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4l-2.8-8.4l-16.7,5.6
l2.8,8.4c1.1,3.4-0.7,7.1-4.1,8.2c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4l-2.8-8.4l-8.1,2.7c-0.7,0.2-1.5,0.4-2.2,0.3
c-2.6-0.1-5.1-1.8-6-4.4c-1.1-3.4,0.7-7.1,4.1-8.2l8.1-2.7l-5.4-16.1l-8.1,2.7c-0.7,0.2-1.5,0.4-2.2,0.3c-2.6-0.1-5.1-1.8-6-4.4
c-1.1-3.4,0.7-7.1,4.1-8.2l8.1-2.7l-2.8-8.4c-1.1-3.4,0.7-7.1,4.1-8.2s7.1,0.7,8.2,4.1l2.8,8.4l16.7-5.6l-2.8-8.4
c-1.1-3.4,0.7-7.1,4.1-8.2s7.1,0.7,8.2,4.1l2.8,8.4l8.1-2.7c3.4-1.1,7.1,0.7,8.2,4.1c1.1,3.4-0.7,7.1-4.1,8.2l-8.1,2.7l5.4,16.1
l8.1-2.7c3.4-1.1,7.1,0.7,8.2,4.1C165.5,140.6,163.7,144.3,160.3,145.4z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 93 93" xml:space="preserve">
<g>
<path fill="#F05133" d="M90,41.8L49.9,1.7c-2.3-2.3-6.1-2.3-8.4,0L33.2,10l10.6,10.6c2.5-0.8,5.3-0.3,7.2,1.7c2,2,2.5,4.8,1.7,7.3
l10.2,10.2c2.5-0.8,5.3-0.3,7.3,1.7c2.8,2.7,2.8,7.2,0,10s-7.2,2.8-10,0c-2.1-2.1-2.6-5.1-1.5-7.7l-9.5-9.5v25
c0.7,0.3,1.3,0.8,1.9,1.3c2.8,2.7,2.8,7.2,0,10c-2.8,2.7-7.2,2.7-10,0c-2.8-2.8-2.8-7.2,0-10c0.7-0.7,1.5-1.2,2.3-1.5V33.8
c-0.8-0.3-1.6-0.9-2.3-1.5c-2.1-2.1-2.6-5.1-1.5-7.7L29.2,14.2L1.7,41.7c-2.3,2.3-2.3,6.1,0,8.4l40.1,40.1c2.3,2.3,6.1,2.3,8.4,0
l39.9-39.9C92.4,47.9,92.4,44.1,90,41.8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 795 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 93 93" xml:space="preserve">
<g>
<path fill="#FFFFFF" fill-opacity="0.74" d="M90,41.8L49.9,1.7c-2.3-2.3-6.1-2.3-8.4,0L33.2,10l10.6,10.6c2.5-0.8,5.3-0.3,7.2,1.7c2,2,2.5,4.8,1.7,7.3
l10.2,10.2c2.5-0.8,5.3-0.3,7.3,1.7c2.8,2.7,2.8,7.2,0,10s-7.2,2.8-10,0c-2.1-2.1-2.6-5.1-1.5-7.7l-9.5-9.5v25
c0.7,0.3,1.3,0.8,1.9,1.3c2.8,2.7,2.8,7.2,0,10c-2.8,2.7-7.2,2.7-10,0c-2.8-2.8-2.8-7.2,0-10c0.7-0.7,1.5-1.2,2.3-1.5V33.8
c-0.8-0.3-1.6-0.9-2.3-1.5c-2.1-2.1-2.6-5.1-1.5-7.7L29.2,14.2L1.7,41.7c-2.3,2.3-2.3,6.1,0,8.4l40.1,40.1c2.3,2.3,6.1,2.3,8.4,0
l39.9-39.9C92.4,47.9,92.4,44.1,90,41.8z">
<animate attributeName="fill" values="#FFFFFF;#F05133;#FFFFFF" dur="1s" repeatCount="indefinite"/>
</path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 941 B

View File

Before

Width:  |  Height:  |  Size: 815 B

After

Width:  |  Height:  |  Size: 815 B

View File

Before

Width:  |  Height:  |  Size: 312 B

After

Width:  |  Height:  |  Size: 312 B

5
images/dark/icon-add.svg Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect fill="#C5C5C5" x="6.5" y="5.5" width="3" height="11"/>
<rect fill="#C5C5C5" x="2.5" y="9.5" width="11" height="3"/>
</svg>

After

Width:  |  Height:  |  Size: 253 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m13,8c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -2,0.89 -2,2c0,0.73 0.41,1.38 1,1.72l0,0.3c-0.02,0.52 -0.23,0.98 -0.63,1.38c-0.4,0.4 -0.86,0.61 -1.38,0.63c-0.83,0.02 -1.48,0.16 -2,0.45l0,-4.76c0.59,-0.34 1,-0.98 1,-1.72c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -1.99,0.89 -1.99,2c0,0.73 0.41,1.38 1,1.72l0,6.56c-0.59,0.35 -1,0.99 -1,1.72c0,1.11 0.89,2 2,2c1.11,0 2,-0.89 2,-2c0,-0.53 -0.2,-1 -0.53,-1.36c0.09,-0.06 0.48,-0.41 0.59,-0.47c0.25,-0.11 0.56,-0.17 0.94,-0.17c1.05,-0.05 1.95,-0.45 2.75,-1.25c0.8,-0.8 1.2,-1.98 1.25,-3.02l-0.02,0c0.61,-0.36 1.02,-1 1.02,-1.73l0,0zm-8,-3.2c0.66,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2c-0.65,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2l0,0zm0,12.41c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0zm6,-8c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m11.86,10c-0.45,-1.72 -2,-3 -3.86,-3c-1.86,0 -3.41,1.28 -3.86,3l-3.14,0l0,2l3.14,0c0.45,1.72 2,3 3.86,3c1.86,0 3.41,-1.28 3.86,-3l3.14,0l0,-2l-3.14,0zm-3.86,3.2c-1.22,0 -2.2,-0.98 -2.2,-2.2c0,-1.22 0.98,-2.2 2.2,-2.2c1.22,0 2.2,0.98 2.2,2.2c0,1.22 -0.98,2.2 -2.2,2.2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 428 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m9,15l2,0l-3,3l-3,-3l2,0l0,-5l2,0l0,5l0,0zm3,-8c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 557 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m9,16l-2,0l0,-7l5,0l0,2l-3,0l0,5l0,0zm-1,-12c-2.19,0 -4.13,1.02 -5.41,2.59l-1.59,-1.59l0,4l4,0l-1.5,-1.5c1.05,-1.33 2.67,-2.2 4.5,-2.2c3.14,0 5.7,2.56 5.7,5.7c0,3.14 -2.56,5.7 -5.7,5.7c-3.14,0 -5.7,-2.56 -5.7,-5.7c0,-0.34 0.03,-0.67 0.09,-1l-1.31,0c-0.05,0.33 -0.08,0.66 -0.08,1c0,3.86 3.14,7 7,7c3.86,0 7,-3.14 7,-7c0,-3.86 -3.14,-7 -7,-7l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 500 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.901149,9.091851l-0.094,0.071c-0.269,0.333 -0.746,1.096 -0.91,2.375c0.057,0.277 0.092,0.495 0.092,0.545c0,2.206 -1.794,4 -4,4a3.986,3.986 0 0 1 -2.817,-1.164a3.987,3.987 0 0 1 -1.163,-2.815c0,-2.206 1.794,-4 4,-4l0.351,0.025l0,1.85s1.626,-1.342 1.631,-1.339l1.869,-1.577l-3.5,-2.917l0,2.218l-0.371,-0.03a5.75,5.75 0 0 0 -4.055,9.826a5.75,5.75 0 0 0 9.826,-4.056a5.725,5.725 0 0 0 -0.859,-3.012z" />
</svg>

After

Width:  |  Height:  |  Size: 553 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.519592,15.157073l-9.039184,0c-1.367793,0 -2.480539,-1.112828 -2.480539,-2.480622s1.112746,-2.480539 2.480539,-2.480539l0.281314,0c0.349178,-0.47173 0.888523,-0.771191 1.476341,-0.815025c0.321917,-1.471535 1.619609,-2.537962 3.165139,-2.537962c1.221543,0 2.341663,0.699516 2.889377,1.772488c0.083027,-0.008618 0.166386,-0.012926 0.250076,-0.012926c1.190221,0 2.194667,0.874105 2.378785,2.027867c0.670514,0.460047 1.07869,1.225023 1.07869,2.046096c0,1.367793 -1.112828,2.480622 -2.480539,2.480622z" />
</svg>

After

Width:  |  Height:  |  Size: 655 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#32cd32" stroke="#C5C5C5" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#cd3131" stroke="#C5C5C5" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#cdcd32" stroke="#C5C5C5" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 490 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m14.414133,16.199437l-3.415492,-3.433421c0.627518,-0.878526 0.995065,-1.945307 0.995065,-3.110698c0,-2.967265 -2.411463,-5.378728 -5.378728,-5.378728c-2.967265,0 -5.378728,2.411463 -5.378728,5.378728c0,2.967265 2.411463,5.378728 5.378728,5.378728c1.165391,0 2.223207,-0.367546 3.110698,-0.995065l3.433421,3.415492c0.170326,0.179291 0.403405,0.268936 0.627518,0.268936c0.224114,0 0.466156,-0.080681 0.627518,-0.268936c0.349617,-0.349617 0.349617,-0.914384 0,-1.264001l0,0.008965zm-7.799155,-2.330782c-2.321817,0 -4.213337,-1.891519 -4.213337,-4.213337c0,-2.321817 1.891519,-4.213337 4.213337,-4.213337c2.321817,0 4.213337,1.891519 4.213337,4.213337c0,2.321817 -1.891519,4.213337 -4.213337,4.213337l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 857 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m14.687501,11.955358l-1.079554,-6.821251c-0.076429,-0.458572 -0.477679,-0.821607 -0.955357,-0.821607l-9.30518,0c-0.477679,0 -0.878929,0.363036 -0.955357,0.821607l-1.079554,6.821251l0,4.776787c0,0.525447 0.429911,0.955357 0.955357,0.955357l11.464288,0c0.525447,0 0.955357,-0.429911 0.955357,-0.955357l0,-4.776787l0,0zm-3.133572,0.525447l-0.420357,0.850268c-0.162411,0.324821 -0.496786,0.535 -0.869375,0.535l-4.547501,0c-0.363036,0 -0.687857,-0.210179 -0.850268,-0.525447l-0.420357,-0.869375c-0.162411,-0.315268 -0.496786,-0.525447 -0.850268,-0.525447l-1.327947,0l0.955357,-6.687501l9.553573,0l0.955357,6.687501l-1.318393,0c-0.372589,0 -0.697411,0.210179 -0.869375,0.525447l0.009554,0.009554z" />
</svg>

After

Width:  |  Height:  |  Size: 846 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#3c8746" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
A
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#7F4E7E" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
C
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#692C77" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
C
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#9E121D" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
D
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#969696" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
I
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#1B80B2" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
M
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#CC6633" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
R
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#6C6C6C" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
U
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.24,10.4c0.19,1.28 -0.2,2.62 -1.2,3.6c-1.47,1.45 -3.74,1.63 -5.41,0.54l1.17,-1.14l-4.3,-0.6l0.6,4.2l1.31,-1.26c2.36,1.74 5.7,1.57 7.84,-0.54c1.24,-1.23 1.81,-2.85 1.74,-4.46l-1.75,-0.34l0,0zm-7.28,-2.4c1.47,-1.45 3.74,-1.63 5.41,-0.54l-1.17,1.14l4.3,0.6l-0.6,-4.2l-1.31,1.26c-2.36,-1.74 -5.7,-1.57 -7.85,0.54c-1.24,1.23 -1.8,2.85 -1.73,4.46l1.75,0.35c-0.19,-1.28 0.2,-2.63 1.2,-3.61l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 546 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.5,11l2.5,2.5c0,0.55 -0.45,1 -1,1l-4,0l0,-1l3.5,0l-2,-2l-7,0l-2,2l3.5,0l0,1l-4,0c-0.55,0 -1,-0.45 -1,-1l2.5,-2.5l-2.5,-2.5c0,-0.55 0.45,-1 1,-1l4,0l0,1l-3.5,0l2,2l7,0l2,-2l-3.5,0l0,-1l4,0c0.55,0 1,0.45 1,1l-2.5,2.5l0,0zm-5.5,-1.5l2,0l0,-3l2,0l-3,-3l-3,3l2,0l0,3l0,0zm2,3l-2,0l0,3l-2,0l3,3l3,-3l-2,0l0,-3l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 467 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m7,12l-2,0l3,-3l3,3l-2,0l0,5l-2,0l0,-5l0,0zm5,-4c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 558 B

BIN
images/gitlens-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 93 93" xml:space="preserve">
<g>
<path fill="#F05133" d="M90,41.8L49.9,1.7c-2.3-2.3-6.1-2.3-8.4,0L33.2,10l10.6,10.6c2.5-0.8,5.3-0.3,7.2,1.7c2,2,2.5,4.8,1.7,7.3
l10.2,10.2c2.5-0.8,5.3-0.3,7.3,1.7c2.8,2.7,2.8,7.2,0,10s-7.2,2.8-10,0c-2.1-2.1-2.6-5.1-1.5-7.7l-9.5-9.5v25
c0.7,0.3,1.3,0.8,1.9,1.3c2.8,2.7,2.8,7.2,0,10c-2.8,2.7-7.2,2.7-10,0c-2.8-2.8-2.8-7.2,0-10c0.7-0.7,1.5-1.2,2.3-1.5V33.8
c-0.8-0.3-1.6-0.9-2.3-1.5c-2.1-2.1-2.6-5.1-1.5-7.7L29.2,14.2L1.7,41.7c-2.3,2.3-2.3,6.1,0,8.4l40.1,40.1c2.3,2.3,6.1,2.3,8.4,0
l39.9-39.9C92.4,47.9,92.4,44.1,90,41.8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 795 B

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 93 93" xml:space="preserve">
<g>
<path fill="#000000" fill-opacity="0.6" d="M90,41.8L49.9,1.7c-2.3-2.3-6.1-2.3-8.4,0L33.2,10l10.6,10.6c2.5-0.8,5.3-0.3,7.2,1.7c2,2,2.5,4.8,1.7,7.3
l10.2,10.2c2.5-0.8,5.3-0.3,7.3,1.7c2.8,2.7,2.8,7.2,0,10s-7.2,2.8-10,0c-2.1-2.1-2.6-5.1-1.5-7.7l-9.5-9.5v25
c0.7,0.3,1.3,0.8,1.9,1.3c2.8,2.7,2.8,7.2,0,10c-2.8,2.7-7.2,2.7-10,0c-2.8-2.8-2.8-7.2,0-10c0.7-0.7,1.5-1.2,2.3-1.5V33.8
c-0.8-0.3-1.6-0.9-2.3-1.5c-2.1-2.1-2.6-5.1-1.5-7.7L29.2,14.2L1.7,41.7c-2.3,2.3-2.3,6.1,0,8.4l40.1,40.1c2.3,2.3,6.1,2.3,8.4,0
l39.9-39.9C92.4,47.9,92.4,44.1,90,41.8z">
<animate attributeName="fill" values="#000000;#F05133;#000000" dur="1s" repeatCount="indefinite"/>
</path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 941 B

View File

Before

Width:  |  Height:  |  Size: 814 B

After

Width:  |  Height:  |  Size: 814 B

View File

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 313 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect fill="#424242" x="6.5" y="5.5" width="3" height="11"/>
<rect fill="#424242" x="2.5" y="9.5" width="11" height="3"/>
</svg>

After

Width:  |  Height:  |  Size: 253 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m13,8c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -2,0.89 -2,2c0,0.73 0.41,1.38 1,1.72l0,0.3c-0.02,0.52 -0.23,0.98 -0.63,1.38c-0.4,0.4 -0.86,0.61 -1.38,0.63c-0.83,0.02 -1.48,0.16 -2,0.45l0,-4.76c0.59,-0.34 1,-0.98 1,-1.72c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -1.99,0.89 -1.99,2c0,0.73 0.41,1.38 1,1.72l0,6.56c-0.59,0.35 -1,0.99 -1,1.72c0,1.11 0.89,2 2,2c1.11,0 2,-0.89 2,-2c0,-0.53 -0.2,-1 -0.53,-1.36c0.09,-0.06 0.48,-0.41 0.59,-0.47c0.25,-0.11 0.56,-0.17 0.94,-0.17c1.05,-0.05 1.95,-0.45 2.75,-1.25c0.8,-0.8 1.2,-1.98 1.25,-3.02l-0.02,0c0.61,-0.36 1.02,-1 1.02,-1.73l0,0zm-8,-3.2c0.66,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2c-0.65,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2l0,0zm0,12.41c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0zm6,-8c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m11.86,10c-0.45,-1.72 -2,-3 -3.86,-3c-1.86,0 -3.41,1.28 -3.86,3l-3.14,0l0,2l3.14,0c0.45,1.72 2,3 3.86,3c1.86,0 3.41,-1.28 3.86,-3l3.14,0l0,-2l-3.14,0zm-3.86,3.2c-1.22,0 -2.2,-0.98 -2.2,-2.2c0,-1.22 0.98,-2.2 2.2,-2.2c1.22,0 2.2,0.98 2.2,2.2c0,1.22 -0.98,2.2 -2.2,2.2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 428 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m9,15l2,0l-3,3l-3,-3l2,0l0,-5l2,0l0,5l0,0zm3,-8c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 557 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m9,16l-2,0l0,-7l5,0l0,2l-3,0l0,5l0,0zm-1,-12c-2.19,0 -4.13,1.02 -5.41,2.59l-1.59,-1.59l0,4l4,0l-1.5,-1.5c1.05,-1.33 2.67,-2.2 4.5,-2.2c3.14,0 5.7,2.56 5.7,5.7c0,3.14 -2.56,5.7 -5.7,5.7c-3.14,0 -5.7,-2.56 -5.7,-5.7c0,-0.34 0.03,-0.67 0.09,-1l-1.31,0c-0.05,0.33 -0.08,0.66 -0.08,1c0,3.86 3.14,7 7,7c3.86,0 7,-3.14 7,-7c0,-3.86 -3.14,-7 -7,-7l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 500 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.901149,9.091851l-0.094,0.071c-0.269,0.333 -0.746,1.096 -0.91,2.375c0.057,0.277 0.092,0.495 0.092,0.545c0,2.206 -1.794,4 -4,4a3.986,3.986 0 0 1 -2.817,-1.164a3.987,3.987 0 0 1 -1.163,-2.815c0,-2.206 1.794,-4 4,-4l0.351,0.025l0,1.85s1.626,-1.342 1.631,-1.339l1.869,-1.577l-3.5,-2.917l0,2.218l-0.371,-0.03a5.75,5.75 0 0 0 -4.055,9.826a5.75,5.75 0 0 0 9.826,-4.056a5.725,5.725 0 0 0 -0.859,-3.012z" />
</svg>

After

Width:  |  Height:  |  Size: 553 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.519592,15.157073l-9.039184,0c-1.367793,0 -2.480539,-1.112828 -2.480539,-2.480622s1.112746,-2.480539 2.480539,-2.480539l0.281314,0c0.349178,-0.47173 0.888523,-0.771191 1.476341,-0.815025c0.321917,-1.471535 1.619609,-2.537962 3.165139,-2.537962c1.221543,0 2.341663,0.699516 2.889377,1.772488c0.083027,-0.008618 0.166386,-0.012926 0.250076,-0.012926c1.190221,0 2.194667,0.874105 2.378785,2.027867c0.670514,0.460047 1.07869,1.225023 1.07869,2.046096c0,1.367793 -1.112828,2.480622 -2.480539,2.480622z" />
</svg>

After

Width:  |  Height:  |  Size: 655 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#32cd32" stroke="#424242" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#cd3131" stroke="#424242" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
<ellipse fill="#cdcd32" stroke="#424242" stroke-width="0.5" rx="3" ry="3" cx="13" cy="4" />
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 490 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m14.414133,16.199437l-3.415492,-3.433421c0.627518,-0.878526 0.995065,-1.945307 0.995065,-3.110698c0,-2.967265 -2.411463,-5.378728 -5.378728,-5.378728c-2.967265,0 -5.378728,2.411463 -5.378728,5.378728c0,2.967265 2.411463,5.378728 5.378728,5.378728c1.165391,0 2.223207,-0.367546 3.110698,-0.995065l3.433421,3.415492c0.170326,0.179291 0.403405,0.268936 0.627518,0.268936c0.224114,0 0.466156,-0.080681 0.627518,-0.268936c0.349617,-0.349617 0.349617,-0.914384 0,-1.264001l0,0.008965zm-7.799155,-2.330782c-2.321817,0 -4.213337,-1.891519 -4.213337,-4.213337c0,-2.321817 1.891519,-4.213337 4.213337,-4.213337c2.321817,0 4.213337,1.891519 4.213337,4.213337c0,2.321817 -1.891519,4.213337 -4.213337,4.213337l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 857 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m14.687501,11.955358l-1.079554,-6.821251c-0.076429,-0.458572 -0.477679,-0.821607 -0.955357,-0.821607l-9.30518,0c-0.477679,0 -0.878929,0.363036 -0.955357,0.821607l-1.079554,6.821251l0,4.776787c0,0.525447 0.429911,0.955357 0.955357,0.955357l11.464288,0c0.525447,0 0.955357,-0.429911 0.955357,-0.955357l0,-4.776787l0,0zm-3.133572,0.525447l-0.420357,0.850268c-0.162411,0.324821 -0.496786,0.535 -0.869375,0.535l-4.547501,0c-0.363036,0 -0.687857,-0.210179 -0.850268,-0.525447l-0.420357,-0.869375c-0.162411,-0.315268 -0.496786,-0.525447 -0.850268,-0.525447l-1.327947,0l0.955357,-6.687501l9.553573,0l0.955357,6.687501l-1.318393,0c-0.372589,0 -0.697411,0.210179 -0.869375,0.525447l0.009554,0.009554z" />
</svg>

After

Width:  |  Height:  |  Size: 846 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#2d883e" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
A
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#9B4F96" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
C
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#682079" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
C
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#B9131A" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
D
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#969696" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
I
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#007ACC" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
M
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#CC6633" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
R
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,6 @@
<svg width="14px" height="14px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect fill="#6C6C6C" x="0" y="0" width="100" height="100" rx="35" ry="35"/>
<text x="50" y="75" font-size="75" text-anchor="middle" style="font-family: Menlo, Monaco, Consolas, &quot;Droid Sans Mono&quot;, &quot;Inconsolata&quot;, &quot;Courier New&quot;, monospace, &quot;Droid Sans Fallback&quot;;" fill="white">
U
</text>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.24,10.4c0.19,1.28 -0.2,2.62 -1.2,3.6c-1.47,1.45 -3.74,1.63 -5.41,0.54l1.17,-1.14l-4.3,-0.6l0.6,4.2l1.31,-1.26c2.36,1.74 5.7,1.57 7.84,-0.54c1.24,-1.23 1.81,-2.85 1.74,-4.46l-1.75,-0.34l0,0zm-7.28,-2.4c1.47,-1.45 3.74,-1.63 5.41,-0.54l-1.17,1.14l4.3,0.6l-0.6,-4.2l-1.31,1.26c-2.36,-1.74 -5.7,-1.57 -7.85,0.54c-1.24,1.23 -1.8,2.85 -1.73,4.46l1.75,0.35c-0.19,-1.28 0.2,-2.63 1.2,-3.61l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 546 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.5,11l2.5,2.5c0,0.55 -0.45,1 -1,1l-4,0l0,-1l3.5,0l-2,-2l-7,0l-2,2l3.5,0l0,1l-4,0c-0.55,0 -1,-0.45 -1,-1l2.5,-2.5l-2.5,-2.5c0,-0.55 0.45,-1 1,-1l4,0l0,1l-3.5,0l2,2l7,0l2,-2l-3.5,0l0,-1l4,0c0.55,0 1,0.45 1,1l-2.5,2.5l0,0zm-5.5,-1.5l2,0l0,-3l2,0l-3,-3l-3,3l2,0l0,3l0,0zm2,3l-2,0l0,3l-2,0l3,3l3,-3l-2,0l0,-3l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 467 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m7,12l-2,0l3,-3l3,3l-2,0l0,5l-2,0l0,-5l0,0zm5,-4c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 12 KiB

1360
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +1,22 @@
{ {
"name": "gitlens", "name": "gitlens",
"version": "4.1.0-beta", "version": "5.0.0",
"author": { "author": {
"name": "Eric Amodio", "name": "Eric Amodio",
"email": "eamodio@gmail.com" "email": "eamodio@gmail.com"
}, },
"publisher": "eamodio", "publisher": "eamodio",
"engines": { "engines": {
"vscode": "^1.12.0" "vscode": "^1.16.0"
}, },
"license": "SEE LICENSE IN LICENSE", "license": "SEE LICENSE IN LICENSE",
"displayName": "Git Lens \u2014 git blame annotations, code lens, and more", "displayName": "Git Lens \u2014 git blame annotations, code lens, and more",
"description": "Supercharge Visual Studio Code's Git capabilities \u2014 Visualize code authorship at a glance via Git blame annotations and code lens, seamlessly navigate and explore the history of a file or branch, gain valuable insights via powerful comparision commands, and so much more", "description": "Supercharge Visual Studio Code's Git capabilities \u2014 Visualize code authorship at a glance via Git blame annotations and code lens, seamlessly navigate and explore the history of a file or branch, gain valuable insights via powerful comparison commands, and so much more",
"badges": [ "badges": [
{ {
"url": "https://badges.gitter.im/vscode-gitlens/Lobby.svg", "url": "https://img.shields.io/badge/chat-on%20slack-brightgreen.svg",
"href": "https://gitter.im/vscode-gitlens/Lobby", "href": "https://join.slack.com/t/vscode-gitlens/shared_invite/MjIxOTgxNDE3NzM0LTE1MDE2Nzk1MTgtMjkwMmZjMzcxNQ",
"description": "Chat at https://gitter.im/vscode-gitlens/Lobby" "description": "Chat at https://vscode-gitlens.slack.com/"
} }
], ],
"categories": [ "categories": [
@@ -37,7 +37,7 @@
"color": "#56098c", "color": "#56098c",
"theme": "dark" "theme": "dark"
}, },
"icon": "images/gitlens-icon.svg", "icon": "images/gitlens-icon.png",
"preview": false, "preview": false,
"homepage": "https://github.com/eamodio/vscode-gitlens/blob/master/README.md", "homepage": "https://github.com/eamodio/vscode-gitlens/blob/master/README.md",
"bugs": { "bugs": {
@@ -122,10 +122,15 @@
"default": true, "default": true,
"description": "Specifies whether or not to trigger hover annotations over the whole line" "description": "Specifies whether or not to trigger hover annotations over the whole line"
}, },
"gitlens.annotations.file.recentChanges.hover.details": {
"type": "boolean",
"default": true,
"description": "Specifies whether or not to provide a commit details hover annotation"
},
"gitlens.annotations.file.recentChanges.hover.changes": { "gitlens.annotations.file.recentChanges.hover.changes": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"description": "Specifies whether or not to provide a changes (diff) hover annotations" "description": "Specifies whether or not to provide a changes (diff) hover annotation"
}, },
"gitlens.annotations.file.recentChanges.hover.wholeLine": { "gitlens.annotations.file.recentChanges.hover.wholeLine": {
"type": "boolean", "type": "boolean",
@@ -167,6 +172,11 @@
"default": false, "default": false,
"description": "Specifies whether or not to trigger hover annotations over the whole line" "description": "Specifies whether or not to trigger hover annotations over the whole line"
}, },
"gitlens.blame.ignoreWhitespace": {
"type": "boolean",
"default": false,
"description": "Specifies whether or not to ignore whitespace when comparing revisions during blame operations"
},
"gitlens.blame.file.annotationType": { "gitlens.blame.file.annotationType": {
"type": "string", "type": "string",
"default": "gutter", "default": "gutter",
@@ -204,7 +214,7 @@
"gitlens.blame.line.enabled": { "gitlens.blame.line.enabled": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"description": "Specifies whether or not to provide a blame annotation for the current line" "description": "Specifies whether or not to provide a blame annotation for the current line, by default\nUse the `gitlens.toggleLineBlame` command to toggle the annotations on and off for the current session"
}, },
"gitlens.blame.line.annotationType": { "gitlens.blame.line.annotationType": {
"type": "string", "type": "string",
@@ -238,7 +248,7 @@
"gitlens.codeLens.enabled": { "gitlens.codeLens.enabled": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"description": "Specifies whether or not to provide any Git code lens" "description": "Specifies whether or not to provide any Git code lens, by default\nUse the `gitlens.toggleCodeLens` command to toggle the Git code lens on and off for the current session"
}, },
"gitlens.codeLens.recentChange.enabled": { "gitlens.codeLens.recentChange.enabled": {
"type": "boolean", "type": "boolean",
@@ -346,6 +356,12 @@
"locations": [ "locations": [
"document" "document"
] ]
},
{
"language": "stylus",
"locations": [
"document"
]
} }
], ],
"items": { "items": {
@@ -397,6 +413,74 @@
"default": false, "default": false,
"description": "Specifies whether or not to show debug information in code lens" "description": "Specifies whether or not to show debug information in code lens"
}, },
"gitlens.defaultDateFormat": {
"type": "string",
"default": null,
"description": "Specifies how all absolute dates will be formatted by default\nSee https://momentjs.com/docs/#/displaying/format/ for valid formats"
},
"gitlens.gitExplorer.commitFormat": {
"type": "string",
"default": "${message} \u00a0\u2022\u00a0 ${authorAgo} \u00a0\u2022\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"
},
"gitlens.gitExplorer.commitFileFormat": {
"type": "string",
"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"
},
"gitlens.gitExplorer.showTrackingBranch": {
"type": "boolean",
"default": true,
"description": "Specifies whether or not to show the tracking branch when displaying local branches in the `GitLens` custom view"
},
"gitlens.gitExplorer.stashFormat": {
"type": "string",
"default": "${message}",
"description": "Specifies the format of stashed 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.stashFileFormat": {
"type": "string",
"default": "${filePath}",
"description": "Specifies the format of a stashed file in the `GitLens` custom view\nAvailable tokens\n ${file} - file name\n ${filePath} - file name and path\n ${path} - file path"
},
"gitlens.gitExplorer.view": {
"type": "string",
"default": "repository",
"enum": [
"history",
"repository"
],
"description": "Specifies the starting view (mode) of the `GitLens` custom view\n `history` - shows the commit history of the active file\n `repository` - shows a repository explorer"
},
"gitlens.remotes": {
"type": "array",
"default": null,
"items": {
"type": "object",
"required": [
"type",
"domain"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Bitbucket",
"BitbucketServer",
"GitHub",
"GitLab"
],
"description": "Specifies the type of the custom remote service\n `Bitbucket`, `BitbucketServer`, `GitHub`, or `GitLab`"
},
"domain": {
"type": "string",
"description": "Specifies the domain name of the custom remote service"
}
}
},
"uniqueItems": true,
"description": "Specifies any custom domains for remote (code-hosting) services"
},
"gitlens.statusBar.enabled": { "gitlens.statusBar.enabled": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
@@ -488,11 +572,6 @@
"default": "rgba(0, 188, 242, 0.6)", "default": "rgba(0, 188, 242, 0.6)",
"description": "Specifies the light theme foreground color of an uncommitted line in the gutter blame annotations. Must be a valid css color" "description": "Specifies the light theme foreground color of an uncommitted line in the gutter blame annotations. Must be a valid css color"
}, },
"gitlens.theme.annotations.file.hover.separateLines": {
"type": "boolean",
"default": false,
"description": "Specifies whether or not hover blame annotations will be separated by a small gap (if heatmap is enabled)"
},
"gitlens.theme.annotations.line.trailing.dark.backgroundColor": { "gitlens.theme.annotations.line.trailing.dark.backgroundColor": {
"type": "string", "type": "string",
"default": null, "default": null,
@@ -728,7 +807,7 @@
}, },
"gitlens.advanced.toggleWhitespace.enabled": { "gitlens.advanced.toggleWhitespace.enabled": {
"type": "boolean", "type": "boolean",
"default": true, "default": false,
"description": "Specifies whether or not to toggle whitespace off then showing blame annotations (*may* be required by certain fonts/themes)" "description": "Specifies whether or not to toggle whitespace off then showing blame annotations (*may* be required by certain fonts/themes)"
} }
} }
@@ -739,34 +818,44 @@
"title": "Directory Compare", "title": "Directory Compare",
"category": "GitLens" "category": "GitLens"
}, },
{
"command": "gitlens.diffWith",
"title": "Compare File Revisions",
"category": "GitLens"
},
{ {
"command": "gitlens.diffWithBranch", "command": "gitlens.diffWithBranch",
"title": "Compare File with...", "title": "Compare File with Branch...",
"category": "GitLens" "category": "GitLens"
}, },
{ {
"command": "gitlens.diffWithNext", "command": "gitlens.diffWithNext",
"title": "Compare File with Next Commit", "title": "Compare File with Next Revision",
"category": "GitLens" "category": "GitLens"
}, },
{ {
"command": "gitlens.diffWithPrevious", "command": "gitlens.diffWithPrevious",
"title": "Compare File with Previous", "title": "Compare File with Previous Revision",
"category": "GitLens" "category": "GitLens"
}, },
{ {
"command": "gitlens.diffLineWithPrevious", "command": "gitlens.diffLineWithPrevious",
"title": "Compare Line Commit with Previous", "title": "Compare Line Revision with Previous",
"category": "GitLens"
},
{
"command": "gitlens.diffWithRevision",
"title": "Compare File with Revision...",
"category": "GitLens" "category": "GitLens"
}, },
{ {
"command": "gitlens.diffWithWorking", "command": "gitlens.diffWithWorking",
"title": "Compare File with Working Tree", "title": "Compare File with Working Revision",
"category": "GitLens" "category": "GitLens"
}, },
{ {
"command": "gitlens.diffLineWithWorking", "command": "gitlens.diffLineWithWorking",
"title": "Compare Line Commit with Working Tree", "title": "Compare Line Revision with Working",
"category": "GitLens" "category": "GitLens"
}, },
{ {
@@ -784,14 +873,36 @@
"title": "Toggle File Blame Annotations", "title": "Toggle File Blame Annotations",
"category": "GitLens", "category": "GitLens",
"icon": { "icon": {
"dark": "images/git-icon-dark.svg", "dark": "images/dark/git-icon.svg",
"light": "images/git-icon-light.svg" "light": "images/light/git-icon.svg"
}
},
{
"command": "gitlens.clearFileAnnotations",
"title": "Clear File Annotations",
"category": "GitLens",
"icon": {
"dark": "images/dark/git-icon-orange.svg",
"light": "images/light/git-icon-orange.svg"
}
},
{
"command": "gitlens.computingFileAnnotations",
"title": "Computing File Annotations...",
"category": "GitLens",
"icon": {
"dark": "images/dark/git-icon-progress.svg",
"light": "images/light/git-icon-progress.svg"
} }
}, },
{ {
"command": "gitlens.toggleFileRecentChanges", "command": "gitlens.toggleFileRecentChanges",
"title": "Toggle Recent File Changes Annotations", "title": "Toggle Recent File Changes Annotations",
"category": "GitLens" "category": "GitLens",
"icon": {
"dark": "images/dark/git-icon.svg",
"light": "images/light/git-icon.svg"
}
}, },
{ {
"command": "gitlens.toggleLineBlame", "command": "gitlens.toggleLineBlame",
@@ -811,7 +922,11 @@
{ {
"command": "gitlens.showCommitSearch", "command": "gitlens.showCommitSearch",
"title": "Search Commits", "title": "Search Commits",
"category": "GitLens" "category": "GitLens",
"icon": {
"dark": "images/dark/icon-search.svg",
"light": "images/light/icon-search.svg"
}
}, },
{ {
"command": "gitlens.showFileHistory", "command": "gitlens.showFileHistory",
@@ -830,7 +945,7 @@
}, },
{ {
"command": "gitlens.showQuickCommitFileDetails", "command": "gitlens.showQuickCommitFileDetails",
"title": "Show Line Commit Details", "title": "Show Commit File Details",
"category": "GitLens" "category": "GitLens"
}, },
{ {
@@ -878,6 +993,11 @@
"title": "Open Changed Files", "title": "Open Changed Files",
"category": "GitLens" "category": "GitLens"
}, },
{
"command": "gitlens.openBranchesInRemote",
"title": "Open Branches in Remote",
"category": "GitLens"
},
{ {
"command": "gitlens.openBranchInRemote", "command": "gitlens.openBranchInRemote",
"title": "Open Branch in Remote", "title": "Open Branch in Remote",
@@ -885,7 +1005,7 @@
}, },
{ {
"command": "gitlens.openCommitInRemote", "command": "gitlens.openCommitInRemote",
"title": "Open Line Commit in Remote", "title": "Open Commit in Remote",
"category": "GitLens" "category": "GitLens"
}, },
{ {
@@ -903,15 +1023,101 @@
"title": "Apply Stashed Changes", "title": "Apply Stashed Changes",
"category": "GitLens" "category": "GitLens"
}, },
{
"command": "gitlens.stashDelete",
"title": "Delete Stashed Changes",
"category": "GitLens"
},
{ {
"command": "gitlens.stashSave", "command": "gitlens.stashSave",
"title": "Stash Changes", "title": "Stash Changes",
"category": "GitLens" "category": "GitLens",
"icon": {
"dark": "images/dark/icon-add.svg",
"light": "images/light/icon-add.svg"
}
}, },
{ {
"command": "gitlens.resetSuppressedWarnings", "command": "gitlens.resetSuppressedWarnings",
"title": "Reset Suppressed Warnings", "title": "Reset Suppressed Warnings",
"category": "GitLens" "category": "GitLens"
},
{
"command": "gitlens.gitExplorer.refresh",
"title": "Refresh",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-refresh.svg",
"light": "images/light/icon-refresh.svg"
}
},
{
"command": "gitlens.gitExplorer.switchToHistoryView",
"title": "Switch to History View",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-history.svg",
"light": "images/light/icon-history.svg"
}
},
{
"command": "gitlens.gitExplorer.switchToRepositoryView",
"title": "Switch to Repository View",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-repo.svg",
"light": "images/light/icon-repo.svg"
}
},
{
"command": "gitlens.gitExplorer.openChanges",
"title": "Open Changes",
"category": "GitLens"
},
{
"command": "gitlens.gitExplorer.openChangesWithWorking",
"title": "Open Changes with Working Tree",
"category": "GitLens"
},
{
"command": "gitlens.gitExplorer.openFile",
"title": "Open File",
"category": "GitLens"
},
{
"command": "gitlens.gitExplorer.openFileRevision",
"title": "Open Revision",
"category": "GitLens"
},
{
"command": "gitlens.gitExplorer.openFileRevisionInRemote",
"title": "Open Revision in Remote",
"category": "GitLens"
},
{
"command": "gitlens.gitExplorer.openChangedFiles",
"title": "Open Files",
"category": "GitLens"
},
{
"command": "gitlens.gitExplorer.openChangedFileChanges",
"title": "Open All Changes",
"category": "GitLens"
},
{
"command": "gitlens.gitExplorer.openChangedFileChangesWithWorking",
"title": "Open All Changes with Working Tree",
"category": "GitLens"
},
{
"command": "gitlens.gitExplorer.openChangedFileRevisions",
"title": "Open Revisions",
"category": "GitLens"
},
{
"command": "gitlens.gitExplorer.applyChanges",
"title": "Apply Changes",
"category": "GitLens"
} }
], ],
"menus": { "menus": {
@@ -920,6 +1126,10 @@
"command": "gitlens.diffDirectory", "command": "gitlens.diffDirectory",
"when": "gitlens:enabled" "when": "gitlens:enabled"
}, },
{
"command": "gitlens.diffWith",
"when": "false"
},
{ {
"command": "gitlens.diffWithBranch", "command": "gitlens.diffWithBranch",
"when": "gitlens:isTracked" "when": "gitlens:isTracked"
@@ -936,6 +1146,10 @@
"command": "gitlens.diffLineWithPrevious", "command": "gitlens.diffLineWithPrevious",
"when": "gitlens:isBlameable" "when": "gitlens:isBlameable"
}, },
{
"command": "gitlens.diffWithRevision",
"when": "gitlens:isTracked"
},
{ {
"command": "gitlens.diffWithWorking", "command": "gitlens.diffWithWorking",
"when": "gitlens:isTracked" "when": "gitlens:isTracked"
@@ -956,6 +1170,14 @@
"command": "gitlens.toggleFileBlame", "command": "gitlens.toggleFileBlame",
"when": "gitlens:isBlameable" "when": "gitlens:isBlameable"
}, },
{
"command": "gitlens.clearFileAnnotations",
"when": "gitlens:annotationStatus == computed"
},
{
"command": "gitlens.computingFileAnnotations",
"when": "false"
},
{ {
"command": "gitlens.toggleFileRecentChanges", "command": "gitlens.toggleFileRecentChanges",
"when": "gitlens:isTracked" "when": "gitlens:isTracked"
@@ -1024,6 +1246,10 @@
"command": "gitlens.openChangedFiles", "command": "gitlens.openChangedFiles",
"when": "gitlens:enabled" "when": "gitlens:enabled"
}, },
{
"command": "gitlens.openBranchesInRemote",
"when": "gitlens:hasRemotes"
},
{ {
"command": "gitlens.openBranchInRemote", "command": "gitlens.openBranchInRemote",
"when": "gitlens:hasRemotes" "when": "gitlens:hasRemotes"
@@ -1051,6 +1277,58 @@
{ {
"command": "gitlens.resetSuppressedWarnings", "command": "gitlens.resetSuppressedWarnings",
"when": "gitlens:enabled" "when": "gitlens:enabled"
},
{
"command": "gitlens.gitExplorer.refresh",
"when": "false"
},
{
"command": "gitlens.gitExplorer.switchToHistoryView",
"when": "gitlens:gitExplorer:view == repository"
},
{
"command": "gitlens.gitExplorer.switchToRepositoryView",
"when": "gitlens:gitExplorer:view == history"
},
{
"command": "gitlens.gitExplorer.openChanges",
"when": "false"
},
{
"command": "gitlens.gitExplorer.openChangesWithWorking",
"when": "false"
},
{
"command": "gitlens.gitExplorer.openFile",
"when": "false"
},
{
"command": "gitlens.gitExplorer.openFileRevision",
"when": "false"
},
{
"command": "gitlens.gitExplorer.openFileRevisionInRemote",
"when": "false"
},
{
"command": "gitlens.gitExplorer.openChangedFiles",
"when": "false"
},
{
"command": "gitlens.gitExplorer.openChangedFileChanges",
"when": "false"
},
{
"command": "gitlens.gitExplorer.openChangedFileChangesWithWorking",
"when": "false"
},
{
"command": "gitlens.gitExplorer.openChangedFileRevisions",
"when": "false"
},
{
"command": "gitlens.gitExplorer.applyChanges",
"when": "false"
} }
], ],
"editor/context": [ "editor/context": [
@@ -1108,17 +1386,28 @@
"editor/title": [ "editor/title": [
{ {
"command": "gitlens.toggleFileBlame", "command": "gitlens.toggleFileBlame",
"when": "gitlens:isBlameable && config.gitlens.advanced.menus.editorTitle.blame", "alt": "gitlens.toggleFileRecentChanges",
"when": "gitlens:isBlameable && !gitlens:annotationStatus && config.gitlens.advanced.menus.editorTitle.blame",
"group": "navigation@100"
},
{
"command": "gitlens.computingFileAnnotations",
"when": "gitlens:annotationStatus == computing && config.gitlens.advanced.menus.editorTitle.blame",
"group": "navigation@100"
},
{
"command": "gitlens.clearFileAnnotations",
"when": "gitlens:annotationStatus == computed && config.gitlens.advanced.menus.editorTitle.blame",
"group": "navigation@100" "group": "navigation@100"
}, },
{ {
"command": "gitlens.openFileInRemote", "command": "gitlens.openFileInRemote",
"when": "gitlens:enabled && config.gitlens.advanced.menus.editorTitleContext.remote", "when": "gitlens:enabled && gitlens:hasRemotes && config.gitlens.advanced.menus.editorTitleContext.remote",
"group": "1_gitlens" "group": "1_gitlens"
}, },
{ {
"command": "gitlens.openRepoInRemote", "command": "gitlens.openRepoInRemote",
"when": "gitlens:enabled && config.gitlens.advanced.menus.editorTitleContext.remote", "when": "gitlens:enabled && gitlens:hasRemotes && config.gitlens.advanced.menus.editorTitleContext.remote",
"group": "1_gitlens" "group": "1_gitlens"
}, },
{ {
@@ -1150,7 +1439,7 @@
"editor/title/context": [ "editor/title/context": [
{ {
"command": "gitlens.openFileInRemote", "command": "gitlens.openFileInRemote",
"when": "gitlens:enabled && config.gitlens.advanced.menus.editorTitleContext.remote", "when": "gitlens:enabled && gitlens:hasRemotes && config.gitlens.advanced.menus.editorTitleContext.remote",
"group": "1_gitlens" "group": "1_gitlens"
}, },
{ {
@@ -1177,7 +1466,7 @@
"explorer/context": [ "explorer/context": [
{ {
"command": "gitlens.openFileInRemote", "command": "gitlens.openFileInRemote",
"when": "gitlens:enabled && config.gitlens.advanced.menus.explorerContext.remote", "when": "gitlens:enabled && gitlens:hasRemotes && config.gitlens.advanced.menus.explorerContext.remote",
"group": "navigation@100" "group": "navigation@100"
}, },
{ {
@@ -1195,6 +1484,269 @@
"when": "gitlens:enabled && config.gitlens.advanced.menus.explorerContext.history", "when": "gitlens:enabled && config.gitlens.advanced.menus.explorerContext.history",
"group": "1_gitlens_1@1" "group": "1_gitlens_1@1"
} }
],
"scm/resourceGroup/context": [
{
"command": "gitlens.openChangedFiles",
"when": "gitlens:enabled",
"group": "1_gitlens@1"
},
{
"command": "gitlens.closeUnchangedFiles",
"when": "gitlens:enabled",
"group": "1_gitlens@2"
},
{
"command": "gitlens.stashSave",
"when": "gitlens:enabled",
"group": "2_gitlens@1"
}
],
"scm/resourceState/context": [
{
"command": "gitlens.openFileInRemote",
"when": "gitlens:enabled && gitlens:hasRemotes",
"group": "navigation"
},
{
"command": "gitlens.diffWithRevision",
"when": "gitlens:enabled",
"group": "1_gitlens@1"
},
{
"command": "gitlens.showQuickFileHistory",
"when": "gitlens:enabled",
"group": "1_gitlens_1@1"
},
{
"command": "gitlens.stashSave",
"when": "gitlens:enabled",
"group": "2_gitlens@1"
}
],
"view/title": [
{
"command": "gitlens.showCommitSearch",
"when": "view == gitlens.gitExplorer",
"group": "navigation@1"
},
{
"command": "gitlens.gitExplorer.switchToHistoryView",
"when": "view == gitlens.gitExplorer && gitlens:gitExplorer:view == repository",
"group": "navigation@2"
},
{
"command": "gitlens.gitExplorer.switchToRepositoryView",
"when": "view == gitlens.gitExplorer && gitlens:gitExplorer:view == history",
"group": "navigation@3"
},
{
"command": "gitlens.gitExplorer.refresh",
"when": "view == gitlens.gitExplorer",
"group": "navigation@4"
}
],
"view/item/context": [
{
"command": "gitlens.openBranchesInRemote",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:branches:remote",
"group": "1_gitlens@1"
},
{
"command": "gitlens.openBranchInRemote",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:branch-history:remote",
"group": "1_gitlens@1"
},
{
"command": "gitlens.openCommitInRemote",
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "1_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangedFileChanges",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "2_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangedFileChangesWithWorking",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "2_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangedFiles",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "3_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangedFileRevisions",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "3_gitlens@2"
},
{
"command": "gitlens.copyShaToClipboard",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "4_gitlens@1"
},
{
"command": "gitlens.copyMessageToClipboard",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "4_gitlens@2"
},
{
"command": "gitlens.showQuickCommitDetails",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "5_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChanges",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "1_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangesWithWorking",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "1_gitlens@2"
},
{
"command": "gitlens.gitExplorer.openFile",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "2_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openFileRevision",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "2_gitlens@2"
},
{
"command": "gitlens.openFileInRemote",
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "3_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openFileRevisionInRemote",
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "3_gitlens@2"
},
{
"command": "gitlens.gitExplorer.applyChanges",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "4_gitlens@1"
},
{
"command": "gitlens.showQuickFileHistory",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit-file && gitlens:gitExplorer:view == repository",
"group": "5_gitlens@1"
},
{
"command": "gitlens.showQuickCommitFileDetails",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "5_gitlens@2"
},
{
"command": "gitlens.gitExplorer.openFile",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:file-history",
"group": "1_gitlens@1"
},
{
"command": "gitlens.openFileInRemote",
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:file-history",
"group": "1_gitlens@2"
},
{
"command": "gitlens.openBranchesInRemote",
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:remote",
"group": "1_gitlens@1"
},
{
"command": "gitlens.openRepoInRemote",
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:remote",
"group": "1_gitlens@2"
},
{
"command": "gitlens.stashSave",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stashes",
"group": "1_gitlens@1"
},
{
"command": "gitlens.stashApply",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "1_gitlens@1"
},
{
"command": "gitlens.stashDelete",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "1_gitlens@2"
},
{
"command": "gitlens.gitExplorer.openChangedFileChanges",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "2_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangedFileChangesWithWorking",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "2_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangedFiles",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "3_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangedFileRevisions",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "3_gitlens@2"
},
{
"command": "gitlens.copyMessageToClipboard",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "4_gitlens@1"
},
{
"command": "gitlens.gitExplorer.applyChanges",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "1_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChanges",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "2_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangesWithWorking",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "2_gitlens@2"
},
{
"command": "gitlens.gitExplorer.openFile",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "3_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openFileRevision",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "3_gitlens@2"
},
{
"command": "gitlens.openFileInRemote",
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "4_gitlens@1"
},
{
"command": "gitlens.showQuickFileHistory",
"when": "view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "5_gitlens@1"
},
{
"command": "gitlens.openRepoInRemote",
"when": "gitlens:hasRemotes && view == gitlens.gitExplorer && viewItem == gitlens:status",
"group": "1_gitlens@1"
},
{
"command": "gitlens.gitExplorer.refresh",
"when": "view == gitlens.gitExplorer && viewItem != gitlens:commit-file && viewItem != gitlens:stash-file",
"group": "9_gitlens@1"
}
] ]
}, },
"keybindings": [ "keybindings": [
@@ -1218,85 +1770,86 @@
"key": "alt+.", "key": "alt+.",
"when": "gitlens:key:." "when": "gitlens:key:."
}, },
{
"command": "gitlens.key.escape",
"key": "escape",
"when": "gitlens:key:escape"
},
{ {
"command": "gitlens.toggleFileBlame", "command": "gitlens.toggleFileBlame",
"key": "alt+b", "key": "alt+b",
"mac": "alt+b",
"when": "editorTextFocus && gitlens:isTracked" "when": "editorTextFocus && gitlens:isTracked"
}, },
{ {
"command": "gitlens.toggleCodeLens", "command": "gitlens.toggleCodeLens",
"key": "shift+alt+b", "key": "shift+alt+b",
"mac": "shift+alt+b",
"when": "editorTextFocus && gitlens:isTracked && gitlens:canToggleCodeLens" "when": "editorTextFocus && gitlens:isTracked && gitlens:canToggleCodeLens"
}, },
{ {
"command": "gitlens.showLastQuickPick", "command": "gitlens.showLastQuickPick",
"key": "alt+-", "key": "alt+-",
"mac": "alt+-",
"when": "gitlens:enabled" "when": "gitlens:enabled"
}, },
{ {
"command": "gitlens.showCommitSearch", "command": "gitlens.showCommitSearch",
"key": "alt+/", "key": "alt+/",
"mac": "alt+/",
"when": "gitlens:enabled" "when": "gitlens:enabled"
}, },
{ {
"command": "gitlens.showQuickFileHistory", "command": "gitlens.showQuickFileHistory",
"key": "alt+h", "key": "alt+h",
"mac": "alt+h",
"when": "gitlens:enabled" "when": "gitlens:enabled"
}, },
{ {
"command": "gitlens.showQuickRepoHistory", "command": "gitlens.showQuickRepoHistory",
"key": "shift+alt+h", "key": "shift+alt+h",
"mac": "shift+alt+h",
"when": "gitlens:enabled" "when": "gitlens:enabled"
}, },
{ {
"command": "gitlens.showQuickRepoStatus", "command": "gitlens.showQuickRepoStatus",
"key": "alt+s", "key": "alt+s",
"mac": "alt+s",
"when": "gitlens:enabled" "when": "gitlens:enabled"
}, },
{ {
"command": "gitlens.showQuickCommitFileDetails", "command": "gitlens.showQuickCommitFileDetails",
"key": "alt+c", "key": "alt+c",
"mac": "alt+c",
"when": "editorTextFocus && gitlens:enabled" "when": "editorTextFocus && gitlens:enabled"
}, },
{ {
"command": "gitlens.diffWithNext", "command": "gitlens.diffWithNext",
"key": "alt+.", "key": "alt+.",
"mac": "alt+.",
"when": "editorTextFocus && gitlens:isTracked" "when": "editorTextFocus && gitlens:isTracked"
}, },
{ {
"command": "gitlens.diffLineWithPrevious", "command": "gitlens.diffLineWithPrevious",
"key": "shift+alt+,", "key": "shift+alt+,",
"mac": "shift+alt+,",
"when": "editorTextFocus && gitlens:isTracked" "when": "editorTextFocus && gitlens:isTracked"
}, },
{ {
"command": "gitlens.diffWithPrevious", "command": "gitlens.diffWithPrevious",
"key": "alt+,", "key": "alt+,",
"mac": "alt+,",
"when": "editorTextFocus && gitlens:isTracked" "when": "editorTextFocus && gitlens:isTracked"
}, },
{ {
"command": "gitlens.diffLineWithWorking", "command": "gitlens.diffLineWithWorking",
"key": "alt+w", "key": "alt+w",
"mac": "alt+w",
"when": "editorTextFocus && gitlens:isTracked" "when": "editorTextFocus && gitlens:isTracked"
}, },
{ {
"command": "gitlens.diffWithWorking", "command": "gitlens.diffWithWorking",
"key": "shift+alt+w", "key": "shift+alt+w",
"mac": "shift+alt+w",
"when": "editorTextFocus && gitlens:isTracked" "when": "editorTextFocus && gitlens:isTracked"
} }
] ],
"views": {
"explorer": [
{
"id": "gitlens.gitExplorer",
"name": "GitLens",
"when": "gitlens:enabled"
}
]
}
}, },
"activationEvents": [ "activationEvents": [
"*" "*"
@@ -1313,27 +1866,28 @@
"vscode:prepublish": "npm install --no-save && npm run compile" "vscode:prepublish": "npm install --no-save && npm run compile"
}, },
"dependencies": { "dependencies": {
"applicationinsights": "0.20.1", "applicationinsights": "0.21.0",
"copy-paste": "1.3.0", "copy-paste": "1.3.0",
"iconv-lite": "0.4.17", "iconv-lite": "0.4.19",
"ignore": "3.3.3", "ignore": "3.3.5",
"lodash.debounce": "4.0.8", "lodash.debounce": "4.0.8",
"lodash.escaperegexp": "4.1.2", "lodash.escaperegexp": "4.1.2",
"lodash.isequal": "4.5.0", "lodash.isequal": "4.5.0",
"lodash.once": "4.1.1", "lodash.once": "4.1.1",
"moment": "2.18.1", "moment": "2.18.1",
"spawn-rx": "2.0.11", "spawn-rx": "2.0.11",
"tmp": "0.0.31" "string-width": "2.1.1",
"tmp": "0.0.33"
}, },
"devDependencies": { "devDependencies": {
"@types/copy-paste": "1.1.30", "@types/copy-paste": "1.1.30",
"@types/iconv-lite": "0.0.1", "@types/iconv-lite": "0.0.1",
"@types/mocha": "2.2.41", "@types/mocha": "2.2.43",
"@types/node": "7.0.29", "@types/node": "8.0.28",
"@types/tmp": "0.0.33", "@types/tmp": "0.0.33",
"mocha": "3.4.2", "mocha": "3.5.2",
"tslint": "5.4.3", "tslint": "5.7.0",
"typescript": "2.3.4", "typescript": "2.5.2",
"vscode": "1.1.0" "vscode": "1.1.5"
} }
} }

View File

@@ -1,15 +1,18 @@
'use strict'; 'use strict';
import { Functions, Objects } from '../system'; import { Functions, Objects } from '../system';
import { DecorationRenderOptions, Disposable, Event, EventEmitter, ExtensionContext, OverviewRulerLane, TextDocument, TextDocumentChangeEvent, TextEditor, TextEditorDecorationType, TextEditorViewColumnChangeEvent, window, workspace } from 'vscode'; import { DecorationRenderOptions, Disposable, Event, EventEmitter, ExtensionContext, OverviewRulerLane, Progress, ProgressLocation, TextDocument, TextDocumentChangeEvent, TextEditor, TextEditorDecorationType, TextEditorViewColumnChangeEvent, window, workspace } from 'vscode';
import { AnnotationProviderBase } from './annotationProvider'; import { AnnotationProviderBase } from './annotationProvider';
import { Keyboard, KeyboardScope, KeyCommand, Keys } from '../keyboard';
import { TextDocumentComparer, TextEditorComparer } from '../comparers'; import { TextDocumentComparer, TextEditorComparer } from '../comparers';
import { ExtensionKey, IConfig, LineHighlightLocations, themeDefaults } from '../configuration'; import { ExtensionKey, IConfig, LineHighlightLocations, themeDefaults } from '../configuration';
import { CommandContext, setCommandContext } from '../constants';
import { BlameabilityChangeEvent, GitContextTracker, GitService, GitUri } from '../gitService'; import { BlameabilityChangeEvent, GitContextTracker, GitService, GitUri } from '../gitService';
import { GutterBlameAnnotationProvider } from './gutterBlameAnnotationProvider'; import { GutterBlameAnnotationProvider } from './gutterBlameAnnotationProvider';
import { HoverBlameAnnotationProvider } from './hoverBlameAnnotationProvider'; import { HoverBlameAnnotationProvider } from './hoverBlameAnnotationProvider';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { RecentChangesAnnotationProvider } from './recentChangesAnnotationProvider'; import { RecentChangesAnnotationProvider } from './recentChangesAnnotationProvider';
import { WhitespaceController } from './whitespaceController'; import { WhitespaceController } from './whitespaceController';
import * as path from 'path';
export type FileAnnotationType = 'gutter' | 'hover' | 'recentChanges'; export type FileAnnotationType = 'gutter' | 'hover' | 'recentChanges';
export const FileAnnotationType = { export const FileAnnotationType = {
@@ -113,7 +116,7 @@ export class AnnotationController extends Disposable {
? cfgTheme.dark.backgroundColor || themeDefaults.lineHighlight.dark.backgroundColor ? cfgTheme.dark.backgroundColor || themeDefaults.lineHighlight.dark.backgroundColor
: undefined, : undefined,
gutterIconPath: cfgBlameHighlight.locations.includes(LineHighlightLocations.Gutter) gutterIconPath: cfgBlameHighlight.locations.includes(LineHighlightLocations.Gutter)
? this.context.asAbsolutePath('images/blame-dark.svg') ? this.context.asAbsolutePath('images/dark/highlight-gutter.svg')
: undefined, : undefined,
overviewRulerColor: cfgBlameHighlight.locations.includes(LineHighlightLocations.OverviewRuler) overviewRulerColor: cfgBlameHighlight.locations.includes(LineHighlightLocations.OverviewRuler)
? cfgTheme.dark.overviewRulerColor || themeDefaults.lineHighlight.dark.overviewRulerColor ? cfgTheme.dark.overviewRulerColor || themeDefaults.lineHighlight.dark.overviewRulerColor
@@ -124,7 +127,7 @@ export class AnnotationController extends Disposable {
? cfgTheme.light.backgroundColor || themeDefaults.lineHighlight.light.backgroundColor ? cfgTheme.light.backgroundColor || themeDefaults.lineHighlight.light.backgroundColor
: undefined, : undefined,
gutterIconPath: cfgBlameHighlight.locations.includes(LineHighlightLocations.Gutter) gutterIconPath: cfgBlameHighlight.locations.includes(LineHighlightLocations.Gutter)
? this.context.asAbsolutePath('images/blame-light.svg') ? this.context.asAbsolutePath('images/light/highlight-gutter.svg')
: undefined, : undefined,
overviewRulerColor: cfgBlameHighlight.locations.includes(LineHighlightLocations.OverviewRuler) overviewRulerColor: cfgBlameHighlight.locations.includes(LineHighlightLocations.OverviewRuler)
? cfgTheme.light.overviewRulerColor || themeDefaults.lineHighlight.light.overviewRulerColor ? cfgTheme.light.overviewRulerColor || themeDefaults.lineHighlight.light.overviewRulerColor
@@ -147,7 +150,7 @@ export class AnnotationController extends Disposable {
? cfgTheme.dark.backgroundColor || themeDefaults.lineHighlight.dark.backgroundColor ? cfgTheme.dark.backgroundColor || themeDefaults.lineHighlight.dark.backgroundColor
: undefined, : undefined,
gutterIconPath: cfgChangesHighlight.locations.includes(LineHighlightLocations.Gutter) gutterIconPath: cfgChangesHighlight.locations.includes(LineHighlightLocations.Gutter)
? this.context.asAbsolutePath('images/blame-dark.svg') ? this.context.asAbsolutePath('images/dark/highlight-gutter.svg')
: undefined, : undefined,
overviewRulerColor: cfgChangesHighlight.locations.includes(LineHighlightLocations.OverviewRuler) overviewRulerColor: cfgChangesHighlight.locations.includes(LineHighlightLocations.OverviewRuler)
? cfgTheme.dark.overviewRulerColor || themeDefaults.lineHighlight.dark.overviewRulerColor ? cfgTheme.dark.overviewRulerColor || themeDefaults.lineHighlight.dark.overviewRulerColor
@@ -158,7 +161,7 @@ export class AnnotationController extends Disposable {
? cfgTheme.light.backgroundColor || themeDefaults.lineHighlight.light.backgroundColor ? cfgTheme.light.backgroundColor || themeDefaults.lineHighlight.light.backgroundColor
: undefined, : undefined,
gutterIconPath: cfgChangesHighlight.locations.includes(LineHighlightLocations.Gutter) gutterIconPath: cfgChangesHighlight.locations.includes(LineHighlightLocations.Gutter)
? this.context.asAbsolutePath('images/blame-light.svg') ? this.context.asAbsolutePath('images/light/highlight-gutter.svg')
: undefined, : undefined,
overviewRulerColor: cfgChangesHighlight.locations.includes(LineHighlightLocations.OverviewRuler) overviewRulerColor: cfgChangesHighlight.locations.includes(LineHighlightLocations.OverviewRuler)
? cfgTheme.light.overviewRulerColor || themeDefaults.lineHighlight.light.overviewRulerColor ? cfgTheme.light.overviewRulerColor || themeDefaults.lineHighlight.light.overviewRulerColor
@@ -193,13 +196,19 @@ export class AnnotationController extends Disposable {
async clear(column: number) { async clear(column: number) {
const provider = this._annotationProviders.get(column); const provider = this._annotationProviders.get(column);
if (!provider) return; if (provider === undefined) return;
this._annotationProviders.delete(column); this._annotationProviders.delete(column);
await provider.dispose(); await provider.dispose();
if (this._annotationProviders.size === 0) { if (this._annotationProviders.size === 0) {
Logger.log(`Remove listener registrations for annotations`); Logger.log(`Remove listener registrations for annotations`);
await setCommandContext(CommandContext.AnnotationStatus, undefined);
this._keyboardScope && this._keyboardScope.dispose();
this._keyboardScope = undefined;
this._annotationsDisposable && this._annotationsDisposable.dispose(); this._annotationsDisposable && this._annotationsDisposable.dispose();
this._annotationsDisposable = undefined; this._annotationsDisposable = undefined;
} }
@@ -207,17 +216,19 @@ export class AnnotationController extends Disposable {
this._onDidToggleAnnotations.fire(); this._onDidToggleAnnotations.fire();
} }
getAnnotationType(editor: TextEditor): FileAnnotationType | undefined { getAnnotationType(editor: TextEditor | undefined): FileAnnotationType | undefined {
const provider = this.getProvider(editor); const provider = this.getProvider(editor);
return provider === undefined ? undefined : provider.annotationType; return provider === undefined ? undefined : provider.annotationType;
} }
getProvider(editor: TextEditor): AnnotationProviderBase | undefined { getProvider(editor: TextEditor | undefined): AnnotationProviderBase | undefined {
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return undefined; if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return undefined;
return this._annotationProviders.get(editor.viewColumn || -1); return this._annotationProviders.get(editor.viewColumn || -1);
} }
private _keyboardScope: KeyboardScope | undefined = undefined;
async showAnnotations(editor: TextEditor, type: FileAnnotationType, shaOrLine?: string | number): Promise<boolean> { async showAnnotations(editor: TextEditor, type: FileAnnotationType, shaOrLine?: string | number): Promise<boolean> {
if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false; if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false;
@@ -227,6 +238,50 @@ export class AnnotationController extends Disposable {
return true; return true;
} }
return window.withProgress({ location: ProgressLocation.Window }, async (progress: Progress<{ message: string }>) => {
await setCommandContext(CommandContext.AnnotationStatus, 'computing');
const computingAnnotations = this._showAnnotationsCore(currentProvider, editor, type, shaOrLine, progress);
const result = await computingAnnotations;
await setCommandContext(CommandContext.AnnotationStatus, result ? 'computed' : undefined);
return computingAnnotations;
});
}
private async _showAnnotationsCore(currentProvider: AnnotationProviderBase | undefined, editor: TextEditor, type: FileAnnotationType, shaOrLine?: string | number, progress?: Progress<{ message: string}>): Promise<boolean> {
if (progress !== undefined) {
let annotationsLabel = 'annotations';
switch (type) {
case FileAnnotationType.Gutter:
case FileAnnotationType.Hover:
annotationsLabel = 'blame annotations';
break;
case FileAnnotationType.RecentChanges:
annotationsLabel = 'recent changes annotations';
break;
}
progress!.report({ message: `Computing ${annotationsLabel} for ${path.basename(editor.document.fileName)}` });
}
// Allows pressing escape to exit the annotations
if (this._keyboardScope === undefined) {
this._keyboardScope = await Keyboard.instance.beginScope({
escape: {
onDidPressKey: (key: Keys) => {
const e = window.activeTextEditor;
if (e === undefined) return Promise.resolve(undefined);
this.clear(e.viewColumn || -1);
return Promise.resolve(undefined);
}
} as KeyCommand
});
}
const gitUri = await GitUri.fromUri(editor.document.uri, this.git); const gitUri = await GitUri.fromUri(editor.document.uri, this.git);
let provider: AnnotationProviderBase | undefined = undefined; let provider: AnnotationProviderBase | undefined = undefined;
@@ -258,7 +313,7 @@ export class AnnotationController extends Disposable {
subscriptions.push(window.onDidChangeTextEditorViewColumn(this._onTextEditorViewColumnChanged, this)); subscriptions.push(window.onDidChangeTextEditorViewColumn(this._onTextEditorViewColumnChanged, this));
subscriptions.push(workspace.onDidChangeTextDocument(this._onTextDocumentChanged, this)); subscriptions.push(workspace.onDidChangeTextDocument(this._onTextDocumentChanged, this));
subscriptions.push(workspace.onDidCloseTextDocument(this._onTextDocumentClosed, this)); subscriptions.push(workspace.onDidCloseTextDocument(this._onTextDocumentClosed, this));
subscriptions.push(this.gitContextTracker.onDidBlameabilityChange(this._onBlameabilityChanged, this)); subscriptions.push(this.gitContextTracker.onDidChangeBlameability(this._onBlameabilityChanged, this));
this._annotationsDisposable = Disposable.from(...subscriptions); this._annotationsDisposable = Disposable.from(...subscriptions);
} }
@@ -268,11 +323,12 @@ export class AnnotationController extends Disposable {
this._onDidToggleAnnotations.fire(); this._onDidToggleAnnotations.fire();
return true; return true;
} }
return false; return false;
} }
async toggleAnnotations(editor: TextEditor, type: FileAnnotationType, shaOrLine?: string | number): Promise<boolean> { async toggleAnnotations(editor: TextEditor, type: FileAnnotationType, shaOrLine?: string | number): Promise<boolean> {
if (!editor || !editor.document || type === FileAnnotationType.RecentChanges ? !this.git.isTrackable(editor.document.uri) : !this.git.isEditorBlameable(editor)) return false; if (!editor || !editor.document || (type === FileAnnotationType.RecentChanges ? !this.git.isTrackable(editor.document.uri) : !this.git.isEditorBlameable(editor))) return false;
const provider = this._annotationProviders.get(editor.viewColumn || -1); const provider = this._annotationProviders.get(editor.viewColumn || -1);
if (provider === undefined) return this.showAnnotations(editor, type, shaOrLine); if (provider === undefined) return this.showAnnotations(editor, type, shaOrLine);

View File

@@ -1,5 +1,5 @@
'use strict'; 'use strict';
import { Functions } from '../system'; // import { Functions } from '../system';
import { Disposable, ExtensionContext, TextDocument, TextEditor, TextEditorDecorationType, TextEditorSelectionChangeEvent, window, workspace } from 'vscode'; import { Disposable, ExtensionContext, TextDocument, TextEditor, TextEditorDecorationType, TextEditorSelectionChangeEvent, window, workspace } from 'vscode';
import { FileAnnotationType } from '../annotations/annotationController'; import { FileAnnotationType } from '../annotations/annotationController';
import { TextDocumentComparer } from '../comparers'; import { TextDocumentComparer } from '../comparers';
@@ -43,19 +43,12 @@ import { WhitespaceController } from './whitespaceController';
async clear() { async clear() {
if (this.editor !== undefined) { if (this.editor !== undefined) {
try { try {
if (this.decoration !== undefined) {
this.editor.setDecorations(this.decoration, []);
}
if (this.highlightDecoration !== undefined) { if (this.highlightDecoration !== undefined) {
this.editor.setDecorations(this.highlightDecoration, []); this.editor.setDecorations(this.highlightDecoration, []);
}
// I have no idea why the decorators sometimes don't get removed, but if they don't try again with a tiny delay if (this.decoration !== undefined) {
await Functions.wait(1); this.editor.setDecorations(this.decoration, []);
if (this.highlightDecoration === undefined) return;
this.editor.setDecorations(this.highlightDecoration, []);
} }
} }
catch (ex) { } catch (ex) { }

View File

@@ -1,6 +1,9 @@
import { DecorationInstanceRenderOptions, DecorationOptions, ThemableDecorationRenderOptions } from 'vscode'; import { Strings } from '../system';
import { DecorationInstanceRenderOptions, DecorationOptions, MarkdownString, ThemableDecorationRenderOptions } from 'vscode';
import { DiffWithCommand, ShowQuickCommitDetailsCommand } from '../commands';
import { IThemeConfig, themeDefaults } from '../configuration'; import { IThemeConfig, themeDefaults } from '../configuration';
import { CommitFormatter, GitCommit, GitService, GitUri, ICommitFormatOptions } from '../gitService'; import { GlyphChars } from '../constants';
import { CommitFormatter, GitCommit, GitDiffChunkLine, GitService, GitUri, ICommitFormatOptions } from '../gitService';
import * as moment from 'moment'; import * as moment from 'moment';
interface IHeatmapConfig { interface IHeatmapConfig {
@@ -20,6 +23,8 @@ interface IRenderOptions {
} }
export const endOfLineIndex = 1000000; export const endOfLineIndex = 1000000;
const escapeMarkdownRegEx = /[`\>\#\*\_\-\+\.]/g;
// const sampleMarkdown = '## message `not code` *not important* _no underline_ \n> don\'t quote me \n- don\'t list me \n+ don\'t list me \n1. don\'t list me \nnot h1 \n=== \nnot h2 \n---\n***\n---\n___';
export class Annotations { export class Annotations {
@@ -43,34 +48,65 @@ export class Annotations {
return '#793738'; return '#793738';
} }
static getHoverMessage(commit: GitCommit, dateFormat: string | null): MarkdownString {
if (dateFormat === null) {
dateFormat = 'MMMM Do, YYYY h:MMa';
}
let message = '';
if (!commit.isUncommitted) {
message = commit.message
// Escape markdown
.replace(escapeMarkdownRegEx, '\\$&')
// Escape markdown header (since the above regex won't match it)
.replace(/^===/gm, `${GlyphChars.ZeroWidthSpace}===`)
// Keep under the same block-quote
.replace(/\n/g, ' \n');
message = `\n\n> ${message}`;
}
const markdown = new MarkdownString(`[\`${commit.shortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(commit.sha)}) &nbsp; __${commit.author}__, ${moment(commit.date).fromNow()} &nbsp; _(${moment(commit.date).format(dateFormat)})_${message}`);
markdown.isTrusted = true;
return markdown;
}
static getHoverDiffMessage(commit: GitCommit, chunkLine: GitDiffChunkLine | undefined): MarkdownString | undefined {
if (chunkLine === undefined) return undefined;
const codeDiff = this._getCodeDiff(chunkLine);
const markdown = new MarkdownString(commit.isUncommitted
? `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs(commit)}) &nbsp; ${GlyphChars.Dash} &nbsp; _uncommitted_\n${codeDiff}`
: `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs(commit)}) &nbsp; ${GlyphChars.Dash} &nbsp; [\`${commit.previousShortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(commit.previousSha!)}) ${GlyphChars.ArrowLeftRight} [\`${commit.shortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(commit.sha)})\n${codeDiff}`);
markdown.isTrusted = true;
return markdown;
}
private static _getCodeDiff(chunkLine: GitDiffChunkLine): string {
const previous = chunkLine.previous === undefined ? undefined : chunkLine.previous[0];
return `\`\`\`
- ${previous === undefined || previous.line === undefined ? '' : previous.line.trim()}
+ ${chunkLine.line === undefined ? '' : chunkLine.line.trim()}
\`\`\``;
}
static async changesHover(commit: GitCommit, line: number, uri: GitUri, git: GitService): Promise<DecorationOptions> { static async changesHover(commit: GitCommit, line: number, uri: GitUri, git: GitService): Promise<DecorationOptions> {
let message: string | undefined = undefined; const chunkLine = await git.getDiffForLine(uri, line + uri.offset, commit.isUncommitted ? undefined : commit.previousSha);
if (commit.isUncommitted) { const message = this.getHoverDiffMessage(commit, chunkLine);
const [previous, current] = await git.getDiffForLine(uri, line + uri.offset);
message = CommitFormatter.toHoverDiff(commit, previous, current);
}
else if (commit.previousSha !== undefined) {
const [previous, current] = await git.getDiffForLine(uri, line + uri.offset, commit.previousSha);
message = CommitFormatter.toHoverDiff(commit, previous, current);
}
return { return {
hoverMessage: message hoverMessage: message
} as DecorationOptions; } as DecorationOptions;
} }
static detailsHover(commit: GitCommit): DecorationOptions { static detailsHover(commit: GitCommit, dateFormat: string | null): DecorationOptions {
const message = CommitFormatter.toHoverAnnotation(commit); const message = this.getHoverMessage(commit, dateFormat);
return { return {
hoverMessage: message hoverMessage: message
} as DecorationOptions; } as DecorationOptions;
} }
static gutter(commit: GitCommit, format: string, dateFormatOrFormatOptions: string | null | ICommitFormatOptions, renderOptions: IRenderOptions, compact: boolean): DecorationOptions { static gutter(commit: GitCommit, format: string, dateFormatOrFormatOptions: string | null | ICommitFormatOptions, renderOptions: IRenderOptions): DecorationOptions {
let content = `\u00a0${CommitFormatter.fromTemplate(format, commit, dateFormatOrFormatOptions)}\u00a0`; const content = Strings.pad(CommitFormatter.fromTemplate(format, commit, dateFormatOrFormatOptions), 1, 1);
if (compact) {
content = '\u00a0'.repeat(content.length);
}
return { return {
renderOptions: { renderOptions: {
@@ -112,24 +148,25 @@ export class Annotations {
before: { before: {
borderStyle: borderStyle, borderStyle: borderStyle,
borderWidth: borderWidth, borderWidth: borderWidth,
height: cfgFileTheme.separateLines ? 'calc(100% - 1px)' : '100%', height: '100%',
margin: '0 26px 0 0', margin: '0 26px -1px 0'
textDecoration: 'none'
}, },
dark: { dark: {
backgroundColor: cfgFileTheme.dark.backgroundColor || undefined, backgroundColor: cfgFileTheme.dark.backgroundColor || undefined,
color: cfgFileTheme.dark.foregroundColor || themeDefaults.annotations.file.gutter.dark.foregroundColor color: cfgFileTheme.dark.foregroundColor || themeDefaults.annotations.file.gutter.dark.foregroundColor,
textDecoration: cfgFileTheme.separateLines ? 'overline solid rgba(0, 0, 0, .2)' : 'none'
} as DecorationInstanceRenderOptions, } as DecorationInstanceRenderOptions,
light: { light: {
backgroundColor: cfgFileTheme.light.backgroundColor || undefined, backgroundColor: cfgFileTheme.light.backgroundColor || undefined,
color: cfgFileTheme.light.foregroundColor || themeDefaults.annotations.file.gutter.light.foregroundColor color: cfgFileTheme.light.foregroundColor || themeDefaults.annotations.file.gutter.light.foregroundColor,
textDecoration: cfgFileTheme.separateLines ? 'overline solid rgba(0, 0, 0, .05)' : 'none'
} as DecorationInstanceRenderOptions } as DecorationInstanceRenderOptions
} as IRenderOptions; } as IRenderOptions;
} }
static hover(commit: GitCommit, renderOptions: IRenderOptions, heatmap: boolean): DecorationOptions { static hover(commit: GitCommit, renderOptions: IRenderOptions, heatmap: boolean, dateFormat: string | null): DecorationOptions {
return { return {
hoverMessage: CommitFormatter.toHoverAnnotation(commit), hoverMessage: this.getHoverMessage(commit, dateFormat),
renderOptions: heatmap ? { before: { ...renderOptions.before } } : undefined renderOptions: heatmap ? { before: { ...renderOptions.before } } : undefined
} as DecorationOptions; } as DecorationOptions;
} }
@@ -141,8 +178,8 @@ export class Annotations {
before: { before: {
borderStyle: 'solid', borderStyle: 'solid',
borderWidth: '0 0 0 2px', borderWidth: '0 0 0 2px',
contentText: '\u200B', contentText: GlyphChars.ZeroWidthSpace,
height: cfgTheme.annotations.file.hover.separateLines ? 'calc(100% - 1px)' : '100%', height: '100%',
margin: '0 26px 0 0', margin: '0 26px 0 0',
textDecoration: 'none' textDecoration: 'none'
} }
@@ -150,11 +187,14 @@ export class Annotations {
} }
static trailing(commit: GitCommit, format: string, dateFormat: string | null, cfgTheme: IThemeConfig): DecorationOptions { static trailing(commit: GitCommit, format: string, dateFormat: string | null, cfgTheme: IThemeConfig): DecorationOptions {
const message = CommitFormatter.fromTemplate(format, commit, dateFormat); const message = CommitFormatter.fromTemplate(format, commit, {
truncateMessageAtNewLine: true,
dateFormat: dateFormat
} as ICommitFormatOptions);
return { return {
renderOptions: { renderOptions: {
after: { after: {
contentText: `\u00a0${message}\u00a0` contentText: Strings.pad(message, 1, 1)
}, },
dark: { dark: {
after: { after: {

View File

@@ -7,7 +7,7 @@ import { WhitespaceController } from './whitespaceController';
export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase { export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase {
protected _blame: Promise<GitBlame>; protected _blame: Promise<GitBlame | undefined>;
constructor(context: ExtensionContext, editor: TextEditor, decoration: TextEditorDecorationType | undefined, highlightDecoration: TextEditorDecorationType | undefined, whitespaceController: WhitespaceController | undefined, protected git: GitService, protected uri: GitUri) { constructor(context: ExtensionContext, editor: TextEditor, decoration: TextEditorDecorationType | undefined, highlightDecoration: TextEditorDecorationType | undefined, whitespaceController: WhitespaceController | undefined, protected git: GitService, protected uri: GitUri) {
super(context, editor, decoration, highlightDecoration, whitespaceController); super(context, editor, decoration, highlightDecoration, whitespaceController);
@@ -63,7 +63,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
whitespacePromise = this.whitespaceController && this.whitespaceController.override(); whitespacePromise = this.whitespaceController && this.whitespaceController.override();
} }
let blame: GitBlame; let blame: GitBlame | undefined;
if (whitespacePromise) { if (whitespacePromise) {
[blame] = await Promise.all([this._blame, whitespacePromise]); [blame] = await Promise.all([this._blame, whitespacePromise]);
} }
@@ -71,7 +71,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
blame = await this._blame; blame = await this._blame;
} }
if (!blame || !blame.lines.length) { if (blame === undefined || !blame.lines.length) {
this.whitespaceController && await this.whitespaceController.restore(); this.whitespaceController && await this.whitespaceController.restore();
return undefined; return undefined;
} }

View File

@@ -2,9 +2,10 @@
import { Strings } from '../system'; import { Strings } from '../system';
import { DecorationOptions, Range } from 'vscode'; import { DecorationOptions, Range } from 'vscode';
import { FileAnnotationType } from './annotationController'; import { FileAnnotationType } from './annotationController';
import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { Annotations, endOfLineIndex } from './annotations'; import { Annotations, endOfLineIndex } from './annotations';
import { ICommitFormatOptions } from '../gitService'; import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { GlyphChars } from '../constants';
import { GitBlameCommit, ICommitFormatOptions } from '../gitService';
import * as moment from 'moment'; import * as moment from 'moment';
export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
@@ -15,52 +16,96 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
const blame = await this.getBlame(true); const blame = await this.getBlame(true);
if (blame === undefined) return false; if (blame === undefined) return false;
// console.time('Computing blame annotations...');
const cfg = this._config.annotations.file.gutter; const cfg = this._config.annotations.file.gutter;
// Precalculate the formatting options so we don't need to do it on each iteration // Precalculate the formatting options so we don't need to do it on each iteration
const tokenOptions = Strings.getTokensFromTemplate(cfg.format) const tokenOptions = Strings.getTokensFromTemplate(cfg.format)
.reduce((map, token) => { .reduce((map, token) => {
map[token.key] = token.options; map[token.key] = token.options as ICommitFormatOptions;
return map; return map;
}, {} as { [token: string]: ICommitFormatOptions }); }, {} as { [token: string]: ICommitFormatOptions });
const options: ICommitFormatOptions = { const options: ICommitFormatOptions = {
dateFormat: cfg.dateFormat, dateFormat: cfg.dateFormat === null ? this._config.defaultDateFormat : cfg.dateFormat,
tokenOptions: tokenOptions tokenOptions: tokenOptions
}; };
const now = moment(); const now = moment();
const offset = this.uri.offset; const offset = this.uri.offset;
let previousLine: string | undefined = undefined;
const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap); const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap);
const dateFormat = this._config.defaultDateFormat;
const separateLines = this._config.theme.annotations.file.gutter.separateLines;
const decorations: DecorationOptions[] = []; const decorations: DecorationOptions[] = [];
const document = this.document;
let commit: GitBlameCommit | undefined;
let compacted = false;
let details: DecorationOptions | undefined;
let gutter: DecorationOptions | undefined;
let previousSha: string | undefined;
for (const l of blame.lines) { for (const l of blame.lines) {
const commit = blame.commits.get(l.sha); commit = blame.commits.get(l.sha);
if (commit === undefined) continue; if (commit === undefined) continue;
const line = l.line + offset; const line = l.line + offset;
const gutter = Annotations.gutter(commit, cfg.format, options, renderOptions, cfg.compact && previousLine === l.sha); if (previousSha === l.sha) {
// Use a shallow copy of the previous decoration options
gutter = { ...gutter } as DecorationOptions;
if (cfg.compact && !compacted) {
// Since we are wiping out the contextText make sure to copy the objects
gutter.renderOptions = { ...gutter.renderOptions };
gutter.renderOptions.before = {
...gutter.renderOptions.before,
...{ contentText: GlyphChars.Space.repeat(Strings.getWidth(gutter.renderOptions!.before!.contentText!)) }
};
if (cfg.compact) { if (separateLines) {
const isEmptyOrWhitespace = this.document.lineAt(line).isEmptyOrWhitespace; gutter.renderOptions.dark = { ...gutter.renderOptions.dark };
previousLine = isEmptyOrWhitespace ? undefined : l.sha; gutter.renderOptions.dark.before = { ...gutter.renderOptions.dark.before, ...{ textDecoration: 'none' } };
gutter.renderOptions.light = { ...gutter.renderOptions.light };
gutter.renderOptions.light.before = { ...gutter.renderOptions.light.before, ...{ textDecoration: 'none' } };
}
compacted = true;
}
const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex;
gutter.range = new Range(line, 0, line, endIndex);
decorations.push(gutter);
if (details !== undefined) {
details = { ...details } as DecorationOptions;
details.range = cfg.hover.wholeLine
? document.validateRange(new Range(line, 0, line, endOfLineIndex))
: gutter.range;
decorations.push(details);
}
continue;
} }
compacted = false;
previousSha = l.sha;
gutter = Annotations.gutter(commit, cfg.format, options, renderOptions);
if (cfg.heatmap.enabled) { if (cfg.heatmap.enabled) {
Annotations.applyHeatmap(gutter, commit.date, now); Annotations.applyHeatmap(gutter, commit.date, now);
} }
const firstNonWhitespace = this.editor.document.lineAt(line).firstNonWhitespaceCharacterIndex; const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex;
gutter.range = this.editor.document.validateRange(new Range(line, 0, line, firstNonWhitespace)); gutter.range = new Range(line, 0, line, endIndex);
decorations.push(gutter); decorations.push(gutter);
if (cfg.hover.details) { if (cfg.hover.details) {
const details = Annotations.detailsHover(commit); details = Annotations.detailsHover(commit, dateFormat);
details.range = cfg.hover.wholeLine details.range = cfg.hover.wholeLine
? this.editor.document.validateRange(new Range(line, 0, line, endOfLineIndex)) ? document.validateRange(new Range(line, 0, line, endOfLineIndex))
: gutter.range; : gutter.range;
decorations.push(details); decorations.push(details);
} }
@@ -70,6 +115,8 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
this.editor.setDecorations(this.decoration!, decorations); this.editor.setDecorations(this.decoration!, decorations);
} }
// console.timeEnd('Computing blame annotations...');
this.selection(shaOrLine, blame); this.selection(shaOrLine, blame);
return true; return true;
} }

View File

@@ -1,8 +1,9 @@
'use strict'; 'use strict';
import { DecorationOptions, Range } from 'vscode'; import { DecorationOptions, Range } from 'vscode';
import { FileAnnotationType } from './annotationController'; import { FileAnnotationType } from './annotationController';
import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { Annotations, endOfLineIndex } from './annotations'; import { Annotations, endOfLineIndex } from './annotations';
import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { GitBlameCommit } from '../gitService';
import * as moment from 'moment'; import * as moment from 'moment';
export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase { export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
@@ -13,24 +14,36 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
const blame = await this.getBlame(this._config.annotations.file.hover.heatmap.enabled); const blame = await this.getBlame(this._config.annotations.file.hover.heatmap.enabled);
if (blame === undefined) return false; if (blame === undefined) return false;
// console.time('Computing blame annotations...');
const cfg = this._config.annotations.file.hover; const cfg = this._config.annotations.file.hover;
const now = moment(); const now = moment();
const offset = this.uri.offset; const offset = this.uri.offset;
const renderOptions = Annotations.hoverRenderOptions(this._config.theme, cfg.heatmap); const renderOptions = Annotations.hoverRenderOptions(this._config.theme, cfg.heatmap);
const dateFormat = this._config.defaultDateFormat;
const decorations: DecorationOptions[] = []; const decorations: DecorationOptions[] = [];
const document = this.document;
let commit: GitBlameCommit | undefined;
let hover: DecorationOptions | undefined;
for (const l of blame.lines) { for (const l of blame.lines) {
const commit = blame.commits.get(l.sha); commit = blame.commits.get(l.sha);
if (commit === undefined) continue; if (commit === undefined) continue;
const line = l.line + offset; const line = l.line + offset;
const hover = Annotations.hover(commit, renderOptions, cfg.heatmap.enabled); hover = Annotations.hover(commit, renderOptions, cfg.heatmap.enabled, dateFormat);
const endIndex = cfg.wholeLine ? endOfLineIndex : this.editor.document.lineAt(line).firstNonWhitespaceCharacterIndex; if (cfg.wholeLine) {
hover.range = this.editor.document.validateRange(new Range(line, 0, line, endIndex)); hover.range = document.validateRange(new Range(line, 0, line, endOfLineIndex));
}
else {
const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex;
hover.range = new Range(line, 0, line, endIndex);
}
if (cfg.heatmap.enabled) { if (cfg.heatmap.enabled) {
Annotations.applyHeatmap(hover, commit.date, now); Annotations.applyHeatmap(hover, commit.date, now);
@@ -43,6 +56,8 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
this.editor.setDecorations(this.decoration!, decorations); this.editor.setDecorations(this.decoration!, decorations);
} }
// console.timeEnd('Computing blame annotations...');
this.selection(shaOrLine, blame); this.selection(shaOrLine, blame);
return true; return true;
} }

View File

@@ -1,9 +1,9 @@
'use strict'; 'use strict';
import { DecorationOptions, ExtensionContext, Position, Range, TextEditor, TextEditorDecorationType } from 'vscode'; import { DecorationOptions, ExtensionContext, MarkdownString, Position, Range, TextEditor, TextEditorDecorationType } from 'vscode';
import { endOfLineIndex } from './annotations'; import { Annotations, endOfLineIndex } from './annotations';
import { FileAnnotationType } from './annotationController'; import { FileAnnotationType } from './annotationController';
import { AnnotationProviderBase } from './annotationProvider'; import { AnnotationProviderBase } from './annotationProvider';
import { CommitFormatter, GitService, GitUri } from '../gitService'; import { GitService, GitUri } from '../gitService';
export class RecentChangesAnnotationProvider extends AnnotationProviderBase { export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
@@ -21,28 +21,41 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
if (diff === undefined) return false; if (diff === undefined) return false;
const cfg = this._config.annotations.file.recentChanges; const cfg = this._config.annotations.file.recentChanges;
const dateFormat = this._config.defaultDateFormat;
const decorators: DecorationOptions[] = []; const decorators: DecorationOptions[] = [];
for (const chunk of diff.chunks) { for (const chunk of diff.chunks) {
let count = chunk.currentPosition.start - 2; let count = chunk.currentPosition.start - 2;
for (const change of chunk.current) { for (const line of chunk.lines) {
if (change === undefined) continue; if (line.line === undefined) continue;
count++; count++;
if (change.state === 'unchanged') continue; if (line.state === 'unchanged') continue;
let endingIndex = 0; let endingIndex = 0;
let message: string | undefined = undefined; if (cfg.hover.details || cfg.hover.changes) {
if (cfg.hover.changes) {
message = CommitFormatter.toHoverDiff(commit, chunk.previous[count], change);
endingIndex = cfg.hover.wholeLine ? endOfLineIndex : this.editor.document.lineAt(count).firstNonWhitespaceCharacterIndex; endingIndex = cfg.hover.wholeLine ? endOfLineIndex : this.editor.document.lineAt(count).firstNonWhitespaceCharacterIndex;
} }
const range = this.editor.document.validateRange(new Range(new Position(count, 0), new Position(count, endingIndex)));
if (cfg.hover.details) {
decorators.push({
hoverMessage: Annotations.getHoverMessage(commit, dateFormat),
range: range
} as DecorationOptions);
}
let message: MarkdownString | undefined = undefined;
if (cfg.hover.changes) {
message = Annotations.getHoverDiffMessage(commit, line);
}
decorators.push({ decorators.push({
hoverMessage: message, hoverMessage: message,
range: this.editor.document.validateRange(new Range(new Position(count, 0), new Position(count, endingIndex))) range: range
} as DecorationOptions); } as DecorationOptions);
} }
} }

81
src/codeLensController.ts Normal file
View File

@@ -0,0 +1,81 @@
'use strict';
import { Objects } from './system';
import { Disposable, ExtensionContext, languages, TextEditor, workspace } from 'vscode';
import { IConfig } from './configuration';
import { CommandContext, ExtensionKey, setCommandContext } from './constants';
import { GitCodeLensProvider } from './gitCodeLensProvider';
import { GitService } from './gitService';
import { Logger } from './logger';
export class CodeLensController extends Disposable {
private _codeLensProvider: GitCodeLensProvider | undefined;
private _codeLensProviderDisposable: Disposable | undefined;
private _config: IConfig;
private _disposable: Disposable | undefined;
constructor(private context: ExtensionContext, private git: GitService) {
super(() => this.dispose());
this._onConfigurationChanged();
const subscriptions: Disposable[] = [];
subscriptions.push(workspace.onDidChangeConfiguration(this._onConfigurationChanged, this));
subscriptions.push(git.onDidChangeGitCache(this._onGitCacheChanged, this));
this._disposable = Disposable.from(...subscriptions);
}
dispose() {
this._disposable && this._disposable.dispose();
this._codeLensProviderDisposable && this._codeLensProviderDisposable.dispose();
this._codeLensProviderDisposable = undefined;
this._codeLensProvider = undefined;
}
private _onConfigurationChanged() {
const cfg = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
if (!Objects.areEquivalent(cfg.codeLens, this._config && this._config.codeLens)) {
Logger.log('CodeLens config changed; resetting CodeLens provider');
if (cfg.codeLens.enabled && (cfg.codeLens.recentChange.enabled || cfg.codeLens.authors.enabled)) {
if (this._codeLensProvider) {
this._codeLensProvider.reset();
}
else {
this._codeLensProvider = new GitCodeLensProvider(this.context, this.git);
this._codeLensProviderDisposable = languages.registerCodeLensProvider(GitCodeLensProvider.selector, this._codeLensProvider);
}
}
else {
this._codeLensProviderDisposable && this._codeLensProviderDisposable.dispose();
this._codeLensProviderDisposable = undefined;
this._codeLensProvider = undefined;
}
setCommandContext(CommandContext.CanToggleCodeLens, cfg.codeLens.recentChange.enabled || cfg.codeLens.authors.enabled);
}
this._config = cfg;
}
private _onGitCacheChanged() {
Logger.log('Git cache changed; resetting CodeLens provider');
this._codeLensProvider && this._codeLensProvider.reset();
}
toggleCodeLens(editor: TextEditor) {
if (!this._config.codeLens.recentChange.enabled && !this._config.codeLens.authors.enabled) return;
Logger.log(`toggleCodeLens()`);
if (this._codeLensProviderDisposable) {
this._codeLensProviderDisposable.dispose();
this._codeLensProviderDisposable = undefined;
return;
}
this._codeLensProviderDisposable = languages.registerCodeLensProvider(GitCodeLensProvider.selector, new GitCodeLensProvider(this.context, this.git));
}
}

View File

@@ -1,19 +1,21 @@
'use strict'; 'use strict';
export * from './commands/common'; export * from './commands/common';
export * from './commands/keyboard'; export * from './commands/clearFileAnnotations';
export * from './commands/closeUnchangedFiles'; export * from './commands/closeUnchangedFiles';
export * from './commands/copyMessageToClipboard'; export * from './commands/copyMessageToClipboard';
export * from './commands/copyShaToClipboard'; export * from './commands/copyShaToClipboard';
export * from './commands/diffDirectory'; export * from './commands/diffDirectory';
export * from './commands/diffLineWithPrevious'; export * from './commands/diffLineWithPrevious';
export * from './commands/diffLineWithWorking'; export * from './commands/diffLineWithWorking';
export * from './commands/diffWith';
export * from './commands/diffWithBranch'; export * from './commands/diffWithBranch';
export * from './commands/diffWithNext'; export * from './commands/diffWithNext';
export * from './commands/diffWithPrevious'; export * from './commands/diffWithPrevious';
export * from './commands/diffWithRevision';
export * from './commands/diffWithWorking'; export * from './commands/diffWithWorking';
export * from './commands/openChangedFiles'; export * from './commands/openChangedFiles';
export * from './commands/openBranchesInRemote';
export * from './commands/openBranchInRemote'; export * from './commands/openBranchInRemote';
export * from './commands/openCommitInRemote'; export * from './commands/openCommitInRemote';
export * from './commands/openFileInRemote'; export * from './commands/openFileInRemote';
@@ -21,16 +23,16 @@ export * from './commands/openInRemote';
export * from './commands/openRepoInRemote'; export * from './commands/openRepoInRemote';
export * from './commands/resetSuppressedWarnings'; export * from './commands/resetSuppressedWarnings';
export * from './commands/showBlameHistory'; export * from './commands/showBlameHistory';
export * from './commands/showCommitSearch';
export * from './commands/showFileBlame'; export * from './commands/showFileBlame';
export * from './commands/showFileHistory'; export * from './commands/showFileHistory';
export * from './commands/showLastQuickPick'; export * from './commands/showLastQuickPick';
export * from './commands/showLineBlame'; export * from './commands/showLineBlame';
export * from './commands/showQuickBranchHistory';
export * from './commands/showQuickCommitDetails'; export * from './commands/showQuickCommitDetails';
export * from './commands/showQuickCommitFileDetails'; export * from './commands/showQuickCommitFileDetails';
export * from './commands/showCommitSearch';
export * from './commands/showQuickFileHistory';
export * from './commands/showQuickBranchHistory';
export * from './commands/showQuickCurrentBranchHistory'; export * from './commands/showQuickCurrentBranchHistory';
export * from './commands/showQuickFileHistory';
export * from './commands/showQuickRepoStatus'; export * from './commands/showQuickRepoStatus';
export * from './commands/showQuickStashList'; export * from './commands/showQuickStashList';
export * from './commands/stashApply'; export * from './commands/stashApply';

View File

@@ -0,0 +1,24 @@
'use strict';
import { TextEditor, TextEditorEdit, Uri, window } from 'vscode';
import { AnnotationController } from '../annotations/annotationController';
import { Commands, EditorCommand } from './common';
import { Logger } from '../logger';
export class ClearFileAnnotationsCommand extends EditorCommand {
constructor(private annotationController: AnnotationController) {
super(Commands.ClearFileAnnotations);
}
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri): Promise<any> {
if (editor === undefined || editor.document === undefined || editor.document.isDirty) return undefined;
try {
return this.annotationController.clear(editor.viewColumn || -1);
}
catch (ex) {
Logger.error(ex, 'ClearFileAnnotationsCommand');
return window.showErrorMessage(`Unable to clear file annotations. See output channel for more details`);
}
}
}

View File

@@ -1,80 +1,87 @@
'use strict'; 'use strict';
import { commands, TextEditor, Uri, window } from 'vscode'; import { commands, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorTracker } from '../activeEditorTracker'; import { ActiveEditorTracker } from '../activeEditorTracker';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { TextEditorComparer, UriComparer } from '../comparers'; import { TextEditorComparer, UriComparer } from '../comparers';
import { BuiltInCommands } from '../constants'; import { BuiltInCommands } from '../constants';
import { GitService } from '../gitService'; import { GitService } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { Messages } from '../messages'; import { Messages } from '../messages';
export interface CloseUnchangedFilesCommandArgs { export interface CloseUnchangedFilesCommandArgs {
uris?: Uri[]; uris?: Uri[];
} }
export class CloseUnchangedFilesCommand extends ActiveEditorCommand { export class CloseUnchangedFilesCommand extends ActiveEditorCommand {
constructor(private git: GitService) { constructor(private git: GitService) {
super(Commands.CloseUnchangedFiles); super(Commands.CloseUnchangedFiles);
} }
async execute(editor: TextEditor, uri?: Uri, args: CloseUnchangedFilesCommandArgs = {}) { async execute(editor?: TextEditor, uri?: Uri, args: CloseUnchangedFilesCommandArgs = {}) {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
try { try {
if (args.uris === undefined) { if (args.uris === undefined) {
const repoPath = await this.git.getRepoPathFromUri(uri); args = { ...args };
if (!repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to close unchanged files`);
const repoPath = await this.git.getRepoPathFromUri(uri);
const status = await this.git.getStatusForRepo(repoPath); if (!repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to close unchanged files`);
if (status === undefined) return window.showWarningMessage(`Unable to close unchanged files`);
const status = await this.git.getStatusForRepo(repoPath);
args.uris = status.files.map(_ => _.Uri); if (status === undefined) return window.showWarningMessage(`Unable to close unchanged files`);
}
args.uris = status.files.map(_ => _.Uri);
if (args.uris.length === 0) return commands.executeCommand(BuiltInCommands.CloseAllEditors); }
const editorTracker = new ActiveEditorTracker(); if (args.uris.length === 0) return commands.executeCommand(BuiltInCommands.CloseAllEditors);
let count = 0; const editorTracker = new ActiveEditorTracker();
let previous = undefined;
let editor = window.activeTextEditor; let count = 0;
while (true) { let previous = undefined;
if (editor !== undefined) { let editor = window.activeTextEditor;
if (TextEditorComparer.equals(previous, editor, { useId: true, usePosition: true })) { while (true) {
break; if (editor !== undefined) {
} if (TextEditorComparer.equals(previous, editor, { useId: true, usePosition: true })) {
break;
if (editor.document !== undefined && }
(editor.document.isDirty || args.uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri)))) {
previous = editor; if (editor.document !== undefined &&
editor = await editorTracker.awaitNext(500); (editor.document.isDirty || args.uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri)))) {
continue; const lastPrevious = previous;
} previous = editor;
} editor = await editorTracker.awaitNext(500);
previous = editor; if (TextEditorComparer.equals(lastPrevious, editor, { useId: true, usePosition: true })) {
editor = await editorTracker.awaitClose(500); break;
}
if (previous === undefined && editor === undefined) { continue;
count++; }
// This is such a shitty hack, but I can't figure out any other reliable way to know that we've cycled through all the editors :( }
if (count >= 4) {
break; previous = editor;
} editor = await editorTracker.awaitClose(500);
}
else { if (previous === undefined && editor === undefined) {
count = 0; count++;
} // This is such a shitty hack, but I can't figure out any other reliable way to know that we've cycled through all the editors :(
} if (count >= 4) {
break;
editorTracker.dispose(); }
}
return undefined; else {
} count = 0;
catch (ex) { }
Logger.error(ex, 'CloseUnchangedFilesCommand'); }
return window.showErrorMessage(`Unable to close unchanged files. See output channel for more details`);
} editorTracker.dispose();
}
return undefined;
}
catch (ex) {
Logger.error(ex, 'CloseUnchangedFilesCommand');
return window.showErrorMessage(`Unable to close unchanged files. See output channel for more details`);
}
}
} }

View File

@@ -1,20 +1,26 @@
'use strict'; 'use strict';
import { commands, Disposable, TextDocumentShowOptions, TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode'; import { commands, Disposable, SourceControlResourceGroup, SourceControlResourceState, TextDocumentShowOptions, TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode';
import { BuiltInCommands } from '../constants'; import { ExplorerNode } from '../views/explorerNodes';
import { GitBranch, GitCommit, GitRemote } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { Telemetry } from '../telemetry'; import { Telemetry } from '../telemetry';
export type Commands = 'gitlens.closeUnchangedFiles' | export type Commands =
'gitlens.clearFileAnnotations' |
'gitlens.closeUnchangedFiles' |
'gitlens.copyMessageToClipboard' | 'gitlens.copyMessageToClipboard' |
'gitlens.copyShaToClipboard' | 'gitlens.copyShaToClipboard' |
'gitlens.diffDirectory' | 'gitlens.diffDirectory' |
'gitlens.diffWith' |
'gitlens.diffWithBranch' | 'gitlens.diffWithBranch' |
'gitlens.diffWithNext' | 'gitlens.diffWithNext' |
'gitlens.diffWithPrevious' | 'gitlens.diffWithPrevious' |
'gitlens.diffLineWithPrevious' | 'gitlens.diffLineWithPrevious' |
'gitlens.diffWithRevision' |
'gitlens.diffWithWorking' | 'gitlens.diffWithWorking' |
'gitlens.diffLineWithWorking' | 'gitlens.diffLineWithWorking' |
'gitlens.openChangedFiles' | 'gitlens.openChangedFiles' |
'gitlens.openBranchesInRemote' |
'gitlens.openBranchInRemote' | 'gitlens.openBranchInRemote' |
'gitlens.openCommitInRemote' | 'gitlens.openCommitInRemote' |
'gitlens.openFileInRemote' | 'gitlens.openFileInRemote' |
@@ -42,17 +48,21 @@ export type Commands = 'gitlens.closeUnchangedFiles' |
'gitlens.toggleFileRecentChanges' | 'gitlens.toggleFileRecentChanges' |
'gitlens.toggleLineBlame'; 'gitlens.toggleLineBlame';
export const Commands = { export const Commands = {
ClearFileAnnotations: 'gitlens.clearFileAnnotations' as Commands,
CloseUnchangedFiles: 'gitlens.closeUnchangedFiles' as Commands, CloseUnchangedFiles: 'gitlens.closeUnchangedFiles' as Commands,
CopyMessageToClipboard: 'gitlens.copyMessageToClipboard' as Commands, CopyMessageToClipboard: 'gitlens.copyMessageToClipboard' as Commands,
CopyShaToClipboard: 'gitlens.copyShaToClipboard' as Commands, CopyShaToClipboard: 'gitlens.copyShaToClipboard' as Commands,
DiffDirectory: 'gitlens.diffDirectory' as Commands, DiffDirectory: 'gitlens.diffDirectory' as Commands,
DiffWith: 'gitlens.diffWith' as Commands,
DiffWithBranch: 'gitlens.diffWithBranch' as Commands, DiffWithBranch: 'gitlens.diffWithBranch' as Commands,
DiffWithNext: 'gitlens.diffWithNext' as Commands, DiffWithNext: 'gitlens.diffWithNext' as Commands,
DiffWithPrevious: 'gitlens.diffWithPrevious' as Commands, DiffWithPrevious: 'gitlens.diffWithPrevious' as Commands,
DiffLineWithPrevious: 'gitlens.diffLineWithPrevious' as Commands, DiffLineWithPrevious: 'gitlens.diffLineWithPrevious' as Commands,
DiffWithRevision: 'gitlens.diffWithRevision' as Commands,
DiffWithWorking: 'gitlens.diffWithWorking' as Commands, DiffWithWorking: 'gitlens.diffWithWorking' as Commands,
DiffLineWithWorking: 'gitlens.diffLineWithWorking' as Commands, DiffLineWithWorking: 'gitlens.diffLineWithWorking' as Commands,
OpenChangedFiles: 'gitlens.openChangedFiles' as Commands, OpenChangedFiles: 'gitlens.openChangedFiles' as Commands,
OpenBranchesInRemote: 'gitlens.openBranchesInRemote' as Commands,
OpenBranchInRemote: 'gitlens.openBranchInRemote' as Commands, OpenBranchInRemote: 'gitlens.openBranchInRemote' as Commands,
OpenCommitInRemote: 'gitlens.openCommitInRemote' as Commands, OpenCommitInRemote: 'gitlens.openCommitInRemote' as Commands,
OpenFileInRemote: 'gitlens.openFileInRemote' as Commands, OpenFileInRemote: 'gitlens.openFileInRemote' as Commands,
@@ -87,33 +97,88 @@ export function getCommandUri(uri?: Uri, editor?: TextEditor): Uri | undefined {
return editor.document.uri; return editor.document.uri;
} }
export type CommandContext = 'gitlens:canToggleCodeLens' | export interface CommandContextParsingOptions {
'gitlens:enabled' | editor: boolean;
'gitlens:hasRemotes' | uri: boolean;
'gitlens:isBlameable' | }
'gitlens:isRepository' |
'gitlens:isTracked' |
'gitlens:key';
export const CommandContext = {
CanToggleCodeLens: 'gitlens:canToggleCodeLens' as CommandContext,
Enabled: 'gitlens:enabled' as CommandContext,
HasRemotes: 'gitlens:hasRemotes' as CommandContext,
IsBlameable: 'gitlens:isBlameable' as CommandContext,
IsRepository: 'gitlens:isRepository' as CommandContext,
IsTracked: 'gitlens:isTracked' as CommandContext,
Key: 'gitlens:key' as CommandContext
};
export function setCommandContext(key: CommandContext | string, value: any) { export interface CommandBaseContext {
return commands.executeCommand(BuiltInCommands.SetContext, key, value); editor?: TextEditor;
uri?: Uri;
}
export interface CommandScmGroupsContext extends CommandBaseContext {
type: 'scm-groups';
scmResourceGroups: SourceControlResourceGroup[];
}
export interface CommandScmStatesContext extends CommandBaseContext {
type: 'scm-states';
scmResourceStates: SourceControlResourceState[];
}
export interface CommandUnknownContext extends CommandBaseContext {
type: 'unknown';
}
export interface CommandUriContext extends CommandBaseContext {
type: 'uri';
}
export interface CommandViewContext extends CommandBaseContext {
type: 'view';
node: ExplorerNode;
}
export function isCommandViewContextWithBranch(context: CommandContext): context is CommandViewContext & { node: (ExplorerNode & { branch: GitBranch }) } {
return context.type === 'view' && (context.node as any).branch && (context.node as any).branch instanceof GitBranch;
}
interface ICommandViewContextWithCommit<T extends GitCommit> extends CommandViewContext {
node: (ExplorerNode & { commit: T });
}
export function isCommandViewContextWithCommit<T extends GitCommit>(context: CommandContext): context is ICommandViewContextWithCommit<T> {
return context.type === 'view' && (context.node as any).commit && (context.node as any).commit instanceof GitCommit;
}
export function isCommandViewContextWithRemote(context: CommandContext): context is CommandViewContext & { node: (ExplorerNode & { remote: GitRemote }) } {
return context.type === 'view' && (context.node as any).remote && (context.node as any).remote instanceof GitRemote;
}
export type CommandContext = CommandScmGroupsContext | CommandScmStatesContext | CommandUnknownContext | CommandUriContext | CommandViewContext;
function isScmResourceGroup(group: any): group is SourceControlResourceGroup {
if (group === undefined) return false;
return (group as SourceControlResourceGroup).id !== undefined && (group.handle !== undefined || (group as SourceControlResourceGroup).label !== undefined || (group as SourceControlResourceGroup).resourceStates !== undefined);
}
function isScmResourceState(state: any): state is SourceControlResourceState {
if (state === undefined) return false;
return (state as SourceControlResourceState).resourceUri !== undefined;
}
function isTextEditor(editor: any): editor is TextEditor {
if (editor === undefined) return false;
return editor.id !== undefined && ((editor as TextEditor).edit !== undefined || (editor as TextEditor).document !== undefined);
} }
export abstract class Command extends Disposable { export abstract class Command extends Disposable {
static getMarkdownCommandArgsCore<T>(command: Commands, args: T): string {
return `command:${command}?${encodeURIComponent(JSON.stringify(args))}`;
}
protected readonly contextParsingOptions: CommandContextParsingOptions = { editor: false, uri: false };
private _disposable: Disposable; private _disposable: Disposable;
constructor(protected command: Commands) { constructor(protected command: Commands) {
super(() => this.dispose()); super(() => this.dispose());
this._disposable = commands.registerCommand(command, this._execute, this); this._disposable = commands.registerCommand(command, this._execute, this);
} }
@@ -121,46 +186,86 @@ export abstract class Command extends Disposable {
this._disposable && this._disposable.dispose(); this._disposable && this._disposable.dispose();
} }
protected _execute(...args: any[]): any { protected async preExecute(context: CommandContext, ...args: any[]): Promise<any> {
Telemetry.trackEvent(this.command);
return this.execute(...args); return this.execute(...args);
} }
abstract execute(...args: any[]): any; abstract execute(...args: any[]): any;
}
export abstract class EditorCommand extends Disposable { protected _execute(...args: any[]): any {
private _disposable: Disposable;
constructor(public readonly command: Commands) {
super(() => this.dispose());
this._disposable = commands.registerTextEditorCommand(command, this._execute, this);
}
dispose() {
this._disposable && this._disposable.dispose();
}
private _execute(editor: TextEditor, edit: TextEditorEdit, ...args: any[]): any {
Telemetry.trackEvent(this.command); Telemetry.trackEvent(this.command);
return this.execute(editor, edit, ...args);
const [context, rest] = Command._parseContext(this.contextParsingOptions, ...args);
return this.preExecute(context, ...rest);
} }
abstract execute(editor: TextEditor, edit: TextEditorEdit, ...args: any[]): any; private static _parseContext(options: CommandContextParsingOptions, ...args: any[]): [CommandContext, any[]] {
let editor: TextEditor | undefined = undefined;
let firstArg = args[0];
if (options.editor && (firstArg === undefined || isTextEditor(firstArg))) {
editor = firstArg;
args = args.slice(1);
firstArg = args[0];
}
if (options.uri && (firstArg === undefined || firstArg instanceof Uri)) {
const [uri, ...rest] = args as [Uri, any];
return [{ type: 'uri', editor: editor, uri: uri }, rest];
}
if (firstArg instanceof ExplorerNode) {
const [node, ...rest] = args as [ExplorerNode, any];
return [{ type: 'view', node: node, uri: node.uri }, rest];
}
if (isScmResourceState(firstArg)) {
const states = [];
let count = 0;
for (const arg of args) {
if (!isScmResourceState(arg)) break;
count++;
states.push(arg);
}
return [{ type: 'scm-states', scmResourceStates: states, uri: states[0].resourceUri }, args.slice(count)];
}
if (isScmResourceGroup(firstArg)) {
const groups = [];
let count = 0;
for (const arg of args) {
if (!isScmResourceGroup(arg)) break;
count++;
groups.push(arg);
}
return [{ type: 'scm-groups', scmResourceGroups: groups }, args.slice(count)];
}
return [{ type: 'unknown', editor: editor }, args];
}
} }
export abstract class ActiveEditorCommand extends Command { export abstract class ActiveEditorCommand extends Command {
protected readonly contextParsingOptions: CommandContextParsingOptions = { editor: true, uri: true };
constructor(public readonly command: Commands) { constructor(public readonly command: Commands) {
super(command); super(command);
} }
protected async preExecute(context: CommandContext, ...args: any[]): Promise<any> {
return this.execute(context.editor, context.uri, ...args);
}
protected _execute(...args: any[]): any { protected _execute(...args: any[]): any {
return super._execute(window.activeTextEditor, ...args); return super._execute(window.activeTextEditor, ...args);
} }
abstract execute(editor: TextEditor, ...args: any[]): any; abstract execute(editor?: TextEditor, ...args: any[]): any;
} }
let lastCommand: { command: string, args: any[] } | undefined = undefined; let lastCommand: { command: string, args: any[] } | undefined = undefined;
@@ -185,6 +290,27 @@ export abstract class ActiveEditorCachedCommand extends ActiveEditorCommand {
abstract execute(editor: TextEditor, ...args: any[]): any; abstract execute(editor: TextEditor, ...args: any[]): any;
} }
export abstract class EditorCommand extends Disposable {
private _disposable: Disposable;
constructor(public readonly command: Commands) {
super(() => this.dispose());
this._disposable = commands.registerTextEditorCommand(command, this._execute, this);
}
dispose() {
this._disposable && this._disposable.dispose();
}
private _execute(editor: TextEditor, edit: TextEditorEdit, ...args: any[]): any {
Telemetry.trackEvent(this.command);
return this.execute(editor, edit, ...args);
}
abstract execute(editor: TextEditor, edit: TextEditorEdit, ...args: any[]): any;
}
export async function openEditor(uri: Uri, options?: TextDocumentShowOptions): Promise<TextEditor | undefined> { export async function openEditor(uri: Uri, options?: TextDocumentShowOptions): Promise<TextEditor | undefined> {
try { try {
const defaults: TextDocumentShowOptions = { const defaults: TextDocumentShowOptions = {

View File

@@ -1,7 +1,7 @@
'use strict'; 'use strict';
import { Iterables } from '../system'; import { Iterables } from '../system';
import { TextEditor, Uri, window } from 'vscode'; import { TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithCommit } from './common';
import { GitService, GitUri } from '../gitService'; import { GitService, GitUri } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { copy } from 'copy-paste'; import { copy } from 'copy-paste';
@@ -17,10 +17,22 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
super(Commands.CopyMessageToClipboard); super(Commands.CopyMessageToClipboard);
} }
async execute(editor: TextEditor, uri?: Uri, args: CopyMessageToClipboardCommandArgs = {}): Promise<any> { protected async preExecute(context: CommandContext, args: CopyMessageToClipboardCommandArgs = {}): Promise<any> {
if (isCommandViewContextWithCommit(context)) {
args = { ...args };
args.sha = context.node.commit.sha;
return this.execute(context.editor, context.node.commit.uri, args);
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args: CopyMessageToClipboardCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
try { try {
args = { ...args };
// If we don't have an editor then get the message of the last commit to the branch // If we don't have an editor then get the message of the last commit to the branch
if (uri === undefined) { if (uri === undefined) {
if (!this.git.repoPath) return undefined; if (!this.git.repoPath) return undefined;
@@ -62,7 +74,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
// Get the full commit message -- since blame only returns the summary // Get the full commit message -- since blame only returns the summary
const commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, args.sha); const commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, args.sha);
if (!commit) return undefined; if (commit === undefined) return undefined;
args.message = commit.message; args.message = commit.message;
} }

View File

@@ -1,7 +1,7 @@
'use strict'; 'use strict';
import { Iterables } from '../system'; import { Iterables } from '../system';
import { TextEditor, Uri, window } from 'vscode'; import { TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithCommit } from './common';
import { GitService, GitUri } from '../gitService'; import { GitService, GitUri } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { copy } from 'copy-paste'; import { copy } from 'copy-paste';
@@ -16,10 +16,22 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
super(Commands.CopyShaToClipboard); super(Commands.CopyShaToClipboard);
} }
async execute(editor: TextEditor, uri?: Uri, args: CopyShaToClipboardCommandArgs = {}): Promise<any> { protected async preExecute(context: CommandContext, args: CopyShaToClipboardCommandArgs = {}): Promise<any> {
if (isCommandViewContextWithCommit(context)) {
args = { ...args };
args.sha = context.node.commit.sha;
return this.execute(context.editor, context.node.commit.uri, args);
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args: CopyShaToClipboardCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
try { try {
args = { ...args };
// If we don't have an editor then get the sha of the last commit to the branch // If we don't have an editor then get the sha of the last commit to the branch
if (uri === undefined) { if (uri === undefined) {
if (!this.git.repoPath) return undefined; if (!this.git.repoPath) return undefined;
@@ -43,7 +55,7 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
try { try {
const blame = await this.git.getBlameForLine(gitUri, blameline); const blame = await this.git.getBlameForLine(gitUri, blameline);
if (!blame) return undefined; if (blame === undefined) return undefined;
args.sha = blame.commit.sha; args.sha = blame.commit.sha;
} }

View File

@@ -2,7 +2,7 @@
import { Iterables } from '../system'; import { Iterables } from '../system';
import { commands, TextEditor, Uri, window } from 'vscode'; import { commands, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { BuiltInCommands } from '../constants'; import { BuiltInCommands, GlyphChars } from '../constants';
import { GitService } from '../gitService'; import { GitService } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { Messages } from '../messages'; import { Messages } from '../messages';
@@ -19,7 +19,7 @@ export class DiffDirectoryCommand extends ActiveEditorCommand {
super(Commands.DiffDirectory); super(Commands.DiffDirectory);
} }
async execute(editor: TextEditor, uri?: Uri, args: DiffDirectoryCommandCommandArgs = {}): Promise<any> { async execute(editor?: TextEditor, uri?: Uri, args: DiffDirectoryCommandCommandArgs = {}): Promise<any> {
const diffTool = await this.git.getConfig('diff.tool'); const diffTool = await this.git.getConfig('diff.tool');
if (!diffTool) { if (!diffTool) {
const result = await window.showWarningMessage(`Unable to open directory compare because there is no Git diff tool configured`, 'View Git Docs'); const result = await window.showWarningMessage(`Unable to open directory compare because there is no Git diff tool configured`, 'View Git Docs');
@@ -35,11 +35,13 @@ export class DiffDirectoryCommand extends ActiveEditorCommand {
if (!repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to open directory compare`); if (!repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to open directory compare`);
if (!args.shaOrBranch1) { if (!args.shaOrBranch1) {
args = { ...args };
const branches = await this.git.getBranches(repoPath); const branches = await this.git.getBranches(repoPath);
const current = Iterables.find(branches, _ => _.current); const current = Iterables.find(branches, _ => _.current);
if (current == null) return window.showWarningMessage(`Unable to open directory compare`); if (current == null) return window.showWarningMessage(`Unable to open directory compare`);
const pick = await BranchesQuickPick.show(branches, `Compare ${current.name} to \u2026`); const pick = await BranchesQuickPick.show(branches, `Compare ${current.name} to ${GlyphChars.Ellipsis}`);
if (pick === undefined) return undefined; if (pick === undefined) return undefined;
if (pick instanceof CommandQuickPickItem) return pick.execute(); if (pick instanceof CommandQuickPickItem) return pick.execute();

View File

@@ -1,16 +1,14 @@
'use strict'; 'use strict';
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { BuiltInCommands } from '../constants'; import { DiffWithCommandArgs } from './diffWith';
import { DiffWithPreviousCommandArgs } from './diffWithPrevious';
import { DiffWithWorkingCommandArgs } from './diffWithWorking';
import { GitCommit, GitService, GitUri } from '../gitService'; import { GitCommit, GitService, GitUri } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { Messages } from '../messages'; import { Messages } from '../messages';
import * as path from 'path';
export interface DiffLineWithPreviousCommandArgs { export interface DiffLineWithPreviousCommandArgs {
commit?: GitCommit; commit?: GitCommit;
line?: number; line?: number;
showOptions?: TextDocumentShowOptions; showOptions?: TextDocumentShowOptions;
} }
@@ -21,12 +19,16 @@ export class DiffLineWithPreviousCommand extends ActiveEditorCommand {
super(Commands.DiffLineWithPrevious); super(Commands.DiffLineWithPrevious);
} }
async execute(editor: TextEditor, uri?: Uri, args: DiffLineWithPreviousCommandArgs = {}): Promise<any> { async execute(editor?: TextEditor, uri?: Uri, args: DiffLineWithPreviousCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
if (uri === undefined) return undefined; if (uri === undefined) return undefined;
const gitUri = await GitUri.fromUri(uri, this.git); const gitUri = await GitUri.fromUri(uri, this.git);
args.line = args.line || (editor === undefined ? gitUri.offset : editor.selection.active.line);
args = { ...args };
if (args.line === undefined) {
args.line = editor === undefined ? gitUri.offset : editor.selection.active.line;
}
if (args.commit === undefined || GitService.isUncommitted(args.commit.sha)) { if (args.commit === undefined || GitService.isUncommitted(args.commit.sha)) {
if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined; if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined;
@@ -39,52 +41,26 @@ export class DiffLineWithPreviousCommand extends ActiveEditorCommand {
if (blame === undefined) return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare'); if (blame === undefined) return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare');
args.commit = blame.commit; args.commit = blame.commit;
// If we don't have a sha or the current commit matches the blame, show the previous
if (gitUri.sha === undefined || gitUri.sha === args.commit.sha) {
return commands.executeCommand(Commands.DiffWithPrevious, new GitUri(uri, args.commit), {
line: args.line,
showOptions: args.showOptions
} as DiffWithPreviousCommandArgs);
}
// If the line is uncommitted, find the previous commit and treat it as a DiffWithWorking
if (args.commit.isUncommitted) {
uri = args.commit.uri;
args.commit = new GitCommit(args.commit.type, args.commit.repoPath, args.commit.previousSha!, args.commit.previousFileName!, args.commit.author, args.commit.date, args.commit.message);
args.line = (blame.line.line + 1) + gitUri.offset;
return commands.executeCommand(Commands.DiffWithWorking, uri, {
commit: args.commit,
line: args.line,
showOptions: args.showOptions
} as DiffWithWorkingCommandArgs);
}
} }
catch (ex) { catch (ex) {
Logger.error(ex, 'DiffWithPreviousLineCommand', `getBlameForLine(${blameline})`); Logger.error(ex, 'DiffLineWithPreviousCommand', `getBlameForLine(${blameline})`);
return window.showErrorMessage(`Unable to open compare. See output channel for more details`); return window.showErrorMessage(`Unable to open compare. See output channel for more details`);
} }
} }
try { const diffArgs: DiffWithCommandArgs = {
const [rhs, lhs] = await Promise.all([ repoPath: args.commit.repoPath,
this.git.getVersionedFile(gitUri.repoPath, gitUri.fsPath, gitUri.sha!), lhs: {
this.git.getVersionedFile(args.commit.repoPath, args.commit.uri.fsPath, args.commit.sha) sha: args.commit.previousSha !== undefined ? args.commit.previousSha : GitService.fakeSha,
]); uri: args.commit.previousUri
},
await commands.executeCommand(BuiltInCommands.Diff, rhs: {
Uri.file(lhs), sha: args.commit.sha,
Uri.file(rhs), uri: args.commit.uri
`${path.basename(args.commit.uri.fsPath)} (${args.commit.shortSha}) \u2194 ${path.basename(gitUri.fsPath)} (${gitUri.shortSha})`, },
args.showOptions); line: args.line,
showOptions: args.showOptions
// TODO: Figure out how to focus the left pane };
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' }); return commands.executeCommand(Commands.DiffWith, diffArgs);
}
catch (ex) {
Logger.error(ex, 'DiffWithPreviousLineCommand', 'getVersionedFile');
return window.showErrorMessage(`Unable to open compare. See output channel for more details`);
}
} }
} }

View File

@@ -1,13 +1,14 @@
'use strict'; 'use strict';
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { DiffWithWorkingCommandArgs } from './diffWithWorking'; import { DiffWithCommandArgs } from './diffWith';
import { GitCommit, GitService, GitUri } from '../gitService'; import { GitCommit, GitService, GitUri } from '../gitService';
import { Messages } from '../messages'; import { Messages } from '../messages';
import { Logger } from '../logger'; import { Logger } from '../logger';
export interface DiffLineWithWorkingCommandArgs { export interface DiffLineWithWorkingCommandArgs {
commit?: GitCommit; commit?: GitCommit;
line?: number; line?: number;
showOptions?: TextDocumentShowOptions; showOptions?: TextDocumentShowOptions;
} }
@@ -18,12 +19,16 @@ export class DiffLineWithWorkingCommand extends ActiveEditorCommand {
super(Commands.DiffLineWithWorking); super(Commands.DiffLineWithWorking);
} }
async execute(editor: TextEditor, uri?: Uri, args: DiffLineWithWorkingCommandArgs = {}): Promise<any> { async execute(editor?: TextEditor, uri?: Uri, args: DiffLineWithWorkingCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
if (uri === undefined) return undefined; if (uri === undefined) return undefined;
const gitUri = await GitUri.fromUri(uri, this.git); const gitUri = await GitUri.fromUri(uri, this.git);
args.line = args.line || (editor === undefined ? gitUri.offset : editor.selection.active.line);
args = { ...args };
if (args.line === undefined) {
args.line = editor === undefined ? gitUri.offset : editor.selection.active.line;
}
if (args.commit === undefined || GitService.isUncommitted(args.commit.sha)) { if (args.commit === undefined || GitService.isUncommitted(args.commit.sha)) {
if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined; if (editor !== undefined && editor.document !== undefined && editor.document.isDirty) return undefined;
@@ -48,6 +53,19 @@ export class DiffLineWithWorkingCommand extends ActiveEditorCommand {
} }
} }
return commands.executeCommand(Commands.DiffWithWorking, uri, args as DiffWithWorkingCommandArgs); const diffArgs: DiffWithCommandArgs = {
repoPath: args.commit.repoPath,
lhs: {
sha: args.commit.sha,
uri: args.commit.uri
},
rhs: {
sha: '',
uri: args.commit.uri
},
line: args.line,
showOptions: args.showOptions
};
return commands.executeCommand(Commands.DiffWith, diffArgs);
} }
} }

142
src/commands/diffWith.ts Normal file
View File

@@ -0,0 +1,142 @@
'use strict';
import { commands, Range, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands } from './common';
import { BuiltInCommands, GlyphChars } from '../constants';
import { GitCommit, GitService } from '../gitService';
import { Logger } from '../logger';
import * as path from 'path';
export interface DiffWithCommandArgsRevision {
sha: string;
uri: Uri;
title?: string;
}
export interface DiffWithCommandArgs {
lhs?: DiffWithCommandArgsRevision;
rhs?: DiffWithCommandArgsRevision;
repoPath?: string;
line?: number;
showOptions?: TextDocumentShowOptions;
}
export class DiffWithCommand extends ActiveEditorCommand {
static getMarkdownCommandArgs(args: DiffWithCommandArgs): string;
static getMarkdownCommandArgs(commit1: GitCommit, commit2: GitCommit): string;
static getMarkdownCommandArgs(argsOrCommit1: DiffWithCommandArgs | GitCommit, commit2?: GitCommit): string {
let args = argsOrCommit1;
if (argsOrCommit1 instanceof GitCommit) {
const commit1 = argsOrCommit1;
if (commit2 === undefined) {
if (commit1.isUncommitted) {
args = {
repoPath: commit1.repoPath,
lhs: {
sha: 'HEAD',
uri: commit1.uri
},
rhs: {
sha: '',
uri: commit1.uri
}
};
}
else {
args = {
repoPath: commit1.repoPath,
lhs: {
sha: commit1.previousSha!,
uri: commit1.previousUri!
},
rhs: {
sha: commit1.sha,
uri: commit1.uri
}
};
}
}
else {
args = {
repoPath: commit1.repoPath,
lhs: {
sha: commit1.sha,
uri: commit1.uri
},
rhs: {
sha: commit2.sha,
uri: commit2.uri
}
};
}
}
return super.getMarkdownCommandArgsCore<DiffWithCommandArgs>(Commands.DiffWith, args);
}
constructor(private git: GitService) {
super(Commands.DiffWith);
}
async execute(editor?: TextEditor, uri?: Uri, args: DiffWithCommandArgs = {}): Promise<any> {
args = { ...args };
if (args.repoPath === undefined || args.lhs === undefined || args.rhs === undefined) return undefined;
try {
const [lhs, rhs] = await Promise.all([
args.lhs.sha !== '' && !GitService.isUncommitted(args.lhs.sha)
? this.git.getVersionedFile(args.repoPath, args.lhs.uri.fsPath, args.lhs.sha)
: args.lhs.uri.fsPath,
args.rhs.sha !== '' && !GitService.isUncommitted(args.rhs.sha)
? this.git.getVersionedFile(args.repoPath, args.rhs.uri.fsPath, args.rhs.sha)
: args.rhs.uri.fsPath
]);
if (args.line !== undefined && args.line !== 0) {
if (args.showOptions === undefined) {
args.showOptions = {};
}
args.showOptions.selection = new Range(args.line, 0, args.line, 0);
}
let rhsPrefix = '';
if (rhs === undefined) {
rhsPrefix = 'deleted in ';
}
else if (lhs === undefined || args.lhs.sha === GitService.fakeSha) {
rhsPrefix = 'added in ';
}
if (args.lhs.title === undefined && lhs !== undefined && args.lhs.sha !== GitService.fakeSha) {
args.lhs.title = (args.lhs.sha === '' || GitService.isUncommitted(args.lhs.sha))
? `${path.basename(args.lhs.uri.fsPath)}`
: `${path.basename(args.lhs.uri.fsPath)} (${GitService.shortenSha(args.lhs.sha)})`;
}
if (args.rhs.title === undefined && args.rhs.sha !== GitService.fakeSha) {
args.rhs.title = (args.rhs.sha === '' || GitService.isUncommitted(args.rhs.sha))
? `${path.basename(args.rhs.uri.fsPath)}`
: `${path.basename(args.rhs.uri.fsPath)} (${rhsPrefix}${GitService.shortenSha(args.rhs.sha)})`;
}
const title = (args.lhs.title !== undefined && args.rhs.title !== undefined)
? `${args.lhs.title} ${GlyphChars.ArrowLeftRight} ${args.rhs.title}`
: args.lhs.title || args.rhs.title;
return await commands.executeCommand(BuiltInCommands.Diff,
lhs === undefined
? GitService.toGitContentUri(GitService.fakeSha, args.lhs.uri.fsPath, args.repoPath)
: Uri.file(lhs),
rhs === undefined
? GitService.toGitContentUri(GitService.fakeSha, args.rhs.uri.fsPath, args.repoPath)
: Uri.file(rhs),
title,
args.showOptions);
}
catch (ex) {
Logger.error(ex, 'DiffWithCommand', 'getVersionedFile');
return window.showErrorMessage(`Unable to open compare. See output channel for more details`);
}
}
}

View File

@@ -1,59 +1,61 @@
'use strict'; 'use strict';
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; import { commands, TextDocumentShowOptions, TextEditor, Uri } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { BuiltInCommands } from '../constants'; import { GlyphChars } from '../constants';
import { GitService, GitUri } from '../gitService'; import { DiffWithCommandArgs } from './diffWith';
import { Logger } from '../logger'; import { GitService, GitUri } from '../gitService';
import { Messages } from '../messages'; import { Messages } from '../messages';
import { BranchesQuickPick, CommandQuickPickItem } from '../quickPicks'; import { BranchesQuickPick, CommandQuickPickItem } from '../quickPicks';
import * as path from 'path'; import * as path from 'path';
export interface DiffWithBranchCommandArgs { export interface DiffWithBranchCommandArgs {
line?: number; line?: number;
showOptions?: TextDocumentShowOptions; showOptions?: TextDocumentShowOptions;
goBackCommand?: CommandQuickPickItem; goBackCommand?: CommandQuickPickItem;
} }
export class DiffWithBranchCommand extends ActiveEditorCommand { export class DiffWithBranchCommand extends ActiveEditorCommand {
constructor(private git: GitService) { constructor(private git: GitService) {
super(Commands.DiffWithBranch); super(Commands.DiffWithBranch);
} }
async execute(editor: TextEditor, uri?: Uri, args: DiffWithBranchCommandArgs = {}): Promise<any> { async execute(editor?: TextEditor, uri?: Uri, args: DiffWithBranchCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
if (uri === undefined) return undefined; if (uri === undefined) return undefined;
args.line = args.line || (editor === undefined ? 0 : editor.selection.active.line); args = { ...args };
if (args.line === undefined) {
const gitUri = await GitUri.fromUri(uri, this.git); args.line = editor === undefined ? 0 : editor.selection.active.line;
if (!gitUri.repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to open branch compare`); }
const branches = await this.git.getBranches(gitUri.repoPath); const gitUri = await GitUri.fromUri(uri, this.git);
const pick = await BranchesQuickPick.show(branches, `Compare ${path.basename(gitUri.fsPath)} to \u2026`, args.goBackCommand); if (!gitUri.repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to open branch compare`);
if (pick === undefined) return undefined;
const branches = await this.git.getBranches(gitUri.repoPath);
if (pick instanceof CommandQuickPickItem) return pick.execute(); const pick = await BranchesQuickPick.show(branches, `Compare ${path.basename(gitUri.fsPath)} to ${GlyphChars.Ellipsis}`, args.goBackCommand);
if (pick === undefined) return undefined;
const branch = pick.branch.name;
if (branch === undefined) return undefined; if (pick instanceof CommandQuickPickItem) return pick.execute();
try { const branch = pick.branch.name;
const compare = await this.git.getVersionedFile(gitUri.repoPath, gitUri.fsPath, branch); if (branch === undefined) return undefined;
await commands.executeCommand(BuiltInCommands.Diff, const diffArgs: DiffWithCommandArgs = {
Uri.file(compare), repoPath: gitUri.repoPath,
gitUri.fileUri(), lhs: {
`${path.basename(gitUri.fsPath)} (${branch}) \u2194 ${path.basename(gitUri.fsPath)}`, sha: pick.branch.remote ? `remotes/${branch}` : branch,
args.showOptions); uri: gitUri as Uri,
title: `${path.basename(gitUri.fsPath)} (${branch})`
// TODO: Figure out how to focus the left pane },
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' }); rhs: {
} sha: '',
catch (ex) { uri: gitUri as Uri
Logger.error(ex, 'DiffWithBranchCommand', 'getVersionedFile'); },
return window.showErrorMessage(`Unable to open branch compare. See output channel for more details`); line: args.line,
} showOptions: args.showOptions
} };
return commands.executeCommand(Commands.DiffWith, diffArgs);
}
} }

View File

@@ -2,16 +2,16 @@
import { Iterables } from '../system'; import { Iterables } from '../system';
import { commands, Range, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; import { commands, Range, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { BuiltInCommands } from '../constants'; import { DiffWithCommandArgs } from './diffWith';
import { GitLogCommit, GitService, GitUri } from '../gitService'; import { GitLogCommit, GitService, GitUri } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { Messages } from '../messages'; import { Messages } from '../messages';
import * as path from 'path';
export interface DiffWithNextCommandArgs { export interface DiffWithNextCommandArgs {
commit?: GitLogCommit; commit?: GitLogCommit;
line?: number;
range?: Range; range?: Range;
line?: number;
showOptions?: TextDocumentShowOptions; showOptions?: TextDocumentShowOptions;
} }
@@ -21,11 +21,14 @@ export class DiffWithNextCommand extends ActiveEditorCommand {
super(Commands.DiffWithNext); super(Commands.DiffWithNext);
} }
async execute(editor: TextEditor, uri?: Uri, args: DiffWithNextCommandArgs = {}): Promise<any> { async execute(editor?: TextEditor, uri?: Uri, args: DiffWithNextCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
if (uri === undefined) return undefined; if (uri === undefined) return undefined;
args.line = args.line || (editor === undefined ? 0 : editor.selection.active.line); args = { ...args };
if (args.line === undefined) {
args.line = editor === undefined ? 0 : editor.selection.active.line;
}
if (args.commit === undefined || !(args.commit instanceof GitLogCommit) || args.range !== undefined) { if (args.commit === undefined || !(args.commit instanceof GitLogCommit) || args.range !== undefined) {
const gitUri = await GitUri.fromUri(uri, this.git); const gitUri = await GitUri.fromUri(uri, this.git);
@@ -38,7 +41,7 @@ export class DiffWithNextCommand extends ActiveEditorCommand {
const sha = args.commit === undefined ? gitUri.sha : args.commit.sha; const sha = args.commit === undefined ? gitUri.sha : args.commit.sha;
const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, undefined, sha !== undefined ? undefined : 2, args.range!); const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, undefined, { maxCount: sha !== undefined ? undefined : 2, range: args.range! });
if (log === undefined) return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare'); if (log === undefined) return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare');
args.commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values()); args.commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values());
@@ -51,24 +54,19 @@ export class DiffWithNextCommand extends ActiveEditorCommand {
if (args.commit.nextSha === undefined) return commands.executeCommand(Commands.DiffWithWorking, uri); if (args.commit.nextSha === undefined) return commands.executeCommand(Commands.DiffWithWorking, uri);
try { const diffArgs: DiffWithCommandArgs = {
const [rhs, lhs] = await Promise.all([ repoPath: args.commit.repoPath,
this.git.getVersionedFile(args.commit.repoPath, args.commit.nextUri.fsPath, args.commit.nextSha), lhs: {
this.git.getVersionedFile(args.commit.repoPath, args.commit.uri.fsPath, args.commit.sha) sha: args.commit.sha,
]); uri: args.commit.uri
},
await commands.executeCommand(BuiltInCommands.Diff, rhs: {
Uri.file(lhs), sha: args.commit.nextSha,
Uri.file(rhs), uri: args.commit.nextUri
`${path.basename(args.commit.uri.fsPath)} (${args.commit.shortSha}) \u2194 ${path.basename(args.commit.nextUri.fsPath)} (${args.commit.nextShortSha})`, },
args.showOptions); line: args.line,
showOptions: args.showOptions
// TODO: Figure out how to focus the left pane };
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' }); return commands.executeCommand(Commands.DiffWith, diffArgs);
}
catch (ex) {
Logger.error(ex, 'DiffWithNextCommand', 'getVersionedFile');
return window.showErrorMessage(`Unable to open compare. See output channel for more details`);
}
} }
} }

View File

@@ -2,17 +2,17 @@
import { Iterables } from '../system'; import { Iterables } from '../system';
import { commands, Range, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; import { commands, Range, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { BuiltInCommands } from '../constants'; import { DiffWithCommandArgs } from './diffWith';
import { DiffWithWorkingCommandArgs } from './diffWithWorking'; import { DiffWithWorkingCommandArgs } from './diffWithWorking';
import { GitCommit, GitService, GitUri } from '../gitService'; import { GitCommit, GitService, GitUri } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { Messages } from '../messages'; import { Messages } from '../messages';
import * as path from 'path';
export interface DiffWithPreviousCommandArgs { export interface DiffWithPreviousCommandArgs {
commit?: GitCommit; commit?: GitCommit;
line?: number;
range?: Range; range?: Range;
line?: number;
showOptions?: TextDocumentShowOptions; showOptions?: TextDocumentShowOptions;
} }
@@ -22,25 +22,31 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
super(Commands.DiffWithPrevious); super(Commands.DiffWithPrevious);
} }
async execute(editor: TextEditor, uri?: Uri, args: DiffWithPreviousCommandArgs = {}): Promise<any> { async execute(editor?: TextEditor, uri?: Uri, args: DiffWithPreviousCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
if (uri === undefined) return undefined; if (uri === undefined) return undefined;
args.line = args.line || (editor === undefined ? 0 : editor.selection.active.line); args = { ...args };
if (args.line === undefined) {
args.line = editor === undefined ? 0 : editor.selection.active.line;
}
if (args.commit === undefined || (args.commit.type !== 'file') || args.range !== undefined) { if (args.commit === undefined || args.commit.type !== 'file' || args.range !== undefined) {
const gitUri = await GitUri.fromUri(uri, this.git); const gitUri = await GitUri.fromUri(uri, this.git);
try { try {
const sha = args.commit === undefined ? gitUri.sha : args.commit.sha; const sha = args.commit === undefined ? gitUri.sha : args.commit.sha;
if (sha === GitService.fakeSha) return Messages.showCommitHasNoPreviousCommitWarningMessage();
const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, undefined, sha !== undefined ? undefined : 2, args.range!); const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, sha, { maxCount: 2, range: args.range!, skipMerges: true });
if (log === undefined) return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare'); if (log === undefined) return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare');
args.commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values()); args.commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values());
// If the sha is missing and the file is uncommitted, then treat it as a DiffWithWorking // If the sha is missing and the file is uncommitted, then treat it as a DiffWithWorking
if (gitUri.sha === undefined && await this.git.isFileUncommitted(gitUri)) return commands.executeCommand(Commands.DiffWithWorking, uri, { commit: args.commit, showOptions: args.showOptions } as DiffWithWorkingCommandArgs); if (gitUri.sha === undefined && await this.git.isFileUncommitted(gitUri)) {
return commands.executeCommand(Commands.DiffWithWorking, uri, { commit: args.commit, showOptions: args.showOptions } as DiffWithWorkingCommandArgs);
}
} }
catch (ex) { catch (ex) {
Logger.error(ex, 'DiffWithPreviousCommand', `getLogForFile(${gitUri.repoPath}, ${gitUri.fsPath})`); Logger.error(ex, 'DiffWithPreviousCommand', `getLogForFile(${gitUri.repoPath}, ${gitUri.fsPath})`);
@@ -48,26 +54,19 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
} }
} }
if (args.commit.previousSha === undefined) return Messages.showCommitHasNoPreviousCommitWarningMessage(args.commit); const diffArgs: DiffWithCommandArgs = {
repoPath: args.commit.repoPath,
try { lhs: {
const [rhs, lhs] = await Promise.all([ sha: args.commit.previousSha !== undefined ? args.commit.previousSha : GitService.fakeSha,
this.git.getVersionedFile(args.commit.repoPath, args.commit.uri.fsPath, args.commit.sha), uri: args.commit.previousUri
this.git.getVersionedFile(args.commit.repoPath, args.commit.previousUri.fsPath, args.commit.previousSha) },
]); rhs: {
sha: args.commit.sha,
await commands.executeCommand(BuiltInCommands.Diff, uri: args.commit.uri
Uri.file(lhs), },
Uri.file(rhs), line: args.line,
`${path.basename(args.commit.previousUri.fsPath)} (${args.commit.previousShortSha}) \u2194 ${path.basename(args.commit.uri.fsPath)} (${args.commit.shortSha})`, showOptions: args.showOptions
args.showOptions); };
return commands.executeCommand(Commands.DiffWith, diffArgs);
// TODO: Figure out how to focus the left pane
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' });
}
catch (ex) {
Logger.error(ex, 'DiffWithPreviousCommand', 'getVersionedFile');
return window.showErrorMessage(`Unable to open compare. See output channel for more details`);
}
} }
} }

View File

@@ -0,0 +1,69 @@
'use strict';
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { DiffWithCommandArgs } from './diffWith';
import { GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
import { Messages } from '../messages';
import { CommandQuickPickItem, FileHistoryQuickPick } from '../quickPicks';
export interface DiffWithRevisionCommandArgs {
maxCount?: number;
line?: number;
showOptions?: TextDocumentShowOptions;
}
export class DiffWithRevisionCommand extends ActiveEditorCommand {
constructor(private git: GitService) {
super(Commands.DiffWithRevision);
}
async execute(editor?: TextEditor, uri?: Uri, args: DiffWithRevisionCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor);
if (uri === undefined) return undefined;
args = { ...args };
if (args.line === undefined) {
args.line = editor === undefined ? 0 : editor.selection.active.line;
}
const gitUri = await GitUri.fromUri(uri, this.git);
if (args.maxCount == null) {
args.maxCount = this.git.config.advanced.maxQuickHistory;
}
const progressCancellation = FileHistoryQuickPick.showProgress(gitUri);
try {
const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, gitUri.sha, { maxCount: args.maxCount });
if (log === undefined) return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open history compare');
if (progressCancellation.token.isCancellationRequested) return undefined;
const pick = await FileHistoryQuickPick.show(this.git, log, gitUri, progressCancellation, { pickerOnly: true });
if (pick === undefined) return undefined;
if (pick instanceof CommandQuickPickItem) return pick.execute();
const diffArgs: DiffWithCommandArgs = {
repoPath: gitUri.repoPath,
lhs: {
sha: pick.commit.sha,
uri: gitUri as Uri
},
rhs: {
sha: '',
uri: gitUri as Uri
},
line: args.line,
showOptions: args.showOptions
};
return await commands.executeCommand(Commands.DiffWith, diffArgs);
}
catch (ex) {
Logger.error(ex, 'DiffWithRevisionCommand');
return window.showErrorMessage(`Unable to open compare. See output channel for more details`);
}
}
}

View File

@@ -1,14 +1,14 @@
'use strict'; 'use strict';
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { BuiltInCommands } from '../constants'; import { DiffWithCommandArgs } from './diffWith';
import { GitCommit, GitService, GitUri } from '../gitService'; import { GitCommit, GitService, GitUri } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { Messages } from '../messages'; import { Messages } from '../messages';
import * as path from 'path';
export interface DiffWithWorkingCommandArgs { export interface DiffWithWorkingCommandArgs {
commit?: GitCommit; commit?: GitCommit;
line?: number; line?: number;
showOptions?: TextDocumentShowOptions; showOptions?: TextDocumentShowOptions;
} }
@@ -19,11 +19,14 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand {
super(Commands.DiffWithWorking); super(Commands.DiffWithWorking);
} }
async execute(editor: TextEditor, uri?: Uri, args: DiffWithWorkingCommandArgs = {}): Promise<any> { async execute(editor?: TextEditor, uri?: Uri, args: DiffWithWorkingCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
if (uri === undefined) return undefined; if (uri === undefined) return undefined;
args.line = args.line || (editor === undefined ? 0 : editor.selection.active.line); args = { ...args };
if (args.line === undefined) {
args.line = editor === undefined ? 0 : editor.selection.active.line;
}
if (args.commit === undefined || GitService.isUncommitted(args.commit.sha)) { if (args.commit === undefined || GitService.isUncommitted(args.commit.sha)) {
const gitUri = await GitUri.fromUri(uri, this.git); const gitUri = await GitUri.fromUri(uri, this.git);
@@ -45,21 +48,19 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand {
const workingFileName = await this.git.findWorkingFileName(gitUri.repoPath, gitUri.fsPath); const workingFileName = await this.git.findWorkingFileName(gitUri.repoPath, gitUri.fsPath);
if (workingFileName === undefined) return undefined; if (workingFileName === undefined) return undefined;
try { const diffArgs: DiffWithCommandArgs = {
const compare = await this.git.getVersionedFile(args.commit.repoPath, args.commit.uri.fsPath, args.commit.sha); repoPath: args.commit.repoPath,
lhs: {
await commands.executeCommand(BuiltInCommands.Diff, sha: args.commit.sha,
Uri.file(compare), uri: args.commit.uri
Uri.file(path.resolve(gitUri.repoPath, workingFileName)), },
`${path.basename(args.commit.uri.fsPath)} (${args.commit.shortSha}) \u2194 ${path.basename(workingFileName)}`, rhs: {
args.showOptions); sha: '',
uri: args.commit.uri
// TODO: Figure out how to focus the left pane },
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' }); line: args.line,
} showOptions: args.showOptions
catch (ex) { };
Logger.error(ex, 'DiffWithWorkingCommand', 'getVersionedFile'); return commands.executeCommand(Commands.DiffWith, diffArgs);
return window.showErrorMessage(`Unable to open compare. See output channel for more details`);
}
} }
} }

View File

@@ -1,7 +1,7 @@
'use strict'; 'use strict';
import { Arrays } from '../system'; import { commands, TextEditor, Uri, window } from 'vscode';
import { commands, TextEditor, TextEditorEdit, Uri, window } from 'vscode'; import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithBranch } from './common';
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; import { GlyphChars } from '../constants';
import { GitService, GitUri } from '../gitService'; import { GitService, GitUri } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
import { BranchesQuickPick, CommandQuickPickItem } from '../quickPicks'; import { BranchesQuickPick, CommandQuickPickItem } from '../quickPicks';
@@ -9,6 +9,7 @@ import { OpenInRemoteCommandArgs } from './openInRemote';
export interface OpenBranchInRemoteCommandArgs { export interface OpenBranchInRemoteCommandArgs {
branch?: string; branch?: string;
remote?: string;
} }
export class OpenBranchInRemoteCommand extends ActiveEditorCommand { export class OpenBranchInRemoteCommand extends ActiveEditorCommand {
@@ -17,7 +18,17 @@ export class OpenBranchInRemoteCommand extends ActiveEditorCommand {
super(Commands.OpenBranchInRemote); super(Commands.OpenBranchInRemote);
} }
async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, args: OpenBranchInRemoteCommandArgs = {}) { protected async preExecute(context: CommandContext, args: OpenBranchInRemoteCommandArgs = {}): Promise<any> {
if (isCommandViewContextWithBranch(context)) {
args = { ...args };
args.branch = context.node.branch.name;
args.remote = context.node.branch.getRemote();
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args: OpenBranchInRemoteCommandArgs = {}) {
uri = getCommandUri(uri, editor); uri = getCommandUri(uri, editor);
const gitUri = uri && await GitUri.fromUri(uri, this.git); const gitUri = uri && await GitUri.fromUri(uri, this.git);
@@ -27,9 +38,11 @@ export class OpenBranchInRemoteCommand extends ActiveEditorCommand {
try { try {
if (args.branch === undefined) { if (args.branch === undefined) {
args = { ...args };
const branches = await this.git.getBranches(repoPath); const branches = await this.git.getBranches(repoPath);
const pick = await BranchesQuickPick.show(branches, `Show history for branch\u2026`); const pick = await BranchesQuickPick.show(branches, `Show history for branch${GlyphChars.Ellipsis}`);
if (pick === undefined) return undefined; if (pick === undefined) return undefined;
if (pick instanceof CommandQuickPickItem) return undefined; if (pick instanceof CommandQuickPickItem) return undefined;
@@ -38,12 +51,14 @@ export class OpenBranchInRemoteCommand extends ActiveEditorCommand {
if (args.branch === undefined) return undefined; if (args.branch === undefined) return undefined;
} }
const remotes = Arrays.uniqueBy(await this.git.getRemotes(repoPath), _ => _.url, _ => !!_.provider); const remotes = (await this.git.getRemotes(repoPath)).filter(r => r.provider !== undefined);
return commands.executeCommand(Commands.OpenInRemote, uri, { return commands.executeCommand(Commands.OpenInRemote, uri, {
resource: { resource: {
type: 'branch', type: 'branch',
branch: args.branch branch: args.branch
}, },
remote: args.remote,
remotes remotes
} as OpenInRemoteCommandArgs); } as OpenInRemoteCommandArgs);
} }

View File

@@ -0,0 +1,51 @@
'use strict';
import { commands, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithRemote } from './common';
import { GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
import { OpenInRemoteCommandArgs } from './openInRemote';
export interface OpenBranchesInRemoteCommandArgs {
remote?: string;
}
export class OpenBranchesInRemoteCommand extends ActiveEditorCommand {
constructor(private git: GitService) {
super(Commands.OpenBranchesInRemote);
}
protected async preExecute(context: CommandContext, args: OpenBranchesInRemoteCommandArgs = {}): Promise<any> {
if (isCommandViewContextWithRemote(context)) {
args = { ...args };
args.remote = context.node.remote.name;
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args: OpenBranchesInRemoteCommandArgs = {}) {
uri = getCommandUri(uri, editor);
const gitUri = uri && await GitUri.fromUri(uri, this.git);
const repoPath = gitUri === undefined ? this.git.repoPath : gitUri.repoPath;
if (!repoPath) return undefined;
try {
const remotes = (await this.git.getRemotes(repoPath)).filter(r => r.provider !== undefined);
return commands.executeCommand(Commands.OpenInRemote, uri, {
resource: {
type: 'branches'
},
remote: args.remote,
remotes
} as OpenInRemoteCommandArgs);
}
catch (ex) {
Logger.error(ex, 'OpenBranchesInRemoteCommand');
return window.showErrorMessage(`Unable to open branches in remote provider. See output channel for more details`);
}
}
}

Some files were not shown because too many files have changed in this diff Show More