mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-02-12 11:08:34 -05:00
Compare commits
19 Commits
v5.1.1-bet
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 3684629c9b | |||
|
|
65a3b31ca5 | ||
|
|
4694fbc1ae | ||
|
|
b56d101f76 | ||
|
|
ce9394297d | ||
|
|
4d18bf708d | ||
|
|
c44e4c6968 | ||
|
|
c5f57172e4 | ||
|
|
dd0a636e24 | ||
|
|
393ec351f0 | ||
|
|
99d6da9c90 | ||
|
|
0eb202b8ae | ||
|
|
65736a6ce7 | ||
|
|
ed42eba8b8 | ||
|
|
2245d82319 | ||
|
|
f7df845dfe | ||
|
|
712544fab8 | ||
|
|
a114e2de87 | ||
|
|
70071448d6 |
37
CHANGELOG.md
37
CHANGELOG.md
@@ -4,19 +4,42 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
|
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [5.3.0] - 2017-09-26
|
||||||
|
|
||||||
## [5.1.1-beta]
|
|
||||||
### Added
|
### Added
|
||||||
- Adds new `Changed Files` node to the `Repository Status` node of the `GitLens` custom view's `Repository View` (enabled via `"gitlens.insiders": true`) -- closes [#139](https://github.com/eamodio/vscode-gitlens/issues/139)
|
- Adds new file layouts to the `GitLens` custom view
|
||||||
- Provides a file-based view of all the changed files in the working tree and/or files in commits that haven't yet been pushed upstream
|
- `auto` - automatically switches between displaying files as a `tree` or `list` based on the `gitlens.gitExplorer.files.threshold` setting and the number of files at each nesting level
|
||||||
- Adds `gitlens.gitExplorer.enabled` setting to specify whether or not to show the `GitLens` custom view - closes [#144](https://github.com/eamodio/vscode-gitlens/issues/144)
|
- `list` - displays files as a list
|
||||||
|
- `tree` - displays files as a tree
|
||||||
|
- Adds `gitlens.gitExplorer.files.layout` setting to specify how the `GitLens` custom view will display files
|
||||||
|
- Adds `gitlens.gitExplorer.files.compact` setting to specify whether or not to compact (flatten) unnecessary file nesting in the `GitLens` custom view
|
||||||
|
- Adds `gitlens.gitExplorer.files.threshold` setting to specify when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the `GitLens` custom view
|
||||||
|
- Adds `${directory}` token to the file formatting settings
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Chnages the default of the `gitlens.gitExplorer.commitFormat` setting to add parentheses around the commit id
|
- Changes `${path}` token to be the full file path in the file formatting settings
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixes [#153](https://github.com/eamodio/vscode-gitlens/issues/153) - New folders treated as files in "Changed Files" section of the sidebar component
|
||||||
|
|
||||||
|
## [5.2.0] - 2017-09-23
|
||||||
|
### Added
|
||||||
|
- Adds new `Changed Files` node to the `Repository Status` node of the `GitLens` custom view's `Repository View` -- closes [#139](https://github.com/eamodio/vscode-gitlens/issues/139)
|
||||||
|
- Provides a at-a-glance view of all "working" changes
|
||||||
|
- Expands to a file-based view of all changed files in the working tree (enabled via `"gitlens.insiders": true`) and/or all files in all commits ahead of the upstream
|
||||||
|
- Adds optional (on by default) working tree status information to the `Repository Status` node in the `GitLens` custom view
|
||||||
|
- Adds `auto` value to `gitlens.gitExplorer.view` setting - closes [#150](https://github.com/eamodio/vscode-gitlens/issues/150)
|
||||||
|
- Adds `gitlens.gitExplorer.enabled` setting to specify whether or not to show the `GitLens` custom view - closes [#144](https://github.com/eamodio/vscode-gitlens/issues/144)
|
||||||
|
- Adds `gitlens.gitExplorer.includeWorkingTree` setting to specify whether or not to include working tree files inside the `Repository Status` node of the `GitLens` custom view
|
||||||
|
- Adds `gitlens.gitExplorer.statusFileFormat` setting to the format of the status of a working or committed file in the `GitLens` custom view
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Changes the sorting (now alphabetical) of files shown in the `GitLens` custom view
|
||||||
|
- Changes the default of the `gitlens.gitExplorer.view` setting to `auto`
|
||||||
|
- Changes the default of the `gitlens.gitExplorer.commitFormat` setting to add parentheses around the commit id
|
||||||
- Removes many menu items from `editor/title` & `editor/title/context` by default -- can be re-enabled via the `gitlens.advanced.menus` setting
|
- Removes many menu items from `editor/title` & `editor/title/context` by default -- can be re-enabled via the `gitlens.advanced.menus` setting
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- Fixes [#146](https://github.com/eamodio/vscode-gitlens/issues/146) - Blame gutter annotation issue when commit contains emoji
|
||||||
- Fixes an issue when running `Open File in Remote` with a multi-line selection wasn't properly opening the selection in GitLab -- thanks to [PR #145](https://github.com/eamodio/vscode-gitlens/pull/145) by Amanda Cameron ([@AmandaCameron](https://github.com/AmandaCameron))!
|
- Fixes an issue when running `Open File in Remote` with a multi-line selection wasn't properly opening the selection in GitLab -- thanks to [PR #145](https://github.com/eamodio/vscode-gitlens/pull/145) by Amanda Cameron ([@AmandaCameron](https://github.com/AmandaCameron))!
|
||||||
- Fixes an issue where the `gitlens.advanced.menus` setting wasn't controlling all the menu items properly
|
- Fixes an issue where the `gitlens.advanced.menus` setting wasn't controlling all the menu items properly
|
||||||
|
|
||||||
|
|||||||
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at eamodio@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
||||||
869
README.md
869
README.md
@@ -1,430 +1,439 @@
|
|||||||
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
||||||
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
||||||
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
[](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
||||||
[](https://join.slack.com/t/vscode-dev-community/shared_invite/enQtMjIxOTgxNDE3NzM0LWU5M2ZiZDU1YjBlMzdlZjA2YjBjYzRhYTM5NTgzMTAxMjdiNWU0ZmQzYWI3MWU5N2Q1YjBiYmQ4MzY0NDE1MzY)
|
[](https://join.slack.com/t/vscode-dev-community/shared_invite/enQtMjIxOTgxNDE3NzM0LWU5M2ZiZDU1YjBlMzdlZjA2YjBjYzRhYTM5NTgzMTAxMjdiNWU0ZmQzYWI3MWU5N2Q1YjBiYmQ4MzY0NDE1MzY)
|
||||||
|
|
||||||
# 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 comparison 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).
|
||||||
|
|
||||||
### Preview — featuring blame annotations, code lens, status bar details, quick pick menus for navigation and exploration, compare with previous, and more
|
### Preview — featuring blame annotations, code lens, status bar details, quick pick menus for navigation and exploration, compare with previous, and more
|
||||||

|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
### Git Blame Annotations
|
### Git Blame Annotations
|
||||||
|
|
||||||
- Adds an unobtrusive, highly [customizable](#line-blame-annotation-settings) and [themeable](#theme-settings), **Git blame annotation** to the end of the current line ([optional](#line-blame-annotation-settings), on by default)
|
- Adds an unobtrusive, highly [customizable](#line-blame-annotation-settings) and [themeable](#theme-settings), **Git blame annotation** to the end of the current line ([optional](#line-blame-annotation-settings), on by default)
|
||||||
|
|
||||||

|

|
||||||
- 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)
|
||||||
- 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)
|
||||||
- Clicking the commit id will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
|
- 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)
|
- 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 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`)
|
- Clicking the current and previous commit ids will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
|
||||||
- Clicking on external link icon will run the the `Open Commit in Remote` command (`gitlens.openCommitInRemote`)
|
- Clicking on external link icon will run the the `Open Commit in Remote` command (`gitlens.openCommitInRemote`)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- Adds on-demand, beautiful, highly [customizable](#file-blame-annotation-settings) and [themeable](#theme-settings), **Git blame annotations** of the whole file
|
- Adds on-demand, beautiful, highly [customizable](#file-blame-annotation-settings) and [themeable](#theme-settings), **Git blame annotations** of the whole file
|
||||||
|
|
||||||

|

|
||||||
- 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)
|
||||||
- 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`)
|
- 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)
|
- 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)
|
- Indicator ranges from bright yellow (newer) to dark brown (older)
|
||||||
- Press `Escape` to quickly toggle the annotations off
|
- 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)
|
||||||
|
|
||||||

|

|
||||||
- Contains the commit author and date, by [default](#status-bar-settings)
|
- Contains the commit author and date, by [default](#status-bar-settings)
|
||||||
- Clicking the status bar item will, by [default](#status-bar-settings), show a **commit details quick pick menu** with commands for comparing, navigating and exploring commits, and more
|
- Clicking the status bar item will, by [default](#status-bar-settings), show a **commit details quick pick menu** with commands for comparing, navigating and exploring commits, and more
|
||||||
- Provides [customizable](#status-bar-settings) click behavior — choose between one of the following
|
- Provides [customizable](#status-bar-settings) click behavior — choose between one of the following
|
||||||
- Toggle file blame annotations on and off
|
- Toggle file blame annotations on and off
|
||||||
- Toggle code lens on and off
|
- Toggle code lens on and off
|
||||||
- Compare the line commit with the previous commit
|
- Compare the line commit with the previous commit
|
||||||
- Compare the line commit with the working tree
|
- Compare the line commit with the working tree
|
||||||
- Show a quick pick menu with details and commands for the commit (default)
|
- Show a quick pick menu with details and commands for the commit (default)
|
||||||
- Show a quick pick menu with file details and commands for the commit
|
- Show a quick pick menu with file details and commands for the commit
|
||||||
- Show a quick pick menu with the commit history of the file
|
- Show a quick pick menu with the commit history of the file
|
||||||
- Show a quick pick menu with the commit history of the current branch
|
- Show a quick pick menu with the commit history of the current branch
|
||||||
|
|
||||||
- Adds a `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) with a shortcut of `alt+b` to toggle the file blame annotations on and off
|
- Adds a `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) with a shortcut of `alt+b` to toggle the file blame annotations on and off
|
||||||
- Also adds a `Show File Blame Annotations` command (`gitlens.showFileBlame`)
|
- Also adds a `Show File Blame Annotations` command (`gitlens.showFileBlame`)
|
||||||
|
|
||||||
- Adds a `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) to toggle the current line blame annotations on and off
|
- Adds a `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) to toggle the current line blame annotations on and off
|
||||||
- Also adds a `Show Line Blame Annotations` command (`gitlens.showLineBlame`)
|
- Also adds a `Show Line Blame Annotations` command (`gitlens.showLineBlame`)
|
||||||
|
|
||||||
### Git Recent Changes Annotations
|
### Git Recent Changes Annotations
|
||||||
|
|
||||||
- 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
|
||||||
- Adds a `details` hover annotation to each line, which provides more commit details ([optional](#file-blame-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`)
|
- 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)
|
- 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 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`)
|
- Clicking the current and previous commit ids will run the `Show Commit Details` command (`gitlens.showQuickCommitDetails`)
|
||||||
- Press `Escape` to quickly toggle the annotations off
|
- 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
|
||||||
|
|
||||||
### Git Code Lens
|
### Git Code Lens
|
||||||
|
|
||||||
- Adds **code lens** to the top of the file and on code blocks ([optional](#code-lens-settings), on by default)
|
- Adds **code lens** to the top of the file and on code blocks ([optional](#code-lens-settings), on by default)
|
||||||
|
|
||||||

|

|
||||||
- **Recent Change** — author and date of the most recent commit for the file or code block
|
- **Recent Change** — author and date of the most recent commit for the file or code block
|
||||||
- Clicking the code lens will, by [default](#code-lens-settings), show a **commit file details quick pick menu** with commands for comparing, navigating and exploring commits, and more
|
- Clicking the code lens will, by [default](#code-lens-settings), show a **commit file details quick pick menu** with commands for comparing, navigating and exploring commits, and more
|
||||||
- **Authors** — number of authors of the file or code block and the most prominent author (if there is more than one)
|
- **Authors** — number of authors of the file or code block and the most prominent author (if there is more than one)
|
||||||
- Clicking the code lens will, by [default](#code-lens-settings), toggle the file Git blame annotations on and off of the whole file
|
- Clicking the code lens will, by [default](#code-lens-settings), toggle the file Git blame annotations on and off of the whole file
|
||||||
- Will be hidden if the author of the most recent commit is also the only author of the file or block, to avoid duplicate information and reduce visual noise
|
- Will be hidden if the author of the most recent commit is also the only author of the file or block, to avoid duplicate information and reduce visual noise
|
||||||
|
|
||||||
- Provides [customizable](#code-lens-settings) click behavior for each code lens — choose between one of the following
|
- Provides [customizable](#code-lens-settings) click behavior for each code lens — choose between one of the following
|
||||||
- Toggle file blame annotations on and off
|
- Toggle file blame annotations on and off
|
||||||
- Compare the commit with the previous commit
|
- Compare the commit with the previous commit
|
||||||
- Show a quick pick menu with details and commands for the commit
|
- Show a quick pick menu with details and commands for the commit
|
||||||
- Show a quick pick menu with file details and commands for the commit
|
- Show a quick pick menu with file details and commands for the commit
|
||||||
- Show a quick pick menu with the commit history of the file
|
- Show a quick pick menu with the commit history of the file
|
||||||
- Show a quick pick menu with the commit history of the current branch
|
- Show a quick pick menu with the commit history of the current branch
|
||||||
|
|
||||||
- Adds a `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) with a shortcut of `shift+alt+b` to toggle the code lens on and off
|
- Adds a `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) with a shortcut of `shift+alt+b` to toggle the code lens on and off
|
||||||
|
|
||||||
### Powerful Comparison Tools
|
### Powerful Comparison Tools
|
||||||
|
|
||||||
- Effortlessly navigate between comparisons 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 Branch...` 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 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 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 Revision` 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 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 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 Revision...` command (`gitlens.diffWithRevision`) to compare the active file with the selected revision of the same file
|
- 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 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 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
|
- 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
|
- Adds a [customizable](#gitlens-custom-view-settings) `GitLens` custom view to the Explorer activity
|
||||||
|
|
||||||
- `Repository View` - provides a full repository explorer
|
- `Repository View` - provides a full repository explorer
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- `Repository Status` node — provides the status of the repository
|
- `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 the name of the current branch, [optionally](#gitlens-custom-view-settings) its working tree status, and its upstream tracking branch and status (if available)
|
||||||
- Provides indicator dots on the repository icon which denote the following:
|
- Provides indicator dots on the repository icon which denote the following:
|
||||||
- `None` - up-to-date with the upstream
|
- `None` - up-to-date with the upstream
|
||||||
- `Green` - ahead of the upstream
|
- `Green` - ahead of the upstream
|
||||||
- `Red` - behind the upstream
|
- `Red` - behind the upstream
|
||||||
- `Yellow` - both ahead of and 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 additional upstream status nodes, if the current branch is tracking a remote branch and
|
||||||
- Provides a context menu with `Open Repository in Remote`, and `Refresh` commands
|
- is behind the upstream — quickly see and explore the specific commits behind the upstream (i.e. commits that haven't been pulled)
|
||||||
|
- is ahead of the upstream — quickly see and explore the specific commits ahead of the upstream (i.e. commits that haven't been pushed)
|
||||||
- `Branches` node — provides a list of the local branches
|
- `Changed Files` node — provides a at-a-glance view of all "working" changes
|
||||||
- Indicates which branch is the current branch and [optionally](#gitlens-custom-view-settings) shows the remote tracking branch
|
- Expands to a file-based view of all changed files in the working tree ([optionally](#gitlens-custom-view-settings)) and/or all files in all commits ahead of the upstream
|
||||||
- Expand each branch to easily see its revision (commit) history
|
- Provides a context menu with `Open Repository in Remote`, and `Refresh` commands
|
||||||
- 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
|
- `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
|
||||||
- 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
|
- Expand each branch to easily see its revision (commit) history
|
||||||
- Provides a context menu on each branch with `Open Branch in Remote`, and `Refresh` commands
|
- 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 with `Open Branches in Remote`, and `Refresh` commands
|
- 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
|
||||||
|
|
||||||
- `Remotes` node — provides a list of remotes
|
- 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
|
||||||
- Indicates the direction of the remote (fetch, push, both), remote service (if applicable), and repository path
|
- Provides a context menu on each branch with `Open Branch in Remote`, and `Refresh` commands
|
||||||
- Expand each remote to see its list of branches
|
- Provides a context menu with `Open Branches in Remote`, and `Refresh` commands
|
||||||
- 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
|
- `Remotes` node — provides a list of remotes
|
||||||
- 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
|
- Indicates the direction of the remote (fetch, push, both), remote service (if applicable), and repository path
|
||||||
- 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
|
- Expand each remote to see its list of branches
|
||||||
- Provides a context menu on each remote with `Open Branches in Remote`, `Open Repository in Remote`, and `Refresh` commands
|
- Expand each branch to easily see its revision (commit) history
|
||||||
- Provides a context menu with a `Refresh` command
|
- 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
|
||||||
- `Stashes` node — provides a list of stashed changes
|
- 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
|
||||||
- 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 on each remote with `Open Branches in Remote`, `Open Repository in Remote`, and `Refresh` commands
|
||||||
- Provides a context menu with `Stash Changes`, and `Refresh` commands
|
- Provides a context menu with a `Refresh` command
|
||||||
- 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
|
- `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
|
||||||
- `History View` - provides the revision history of the active file
|
- 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
|
||||||
|
|
||||||
- Automatically updates to track the active editor
|
- `History View` - provides the revision history of the active file
|
||||||
- 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
|
- Automatically updates to track the active editor
|
||||||
- Provides toolbar commands to `Search Commits`, `Switch to Repository View` or `Switch to History View`, and `Refresh`
|
- 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
|
||||||
- Adds a `Search Commits` command (`gitlens.showCommitSearch`) with a shortcut of `alt+/` to search for commits by message, author, file(s), or commit id
|
|
||||||
|
- Quickly switch between views using the `Switch to Repository View` or `Switch to History View` commands
|
||||||
- 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
|
- Provides toolbar commands to `Search Commits`, `Switch to Repository View` or `Switch to History View`, and `Refresh`
|
||||||
- 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
|
- Adds a `Search Commits` command (`gitlens.showCommitSearch`) with a shortcut of `alt+/` to search for commits by message, author, file(s), or commit id
|
||||||
- `Open Branch in Remote` command (`gitlens.openBranchInRemote`) — opens the current branch commits 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
|
- 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
|
||||||
- `Open File in Remote` command (`gitlens.openFileInRemote`) — opens the active file/revision in the supported remote service
|
- Also supports [remote services with custom domains](#custom-remotes-settings), such as **BitBucket, Bitbucket Server (previously called Stash), GitHub, GitHub Enterprise, GitLab**
|
||||||
- `Open Repository in Remote` command (`gitlens.openRepoInRemote`) — opens the repository in the supported remote service
|
- `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
|
||||||
- Adds a `Show Current Branch History` command (`gitlens.showQuickRepoHistory`) with a shortcut of `shift+alt+h` to show a paged **branch history quick pick menu** of the current branch for exploring its commit history
|
- `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 Repository in Remote` command (`gitlens.openRepoInRemote`) — opens the repository in the supported remote service
|
||||||
|
|
||||||
- Provides entries to `Show Commit Search` and `Open Branch in <remote-service>` when available
|
- Adds a `Show Current Branch History` command (`gitlens.showQuickRepoHistory`) with a shortcut of `shift+alt+h` to show a paged **branch history quick pick menu** of the current branch for exploring its commit history
|
||||||
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
|
|
||||||
- Navigate pages via `alt+,` and `alt+.` to go backward and forward respectively
|

|
||||||
|
|
||||||
- Adds a `Show Branch History` command (`gitlens.showQuickBranchHistory`) to show a paged **branch history quick pick menu** of the selected branch for exploring its commit history
|
- Provides entries to `Show Commit Search` and `Open Branch in <remote-service>` when available
|
||||||
- Provides the same features as `Show Current Branch History` above
|
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
|
||||||
|
- Navigate pages via `alt+,` and `alt+.` to go backward and forward respectively
|
||||||
- Adds a `Show File History` command (`gitlens.showQuickFileHistory`) to show a paged **file history quick pick menu** of the active file for exploring its commit history
|
|
||||||
|
- Adds a `Show Branch History` command (`gitlens.showQuickBranchHistory`) to show a paged **branch history quick pick menu** of the selected branch for exploring its commit history
|
||||||

|
- Provides the same features as `Show Current Branch History` above
|
||||||
|
|
||||||
- Provides entries to `Show Branch History` and `Open File in <remote-service>` when available
|
- Adds a `Show File History` command (`gitlens.showQuickFileHistory`) to show a paged **file history quick pick menu** of the active file for exploring its commit history
|
||||||
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
|
|
||||||
- Navigate pages via `alt+,` and `alt+.` to go backward and forward respectively
|

|
||||||
|
|
||||||
- Adds a `Show Commit Details` command (`gitlens.showQuickCommitDetails`) to show a **commit details quick pick menu** of the most recent commit of the active file
|
- Provides entries to `Show Branch History` and `Open File in <remote-service>` when available
|
||||||
|
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
|
||||||

|
- Navigate pages via `alt+,` and `alt+.` to go backward and forward respectively
|
||||||
|
|
||||||
- Quickly see the set of files changed in the commit, complete with status indicators for adds, changes, renames, and deletes
|
- Adds a `Show Commit Details` command (`gitlens.showQuickCommitDetails`) to show a **commit details quick pick menu** of the most recent commit of the active file
|
||||||
- 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
|

|
||||||
- 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 comparison of the current revision with the previous one
|
- Quickly see the set of files changed in the commit, complete with status indicators for adds, changes, renames, and deletes
|
||||||
|
- Provides entries to `Copy to Clipboard`, `Directory Compare`, `Open Changed Files`, `Open File in <remote-service>` when available, and more
|
||||||
- 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
|
- 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 a file entry in the `Changed Files` section to preview the comparison of the current revision with the previous one
|
||||||
|
|
||||||
- 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
|
- 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
|
||||||
- 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
|

|
||||||
|
|
||||||
- Adds a `Show Repository Status` command (`gitlens.showQuickRepoStatus`) with a shortcut of `alt+s` to show a **repository status quick pick menu** for visualizing the current repository status
|
- 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
|
||||||

|
- 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
|
||||||
|
|
||||||
- Quickly see upstream status (if an Git upstream is configured) — complete with ahead and behind information
|
- Adds a `Show Repository Status` command (`gitlens.showQuickRepoStatus`) with a shortcut of `alt+s` to show a **repository status quick pick menu** for visualizing the current repository status
|
||||||
- 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. 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
|
|
||||||
- Provides entries to `Show Stashed Changes`, `Open Changed Files`, and `Close Unchanged Files`
|
- Quickly see upstream status (if an Git upstream is configured) — complete with ahead and behind information
|
||||||
- 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
|
- 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
|
||||||
- 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
|
- 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
|
||||||
- Adds a `Show Stashed Changes` command (`gitlens.showQuickStashList`) to show a **stashed changes quick pick menu** for exploring your repository stash history
|
- 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 a file entry in the `Staged Files` or `Unstaged Files` sections to preview the comparison of the working file with the previous revision
|
||||||
|
|
||||||
- Provides entries to `Stash Changes`
|
- Adds a `Show Stashed Changes` command (`gitlens.showQuickStashList`) to show a **stashed changes quick pick menu** for exploring your repository stash history
|
||||||
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
|
|
||||||
|

|
||||||
- Choosing a stash entry shows a **stash details quick pick menu** which is very similar to the **commit details quick pick menu** above
|
|
||||||
|
- Provides entries to `Stash Changes`
|
||||||

|
- Navigate back to the previous quick pick menu via `alt+left arrow`, if available
|
||||||
|
|
||||||
- Quickly see the set of files changed in the stash, complete with status indicators for adds, changes, renames, and deletes
|
- Choosing a stash entry shows a **stash details quick pick menu** which is very similar to the **commit details quick pick menu** above
|
||||||
- Provides entries to `Copy Message to Clipboard`, `Directory Compare`, and `Open Changed Files`
|
|
||||||
- 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
|
|
||||||
- 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
|
- Quickly see the set of files changed in the stash, complete with status indicators for adds, changes, renames, and deletes
|
||||||
- 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
|
- Provides entries to `Copy Message to Clipboard`, `Directory Compare`, and `Open Changed Files`
|
||||||
|
- Provides entries to `Apply Stashed Changes` and `Delete Stashed Changes` — both require a confirmation
|
||||||
- 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
|
- 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
|
||||||
- Adds a `Open File History Explorer` command (`gitlens.showFileHistory`) to show a **file history explorer** (peek style) to visualize the history of a file
|
- 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
|
||||||
- Likely to be deprecated in a future release, add your voice to [#66](https://github.com/eamodio/vscode-gitlens/issues/66) if you feel it should not be removed
|
|
||||||
|
- 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 `Open Blame History Explorer` command (`gitlens.showBlameHistory`) to show a **blame history explorer** (peek style) to visualize the blame history of a file or code block
|
|
||||||
- Likely to be deprecated in a future release, add your voice to [#66](https://github.com/eamodio/vscode-gitlens/issues/66) if you feel it should not be removed
|
- Adds a `Open File History Explorer` command (`gitlens.showFileHistory`) to show a **file history explorer** (peek style) to visualize the history of a file
|
||||||
|
- Likely to be deprecated in a future release, add your voice to [#66](https://github.com/eamodio/vscode-gitlens/issues/66) if you feel it should not be removed
|
||||||
### And More
|
|
||||||
|
- Adds a `Open Blame History Explorer` command (`gitlens.showBlameHistory`) to show a **blame history explorer** (peek style) to visualize the blame history of a file or code block
|
||||||
- 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
|
- Likely to be deprecated in a future release, add your voice to [#66](https://github.com/eamodio/vscode-gitlens/issues/66) if you feel it should not be removed
|
||||||
|
|
||||||
- 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
|
### And More
|
||||||
|
|
||||||
- Adds a `Open Changed Files` command (`gitlens.openChangedFiles`) to open any files with working tree changes
|
- 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 `Close Unchanged Files` command (`gitlens.closeUnchangedFiles`) to close any files without working tree changes
|
- 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 `Apply Stashed Changes` command (`gitlens.stashApply`) to chose a stash entry to apply to the working tree from a quick pick menu
|
- Adds a `Open Changed Files` command (`gitlens.openChangedFiles`) to open any files with working tree changes
|
||||||
|
|
||||||
- Adds a `Stash Changes` command (`gitlens.stashSave`) to save any working tree changes to the stash — can optionally provide a stash message
|
- Adds a `Close Unchanged Files` command (`gitlens.closeUnchangedFiles`) to close any files without working tree changes
|
||||||
- Also adds the command to the Source Control items context menu to stash an individual or group of files, works with multi-select too!
|
|
||||||
|
- Adds a `Apply Stashed Changes` command (`gitlens.stashApply`) to chose a stash entry to apply to the working tree from a quick pick menu
|
||||||
## Insiders
|
|
||||||
|
- Adds a `Stash Changes` command (`gitlens.stashSave`) to save any working tree changes to the stash — can optionally provide a stash message
|
||||||
Add [`"gitlens.insiders": true`](#general-extension-settings) to your settings to join the insiders channel and get early access to upcoming features. Be aware that because this provides early access expect there to be issues.
|
- Also adds the command to the Source Control items context menu to stash an individual or group of files, works with multi-select too!
|
||||||
|
|
||||||
## Extension Settings
|
## Insiders
|
||||||
|
|
||||||
GitLens is highly customizable and provides many configuration settings to allow the personalization of almost all features
|
Add [`"gitlens.insiders": true`](#general-extension-settings) to your settings to join the insiders channel and get early access to upcoming features. Be aware that because this provides early access expect there to be issues.
|
||||||
|
|
||||||
### General Settings
|
## Extension Settings
|
||||||
|
|
||||||
|Name | Description
|
GitLens is highly customizable and provides many configuration settings to allow the personalization of almost all features
|
||||||
|-----|------------
|
|
||||||
|`gitlens.defaultDateFormat`|Specifies how all absolute dates will be formatted by default\nSee https://momentjs.com/docs/#/displaying/format/ for valid formats
|
### General Settings
|
||||||
|`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
|
|Name | Description
|
||||||
|
|-----|------------
|
||||||
### Blame Settings
|
|`gitlens.defaultDateFormat`|Specifies how all absolute dates will be formatted by default<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
|
||||||
|
|`gitlens.insiders`|Opts into the insiders channel -- provides access to upcoming features
|
||||||
|Name | Description
|
|`gitlens.outputLevel`|Specifies how much (if any) output will be sent to the GitLens output channel
|
||||||
|-----|------------
|
|
||||||
|`gitlens.blame.ignoreWhitespace`|Specifies whether or not to ignore whitespace when comparing revisions during blame operations
|
### Blame Settings
|
||||||
|
|
||||||
#### File Blame Annotation Settings
|
|Name | Description
|
||||||
|
|-----|------------
|
||||||
|Name | Description
|
|`gitlens.blame.ignoreWhitespace`|Specifies whether or not to ignore whitespace when comparing revisions during blame operations
|
||||||
|-----|------------
|
|
||||||
|`gitlens.blame.file.annotationType`|Specifies the type of blame annotations that will be shown for the current file<br />`gutter` - adds an annotation to the beginning of each line<br />`hover` - shows annotations when hovering over each line
|
#### File Blame Annotation Settings
|
||||||
|`gitlens.blame.file.lineHighlight.enabled`|Specifies whether or not to highlight lines associated with the current line
|
|
||||||
|`gitlens.blame.file.lineHighlight.locations`|Specifies where the associated line highlights 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)
|
|Name | Description
|
||||||
|`gitlens.annotations.file.gutter.format`|Specifies the format of the gutter 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.file.gutter.dateFormat`)<br />`${authorAgo}` - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|
|-----|------------
|
||||||
|`gitlens.annotations.file.gutter.dateFormat`|Specifies how to format absolute dates (using the `${date}` token) in gutter blame annotations<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
|
|`gitlens.blame.file.annotationType`|Specifies the type of blame annotations that will be shown for the current file<br />`gutter` - adds an annotation to the beginning of each line<br />`hover` - shows annotations when hovering over each line
|
||||||
|`gitlens.annotations.file.gutter.compact`|Specifies whether or not to compact (deduplicate) matching adjacent gutter blame annotations
|
|`gitlens.blame.file.lineHighlight.enabled`|Specifies whether or not to highlight lines associated with the current line
|
||||||
|`gitlens.annotations.file.gutter.heatmap.enabled`|Specifies whether or not to provide a heatmap indicator in the gutter blame annotations
|
|`gitlens.blame.file.lineHighlight.locations`|Specifies where the associated line highlights 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.gutter.heatmap.location`|Specifies where the heatmap indicators will be shown in the gutter blame annotations<br />`left` - adds a heatmap indicator on the left edge of the gutter blame annotations<br />`right` - adds a heatmap indicator on the right edge of the gutter blame annotations
|
|`gitlens.annotations.file.gutter.format`|Specifies the format of the gutter 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.file.gutter.dateFormat`)<br />`${authorAgo}` - commit author, relative commit date<br />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|
||||||
|`gitlens.annotations.file.gutter.hover.details`|Specifies whether or not to provide a commit details hover annotation over the gutter blame annotations
|
|`gitlens.annotations.file.gutter.dateFormat`|Specifies how to format absolute dates (using the `${date}` token) in gutter blame annotations<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
|
||||||
|`gitlens.annotations.file.gutter.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
|
|`gitlens.annotations.file.gutter.compact`|Specifies whether or not to compact (deduplicate) matching adjacent gutter blame annotations
|
||||||
|`gitlens.annotations.file.hover.heatmap.enabled`|Specifies whether or not to provide heatmap indicators on the left edge of each line
|
|`gitlens.annotations.file.gutter.heatmap.enabled`|Specifies whether or not to provide a heatmap indicator in the gutter blame annotations
|
||||||
|`gitlens.annotations.file.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
|
|`gitlens.annotations.file.gutter.heatmap.location`|Specifies where the heatmap indicators will be shown in the gutter blame annotations<br />`left` - adds a heatmap indicator on the left edge of the gutter blame annotations<br />`right` - adds a heatmap indicator on the right edge of the gutter blame annotations
|
||||||
|
|`gitlens.annotations.file.gutter.hover.details`|Specifies whether or not to provide a commit details hover annotation over the gutter blame annotations
|
||||||
#### Line Blame Annotation Settings
|
|`gitlens.annotations.file.gutter.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
|
||||||
|
|`gitlens.annotations.file.hover.heatmap.enabled`|Specifies whether or not to provide heatmap indicators on the left edge of each line
|
||||||
|Name | Description
|
|`gitlens.annotations.file.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole 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
|
#### Line Blame Annotation Settings
|
||||||
|`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
|
|Name | Description
|
||||||
|`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.hover.details`|Specifies whether or not to provide a commit details hover annotation over the trailing blame annotations
|
|`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.annotations.line.trailing.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation over the trailing blame annotations
|
|`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.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole 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.hover.details`|Specifies whether or not to provide a commit details hover annotation for the current line
|
|`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.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation for the current line
|
|`gitlens.annotations.line.trailing.hover.details`|Specifies whether or not to provide a commit details hover annotation over the trailing blame annotations
|
||||||
|
|`gitlens.annotations.line.trailing.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation over the trailing blame annotations
|
||||||
### File Recent Changes Annotation Settings
|
|`gitlens.annotations.line.trailing.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line
|
||||||
|
|`gitlens.annotations.line.hover.details`|Specifies whether or not to provide a commit details hover annotation for the current line
|
||||||
|Name | Description
|
|`gitlens.annotations.line.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation for the current line
|
||||||
|-----|------------
|
|
||||||
|`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)
|
### File Recent Changes Annotation Settings
|
||||||
|`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
|
|Name | Description
|
||||||
|
|-----|------------
|
||||||
### Code Lens Settings
|
|`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.details`|Specifies whether or not to provide a commit details hover annotation
|
||||||
|Name | Description
|
|`gitlens.annotations.file.recentChanges.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation
|
||||||
|-----|------------
|
|
||||||
|`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
|
### Code Lens Settings
|
||||||
|`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
|
|Name | Description
|
||||||
|`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.command`|Specifies the command to be executed when the `authors` 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.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.locations`|Specifies where Git code lens will be shown in the document<br />`document` - adds code lens at the top of the document<br />`containers` - adds code lens at the start of container-like symbols (modules, classes, interfaces, etc)<br />`blocks` - adds code lens at the start of block-like symbols (functions, methods, properties, etc) lines<br />`custom` - adds code lens at the start of symbols contained in `gitlens.codeLens.locationCustomSymbols`
|
|`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.customLocationSymbols`|Specifies the set of document symbols where Git code lens will be shown in the document
|
|`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.perLanguageLocations`|Specifies where Git code lens will be shown in the document for the specified languages
|
|`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.command`|Specifies the command to be executed when the `authors` 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 Custom View Settings
|
|`gitlens.codeLens.locations`|Specifies where Git code lens will be shown in the document<br />`document` - adds code lens at the top of the document<br />`containers` - adds code lens at the start of container-like symbols (modules, classes, interfaces, etc)<br />`blocks` - adds code lens at the start of block-like symbols (functions, methods, properties, etc) lines<br />`custom` - adds code lens at the start of symbols contained in `gitlens.codeLens.locationCustomSymbols`
|
||||||
|
|`gitlens.codeLens.customLocationSymbols`|Specifies the set of document symbols where Git code lens will be shown in the document
|
||||||
|Name | Description
|
|`gitlens.codeLens.perLanguageLocations`|Specifies where Git code lens will be shown in the document for the specified languages
|
||||||
|-----|------------
|
|
||||||
|`gitlens.gitExplorer.enabled`|Specifies whether or not to show the `GitLens` custom view"
|
### GitLens Custom View Settings
|
||||||
|`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"
|
|Name | Description
|
||||||
|`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.enabled`|Specifies whether or not to show the `GitLens` custom view"
|
||||||
|`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.view`|Specifies the starting view (mode) of the `GitLens` custom view<br /> `auto` - shows the last selected view, defaults to `repository`<br />`history` - shows the commit history of the active file<br />`repository` - shows a repository explorer"
|
||||||
|`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
|
|`gitlens.gitExplorer.files.layout`|Specifies how the `GitLens` custom view will display files<br /> `auto` - automatically switches between displaying files as a `tree` or `list` based on the `gitlens.gitExplorer.files.threshold` setting and the number of files at each nesting level<br /> `list` - displays files as a list<br /> `tree` - displays files as a tree
|
||||||
|
|`gitlens.gitExplorer.files.compact`|Specifies whether or not to compact (flatten) unnecessary file nesting in the `GitLens` custom view<br />Only applies when displaying files as a `tree` or `auto`
|
||||||
### Custom Remotes Settings
|
|`gitlens.gitExplorer.files.threshold`|Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the `GitLens` custom view<br />Only applies when displaying files as `auto`
|
||||||
|
|`gitlens.gitExplorer.includeWorkingTree`|Specifies whether or not to include working tree files inside the `Repository Status` node of the `GitLens` custom view
|
||||||
|Name | Description
|
|`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.remotes`|Specifies any custom domains for remote (code-hosting) services<br />Example: ```"gitlens.remotes": [{ "domain": "git.corporate-url.com", "type": "GitHub" }]```
|
|`gitlens.gitExplorer.commitFileFormat`|Specifies the format of a committed file in the `GitLens` custom view<br />Available tokens<br /> ${directory} - directory name<br /> ${file} - file name<br /> ${filePath} - formatted file name and path<br /> ${path} - full 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
|
||||||
### Status Bar Settings
|
|`gitlens.gitExplorer.stashFileFormat`|Specifies the format of a stashed file in the `GitLens` custom view<br />Available tokens<br /> ${directory} - directory name<br /> ${file} - file name<br /> ${filePath} - formatted file name and path<br /> ${path} - full file path
|
||||||
|
|`gitlens.gitExplorer.statusFileFormat`|Specifies the format of the status of a working or committed file in the `GitLens` custom view<br />Available tokens<br /> ${directory} - directory name<br /> ${file} - file name<br /> ${filePath} - formatted file name and path<br /> ${path} - full file path<br />${working} - optional indicator if the file is uncommitted
|
||||||
|Name | Description
|
|
||||||
|-----|------------
|
### Custom Remotes Settings
|
||||||
|`gitlens.statusBar.enabled`|Specifies whether or not to provide blame information on the status bar
|
|
||||||
|`gitlens.statusBar.alignment`|Specifies the blame alignment in the status bar<br />`left` - align to the left, `right` - align to the right
|
|Name | Description
|
||||||
|`gitlens.statusBar.command`|Specifies the command to be executed when the blame status bar item 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 line commit with the previous<br />`gitlens.diffWithWorking` - compares the current line commit with the working tree<br />`gitlens.toggleCodeLens` - toggles Git code lens<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.statusBar.format`|Specifies the format of the blame information on the status bar<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 />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|
|`gitlens.remotes`|Specifies any custom domains for remote (code-hosting) services<br />Example: ```"gitlens.remotes": [{ "domain": "git.corporate-url.com", "type": "GitHub" }]```
|
||||||
|`gitlens.statusBar.dateFormat`|Specifies the date format of absolute dates shown in the blame information on the status bar<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
|
|
||||||
|
### Status Bar Settings
|
||||||
### Strings Settings
|
|
||||||
|
|Name | Description
|
||||||
|Name | Description
|
|-----|------------
|
||||||
|-----|------------
|
|`gitlens.statusBar.enabled`|Specifies whether or not to provide blame information on the status bar
|
||||||
|`gitlens.strings.codeLens.unsavedChanges.recentChangeAndAuthors`|Specifies the string to be shown in place of both the `recent change` and `authors` code lens when there are unsaved changes
|
|`gitlens.statusBar.alignment`|Specifies the blame alignment in the status bar<br />`left` - align to the left, `right` - align to the right
|
||||||
|`gitlens.strings.codeLens.unsavedChanges.recentChangeOnly`|Specifies the string to be shown in place of the `recent change` code lens when there are unsaved changes
|
|`gitlens.statusBar.command`|Specifies the command to be executed when the blame status bar item 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 line commit with the previous<br />`gitlens.diffWithWorking` - compares the current line commit with the working tree<br />`gitlens.toggleCodeLens` - toggles Git code lens<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.strings.codeLens.unsavedChanges.authorsOnly`|Specifies the string to be shown in place of the `authors` code lens when there are unsaved changes
|
|`gitlens.statusBar.format`|Specifies the format of the blame information on the status bar<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 />See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting
|
||||||
|
|`gitlens.statusBar.dateFormat`|Specifies the date format of absolute dates shown in the blame information on the status bar<br />See https://momentjs.com/docs/#/displaying/format/ for valid formats
|
||||||
### Theme Settings
|
|
||||||
|
### Strings Settings
|
||||||
|Name | Description
|
|
||||||
|-----|------------
|
|Name | Description
|
||||||
|`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.strings.codeLens.unsavedChanges.recentChangeAndAuthors`|Specifies the string to be shown in place of both the `recent change` and `authors` code lens when there are unsaved changes
|
||||||
|`gitlens.theme.annotations.file.gutter.light.backgroundColor`|Specifies the light theme background color of the gutter blame annotations
|
|`gitlens.strings.codeLens.unsavedChanges.recentChangeOnly`|Specifies the string to be shown in place of the `recent change` code lens when there are unsaved changes
|
||||||
|`gitlens.theme.annotations.file.gutter.dark.foregroundColor`|Specifies the dark theme foreground color of the gutter blame annotations
|
|`gitlens.strings.codeLens.unsavedChanges.authorsOnly`|Specifies the string to be shown in place of the `authors` code lens when there are unsaved changes
|
||||||
|`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
|
### Theme Settings
|
||||||
|`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.line.trailing.dark.backgroundColor`|Specifies the dark theme background color of the trailing blame annotation
|
|Name | Description
|
||||||
|`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.file.gutter.separateLines`|Specifies whether or not gutter blame annotations will have line separators
|
||||||
|`gitlens.theme.annotations.line.trailing.light.foregroundColor`|Specifies the light theme foreground color of the trailing blame annotation
|
|`gitlens.theme.annotations.file.gutter.dark.backgroundColor`|Specifies the dark theme background color of the gutter blame annotations
|
||||||
|`gitlens.theme.lineHighlight.dark.backgroundColor`|Specifies the dark theme background color of the associated line highlights in blame annotations. Must be a valid css color
|
|`gitlens.theme.annotations.file.gutter.light.backgroundColor`|Specifies the light theme background color of the gutter blame annotations
|
||||||
|`gitlens.theme.lineHighlight.light.backgroundColor`|Specifies the light theme background color of the associated line highlights in blame annotations. Must be a valid css color
|
|`gitlens.theme.annotations.file.gutter.dark.foregroundColor`|Specifies the dark theme foreground color of the gutter blame annotations
|
||||||
|`gitlens.theme.lineHighlight.dark.overviewRulerColor`|Specifies the dark theme overview ruler color of the associated line highlights in blame annotations
|
|`gitlens.theme.annotations.file.gutter.light.foregroundColor`|Specifies the light theme foreground color of the gutter blame annotations
|
||||||
|`gitlens.theme.lineHighlight.light.overviewRulerColor`|Specifies the light theme overview ruler color of the associated line highlights in 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
|
||||||
### Advanced Settings
|
|`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
|
||||||
|Name | Description
|
|`gitlens.theme.annotations.line.trailing.dark.foregroundColor`|Specifies the dark theme foreground color of the trailing blame annotation
|
||||||
|-----|------------
|
|`gitlens.theme.annotations.line.trailing.light.foregroundColor`|Specifies the light theme foreground color of the trailing blame annotation
|
||||||
|`gitlens.advanced.telemetry.enabled`|Specifies whether or not to enable GitLens telemetry (even if enabled still abides by the overall `telemetry.enableTelemetry` setting
|
|`gitlens.theme.lineHighlight.dark.backgroundColor`|Specifies the dark theme background color of the associated line highlights in blame annotations. Must be a valid css color
|
||||||
|`gitlens.advanced.menus`|Specifies which commands will be added to which menus
|
|`gitlens.theme.lineHighlight.light.backgroundColor`|Specifies the light theme background color of the associated line highlights in blame annotations. Must be a valid css color
|
||||||
|`gitlens.advanced.caching.enabled`|Specifies whether git output will be cached
|
|`gitlens.theme.lineHighlight.dark.overviewRulerColor`|Specifies the dark theme overview ruler color of the associated line highlights in blame annotations
|
||||||
|`gitlens.advanced.caching.maxLines`|Specifies the threshold for caching larger documents
|
|`gitlens.theme.lineHighlight.light.overviewRulerColor`|Specifies the light theme overview ruler color of the associated line highlights in blame annotations
|
||||||
|`gitlens.advanced.git`|Specifies the git path to use
|
|
||||||
|`gitlens.advanced.gitignore.enabled`|Specifies whether or not to parse the root .gitignore file for better performance (i.e. avoids blaming excluded files)
|
### Advanced Settings
|
||||||
|`gitlens.advanced.maxQuickHistory`|Specifies the maximum number of QuickPick history entries to show
|
|
||||||
|`gitlens.advanced.quickPick.closeOnFocusOut`|Specifies whether or not to close the QuickPick menu when focus is lost
|
|Name | Description
|
||||||
|
|-----|------------
|
||||||
## Known Issues
|
|`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
|
||||||
- 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`
|
|`gitlens.advanced.caching.enabled`|Specifies whether git output will be cached
|
||||||
|
|`gitlens.advanced.caching.maxLines`|Specifies the threshold for caching larger documents
|
||||||
## Contributors
|
|`gitlens.advanced.git`|Specifies the git path to use
|
||||||
|
|`gitlens.advanced.gitignore.enabled`|Specifies whether or not to parse the root .gitignore file for better performance (i.e. avoids blaming excluded files)
|
||||||
A big thanks to the people that have contributed to this project:
|
|`gitlens.advanced.maxQuickHistory`|Specifies the maximum number of QuickPick history entries to show
|
||||||
|
|`gitlens.advanced.quickPick.closeOnFocusOut`|Specifies whether or not to close the QuickPick menu when focus is lost
|
||||||
- Amanda Cameron ([@AmandaCameron](https://github.com/AmandaCameron)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=AmandaCameron))
|
|
||||||
- Peng Lyu ([@rebornix](https://github.com/rebornix)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=rebornix))
|
## Known Issues
|
||||||
- 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))
|
- 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`
|
||||||
- Zack Schuster ([@zackschuster](https://github.com/zackschuster)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=zackschuster)
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
A big thanks to the people that have contributed to this project:
|
||||||
|
|
||||||
|
- Amanda Cameron ([@AmandaCameron](https://github.com/AmandaCameron)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=AmandaCameron))
|
||||||
|
- Peng Lyu ([@rebornix](https://github.com/rebornix)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=rebornix))
|
||||||
|
- 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)
|
||||||
|
|||||||
4
images/dark/icon-diff.svg
Normal file
4
images/dark/icon-diff.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg width="16" height="22" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#C5C5C5" d="m7.5,10l2,0l0,1l-2,0l0,2l-1,0l0,-2l-2,0l0,-1l2,0l0,-2l1,0l0,2l0,0zm-3,6l5,0l0,-1l-5,0l0,1l0,0zm4.5,-11l3.5,3.5l0,9.5c0,0.55 -0.45,1 -1,1l-9,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l6.5,0l0,0zm2.5,4l-3,-3l-6,0l0,12l9,0l0,-9l0,0zm-1.5,-6l-5.5,0l0,1l5,0l4,4l0,8l1,0l0,-8.5l-4.5,-4.5l0,0z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 437 B |
4
images/light/icon-diff.svg
Normal file
4
images/light/icon-diff.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg width="16" height="22" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#424242" d="m7.5,10l2,0l0,1l-2,0l0,2l-1,0l0,-2l-2,0l0,-1l2,0l0,-2l1,0l0,2l0,0zm-3,6l5,0l0,-1l-5,0l0,1l0,0zm4.5,-11l3.5,3.5l0,9.5c0,0.55 -0.45,1 -1,1l-9,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l6.5,0l0,0zm2.5,4l-3,-3l-6,0l0,12l9,0l0,-9l0,0zm-1.5,-6l-5.5,0l0,1l5,0l4,4l0,8l1,0l0,-8.5l-4.5,-4.5l0,0z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 437 B |
292
package-lock.json
generated
292
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gitlens",
|
"name": "gitlens",
|
||||||
"version": "5.1.1-beta",
|
"version": "5.3.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
"integrity": "sha1-qjuL2ivlErGuCgV7lC6GnDcKVWk=",
|
"integrity": "sha1-qjuL2ivlErGuCgV7lC6GnDcKVWk=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/node": "8.0.28"
|
"@types/node": "8.0.31"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/mocha": {
|
"@types/mocha": {
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "8.0.28",
|
"version": "8.0.31",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.28.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.31.tgz",
|
||||||
"integrity": "sha512-HupkFXEv3O3KSzcr3Ylfajg0kaerBg1DyaZzRBBQfrU3NN1mTBRE7sCveqHwXLS5Yrjvww8qFzkzYQQakG9FuQ==",
|
"integrity": "sha512-R+LdMJHJQwRd/Ca0Nr5KnwbSWHxTD3DWz4ivqoPeNH+YPcuirMWK+Ti9Mx32jOecmPhHOCd+6CefU5e1eVq2Ew==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/tmp": {
|
"@types/tmp": {
|
||||||
@@ -38,19 +38,22 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "4.11.8",
|
"version": "5.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.3.tgz",
|
||||||
"integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
|
"integrity": "sha1-wG9Zh3jETGsWGrr+NGa4GtGBTtI=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"co": "4.6.0",
|
"co": "4.6.0",
|
||||||
|
"fast-deep-equal": "1.0.0",
|
||||||
|
"json-schema-traverse": "0.3.1",
|
||||||
"json-stable-stringify": "1.0.1"
|
"json-stable-stringify": "1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "3.0.0",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
|
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
@@ -249,21 +252,6 @@
|
|||||||
"supports-color": "2.0.0"
|
"supports-color": "2.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-regex": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||||
@@ -385,15 +373,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dateformat": {
|
"dateformat": {
|
||||||
"version": "2.0.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
|
||||||
"integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=",
|
"integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.6.8",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
"integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
@@ -597,6 +585,12 @@
|
|||||||
"time-stamp": "1.1.0"
|
"time-stamp": "1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fast-deep-equal": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"fd-slicer": {
|
"fd-slicer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
|
||||||
@@ -684,7 +678,7 @@
|
|||||||
"graceful-fs": "4.1.11",
|
"graceful-fs": "4.1.11",
|
||||||
"inherits": "2.0.3",
|
"inherits": "2.0.3",
|
||||||
"mkdirp": "0.5.1",
|
"mkdirp": "0.5.1",
|
||||||
"rimraf": "2.6.1"
|
"rimraf": "2.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"generate-function": {
|
"generate-function": {
|
||||||
@@ -1003,7 +997,7 @@
|
|||||||
"oauth-sign": "0.8.2",
|
"oauth-sign": "0.8.2",
|
||||||
"qs": "6.3.2",
|
"qs": "6.3.2",
|
||||||
"stringstream": "0.0.5",
|
"stringstream": "0.0.5",
|
||||||
"tough-cookie": "2.3.2",
|
"tough-cookie": "2.3.3",
|
||||||
"tunnel-agent": "0.4.3",
|
"tunnel-agent": "0.4.3",
|
||||||
"uuid": "3.1.0"
|
"uuid": "3.1.0"
|
||||||
}
|
}
|
||||||
@@ -1086,7 +1080,7 @@
|
|||||||
"array-uniq": "1.0.3",
|
"array-uniq": "1.0.3",
|
||||||
"beeper": "1.1.1",
|
"beeper": "1.1.1",
|
||||||
"chalk": "1.1.3",
|
"chalk": "1.1.3",
|
||||||
"dateformat": "2.0.0",
|
"dateformat": "2.2.0",
|
||||||
"fancy-log": "1.3.0",
|
"fancy-log": "1.3.0",
|
||||||
"gulplog": "1.0.0",
|
"gulplog": "1.0.0",
|
||||||
"has-gulplog": "0.1.0",
|
"has-gulplog": "0.1.0",
|
||||||
@@ -1187,9 +1181,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"har-schema": {
|
"har-schema": {
|
||||||
"version": "1.0.5",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||||
"integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
|
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"har-validator": {
|
"har-validator": {
|
||||||
@@ -1211,14 +1205,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "2.1.1"
|
"ansi-regex": "2.1.1"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"has-flag": {
|
"has-flag": {
|
||||||
@@ -1336,11 +1322,6 @@
|
|||||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"is-fullwidth-code-point": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
|
|
||||||
},
|
|
||||||
"is-glob": {
|
"is-glob": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
|
||||||
@@ -1459,6 +1440,12 @@
|
|||||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
|
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||||
|
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"json-stable-stringify": {
|
"json-stable-stringify": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
|
||||||
@@ -1794,9 +1781,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"version": "3.5.2",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz",
|
||||||
"integrity": "sha512-iH5zl7afRZl1GvD0pnrRlazgc9Z/o34pXWmTFi8xNIMFKXgNL1SoBTDDb9sJfbV/sJV/j8X+0gvwY1QS1He7Nw==",
|
"integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"browser-stdout": "1.3.0",
|
"browser-stdout": "1.3.0",
|
||||||
@@ -1811,6 +1798,17 @@
|
|||||||
"lodash.create": "3.1.1",
|
"lodash.create": "3.1.1",
|
||||||
"mkdirp": "0.5.1",
|
"mkdirp": "0.5.1",
|
||||||
"supports-color": "3.1.2"
|
"supports-color": "3.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "2.6.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
|
||||||
|
"integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"moment": {
|
"moment": {
|
||||||
@@ -1971,9 +1969,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"performance-now": {
|
"performance-now": {
|
||||||
"version": "0.2.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||||
"integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
|
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"pinkie": {
|
"pinkie": {
|
||||||
@@ -2120,57 +2118,147 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"request": {
|
"request": {
|
||||||
"version": "2.81.0",
|
"version": "2.82.0",
|
||||||
"resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
|
"resolved": "https://registry.npmjs.org/request/-/request-2.82.0.tgz",
|
||||||
"integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
|
"integrity": "sha512-/QWqfmyTfQ4OYs6EhB1h2wQsX9ZxbuNePCvCm0Mdz/mxw73mjdg0D4QdIl0TQBFs35CZmMXLjk0iCGK395CUDg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"aws-sign2": "0.6.0",
|
"aws-sign2": "0.7.0",
|
||||||
"aws4": "1.6.0",
|
"aws4": "1.6.0",
|
||||||
"caseless": "0.12.0",
|
"caseless": "0.12.0",
|
||||||
"combined-stream": "1.0.5",
|
"combined-stream": "1.0.5",
|
||||||
"extend": "3.0.1",
|
"extend": "3.0.1",
|
||||||
"forever-agent": "0.6.1",
|
"forever-agent": "0.6.1",
|
||||||
"form-data": "2.1.4",
|
"form-data": "2.3.1",
|
||||||
"har-validator": "4.2.1",
|
"har-validator": "5.0.3",
|
||||||
"hawk": "3.1.3",
|
"hawk": "6.0.2",
|
||||||
"http-signature": "1.1.1",
|
"http-signature": "1.2.0",
|
||||||
"is-typedarray": "1.0.0",
|
"is-typedarray": "1.0.0",
|
||||||
"isstream": "0.1.2",
|
"isstream": "0.1.2",
|
||||||
"json-stringify-safe": "5.0.1",
|
"json-stringify-safe": "5.0.1",
|
||||||
"mime-types": "2.1.17",
|
"mime-types": "2.1.17",
|
||||||
"oauth-sign": "0.8.2",
|
"oauth-sign": "0.8.2",
|
||||||
"performance-now": "0.2.0",
|
"performance-now": "2.1.0",
|
||||||
"qs": "6.4.0",
|
"qs": "6.5.1",
|
||||||
"safe-buffer": "5.1.1",
|
"safe-buffer": "5.1.1",
|
||||||
"stringstream": "0.0.5",
|
"stringstream": "0.0.5",
|
||||||
"tough-cookie": "2.3.2",
|
"tough-cookie": "2.3.3",
|
||||||
"tunnel-agent": "0.6.0",
|
"tunnel-agent": "0.6.0",
|
||||||
"uuid": "3.1.0"
|
"uuid": "3.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"assert-plus": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"aws-sign2": {
|
||||||
|
"version": "0.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||||
|
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"boom": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
|
||||||
|
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"hoek": "4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"caseless": {
|
"caseless": {
|
||||||
"version": "0.12.0",
|
"version": "0.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
|
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"har-validator": {
|
"cryptiles": {
|
||||||
"version": "4.2.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
|
||||||
"integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
|
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "4.11.8",
|
"boom": "5.2.0"
|
||||||
"har-schema": "1.0.5"
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"boom": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"hoek": "4.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"form-data": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz",
|
||||||
|
"integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"asynckit": "0.4.0",
|
||||||
|
"combined-stream": "1.0.5",
|
||||||
|
"mime-types": "2.1.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"har-validator": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
||||||
|
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ajv": "5.2.3",
|
||||||
|
"har-schema": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hawk": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"boom": "4.3.1",
|
||||||
|
"cryptiles": "3.1.2",
|
||||||
|
"hoek": "4.2.0",
|
||||||
|
"sntp": "2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hoek": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"http-signature": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"assert-plus": "1.0.0",
|
||||||
|
"jsprim": "1.4.1",
|
||||||
|
"sshpk": "1.13.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"qs": {
|
"qs": {
|
||||||
"version": "6.4.0",
|
"version": "6.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
|
||||||
"integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
|
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"sntp": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sntp/-/sntp-2.0.2.tgz",
|
||||||
|
"integrity": "sha1-UGQRDwr4X3z9t9a2ekACjOUrSys=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"hoek": "4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"tunnel-agent": {
|
"tunnel-agent": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||||
@@ -2198,9 +2286,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rimraf": {
|
"rimraf": {
|
||||||
"version": "2.6.1",
|
"version": "2.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
|
||||||
"integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
|
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"glob": "7.1.1"
|
"glob": "7.1.1"
|
||||||
@@ -2260,7 +2348,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/spawn-rx/-/spawn-rx-2.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/spawn-rx/-/spawn-rx-2.0.11.tgz",
|
||||||
"integrity": "sha1-ZUUa1lZigB2up1VJgyp4LeAEjb8=",
|
"integrity": "sha1-ZUUa1lZigB2up1VJgyp4LeAEjb8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "2.6.8",
|
"debug": "2.6.9",
|
||||||
"lodash.assign": "4.2.0",
|
"lodash.assign": "4.2.0",
|
||||||
"rxjs": "5.4.3"
|
"rxjs": "5.4.3"
|
||||||
}
|
}
|
||||||
@@ -2334,15 +2422,6 @@
|
|||||||
"integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=",
|
"integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"string-width": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
|
||||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
|
||||||
"requires": {
|
|
||||||
"is-fullwidth-code-point": "2.0.0",
|
|
||||||
"strip-ansi": "4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
@@ -2359,11 +2438,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "4.0.0",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "3.0.0"
|
"ansi-regex": "2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip-bom": {
|
"strip-bom": {
|
||||||
@@ -2466,9 +2546,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tough-cookie": {
|
"tough-cookie": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz",
|
||||||
"integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=",
|
"integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"punycode": "1.4.1"
|
"punycode": "1.4.1"
|
||||||
@@ -2495,13 +2575,13 @@
|
|||||||
"resolve": "1.4.0",
|
"resolve": "1.4.0",
|
||||||
"semver": "5.4.1",
|
"semver": "5.4.1",
|
||||||
"tslib": "1.7.1",
|
"tslib": "1.7.1",
|
||||||
"tsutils": "2.8.2"
|
"tsutils": "2.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tsutils": {
|
"tsutils": {
|
||||||
"version": "2.8.2",
|
"version": "2.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.9.0.tgz",
|
||||||
"integrity": "sha1-LBSGukMSYIRbCsb5Aq/Z1wio6mo=",
|
"integrity": "sha1-fhU3tVa6tocvp+ZIXf9FsHbVUz0=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "1.7.1"
|
"tslib": "1.7.1"
|
||||||
@@ -2521,9 +2601,9 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.3.tgz",
|
||||||
"integrity": "sha1-A4qV99m7tCCxvzW6MdTFwd0//jQ=",
|
"integrity": "sha512-ptLSQs2S4QuS6/OD1eAKG+S5G8QQtrU5RT32JULdZQtM1L3WTi34Wsu48Yndzi8xsObRAB9RPt/KhA9wlpEF6w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"unique-stream": {
|
"unique-stream": {
|
||||||
@@ -2714,8 +2794,8 @@
|
|||||||
"gulp-symdest": "1.1.0",
|
"gulp-symdest": "1.1.0",
|
||||||
"gulp-untar": "0.0.6",
|
"gulp-untar": "0.0.6",
|
||||||
"gulp-vinyl-zip": "1.4.0",
|
"gulp-vinyl-zip": "1.4.0",
|
||||||
"mocha": "3.5.2",
|
"mocha": "3.5.3",
|
||||||
"request": "2.81.0",
|
"request": "2.82.0",
|
||||||
"semver": "5.4.1",
|
"semver": "5.4.1",
|
||||||
"source-map-support": "0.4.18",
|
"source-map-support": "0.4.18",
|
||||||
"url-parse": "1.1.9",
|
"url-parse": "1.1.9",
|
||||||
|
|||||||
73
package.json
73
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gitlens",
|
"name": "gitlens",
|
||||||
"version": "5.1.1-beta",
|
"version": "5.3.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Eric Amodio",
|
"name": "Eric Amodio",
|
||||||
"email": "eamodio@gmail.com"
|
"email": "eamodio@gmail.com"
|
||||||
@@ -303,7 +303,7 @@
|
|||||||
"minItems": 1,
|
"minItems": 1,
|
||||||
"maxItems": 4,
|
"maxItems": 4,
|
||||||
"uniqueItems": true,
|
"uniqueItems": true,
|
||||||
"description": "Specifies where Git code lens will be shown in the document\n `document` - adds code lens at the top of the document\n `containers` - adds code lens at the start of container-like symbols (modules, classes, interfaces, etc)\n `blocks` - adds code lens at the start of block-like symbols (functions, methods, properties, etc) lines\n `custom` - adds code lens at the start of symbols contained in `gitlens.codeLens.locationCustomSymbols`"
|
"description": "Specifies where Git code lens will be shown in the document\n `document` - adds code lens at the top of the document\n `containers` - adds code lens at the start of container-like symbols (modules, classes, interfaces, etc)\n `blocks` - adds code lens at the start of block-like symbols (functions, methods, properties, etc) lines\n `custom` - adds code lens at the start of symbols contained in `gitlens.codeLens.locationCustomSymbols`"
|
||||||
},
|
},
|
||||||
"gitlens.codeLens.customLocationSymbols": {
|
"gitlens.codeLens.customLocationSymbols": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@@ -388,7 +388,7 @@
|
|||||||
"minItems": 1,
|
"minItems": 1,
|
||||||
"maxItems": 4,
|
"maxItems": 4,
|
||||||
"uniqueItems": true,
|
"uniqueItems": true,
|
||||||
"description": "Specifies where Git code lens will be shown in the document for the specified language\n `document` - adds code lens at the top of the document\n `containers` - adds code lens at the start of container-like symbols (modules, classes, interfaces, etc)\n `blocks` - adds code lens at the start of block-like symbols (functions, methods, properties, etc) lines\n `custom` - adds code lens at the start of symbols contained in `customSymbols`"
|
"description": "Specifies where Git code lens will be shown in the document for the specified language\n `document` - adds code lens at the top of the document\n `containers` - adds code lens at the start of container-like symbols (modules, classes, interfaces, etc)\n `blocks` - adds code lens at the start of block-like symbols (functions, methods, properties, etc) lines\n `custom` - adds code lens at the start of symbols contained in `customSymbols`"
|
||||||
},
|
},
|
||||||
"customSymbols": {
|
"customSymbols": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@@ -421,13 +421,38 @@
|
|||||||
"gitlens.gitExplorer.commitFileFormat": {
|
"gitlens.gitExplorer.commitFileFormat": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "${filePath}",
|
"default": "${filePath}",
|
||||||
"description": "Specifies the format of a committed file in the `GitLens` custom view\nAvailable tokens\n ${file} - file name\n ${filePath} - file name and path\n ${path} - file path"
|
"description": "Specifies the format of a committed file in the `GitLens` custom view\nAvailable tokens\n ${directory} - directory name\n ${file} - file name\n ${filePath} - formatted file name and path\n ${path} - full file path"
|
||||||
},
|
},
|
||||||
"gitlens.gitExplorer.enabled": {
|
"gitlens.gitExplorer.enabled": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true,
|
"default": true,
|
||||||
"description": "Specifies whether or not to show the `GitLens` custom view"
|
"description": "Specifies whether or not to show the `GitLens` custom view"
|
||||||
},
|
},
|
||||||
|
"gitlens.gitExplorer.files.layout": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "auto",
|
||||||
|
"enum": [
|
||||||
|
"auto",
|
||||||
|
"list",
|
||||||
|
"tree"
|
||||||
|
],
|
||||||
|
"description": "Specifies how the `GitLens` custom view will display files\n `auto` - automatically switches between displaying files as a `tree` or `list` based on the `gitlens.gitExplorer.files.threshold` setting and the number of files at each nesting level\n `list` - displays files as a list\n `tree` - displays files as a tree"
|
||||||
|
},
|
||||||
|
"gitlens.gitExplorer.files.compact": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Specifies whether or not to compact (flatten) unnecessary file nesting in the `GitLens` custom view\nOnly applies when displaying files as a `tree` or `auto`"
|
||||||
|
},
|
||||||
|
"gitlens.gitExplorer.files.threshold": {
|
||||||
|
"type": "number",
|
||||||
|
"default": 5,
|
||||||
|
"description": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the `GitLens` custom view\nOnly applies when displaying files as `auto`"
|
||||||
|
},
|
||||||
|
"gitlens.gitExplorer.includeWorkingTree": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Specifies whether or not to include working tree files inside the `Repository Status` node of the `GitLens` custom view"
|
||||||
|
},
|
||||||
"gitlens.gitExplorer.showTrackingBranch": {
|
"gitlens.gitExplorer.showTrackingBranch": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true,
|
"default": true,
|
||||||
@@ -441,16 +466,22 @@
|
|||||||
"gitlens.gitExplorer.stashFileFormat": {
|
"gitlens.gitExplorer.stashFileFormat": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "${filePath}",
|
"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"
|
"description": "Specifies the format of a stashed file in the `GitLens` custom view\nAvailable tokens\n ${directory} - directory name\n ${file} - file name\n ${filePath} - formatted file name and path\n ${path} - full file path"
|
||||||
|
},
|
||||||
|
"gitlens.gitExplorer.statusFileFormat": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "${working}${filePath}",
|
||||||
|
"description": "Specifies the format of the status of a working or committed file in the `GitLens` custom view\nAvailable tokens\n ${directory} - directory name\n ${file} - file name\n ${filePath} - formatted file name and path\n ${path} - full file path\n ${working} - optional indicator if the file is uncommitted"
|
||||||
},
|
},
|
||||||
"gitlens.gitExplorer.view": {
|
"gitlens.gitExplorer.view": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "repository",
|
"default": "auto",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
"auto",
|
||||||
"history",
|
"history",
|
||||||
"repository"
|
"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"
|
"description": "Specifies the starting view (mode) of the `GitLens` custom view\n `auto` - shows the last selected view, defaults to `repository`\n `history` - shows the commit history of the active file\n `repository` - shows a repository explorer"
|
||||||
},
|
},
|
||||||
"gitlens.remotes": {
|
"gitlens.remotes": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@@ -1037,6 +1068,11 @@
|
|||||||
"light": "images/light/icon-add.svg"
|
"light": "images/light/icon-add.svg"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.externalDiff",
|
||||||
|
"title": "Open Changes (with difftool)",
|
||||||
|
"category": "GitLens"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "gitlens.resetSuppressedWarnings",
|
"command": "gitlens.resetSuppressedWarnings",
|
||||||
"title": "Reset Suppressed Warnings",
|
"title": "Reset Suppressed Warnings",
|
||||||
@@ -1489,17 +1525,22 @@
|
|||||||
{
|
{
|
||||||
"command": "gitlens.openChangedFiles",
|
"command": "gitlens.openChangedFiles",
|
||||||
"when": "gitlens:enabled",
|
"when": "gitlens:enabled",
|
||||||
"group": "1_gitlens@1"
|
"group": "2_gitlens@1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "gitlens.closeUnchangedFiles",
|
"command": "gitlens.closeUnchangedFiles",
|
||||||
"when": "gitlens:enabled",
|
"when": "gitlens:enabled",
|
||||||
"group": "1_gitlens@2"
|
"group": "2_gitlens@2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.externalDiff",
|
||||||
|
"when": "gitlens:enabled",
|
||||||
|
"group": "2_gitlens@3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "gitlens.stashSave",
|
"command": "gitlens.stashSave",
|
||||||
"when": "gitlens:enabled",
|
"when": "gitlens:enabled",
|
||||||
"group": "2_gitlens@1"
|
"group": "3_gitlens@1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"scm/resourceState/context": [
|
"scm/resourceState/context": [
|
||||||
@@ -1508,6 +1549,11 @@
|
|||||||
"when": "gitlens:enabled && gitlens:hasRemotes",
|
"when": "gitlens:enabled && gitlens:hasRemotes",
|
||||||
"group": "navigation"
|
"group": "navigation"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "gitlens.externalDiff",
|
||||||
|
"when": "gitlens:enabled",
|
||||||
|
"group": "navigation"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "gitlens.diffWithRevision",
|
"command": "gitlens.diffWithRevision",
|
||||||
"when": "gitlens:enabled",
|
"when": "gitlens:enabled",
|
||||||
@@ -1921,18 +1967,17 @@
|
|||||||
"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",
|
||||||
"string-width": "2.1.1",
|
|
||||||
"tmp": "0.0.33"
|
"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.43",
|
"@types/mocha": "2.2.43",
|
||||||
"@types/node": "8.0.28",
|
"@types/node": "8.0.31",
|
||||||
"@types/tmp": "0.0.33",
|
"@types/tmp": "0.0.33",
|
||||||
"mocha": "3.5.2",
|
"mocha": "3.5.3",
|
||||||
"tslint": "5.7.0",
|
"tslint": "5.7.0",
|
||||||
"typescript": "2.5.2",
|
"typescript": "2.5.3",
|
||||||
"vscode": "1.1.5"
|
"vscode": "1.1.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Dates, Strings } from '../system';
|
import { Dates, Objects, Strings } from '../system';
|
||||||
import { DecorationInstanceRenderOptions, DecorationOptions, MarkdownString, ThemableDecorationRenderOptions } from 'vscode';
|
import { DecorationInstanceRenderOptions, DecorationOptions, MarkdownString, ThemableDecorationRenderOptions } from 'vscode';
|
||||||
import { DiffWithCommand, OpenCommitInRemoteCommand, ShowQuickCommitDetailsCommand } from '../commands';
|
import { DiffWithCommand, OpenCommitInRemoteCommand, ShowQuickCommitDetailsCommand } from '../commands';
|
||||||
import { IThemeConfig, themeDefaults } from '../configuration';
|
import { IThemeConfig, themeDefaults } from '../configuration';
|
||||||
@@ -109,14 +109,14 @@ export class Annotations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gutter(commit: GitCommit, format: string, dateFormatOrFormatOptions: string | null | ICommitFormatOptions, renderOptions: IRenderOptions): DecorationOptions {
|
static gutter(commit: GitCommit, format: string, dateFormatOrFormatOptions: string | null | ICommitFormatOptions, renderOptions: IRenderOptions): DecorationOptions {
|
||||||
const content = Strings.pad(CommitFormatter.fromTemplate(format, commit, dateFormatOrFormatOptions), 1, 1);
|
const message = CommitFormatter.fromTemplate(format, commit, dateFormatOrFormatOptions);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
renderOptions: {
|
renderOptions: {
|
||||||
before: {
|
before: {
|
||||||
...renderOptions.before,
|
...renderOptions.before,
|
||||||
...{
|
...{
|
||||||
contentText: content
|
contentText: Strings.pad(message.replace(/ /g, GlyphChars.Space), 1, 1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
@@ -133,9 +133,23 @@ export class Annotations {
|
|||||||
} as DecorationOptions;
|
} as DecorationOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gutterRenderOptions(cfgTheme: IThemeConfig, heatmap: IHeatmapConfig): IRenderOptions {
|
static gutterRenderOptions(cfgTheme: IThemeConfig, heatmap: IHeatmapConfig, options: ICommitFormatOptions): IRenderOptions {
|
||||||
const cfgFileTheme = cfgTheme.annotations.file.gutter;
|
const cfgFileTheme = cfgTheme.annotations.file.gutter;
|
||||||
|
|
||||||
|
// Try to get the width of the string, if there is a cap
|
||||||
|
let width = 4; // Start with a padding
|
||||||
|
for (const token of Objects.values(options.tokenOptions!)) {
|
||||||
|
if (token === undefined) continue;
|
||||||
|
|
||||||
|
// If any token is uncapped, kick out and set no max
|
||||||
|
if (token.truncateTo == null) {
|
||||||
|
width = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
width += token.truncateTo;
|
||||||
|
}
|
||||||
|
|
||||||
let borderStyle = undefined;
|
let borderStyle = undefined;
|
||||||
let borderWidth = undefined;
|
let borderWidth = undefined;
|
||||||
if (heatmap.enabled) {
|
if (heatmap.enabled) {
|
||||||
@@ -152,7 +166,8 @@ export class Annotations {
|
|||||||
borderStyle: borderStyle,
|
borderStyle: borderStyle,
|
||||||
borderWidth: borderWidth,
|
borderWidth: borderWidth,
|
||||||
height: '100%',
|
height: '100%',
|
||||||
margin: '0 26px -1px 0'
|
margin: '0 26px -1px 0',
|
||||||
|
width: (width > 4) ? `${width}ch` : undefined
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
backgroundColor: cfgFileTheme.dark.backgroundColor || undefined,
|
backgroundColor: cfgFileTheme.dark.backgroundColor || undefined,
|
||||||
@@ -195,10 +210,11 @@ export class Annotations {
|
|||||||
truncateMessageAtNewLine: true,
|
truncateMessageAtNewLine: true,
|
||||||
dateFormat: dateFormat
|
dateFormat: dateFormat
|
||||||
} as ICommitFormatOptions);
|
} as ICommitFormatOptions);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
renderOptions: {
|
renderOptions: {
|
||||||
after: {
|
after: {
|
||||||
contentText: Strings.pad(message, 1, 1)
|
contentText: Strings.pad(message.replace(/ /g, GlyphChars.Space), 1, 1)
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
after: {
|
after: {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
|
|||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const offset = this.uri.offset;
|
const offset = this.uri.offset;
|
||||||
const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap);
|
const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap, options);
|
||||||
const separateLines = this._config.theme.annotations.file.gutter.separateLines;
|
const separateLines = this._config.theme.annotations.file.gutter.separateLines;
|
||||||
|
|
||||||
const decorations: DecorationOptions[] = [];
|
const decorations: DecorationOptions[] = [];
|
||||||
@@ -58,7 +58,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
|
|||||||
...gutter.renderOptions,
|
...gutter.renderOptions,
|
||||||
before: {
|
before: {
|
||||||
...gutter.renderOptions!.before,
|
...gutter.renderOptions!.before,
|
||||||
contentText: GlyphChars.Space.repeat(Strings.getWidth(gutter.renderOptions!.before!.contentText!))
|
contentText: GlyphChars.Space.repeat(Strings.width(gutter.renderOptions!.before!.contentText!))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export * from './commands/diffWithNext';
|
|||||||
export * from './commands/diffWithPrevious';
|
export * from './commands/diffWithPrevious';
|
||||||
export * from './commands/diffWithRevision';
|
export * from './commands/diffWithRevision';
|
||||||
export * from './commands/diffWithWorking';
|
export * from './commands/diffWithWorking';
|
||||||
|
export * from './commands/externalDiff';
|
||||||
export * from './commands/openChangedFiles';
|
export * from './commands/openChangedFiles';
|
||||||
export * from './commands/openBranchesInRemote';
|
export * from './commands/openBranchesInRemote';
|
||||||
export * from './commands/openBranchInRemote';
|
export * from './commands/openBranchInRemote';
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export type Commands =
|
|||||||
'gitlens.diffWithRevision' |
|
'gitlens.diffWithRevision' |
|
||||||
'gitlens.diffWithWorking' |
|
'gitlens.diffWithWorking' |
|
||||||
'gitlens.diffLineWithWorking' |
|
'gitlens.diffLineWithWorking' |
|
||||||
|
'gitlens.externalDiff' |
|
||||||
'gitlens.openChangedFiles' |
|
'gitlens.openChangedFiles' |
|
||||||
'gitlens.openBranchesInRemote' |
|
'gitlens.openBranchesInRemote' |
|
||||||
'gitlens.openBranchInRemote' |
|
'gitlens.openBranchInRemote' |
|
||||||
@@ -61,6 +62,7 @@ export const Commands = {
|
|||||||
DiffWithRevision: 'gitlens.diffWithRevision' 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,
|
||||||
|
ExternalDiff: 'gitlens.externalDiff' as Commands,
|
||||||
OpenChangedFiles: 'gitlens.openChangedFiles' as Commands,
|
OpenChangedFiles: 'gitlens.openChangedFiles' as Commands,
|
||||||
OpenBranchesInRemote: 'gitlens.openBranchesInRemote' as Commands,
|
OpenBranchesInRemote: 'gitlens.openBranchesInRemote' as Commands,
|
||||||
OpenBranchInRemote: 'gitlens.openBranchInRemote' as Commands,
|
OpenBranchInRemote: 'gitlens.openBranchInRemote' as Commands,
|
||||||
|
|||||||
115
src/commands/externalDiff.ts
Normal file
115
src/commands/externalDiff.ts
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
'use strict';
|
||||||
|
import { commands, SourceControlResourceState, Uri, window } from 'vscode';
|
||||||
|
import { Command, Commands } from './common';
|
||||||
|
import { BuiltInCommands } from '../constants';
|
||||||
|
import { CommandContext } from '../commands';
|
||||||
|
import { GitService } from '../gitService';
|
||||||
|
import { Logger } from '../logger';
|
||||||
|
import { Messages } from '../messages';
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
INDEX_MODIFIED,
|
||||||
|
INDEX_ADDED,
|
||||||
|
INDEX_DELETED,
|
||||||
|
INDEX_RENAMED,
|
||||||
|
INDEX_COPIED,
|
||||||
|
|
||||||
|
MODIFIED,
|
||||||
|
DELETED,
|
||||||
|
UNTRACKED,
|
||||||
|
IGNORED,
|
||||||
|
|
||||||
|
ADDED_BY_US,
|
||||||
|
ADDED_BY_THEM,
|
||||||
|
DELETED_BY_US,
|
||||||
|
DELETED_BY_THEM,
|
||||||
|
BOTH_ADDED,
|
||||||
|
BOTH_DELETED,
|
||||||
|
BOTH_MODIFIED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ResourceGroupType {
|
||||||
|
Merge,
|
||||||
|
Index,
|
||||||
|
WorkingTree
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Resource extends SourceControlResourceState {
|
||||||
|
readonly resourceGroupType: ResourceGroupType;
|
||||||
|
readonly type: Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExternalDiffFile {
|
||||||
|
constructor(public uri: Uri, public staged: boolean) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExternalDiffCommandArgs {
|
||||||
|
files?: ExternalDiffFile[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExternalDiffCommand extends Command {
|
||||||
|
constructor(private git: GitService) {
|
||||||
|
super(Commands.ExternalDiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async preExecute(context: CommandContext, args: ExternalDiffCommandArgs = {}): Promise<any> {
|
||||||
|
if (context.type === 'scm-states') {
|
||||||
|
args = { ...args };
|
||||||
|
args.files = context.scmResourceStates.map<ExternalDiffFile>((_: Resource) => new ExternalDiffFile(_.resourceUri, _.resourceGroupType === ResourceGroupType.Index));
|
||||||
|
|
||||||
|
return this.execute(args);
|
||||||
|
} else if (context.type === 'scm-groups') {
|
||||||
|
const isModified = (status: Status): boolean => status === Status.BOTH_MODIFIED || status === Status.INDEX_MODIFIED || status === Status.MODIFIED;
|
||||||
|
|
||||||
|
args = { ...args };
|
||||||
|
args.files = context.scmResourceGroups[0].resourceStates.filter((_: Resource) => isModified(_.type)).map<ExternalDiffFile>((_: Resource) => new ExternalDiffFile(_.resourceUri, _.resourceGroupType === ResourceGroupType.Index));
|
||||||
|
|
||||||
|
return this.execute(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.execute(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute(args: ExternalDiffCommandArgs = {}) {
|
||||||
|
try {
|
||||||
|
const diffTool = await this.git.getConfig('diff.tool');
|
||||||
|
if (!diffTool) {
|
||||||
|
const result = await window.showWarningMessage(`Unable to open file compare because there is no Git diff tool configured`, 'View Git Docs');
|
||||||
|
if (!result) return undefined;
|
||||||
|
|
||||||
|
return commands.executeCommand(BuiltInCommands.Open, Uri.parse('https://git-scm.com/docs/git-config#git-config-difftool'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const repoPath = await this.git.getRepoPathFromUri(undefined);
|
||||||
|
if (!repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to open changed files`);
|
||||||
|
|
||||||
|
if (!args.files) {
|
||||||
|
const status = await this.git.getStatusForRepo(repoPath);
|
||||||
|
if (status === undefined) return window.showWarningMessage(`Unable to open changed files`);
|
||||||
|
|
||||||
|
args.files = [];
|
||||||
|
|
||||||
|
for (const file of status.files) {
|
||||||
|
if (file.indexStatus === 'M') {
|
||||||
|
args.files.push(new ExternalDiffFile(file.Uri, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.workTreeStatus === 'M') {
|
||||||
|
args.files.push(new ExternalDiffFile(file.Uri, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const file of args.files) {
|
||||||
|
this.git.openDiffTool(repoPath, file.uri, file.staged);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
Logger.error(ex, 'ExternalDiffCommand');
|
||||||
|
return window.showErrorMessage(`Unable to open external diff. See output channel for more details`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ export class ResetSuppressedWarningsCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async execute() {
|
async execute() {
|
||||||
for (const key of Objects.values<string>(SuppressedKeys)) {
|
for (const key of Objects.values(SuppressedKeys)) {
|
||||||
await this.context.globalState.update(key, false);
|
await this.context.globalState.update(key, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,16 @@ export const CustomRemoteType = {
|
|||||||
GitLab: 'GitLab' as CustomRemoteType
|
GitLab: 'GitLab' as CustomRemoteType
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GitExplorerFilesLayout =
|
||||||
|
'auto' |
|
||||||
|
'list' |
|
||||||
|
'tree';
|
||||||
|
export const GitExplorerFilesLayout = {
|
||||||
|
Auto: 'auto' as GitExplorerFilesLayout,
|
||||||
|
List: 'list' as GitExplorerFilesLayout,
|
||||||
|
Tree: 'tree' as GitExplorerFilesLayout
|
||||||
|
};
|
||||||
|
|
||||||
export type StatusBarCommand =
|
export type StatusBarCommand =
|
||||||
'gitlens.toggleFileBlame' |
|
'gitlens.toggleFileBlame' |
|
||||||
'gitlens.showBlameHistory' |
|
'gitlens.showBlameHistory' |
|
||||||
@@ -132,6 +142,24 @@ export interface ICodeLensLanguageLocation {
|
|||||||
customSymbols?: string[];
|
customSymbols?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IGitExplorerConfig {
|
||||||
|
enabled: boolean;
|
||||||
|
view: GitExplorerView;
|
||||||
|
files: {
|
||||||
|
layout: GitExplorerFilesLayout;
|
||||||
|
compact: boolean;
|
||||||
|
threshold: number;
|
||||||
|
};
|
||||||
|
includeWorkingTree: boolean;
|
||||||
|
showTrackingBranch: boolean;
|
||||||
|
commitFormat: string;
|
||||||
|
commitFileFormat: string;
|
||||||
|
stashFormat: string;
|
||||||
|
stashFileFormat: string;
|
||||||
|
statusFileFormat: string;
|
||||||
|
// dateFormat: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IRemotesConfig {
|
export interface IRemotesConfig {
|
||||||
type: CustomRemoteType;
|
type: CustomRemoteType;
|
||||||
domain: string;
|
domain: string;
|
||||||
@@ -316,16 +344,7 @@ export interface IConfig {
|
|||||||
|
|
||||||
defaultDateFormat: string | null;
|
defaultDateFormat: string | null;
|
||||||
|
|
||||||
gitExplorer: {
|
gitExplorer: IGitExplorerConfig;
|
||||||
enabled: boolean;
|
|
||||||
view: GitExplorerView;
|
|
||||||
showTrackingBranch: boolean;
|
|
||||||
commitFormat: string;
|
|
||||||
commitFileFormat: string;
|
|
||||||
stashFormat: string;
|
|
||||||
stashFileFormat: string;
|
|
||||||
// dateFormat: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
remotes: IRemotesConfig[];
|
remotes: IRemotesConfig[];
|
||||||
|
|
||||||
|
|||||||
@@ -81,10 +81,12 @@ export type GlyphChars = '\u21a9' |
|
|||||||
'\u21e8' |
|
'\u21e8' |
|
||||||
'\u2191' |
|
'\u2191' |
|
||||||
'\u2197' |
|
'\u2197' |
|
||||||
|
'\u2217' |
|
||||||
'\u2713' |
|
'\u2713' |
|
||||||
'\u2014' |
|
'\u2014' |
|
||||||
'\u2022' |
|
'\u2022' |
|
||||||
'\u2026' |
|
'\u2026' |
|
||||||
|
'\u270E' |
|
||||||
'\u00a0' |
|
'\u00a0' |
|
||||||
'\u200b';
|
'\u200b';
|
||||||
export const GlyphChars = {
|
export const GlyphChars = {
|
||||||
@@ -97,15 +99,22 @@ export const GlyphChars = {
|
|||||||
ArrowRightHollow: '\u21e8' as GlyphChars,
|
ArrowRightHollow: '\u21e8' as GlyphChars,
|
||||||
ArrowUp: '\u2191' as GlyphChars,
|
ArrowUp: '\u2191' as GlyphChars,
|
||||||
ArrowUpRight: '\u2197' as GlyphChars,
|
ArrowUpRight: '\u2197' as GlyphChars,
|
||||||
|
Asterisk: '\u2217' as GlyphChars,
|
||||||
Check: '\u2713' as GlyphChars,
|
Check: '\u2713' as GlyphChars,
|
||||||
Dash: '\u2014' as GlyphChars,
|
Dash: '\u2014' as GlyphChars,
|
||||||
Dot: '\u2022' as GlyphChars,
|
Dot: '\u2022' as GlyphChars,
|
||||||
Ellipsis: '\u2026' as GlyphChars,
|
Ellipsis: '\u2026' as GlyphChars,
|
||||||
|
Pensil: '\u270E' as GlyphChars,
|
||||||
Space: '\u00a0' as GlyphChars,
|
Space: '\u00a0' as GlyphChars,
|
||||||
ZeroWidthSpace: '\u200b' as GlyphChars
|
ZeroWidthSpace: '\u200b' as GlyphChars
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WorkspaceState = 'gitlensVersion';
|
export type GlobalState = 'gitlensVersion';
|
||||||
|
export const GlobalState = {
|
||||||
|
GitLensVersion: 'gitlensVersion' as GlobalState
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WorkspaceState = 'gitlens:gitExplorer:view';
|
||||||
export const WorkspaceState = {
|
export const WorkspaceState = {
|
||||||
GitLensVersion: 'gitlensVersion' as WorkspaceState
|
GitExplorerView: 'gitlens:gitExplorer:view' as WorkspaceState
|
||||||
};
|
};
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
import { commands, ExtensionContext, extensions, languages, window, workspace } from 'vscode';
|
import { commands, ExtensionContext, extensions, languages, window, workspace } from 'vscode';
|
||||||
import { AnnotationController } from './annotations/annotationController';
|
import { AnnotationController } from './annotations/annotationController';
|
||||||
import { CloseUnchangedFilesCommand, OpenChangedFilesCommand } from './commands';
|
import { CloseUnchangedFilesCommand, OpenChangedFilesCommand } from './commands';
|
||||||
|
import { ExternalDiffCommand } from './commands';
|
||||||
import { OpenBranchesInRemoteCommand, OpenBranchInRemoteCommand, OpenCommitInRemoteCommand, OpenFileInRemoteCommand, OpenInRemoteCommand, OpenRepoInRemoteCommand } from './commands';
|
import { OpenBranchesInRemoteCommand, OpenBranchInRemoteCommand, OpenCommitInRemoteCommand, OpenFileInRemoteCommand, OpenInRemoteCommand, OpenRepoInRemoteCommand } from './commands';
|
||||||
import { CopyMessageToClipboardCommand, CopyShaToClipboardCommand } from './commands';
|
import { CopyMessageToClipboardCommand, CopyShaToClipboardCommand } from './commands';
|
||||||
import { DiffDirectoryCommand, DiffLineWithPreviousCommand, DiffLineWithWorkingCommand, DiffWithBranchCommand, DiffWithCommand, DiffWithNextCommand, DiffWithPreviousCommand, DiffWithRevisionCommand, DiffWithWorkingCommand } from './commands';
|
import { DiffDirectoryCommand, DiffLineWithPreviousCommand, DiffLineWithWorkingCommand, DiffWithBranchCommand, DiffWithCommand, DiffWithNextCommand, DiffWithPreviousCommand, DiffWithRevisionCommand, DiffWithWorkingCommand } from './commands';
|
||||||
@@ -16,7 +17,7 @@ import { ShowQuickRepoStatusCommand, ShowQuickStashListCommand } from './command
|
|||||||
import { StashApplyCommand, StashDeleteCommand, StashSaveCommand } from './commands';
|
import { StashApplyCommand, StashDeleteCommand, StashSaveCommand } from './commands';
|
||||||
import { ToggleCodeLensCommand } from './commands';
|
import { ToggleCodeLensCommand } from './commands';
|
||||||
import { CodeLensLocations, IConfig, LineHighlightLocations } from './configuration';
|
import { CodeLensLocations, IConfig, LineHighlightLocations } from './configuration';
|
||||||
import { ApplicationInsightsKey, CommandContext, ExtensionKey, QualifiedExtensionId, setCommandContext, WorkspaceState } from './constants';
|
import { ApplicationInsightsKey, CommandContext, ExtensionKey, GlobalState, QualifiedExtensionId, setCommandContext } from './constants';
|
||||||
import { CodeLensController } from './codeLensController';
|
import { CodeLensController } from './codeLensController';
|
||||||
import { CurrentLineController, LineAnnotationType } from './currentLineController';
|
import { CurrentLineController, LineAnnotationType } from './currentLineController';
|
||||||
import { RemoteProviderFactory } from './git/remotes/factory';
|
import { RemoteProviderFactory } from './git/remotes/factory';
|
||||||
@@ -71,7 +72,7 @@ export async function activate(context: ExtensionContext) {
|
|||||||
notifyOnUnsupportedGitVersion(context, gitVersion);
|
notifyOnUnsupportedGitVersion(context, gitVersion);
|
||||||
notifyOnNewGitLensVersion(context, gitlensVersion);
|
notifyOnNewGitLensVersion(context, gitlensVersion);
|
||||||
|
|
||||||
await context.globalState.update(WorkspaceState.GitLensVersion, gitlensVersion);
|
await context.globalState.update(GlobalState.GitLensVersion, gitlensVersion);
|
||||||
|
|
||||||
const git = new GitService(repoPath);
|
const git = new GitService(repoPath);
|
||||||
context.subscriptions.push(git);
|
context.subscriptions.push(git);
|
||||||
@@ -99,6 +100,7 @@ export async function activate(context: ExtensionContext) {
|
|||||||
context.subscriptions.push(commands.registerTextEditorCommand('gitlens.computingFileAnnotations', () => { }));
|
context.subscriptions.push(commands.registerTextEditorCommand('gitlens.computingFileAnnotations', () => { }));
|
||||||
|
|
||||||
context.subscriptions.push(new CloseUnchangedFilesCommand(git));
|
context.subscriptions.push(new CloseUnchangedFilesCommand(git));
|
||||||
|
context.subscriptions.push(new ExternalDiffCommand(git));
|
||||||
context.subscriptions.push(new OpenChangedFilesCommand(git));
|
context.subscriptions.push(new OpenChangedFilesCommand(git));
|
||||||
context.subscriptions.push(new CopyMessageToClipboardCommand(git));
|
context.subscriptions.push(new CopyMessageToClipboardCommand(git));
|
||||||
context.subscriptions.push(new CopyShaToClipboardCommand(git));
|
context.subscriptions.push(new CopyShaToClipboardCommand(git));
|
||||||
@@ -148,7 +150,7 @@ export async function activate(context: ExtensionContext) {
|
|||||||
export function deactivate() { }
|
export function deactivate() { }
|
||||||
|
|
||||||
async function migrateSettings(context: ExtensionContext) {
|
async function migrateSettings(context: ExtensionContext) {
|
||||||
const previousVersion = context.globalState.get<string>(WorkspaceState.GitLensVersion);
|
const previousVersion = context.globalState.get<string>(GlobalState.GitLensVersion);
|
||||||
if (previousVersion === undefined) return;
|
if (previousVersion === undefined) return;
|
||||||
|
|
||||||
const [major] = previousVersion.split('.');
|
const [major] = previousVersion.split('.');
|
||||||
@@ -274,7 +276,7 @@ async function migrateSettings(context: ExtensionContext) {
|
|||||||
async function notifyOnNewGitLensVersion(context: ExtensionContext, version: string) {
|
async function notifyOnNewGitLensVersion(context: ExtensionContext, version: string) {
|
||||||
if (context.globalState.get(SuppressedKeys.UpdateNotice, false)) return;
|
if (context.globalState.get(SuppressedKeys.UpdateNotice, false)) return;
|
||||||
|
|
||||||
const previousVersion = context.globalState.get<string>(WorkspaceState.GitLensVersion);
|
const previousVersion = context.globalState.get<string>(GlobalState.GitLensVersion);
|
||||||
|
|
||||||
if (previousVersion === undefined) {
|
if (previousVersion === undefined) {
|
||||||
Logger.log(`GitLens first-time install`);
|
Logger.log(`GitLens first-time install`);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export abstract class Formatter<TItem = any, TOptions extends IFormatOptions = I
|
|||||||
|
|
||||||
let max = options.truncateTo;
|
let max = options.truncateTo;
|
||||||
|
|
||||||
const width = Strings.getWidth(s);
|
const width = Strings.width(s);
|
||||||
if (max === undefined) {
|
if (max === undefined) {
|
||||||
if (this.collapsableWhitespace === 0) return s;
|
if (this.collapsableWhitespace === 0) return s;
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import { Strings } from '../../system';
|
import { Strings } from '../../system';
|
||||||
|
import { GlyphChars } from '../../constants';
|
||||||
import { Formatter, IFormatOptions } from './formatter';
|
import { Formatter, IFormatOptions } from './formatter';
|
||||||
import { GitStatusFile, IGitStatusFile } from '../models/status';
|
import { GitStatusFile, IGitStatusFile, IGitStatusFileWithCommit } from '../models/status';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
export interface IStatusFormatOptions extends IFormatOptions {
|
export interface IStatusFormatOptions extends IFormatOptions {
|
||||||
|
relativePath?: string;
|
||||||
|
|
||||||
tokenOptions?: {
|
tokenOptions?: {
|
||||||
|
directory?: Strings.ITokenOptions;
|
||||||
file?: Strings.ITokenOptions;
|
file?: Strings.ITokenOptions;
|
||||||
filePath?: Strings.ITokenOptions;
|
filePath?: Strings.ITokenOptions;
|
||||||
path?: Strings.ITokenOptions;
|
path?: Strings.ITokenOptions;
|
||||||
@@ -14,21 +18,31 @@ export interface IStatusFormatOptions extends IFormatOptions {
|
|||||||
|
|
||||||
export class StatusFileFormatter extends Formatter<IGitStatusFile, IStatusFormatOptions> {
|
export class StatusFileFormatter extends Formatter<IGitStatusFile, IStatusFormatOptions> {
|
||||||
|
|
||||||
|
get directory() {
|
||||||
|
const directory = GitStatusFile.getFormattedDirectory(this._item, false, this._options.relativePath);
|
||||||
|
return this._padOrTruncate(directory, this._options.tokenOptions!.file);
|
||||||
|
}
|
||||||
|
|
||||||
get file() {
|
get file() {
|
||||||
const file = path.basename(this._item.fileName);
|
const file = path.basename(this._item.fileName);
|
||||||
return this._padOrTruncate(file, this._options.tokenOptions!.file);
|
return this._padOrTruncate(file, this._options.tokenOptions!.file);
|
||||||
}
|
}
|
||||||
|
|
||||||
get filePath() {
|
get filePath() {
|
||||||
const filePath = GitStatusFile.getFormattedPath(this._item);
|
const filePath = GitStatusFile.getFormattedPath(this._item, undefined, this._options.relativePath);
|
||||||
return this._padOrTruncate(filePath, this._options.tokenOptions!.filePath);
|
return this._padOrTruncate(filePath, this._options.tokenOptions!.filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
get path() {
|
get path() {
|
||||||
const directory = GitStatusFile.getFormattedDirectory(this._item, false);
|
const directory = GitStatusFile.getRelativePath(this._item, this._options.relativePath);
|
||||||
return this._padOrTruncate(directory, this._options.tokenOptions!.file);
|
return this._padOrTruncate(directory, this._options.tokenOptions!.file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get working() {
|
||||||
|
const commit = (this._item as IGitStatusFileWithCommit).commit;
|
||||||
|
return (commit !== undefined && commit.isUncommitted) ? `${GlyphChars.Pensil} ${GlyphChars.Space}` : '';
|
||||||
|
}
|
||||||
|
|
||||||
static fromTemplate(template: string, status: IGitStatusFile, dateFormat: string | null): string;
|
static fromTemplate(template: string, status: IGitStatusFile, dateFormat: string | null): string;
|
||||||
static fromTemplate(template: string, status: IGitStatusFile, options?: IStatusFormatOptions): string;
|
static fromTemplate(template: string, status: IGitStatusFile, options?: IStatusFormatOptions): string;
|
||||||
static fromTemplate(template: string, status: IGitStatusFile, dateFormatOrOptions?: string | null | IStatusFormatOptions): string;
|
static fromTemplate(template: string, status: IGitStatusFile, dateFormatOrOptions?: string | null | IStatusFormatOptions): string;
|
||||||
|
|||||||
@@ -259,6 +259,14 @@ export class Git {
|
|||||||
return gitCommand({ cwd: repoPath }, ...params);
|
return gitCommand({ cwd: repoPath }, ...params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static diff_shortstat(repoPath: string, sha?: string) {
|
||||||
|
const params = [`diff`, `--shortstat`, `--no-ext-diff`];
|
||||||
|
if (sha) {
|
||||||
|
params.push(sha);
|
||||||
|
}
|
||||||
|
return gitCommand({ cwd: repoPath }, ...params);
|
||||||
|
}
|
||||||
|
|
||||||
static difftool_dirDiff(repoPath: string, sha1: string, sha2?: string) {
|
static difftool_dirDiff(repoPath: string, sha1: string, sha2?: string) {
|
||||||
const params = [`difftool`, `--dir-diff`, sha1];
|
const params = [`difftool`, `--dir-diff`, sha1];
|
||||||
if (sha2) {
|
if (sha2) {
|
||||||
@@ -268,6 +276,17 @@ export class Git {
|
|||||||
return gitCommand({ cwd: repoPath }, ...params);
|
return gitCommand({ cwd: repoPath }, ...params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static difftool_fileDiff(repoPath: string, fileName: string, staged: boolean) {
|
||||||
|
const params = [`difftool`, `--no-prompt`];
|
||||||
|
if (staged) {
|
||||||
|
params.push('--staged');
|
||||||
|
}
|
||||||
|
params.push('--');
|
||||||
|
params.push(fileName);
|
||||||
|
|
||||||
|
return gitCommand({ cwd: repoPath }, ...params);
|
||||||
|
}
|
||||||
|
|
||||||
static log(repoPath: string, sha?: string, maxCount?: number, reverse: boolean = false) {
|
static log(repoPath: string, sha?: string, maxCount?: number, reverse: boolean = false) {
|
||||||
const params = [...defaultLogParams, `-m`];
|
const params = [...defaultLogParams, `-m`];
|
||||||
if (maxCount && !reverse) {
|
if (maxCount && !reverse) {
|
||||||
@@ -332,6 +351,14 @@ export class Git {
|
|||||||
return gitCommand({ cwd: repoPath }, ...params, ...search);
|
return gitCommand({ cwd: repoPath }, ...params, ...search);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static log_shortstat(repoPath: string, sha?: string) {
|
||||||
|
const params = [`log`, `--shortstat`, `--oneline`];
|
||||||
|
if (sha) {
|
||||||
|
params.push(sha);
|
||||||
|
}
|
||||||
|
return gitCommand({ cwd: repoPath }, ...params);
|
||||||
|
}
|
||||||
|
|
||||||
static async ls_files(repoPath: string, fileName: string): Promise<string> {
|
static async ls_files(repoPath: string, fileName: string): Promise<string> {
|
||||||
try {
|
try {
|
||||||
return await gitCommand({ cwd: repoPath, overrideErrorHandling: true }, 'ls-files', fileName);
|
return await gitCommand({ cwd: repoPath, overrideErrorHandling: true }, 'ls-files', fileName);
|
||||||
@@ -404,7 +431,7 @@ export class Git {
|
|||||||
|
|
||||||
static status(repoPath: string, porcelainVersion: number = 1): Promise<string> {
|
static status(repoPath: string, porcelainVersion: number = 1): Promise<string> {
|
||||||
const porcelain = porcelainVersion >= 2 ? `--porcelain=v${porcelainVersion}` : '--porcelain';
|
const porcelain = porcelainVersion >= 2 ? `--porcelain=v${porcelainVersion}` : '--porcelain';
|
||||||
return gitCommand({ cwd: repoPath }, 'status', porcelain, '--branch');
|
return gitCommand({ cwd: repoPath }, 'status', porcelain, '--branch', '-u');
|
||||||
}
|
}
|
||||||
|
|
||||||
static status_file(repoPath: string, fileName: string, porcelainVersion: number = 1): Promise<string> {
|
static status_file(repoPath: string, fileName: string, porcelainVersion: number = 1): Promise<string> {
|
||||||
|
|||||||
@@ -63,11 +63,14 @@ export class GitUri extends Uri {
|
|||||||
return Uri.file(this.sha ? this.path : this.fsPath);
|
return Uri.file(this.sha ? this.path : this.fsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormattedPath(separator: string = Strings.pad(GlyphChars.Dot, 2, 2)): string {
|
getFormattedPath(separator: string = Strings.pad(GlyphChars.Dot, 2, 2), relativeTo?: string): string {
|
||||||
let directory = path.dirname(this.fsPath);
|
let directory = path.dirname(this.fsPath);
|
||||||
if (this.repoPath) {
|
if (this.repoPath) {
|
||||||
directory = path.relative(this.repoPath, directory);
|
directory = path.relative(this.repoPath, directory);
|
||||||
}
|
}
|
||||||
|
if (relativeTo !== undefined) {
|
||||||
|
directory = path.relative(relativeTo, directory);
|
||||||
|
}
|
||||||
directory = GitService.normalizePath(directory);
|
directory = GitService.normalizePath(directory);
|
||||||
|
|
||||||
return (!directory || directory === '.')
|
return (!directory || directory === '.')
|
||||||
@@ -75,8 +78,12 @@ export class GitUri extends Uri {
|
|||||||
: `${path.basename(this.fsPath)}${separator}${directory}`;
|
: `${path.basename(this.fsPath)}${separator}${directory}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRelativePath(): string {
|
getRelativePath(relativeTo?: string): string {
|
||||||
return GitService.normalizePath(path.relative(this.repoPath || '', this.fsPath));
|
let relativePath = path.relative(this.repoPath || '', this.fsPath);
|
||||||
|
if (relativeTo !== undefined) {
|
||||||
|
relativePath = path.relative(relativeTo, relativePath);
|
||||||
|
}
|
||||||
|
return GitService.normalizePath(relativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async fromUri(uri: Uri, git: GitService) {
|
static async fromUri(uri: Uri, git: GitService) {
|
||||||
@@ -104,15 +111,19 @@ export class GitUri extends Uri {
|
|||||||
return new GitUri(uri, repoPathOrCommit);
|
return new GitUri(uri, repoPathOrCommit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDirectory(fileName: string): string {
|
static getDirectory(fileName: string, relativeTo?: string): string {
|
||||||
const directory: string | undefined = GitService.normalizePath(path.dirname(fileName));
|
let directory: string | undefined = path.dirname(fileName);
|
||||||
|
if (relativeTo !== undefined) {
|
||||||
|
directory = path.relative(relativeTo, directory);
|
||||||
|
}
|
||||||
|
directory = GitService.normalizePath(directory);
|
||||||
return (!directory || directory === '.') ? '' : directory;
|
return (!directory || directory === '.') ? '' : directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getFormattedPath(fileNameOrUri: string | Uri, separator: string = Strings.pad(GlyphChars.Dot, 2, 2)): string {
|
static getFormattedPath(fileNameOrUri: string | Uri, separator: string = Strings.pad(GlyphChars.Dot, 2, 2), relativeTo?: string): string {
|
||||||
let fileName: string;
|
let fileName: string;
|
||||||
if (fileNameOrUri instanceof Uri) {
|
if (fileNameOrUri instanceof Uri) {
|
||||||
if (fileNameOrUri instanceof GitUri) return fileNameOrUri.getFormattedPath(separator);
|
if (fileNameOrUri instanceof GitUri) return fileNameOrUri.getFormattedPath(separator, relativeTo);
|
||||||
|
|
||||||
fileName = fileNameOrUri.fsPath;
|
fileName = fileNameOrUri.fsPath;
|
||||||
}
|
}
|
||||||
@@ -120,11 +131,29 @@ export class GitUri extends Uri {
|
|||||||
fileName = fileNameOrUri;
|
fileName = fileNameOrUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
const directory = GitUri.getDirectory(fileName);
|
const directory = GitUri.getDirectory(fileName, relativeTo);
|
||||||
return !directory
|
return !directory
|
||||||
? path.basename(fileName)
|
? path.basename(fileName)
|
||||||
: `${path.basename(fileName)}${separator}${directory}`;
|
: `${path.basename(fileName)}${separator}${directory}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getRelativePath(fileNameOrUri: string | Uri, relativeTo?: string, repoPath?: string): string {
|
||||||
|
let fileName: string;
|
||||||
|
if (fileNameOrUri instanceof Uri) {
|
||||||
|
if (fileNameOrUri instanceof GitUri) return fileNameOrUri.getRelativePath(relativeTo);
|
||||||
|
|
||||||
|
fileName = fileNameOrUri.fsPath;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fileName = fileNameOrUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
let relativePath = path.relative(repoPath || '', fileName);
|
||||||
|
if (relativeTo !== undefined) {
|
||||||
|
relativePath = path.relative(relativeTo, relativePath);
|
||||||
|
}
|
||||||
|
return GitService.normalizePath(relativePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGitCommitInfo {
|
export interface IGitCommitInfo {
|
||||||
|
|||||||
@@ -33,4 +33,10 @@ export interface GitDiff {
|
|||||||
chunks: GitDiffChunk[];
|
chunks: GitDiffChunk[];
|
||||||
|
|
||||||
diff?: string;
|
diff?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GitDiffShortStat {
|
||||||
|
files: number;
|
||||||
|
insertions: number;
|
||||||
|
deletions: number;
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ import { Strings } from '../../system';
|
|||||||
import { Uri } from 'vscode';
|
import { Uri } from 'vscode';
|
||||||
import { GlyphChars } from '../../constants';
|
import { GlyphChars } from '../../constants';
|
||||||
import { GitUri } from '../gitUri';
|
import { GitUri } from '../gitUri';
|
||||||
|
import { GitLogCommit } from './logCommit';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
export interface GitStatus {
|
export interface GitStatus {
|
||||||
@@ -25,13 +26,19 @@ export interface IGitStatusFile {
|
|||||||
status: GitStatusFileStatus;
|
status: GitStatusFileStatus;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
originalFileName?: string;
|
originalFileName?: string;
|
||||||
|
workTreeStatus: GitStatusFileStatus;
|
||||||
|
indexStatus: GitStatusFileStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGitStatusFileWithCommit extends IGitStatusFile {
|
||||||
|
commit: GitLogCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GitStatusFile implements IGitStatusFile {
|
export class GitStatusFile implements IGitStatusFile {
|
||||||
|
|
||||||
originalFileName?: string;
|
originalFileName?: string;
|
||||||
|
|
||||||
constructor(public repoPath: string, public status: GitStatusFileStatus, public fileName: string, public staged: boolean, originalFileName?: string) {
|
constructor(public repoPath: string, public status: GitStatusFileStatus, public workTreeStatus: GitStatusFileStatus, public indexStatus: GitStatusFileStatus, public fileName: string, public staged: boolean, originalFileName?: string) {
|
||||||
this.originalFileName = originalFileName;
|
this.originalFileName = originalFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,15 +58,19 @@ export class GitStatusFile implements IGitStatusFile {
|
|||||||
return Uri.file(path.resolve(this.repoPath, this.fileName));
|
return Uri.file(path.resolve(this.repoPath, this.fileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
static getFormattedDirectory(status: IGitStatusFile, includeOriginal: boolean = false): string {
|
static getFormattedDirectory(status: IGitStatusFile, includeOriginal: boolean = false, relativeTo?: string): string {
|
||||||
const directory = GitUri.getDirectory(status.fileName);
|
const directory = GitUri.getDirectory(status.fileName, relativeTo);
|
||||||
return (includeOriginal && status.status === 'R' && status.originalFileName)
|
return (includeOriginal && status.status === 'R' && status.originalFileName)
|
||||||
? `${directory} ${Strings.pad(GlyphChars.ArrowLeft, 1, 1)} ${status.originalFileName}`
|
? `${directory} ${Strings.pad(GlyphChars.ArrowLeft, 1, 1)} ${status.originalFileName}`
|
||||||
: directory;
|
: directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getFormattedPath(status: IGitStatusFile, separator: string = Strings.pad(GlyphChars.Dot, 2, 2)): string {
|
static getFormattedPath(status: IGitStatusFile, separator: string = Strings.pad(GlyphChars.Dot, 2, 2), relativeTo?: string): string {
|
||||||
return GitUri.getFormattedPath(status.fileName, separator);
|
return GitUri.getFormattedPath(status.fileName, separator, relativeTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getRelativePath(status: IGitStatusFile, relativeTo?: string): string {
|
||||||
|
return GitUri.getRelativePath(status.fileName, relativeTo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import { Iterables, Strings } from '../../system';
|
import { Iterables, Strings } from '../../system';
|
||||||
import { GitDiff, GitDiffChunk, GitDiffChunkLine, GitDiffLine } from './../git';
|
import { GitDiff, GitDiffChunk, GitDiffChunkLine, GitDiffLine, GitDiffShortStat } from './../git';
|
||||||
|
|
||||||
const unifiedDiffRegex = /^@@ -([\d]+),([\d]+) [+]([\d]+),([\d]+) @@([\s\S]*?)(?=^@@)/gm;
|
const unifiedDiffRegex = /^@@ -([\d]+),([\d]+) [+]([\d]+),([\d]+) @@([\s\S]*?)(?=^@@)/gm;
|
||||||
|
const shortStatDiffRegex = /^\s*(\d+)\sfiles? changed(?:,\s+(\d+)\s+insertions?\(\+\))?(?:,\s+(\d+)\s+deletions?\(-\))?/;
|
||||||
|
|
||||||
export class GitDiffParser {
|
export class GitDiffParser {
|
||||||
|
|
||||||
@@ -116,4 +117,20 @@ export class GitDiffParser {
|
|||||||
|
|
||||||
return chunkLines;
|
return chunkLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static parseShortStat(data: string): GitDiffShortStat | undefined {
|
||||||
|
if (!data) return undefined;
|
||||||
|
|
||||||
|
const match = shortStatDiffRegex.exec(data);
|
||||||
|
if (match == null) return undefined;
|
||||||
|
|
||||||
|
const files = match[1];
|
||||||
|
const insertions = match[2];
|
||||||
|
const deletions = match[3];
|
||||||
|
return {
|
||||||
|
files: files == null ? 0 : parseInt(files, 10),
|
||||||
|
insertions: insertions == null ? 0 : parseInt(insertions, 10),
|
||||||
|
deletions: deletions == null ? 0 : parseInt(deletions, 10)
|
||||||
|
} as GitDiffShortStat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,8 @@ interface FileStatusEntry {
|
|||||||
status: GitStatusFileStatus;
|
status: GitStatusFileStatus;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
originalFileName: string;
|
originalFileName: string;
|
||||||
|
workTreeStatus: GitStatusFileStatus;
|
||||||
|
indexStatus: GitStatusFileStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
const aheadStatusV1Regex = /(?:ahead ([0-9]+))/;
|
const aheadStatusV1Regex = /(?:ahead ([0-9]+))/;
|
||||||
@@ -69,7 +71,7 @@ export class GitStatusParser {
|
|||||||
else {
|
else {
|
||||||
entry = this._parseFileEntry(rawStatus, fileName);
|
entry = this._parseFileEntry(rawStatus, fileName);
|
||||||
}
|
}
|
||||||
status.files.push(new GitStatusFile(repoPath, entry.status, entry.fileName, entry.staged, entry.originalFileName));
|
status.files.push(new GitStatusFile(repoPath, entry.status, entry.workTreeStatus, entry.indexStatus, entry.fileName, entry.staged, entry.originalFileName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,7 +119,7 @@ export class GitStatusParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (entry !== undefined) {
|
if (entry !== undefined) {
|
||||||
status.files.push(new GitStatusFile(repoPath, entry.status, entry.fileName, entry.staged, entry.originalFileName));
|
status.files.push(new GitStatusFile(repoPath, entry.status, entry.workTreeStatus, entry.indexStatus, entry.fileName, entry.staged, entry.originalFileName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,7 +133,9 @@ export class GitStatusParser {
|
|||||||
status: (indexStatus || workTreeStatus || '?') as GitStatusFileStatus,
|
status: (indexStatus || workTreeStatus || '?') as GitStatusFileStatus,
|
||||||
fileName: fileName,
|
fileName: fileName,
|
||||||
originalFileName: originalFileName,
|
originalFileName: originalFileName,
|
||||||
staged: !!indexStatus
|
staged: !!indexStatus,
|
||||||
|
indexStatus: indexStatus,
|
||||||
|
workTreeStatus: workTreeStatus
|
||||||
} as FileStatusEntry;
|
} as FileStatusEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ import { Disposable, Event, EventEmitter, FileSystemWatcher, Location, Position,
|
|||||||
import { IConfig } from './configuration';
|
import { IConfig } from './configuration';
|
||||||
import { DocumentSchemes, ExtensionKey, GlyphChars } from './constants';
|
import { DocumentSchemes, ExtensionKey, GlyphChars } from './constants';
|
||||||
import { RemoteProviderFactory } from './git/remotes/factory';
|
import { RemoteProviderFactory } from './git/remotes/factory';
|
||||||
import { Git, GitAuthor, GitBlame, GitBlameCommit, GitBlameLine, GitBlameLines, GitBlameParser, GitBranch, GitBranchParser, GitCommit, GitDiff, GitDiffChunkLine, GitDiffParser, GitLog, GitLogCommit, GitLogParser, GitRemote, GitRemoteParser, GitStash, GitStashParser, GitStatus, GitStatusFile, GitStatusParser, IGit, setDefaultEncoding } from './git/git';
|
import { Git, GitAuthor, GitBlame, GitBlameCommit, GitBlameLine, GitBlameLines, GitBlameParser, GitBranch, GitBranchParser, GitCommit, GitDiff, GitDiffChunkLine, GitDiffParser, GitDiffShortStat, GitLog, GitLogCommit, GitLogParser, GitRemote, GitRemoteParser, GitStash, GitStashParser, GitStatus, GitStatusFile, GitStatusParser, IGit, setDefaultEncoding } from './git/git';
|
||||||
import { GitUri, IGitCommitInfo, IGitUriData } from './git/gitUri';
|
import { GitUri, IGitCommitInfo, IGitUriData } from './git/gitUri';
|
||||||
import { Logger } from './logger';
|
import { Logger } from './logger';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
@@ -86,6 +86,11 @@ export class GitService extends Disposable {
|
|||||||
return this._onDidChangeGitCache.event;
|
return this._onDidChangeGitCache.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _onDidChangeFileSystem = new EventEmitter<Uri>();
|
||||||
|
get onDidChangeFileSystem(): Event<Uri> {
|
||||||
|
return this._onDidChangeFileSystem.event;
|
||||||
|
}
|
||||||
|
|
||||||
private _onDidChangeRepo = new EventEmitter<RepoChangedReasons[]>();
|
private _onDidChangeRepo = new EventEmitter<RepoChangedReasons[]>();
|
||||||
get onDidChangeRepo(): Event<RepoChangedReasons[]> {
|
get onDidChangeRepo(): Event<RepoChangedReasons[]> {
|
||||||
return this._onDidChangeRepo.event;
|
return this._onDidChangeRepo.event;
|
||||||
@@ -121,14 +126,16 @@ export class GitService extends Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
|
this.stopWatchingFileSystem();
|
||||||
|
|
||||||
|
this._repoWatcher && this._repoWatcher.dispose();
|
||||||
|
this._repoWatcher = undefined;
|
||||||
|
|
||||||
this._disposable && this._disposable.dispose();
|
this._disposable && this._disposable.dispose();
|
||||||
|
|
||||||
this._cacheDisposable && this._cacheDisposable.dispose();
|
this._cacheDisposable && this._cacheDisposable.dispose();
|
||||||
this._cacheDisposable = undefined;
|
this._cacheDisposable = undefined;
|
||||||
|
|
||||||
this._repoWatcher && this._repoWatcher.dispose();
|
|
||||||
this._repoWatcher = undefined;
|
|
||||||
|
|
||||||
this._gitCache.clear();
|
this._gitCache.clear();
|
||||||
this._remotesCache.clear();
|
this._remotesCache.clear();
|
||||||
this._uriCache.clear();
|
this._uriCache.clear();
|
||||||
@@ -156,6 +163,8 @@ export class GitService extends Disposable {
|
|||||||
disposables.push(workspace.onDidChangeTextDocument(this._onTextDocumentChanged, this));
|
disposables.push(workspace.onDidChangeTextDocument(this._onTextDocumentChanged, this));
|
||||||
disposables.push(workspace.onDidSaveTextDocument(d => this._removeCachedEntry(d, RemoveCacheReason.DocumentSaved)));
|
disposables.push(workspace.onDidSaveTextDocument(d => this._removeCachedEntry(d, RemoveCacheReason.DocumentSaved)));
|
||||||
disposables.push(this._repoWatcher.onDidChange(this._onRepoChanged, this));
|
disposables.push(this._repoWatcher.onDidChange(this._onRepoChanged, this));
|
||||||
|
disposables.push(this._repoWatcher.onDidCreate(this._onRepoChanged, this));
|
||||||
|
disposables.push(this._repoWatcher.onDidDelete(this._onRepoChanged, this));
|
||||||
|
|
||||||
this._cacheDisposable = Disposable.from(...disposables);
|
this._cacheDisposable = Disposable.from(...disposables);
|
||||||
}
|
}
|
||||||
@@ -599,6 +608,11 @@ export class GitService extends Disposable {
|
|||||||
return Git.normalizePath(typeof fileNameOrUri === 'string' ? fileNameOrUri : fileNameOrUri.fsPath).toLowerCase();
|
return Git.normalizePath(typeof fileNameOrUri === 'string' ? fileNameOrUri : fileNameOrUri.fsPath).toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getChangedFilesCount(repoPath: string, sha?: string): Promise<GitDiffShortStat | undefined> {
|
||||||
|
const data = await Git.diff_shortstat(repoPath, sha);
|
||||||
|
return GitDiffParser.parseShortStat(data);
|
||||||
|
}
|
||||||
|
|
||||||
async getConfig(key: string, repoPath?: string): Promise<string> {
|
async getConfig(key: string, repoPath?: string): Promise<string> {
|
||||||
Logger.log(`getConfig('${key}', '${repoPath}')`);
|
Logger.log(`getConfig('${key}', '${repoPath}')`);
|
||||||
|
|
||||||
@@ -1022,12 +1036,45 @@ export class GitService extends Disposable {
|
|||||||
return !!result;
|
return !!result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openDiffTool(repoPath: string, uri: Uri, staged: boolean) {
|
||||||
|
Logger.log(`openDiffTool('${repoPath}', '${uri}', ${staged})`);
|
||||||
|
|
||||||
|
return Git.difftool_fileDiff(repoPath, uri.fsPath, staged);
|
||||||
|
}
|
||||||
|
|
||||||
openDirectoryDiff(repoPath: string, sha1: string, sha2?: string) {
|
openDirectoryDiff(repoPath: string, sha1: string, sha2?: string) {
|
||||||
Logger.log(`openDirectoryDiff('${repoPath}', ${sha1}, ${sha2})`);
|
Logger.log(`openDirectoryDiff('${repoPath}', ${sha1}, ${sha2})`);
|
||||||
|
|
||||||
return Git.difftool_dirDiff(repoPath, sha1, sha2);
|
return Git.difftool_dirDiff(repoPath, sha1, sha2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _fsWatcherDisposable: Disposable | undefined;
|
||||||
|
|
||||||
|
startWatchingFileSystem() {
|
||||||
|
if (this._fsWatcherDisposable !== undefined) return;
|
||||||
|
|
||||||
|
const debouncedFn = Functions.debounce((uri: Uri) => this._onDidChangeFileSystem.fire(uri), 2500);
|
||||||
|
const fn = (uri: Uri) => {
|
||||||
|
// Ignore .git changes
|
||||||
|
if (/\.git/.test(uri.fsPath)) return;
|
||||||
|
|
||||||
|
debouncedFn(uri);
|
||||||
|
};
|
||||||
|
|
||||||
|
const watcher = workspace.createFileSystemWatcher(`**`);
|
||||||
|
this._fsWatcherDisposable = Disposable.from(
|
||||||
|
watcher,
|
||||||
|
watcher.onDidChange(fn),
|
||||||
|
watcher.onDidCreate(fn),
|
||||||
|
watcher.onDidDelete(fn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
stopWatchingFileSystem() {
|
||||||
|
this._fsWatcherDisposable && this._fsWatcherDisposable.dispose();
|
||||||
|
this._fsWatcherDisposable = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
stashApply(repoPath: string, stashName: string, deleteAfter: boolean = false) {
|
stashApply(repoPath: string, stashName: string, deleteAfter: boolean = false) {
|
||||||
Logger.log(`stashApply('${repoPath}', ${stashName}, ${deleteAfter})`);
|
Logger.log(`stashApply('${repoPath}', ${stashName}, ${deleteAfter})`);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
import { Objects } from './object';
|
||||||
|
|
||||||
export namespace Arrays {
|
export namespace Arrays {
|
||||||
|
export function countUniques<T>(array: T[], accessor: (item: T) => string): { [key: string]: number } {
|
||||||
|
const uniqueCounts = Object.create(null);
|
||||||
|
for (const item of array) {
|
||||||
|
const value = accessor(item);
|
||||||
|
uniqueCounts[value] = (uniqueCounts[value] || 0) + 1;
|
||||||
|
}
|
||||||
|
return uniqueCounts;
|
||||||
|
}
|
||||||
|
|
||||||
export function groupBy<T>(array: T[], accessor: (item: T) => string): { [key: string]: T[] } {
|
export function groupBy<T>(array: T[], accessor: (item: T) => string): { [key: string]: T[] } {
|
||||||
return array.reduce((previous, current) => {
|
return array.reduce((previous, current) => {
|
||||||
const value = accessor(current);
|
const value = accessor(current);
|
||||||
@@ -10,6 +20,96 @@ export namespace Arrays {
|
|||||||
}, Object.create(null));
|
}, Object.create(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IHierarchicalItem<T> {
|
||||||
|
name: string;
|
||||||
|
relativePath: string;
|
||||||
|
value?: T;
|
||||||
|
|
||||||
|
// parent?: IHierarchicalItem<T>;
|
||||||
|
children: { [key: string]: IHierarchicalItem<T> } | undefined;
|
||||||
|
descendants: T[] | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function makeHierarchical<T>(values: T[], splitPath: (i: T) => string[], joinPath: (...paths: string[]) => string, compact: boolean = false): IHierarchicalItem<T> {
|
||||||
|
const seed = {
|
||||||
|
name: '',
|
||||||
|
relativePath: '',
|
||||||
|
children: Object.create(null),
|
||||||
|
descendants: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const hierarchy = values.reduce((root: IHierarchicalItem<T>, value) => {
|
||||||
|
let folder = root;
|
||||||
|
|
||||||
|
let relativePath = '';
|
||||||
|
for (const folderName of splitPath(value)) {
|
||||||
|
relativePath = joinPath(relativePath, folderName);
|
||||||
|
|
||||||
|
if (folder.children === undefined) {
|
||||||
|
folder.children = Object.create(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
let f = folder.children![folderName];
|
||||||
|
if (f === undefined) {
|
||||||
|
folder.children![folderName] = f = {
|
||||||
|
name: folderName,
|
||||||
|
relativePath: relativePath,
|
||||||
|
// parent: folder,
|
||||||
|
children: undefined,
|
||||||
|
descendants: undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (folder.descendants === undefined) {
|
||||||
|
folder.descendants = [];
|
||||||
|
}
|
||||||
|
folder.descendants.push(value);
|
||||||
|
folder = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
folder.value = value;
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}, seed);
|
||||||
|
|
||||||
|
if (compact) return compactHierarchy(hierarchy, joinPath, true);
|
||||||
|
return hierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compactHierarchy<T>(root: IHierarchicalItem<T>, joinPath: (...paths: string[]) => string, isRoot: boolean = true): IHierarchicalItem<T> {
|
||||||
|
if (root.children === undefined) return root;
|
||||||
|
|
||||||
|
const children = [...Objects.values(root.children)];
|
||||||
|
|
||||||
|
// // Attempts less nesting but duplicate roots
|
||||||
|
// if (!isRoot && children.every(c => c.value === undefined)) {
|
||||||
|
// const parentSiblings = root.parent!.children!;
|
||||||
|
// if (parentSiblings[root.name] !== undefined) {
|
||||||
|
// delete parentSiblings[root.name];
|
||||||
|
|
||||||
|
// for (const child of children) {
|
||||||
|
// child.name = joinPath(root.name, child.name);
|
||||||
|
// parentSiblings[child.name] = child;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (const child of children) {
|
||||||
|
compactHierarchy(child, joinPath, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isRoot && children.length === 1) {
|
||||||
|
const child = children[0];
|
||||||
|
if (child.value === undefined) {
|
||||||
|
root.name = joinPath(root.name, child.name);
|
||||||
|
root.relativePath = child.relativePath;
|
||||||
|
root.children = child.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
export function uniqueBy<T>(array: T[], accessor: (item: T) => any, predicate?: (item: T) => boolean): T[] {
|
export function uniqueBy<T>(array: T[], accessor: (item: T) => any, predicate?: (item: T) => boolean): T[] {
|
||||||
const uniqueValues = Object.create(null);
|
const uniqueValues = Object.create(null);
|
||||||
return array.filter(_ => {
|
return array.filter(_ => {
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ export namespace Objects {
|
|||||||
return _isEqual(first, second);
|
return _isEqual(first, second);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* entries(o: any): IterableIterator<[string, any]> {
|
export function entries<T>(o: { [key: string]: T }): IterableIterator<[string, T]>;
|
||||||
|
export function entries<T>(o: { [key: number]: T }): IterableIterator<[string, T]>;
|
||||||
|
export function* entries<T>(o: any): IterableIterator<[string, T]> {
|
||||||
for (const key in o) {
|
for (const key in o) {
|
||||||
yield [key, o[key]];
|
yield [key, o[key]];
|
||||||
}
|
}
|
||||||
@@ -56,6 +58,8 @@ export namespace Objects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function values<T>(o: { [key: string]: T }): IterableIterator<T>;
|
||||||
|
export function values<T>(o: { [key: number]: T }): IterableIterator<T>;
|
||||||
export function* values<T>(o: any): IterableIterator<T> {
|
export function* values<T>(o: any): IterableIterator<T> {
|
||||||
for (const key in o) {
|
for (const key in o) {
|
||||||
yield o[key];
|
yield o[key];
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const _escapeRegExp = require('lodash.escaperegexp');
|
const _escapeRegExp = require('lodash.escaperegexp');
|
||||||
const stringWidth = require('string-width');
|
|
||||||
|
|
||||||
export namespace Strings {
|
export namespace Strings {
|
||||||
export function escapeRegExp(s: string): string {
|
export function escapeRegExp(s: string): string {
|
||||||
return _escapeRegExp(s);
|
return _escapeRegExp(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getWidth(s: string): number {
|
|
||||||
return stringWidth(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
const TokenRegex = /\$\{([^|]*?)(?:\|(\d+)(\-|\?)?)?\}/g;
|
const TokenRegex = /\$\{([^|]*?)(?:\|(\d+)(\-|\?)?)?\}/g;
|
||||||
const TokenSanitizeRegex = /\$\{(\w*?)(?:\W|\d)*?\}/g;
|
const TokenSanitizeRegex = /\$\{(\w*?)(?:\W|\d)*?\}/g;
|
||||||
|
|
||||||
@@ -68,19 +63,19 @@ export namespace Strings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function padLeft(s: string, padTo: number, padding: string = '\u00a0') {
|
export function padLeft(s: string, padTo: number, padding: string = '\u00a0') {
|
||||||
const diff = padTo - getWidth(s);
|
const diff = padTo - width(s);
|
||||||
return (diff <= 0) ? s : '\u00a0'.repeat(diff) + s;
|
return (diff <= 0) ? s : '\u00a0'.repeat(diff) + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function padLeftOrTruncate(s: string, max: number, padding?: string) {
|
export function padLeftOrTruncate(s: string, max: number, padding?: string) {
|
||||||
const len = getWidth(s);
|
const len = width(s);
|
||||||
if (len < max) return padLeft(s, max, padding);
|
if (len < max) return padLeft(s, max, padding);
|
||||||
if (len > max) return truncate(s, max);
|
if (len > max) return truncate(s, max);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function padRight(s: string, padTo: number, padding: string = '\u00a0') {
|
export function padRight(s: string, padTo: number, padding: string = '\u00a0') {
|
||||||
const diff = padTo - getWidth(s);
|
const diff = padTo - width(s);
|
||||||
return (diff <= 0) ? s : s + '\u00a0'.repeat(diff);
|
return (diff <= 0) ? s : s + '\u00a0'.repeat(diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,14 +83,14 @@ export namespace Strings {
|
|||||||
const left = max < 0;
|
const left = max < 0;
|
||||||
max = Math.abs(max);
|
max = Math.abs(max);
|
||||||
|
|
||||||
const len = getWidth(s);
|
const len = width(s);
|
||||||
if (len < max) return left ? padLeft(s, max, padding) : padRight(s, max, padding);
|
if (len < max) return left ? padLeft(s, max, padding) : padRight(s, max, padding);
|
||||||
if (len > max) return truncate(s, max);
|
if (len > max) return truncate(s, max);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function padRightOrTruncate(s: string, max: number, padding?: string) {
|
export function padRightOrTruncate(s: string, max: number, padding?: string) {
|
||||||
const len = getWidth(s);
|
const len = width(s);
|
||||||
if (len < max) return padRight(s, max, padding);
|
if (len < max) return padRight(s, max, padding);
|
||||||
if (len > max) return truncate(s, max);
|
if (len > max) return truncate(s, max);
|
||||||
return s;
|
return s;
|
||||||
@@ -112,15 +107,15 @@ export namespace Strings {
|
|||||||
export function truncate(s: string, truncateTo: number, ellipsis: string = '\u2026') {
|
export function truncate(s: string, truncateTo: number, ellipsis: string = '\u2026') {
|
||||||
if (!s) return s;
|
if (!s) return s;
|
||||||
|
|
||||||
const len = getWidth(s);
|
const len = width(s);
|
||||||
if (len <= truncateTo) return s;
|
if (len <= truncateTo) return s;
|
||||||
if (len === s.length) return `${s.substring(0, truncateTo - 1)}${ellipsis}`;
|
if (len === s.length) return `${s.substring(0, truncateTo - 1)}${ellipsis}`;
|
||||||
|
|
||||||
// Skip ahead to start as far as we can by assuming all the double-width characters won't be truncated
|
// Skip ahead to start as far as we can by assuming all the double-width characters won't be truncated
|
||||||
let chars = Math.floor(truncateTo / (len / s.length));
|
let chars = Math.floor(truncateTo / (len / s.length));
|
||||||
let count = getWidth(s.substring(0, chars));
|
let count = width(s.substring(0, chars));
|
||||||
while (count < truncateTo) {
|
while (count < truncateTo) {
|
||||||
count += getWidth(s[chars++]);
|
count += width(s[chars++]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count >= truncateTo) {
|
if (count >= truncateTo) {
|
||||||
@@ -129,4 +124,107 @@ export namespace Strings {
|
|||||||
|
|
||||||
return `${s.substring(0, chars)}${ellipsis}`;
|
return `${s.substring(0, chars)}${ellipsis}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ansiRegex = /[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))/g;
|
||||||
|
|
||||||
|
export function width(s: string): number {
|
||||||
|
if (!s || s.length === 0) return 0;
|
||||||
|
|
||||||
|
s = s.replace(ansiRegex, '');
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
let emoji = 0;
|
||||||
|
let joiners = 0;
|
||||||
|
|
||||||
|
const graphemes = [...s];
|
||||||
|
for (let i = 0; i < graphemes.length; i++) {
|
||||||
|
const code = graphemes[i].codePointAt(0)!;
|
||||||
|
|
||||||
|
// Ignore control characters
|
||||||
|
if (code <= 0x1F || (code >= 0x7F && code <= 0x9F)) continue;
|
||||||
|
|
||||||
|
// Ignore combining characters
|
||||||
|
if (code >= 0x300 && code <= 0x36F) continue;
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/30757193/find-out-if-character-in-string-is-emoji
|
||||||
|
if (
|
||||||
|
(code >= 0x1F600 && code <= 0x1F64F) || // Emoticons
|
||||||
|
(code >= 0x1F300 && code <= 0x1F5FF) || // Misc Symbols and Pictographs
|
||||||
|
(code >= 0x1F680 && code <= 0x1F6FF) || // Transport and Map
|
||||||
|
(code >= 0x2600 && code <= 0x26FF) || // Misc symbols
|
||||||
|
(code >= 0x2700 && code <= 0x27BF) || // Dingbats
|
||||||
|
(code >= 0xFE00 && code <= 0xFE0F) || // Variation Selectors
|
||||||
|
(code >= 0x1F900 && code <= 0x1F9FF) || // Supplemental Symbols and Pictographs
|
||||||
|
(code >= 65024 && code <= 65039) || // Variation selector
|
||||||
|
(code >= 8400 && code <= 8447) // Combining Diacritical Marks for Symbols
|
||||||
|
) {
|
||||||
|
if (code >= 0x1F3FB && code <= 0x1F3FF) continue; // emoji modifier fitzpatrick type
|
||||||
|
|
||||||
|
emoji++;
|
||||||
|
count += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore zero-width joiners '\u200d'
|
||||||
|
if (code === 8205) {
|
||||||
|
joiners++;
|
||||||
|
count -= 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Surrogates
|
||||||
|
if (code > 0xFFFF) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
count += isFullwidthCodePoint(code) ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const offset = emoji - joiners;
|
||||||
|
if (offset > 1) {
|
||||||
|
count += offset - 1;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFullwidthCodePoint(cp: number) {
|
||||||
|
// code points are derived from:
|
||||||
|
// http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt
|
||||||
|
if (
|
||||||
|
cp >= 0x1100 && (
|
||||||
|
cp <= 0x115f || // Hangul Jamo
|
||||||
|
cp === 0x2329 || // LEFT-POINTING ANGLE BRACKET
|
||||||
|
cp === 0x232a || // RIGHT-POINTING ANGLE BRACKET
|
||||||
|
// CJK Radicals Supplement .. Enclosed CJK Letters and Months
|
||||||
|
(0x2e80 <= cp && cp <= 0x3247 && cp !== 0x303f) ||
|
||||||
|
// Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A
|
||||||
|
(0x3250 <= cp && cp <= 0x4dbf) ||
|
||||||
|
// CJK Unified Ideographs .. Yi Radicals
|
||||||
|
(0x4e00 <= cp && cp <= 0xa4c6) ||
|
||||||
|
// Hangul Jamo Extended-A
|
||||||
|
(0xa960 <= cp && cp <= 0xa97c) ||
|
||||||
|
// Hangul Syllables
|
||||||
|
(0xac00 <= cp && cp <= 0xd7a3) ||
|
||||||
|
// CJK Compatibility Ideographs
|
||||||
|
(0xf900 <= cp && cp <= 0xfaff) ||
|
||||||
|
// Vertical Forms
|
||||||
|
(0xfe10 <= cp && cp <= 0xfe19) ||
|
||||||
|
// CJK Compatibility Forms .. Small Form Variants
|
||||||
|
(0xfe30 <= cp && cp <= 0xfe6b) ||
|
||||||
|
// Halfwidth and Fullwidth Forms
|
||||||
|
(0xff01 <= cp && cp <= 0xff60) ||
|
||||||
|
(0xffe0 <= cp && cp <= 0xffe6) ||
|
||||||
|
// Kana Supplement
|
||||||
|
(0x1b000 <= cp && cp <= 0x1b001) ||
|
||||||
|
// Enclosed Ideographic Supplement
|
||||||
|
(0x1f200 <= cp && cp <= 0x1f251) ||
|
||||||
|
// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
|
||||||
|
(0x20000 <= cp && cp <= 0x3fffd)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
||||||
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
||||||
import { ExplorerNode, ResourceType } from './explorerNode';
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
import { CommitFormatter, getGitStatusIcon, GitBranch, GitCommit, GitService, GitUri, ICommitFormatOptions, IGitStatusFile, StatusFileFormatter } from '../gitService';
|
import { CommitFormatter, getGitStatusIcon, GitBranch, GitCommit, GitService, GitUri, ICommitFormatOptions, IGitStatusFile, IStatusFormatOptions, StatusFileFormatter } from '../gitService';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
export enum CommitFileNodeDisplayAs {
|
export enum CommitFileNodeDisplayAs {
|
||||||
@@ -17,6 +17,8 @@ export enum CommitFileNodeDisplayAs {
|
|||||||
|
|
||||||
export class CommitFileNode extends ExplorerNode {
|
export class CommitFileNode extends ExplorerNode {
|
||||||
|
|
||||||
|
readonly priority: boolean = false;
|
||||||
|
readonly repoPath: string;
|
||||||
readonly resourceType: ResourceType = 'gitlens:commit-file';
|
readonly resourceType: ResourceType = 'gitlens:commit-file';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -28,6 +30,7 @@ export class CommitFileNode extends ExplorerNode {
|
|||||||
public readonly branch?: GitBranch
|
public readonly branch?: GitBranch
|
||||||
) {
|
) {
|
||||||
super(new GitUri(Uri.file(path.resolve(commit.repoPath, status.fileName)), { repoPath: commit.repoPath, fileName: status.fileName, sha: commit.sha }));
|
super(new GitUri(Uri.file(path.resolve(commit.repoPath, status.fileName)), { repoPath: commit.repoPath, fileName: status.fileName, sha: commit.sha }));
|
||||||
|
this.repoPath = commit.repoPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
@@ -36,20 +39,13 @@ export class CommitFileNode extends ExplorerNode {
|
|||||||
|
|
||||||
async getTreeItem(): Promise<TreeItem> {
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
if (this.commit.type !== 'file') {
|
if (this.commit.type !== 'file') {
|
||||||
const log = await this.git.getLogForFile(this.commit.repoPath, this.status.fileName, this.commit.sha, { maxCount: 2 });
|
const log = await this.git.getLogForFile(this.repoPath, this.status.fileName, this.commit.sha, { maxCount: 2 });
|
||||||
if (log !== undefined) {
|
if (log !== undefined) {
|
||||||
this.commit = log.commits.get(this.commit.sha) || this.commit;
|
this.commit = log.commits.get(this.commit.sha) || this.commit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const label = (this.displayAs & CommitFileNodeDisplayAs.CommitLabel)
|
const item = new TreeItem(this.label, TreeItemCollapsibleState.None);
|
||||||
? CommitFormatter.fromTemplate(this.getCommitTemplate(), this.commit, {
|
|
||||||
truncateMessageAtNewLine: true,
|
|
||||||
dataFormat: this.git.config.defaultDateFormat
|
|
||||||
} as ICommitFormatOptions)
|
|
||||||
: StatusFileFormatter.fromTemplate(this.getCommitFileTemplate(), this.status);
|
|
||||||
|
|
||||||
const item = new TreeItem(label, TreeItemCollapsibleState.None);
|
|
||||||
item.contextValue = this.resourceType;
|
item.contextValue = this.resourceType;
|
||||||
|
|
||||||
const icon = (this.displayAs & CommitFileNodeDisplayAs.CommitIcon)
|
const icon = (this.displayAs & CommitFileNodeDisplayAs.CommitIcon)
|
||||||
@@ -63,9 +59,44 @@ export class CommitFileNode extends ExplorerNode {
|
|||||||
|
|
||||||
item.command = this.getCommand();
|
item.command = this.getCommand();
|
||||||
|
|
||||||
|
// Only cache the label for a single refresh
|
||||||
|
this._label = undefined;
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _folderName: string | undefined;
|
||||||
|
get folderName() {
|
||||||
|
if (this._folderName === undefined) {
|
||||||
|
this._folderName = path.dirname(this.uri.getRelativePath());
|
||||||
|
}
|
||||||
|
return this._folderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _label: string | undefined;
|
||||||
|
get label() {
|
||||||
|
if (this._label === undefined) {
|
||||||
|
this._label = (this.displayAs & CommitFileNodeDisplayAs.CommitLabel)
|
||||||
|
? CommitFormatter.fromTemplate(this.getCommitTemplate(), this.commit, {
|
||||||
|
truncateMessageAtNewLine: true,
|
||||||
|
dataFormat: this.git.config.defaultDateFormat
|
||||||
|
} as ICommitFormatOptions)
|
||||||
|
: StatusFileFormatter.fromTemplate(this.getCommitFileTemplate(),
|
||||||
|
this.status,
|
||||||
|
{ relativePath: this.relativePath } as IStatusFormatOptions);
|
||||||
|
}
|
||||||
|
return this._label;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _relativePath: string | undefined;
|
||||||
|
get relativePath(): string | undefined {
|
||||||
|
return this._relativePath;
|
||||||
|
}
|
||||||
|
set relativePath(value: string | undefined) {
|
||||||
|
this._relativePath = value;
|
||||||
|
this._label = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
protected getCommitTemplate() {
|
protected getCommitTemplate() {
|
||||||
return this.git.config.gitExplorer.commitFormat;
|
return this.git.config.gitExplorer.commitFormat;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import { Iterables } from '../system';
|
import { Arrays, Iterables } from '../system';
|
||||||
import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
||||||
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
||||||
import { CommitFileNode, CommitFileNodeDisplayAs } from './commitFileNode';
|
import { CommitFileNode, CommitFileNodeDisplayAs } from './commitFileNode';
|
||||||
|
import { GitExplorerFilesLayout } from '../configuration';
|
||||||
|
import { FolderNode, IFileExplorerNode } from './folderNode';
|
||||||
import { ExplorerNode, ResourceType } from './explorerNode';
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
import { CommitFormatter, GitBranch, GitLogCommit, GitService, GitUri, ICommitFormatOptions } from '../gitService';
|
import { CommitFormatter, GitBranch, GitLogCommit, GitService, GitUri, ICommitFormatOptions } from '../gitService';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
export class CommitNode extends ExplorerNode {
|
export class CommitNode extends ExplorerNode {
|
||||||
|
|
||||||
|
readonly repoPath: string;
|
||||||
readonly resourceType: ResourceType = 'gitlens:commit';
|
readonly resourceType: ResourceType = 'gitlens:commit';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -17,16 +21,33 @@ export class CommitNode extends ExplorerNode {
|
|||||||
public readonly branch?: GitBranch
|
public readonly branch?: GitBranch
|
||||||
) {
|
) {
|
||||||
super(new GitUri(commit.uri, commit));
|
super(new GitUri(commit.uri, commit));
|
||||||
|
this.repoPath = commit.repoPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
const log = await this.git.getLogForRepo(this.commit.repoPath, this.commit.sha, 1);
|
const repoPath = this.repoPath;
|
||||||
|
|
||||||
|
const log = await this.git.getLogForRepo(repoPath, this.commit.sha, 1);
|
||||||
if (log === undefined) return [];
|
if (log === undefined) return [];
|
||||||
|
|
||||||
const commit = Iterables.first(log.commits.values());
|
const commit = Iterables.first(log.commits.values());
|
||||||
if (commit === undefined) return [];
|
if (commit === undefined) return [];
|
||||||
|
|
||||||
return [...Iterables.map(commit.fileStatuses, s => new CommitFileNode(s, commit, this.context, this.git, CommitFileNodeDisplayAs.File, this.branch))];
|
let children: IFileExplorerNode[] = [
|
||||||
|
...Iterables.map(commit.fileStatuses, s => new CommitFileNode(s, commit, this.context, this.git, CommitFileNodeDisplayAs.File, this.branch))
|
||||||
|
];
|
||||||
|
|
||||||
|
if (this.git.config.gitExplorer.files.layout !== GitExplorerFilesLayout.List) {
|
||||||
|
const hierarchy = Arrays.makeHierarchical(children, n => n.uri.getRelativePath().split('/'),
|
||||||
|
(...paths: string[]) => GitService.normalizePath(path.join(...paths)), this.git.config.gitExplorer.files.compact);
|
||||||
|
|
||||||
|
const root = new FolderNode(repoPath, '', undefined, hierarchy, this.git.config.gitExplorer);
|
||||||
|
children = await root.getChildren() as IFileExplorerNode[];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
children.sort((a, b) => a.label!.localeCompare(b.label!));
|
||||||
|
}
|
||||||
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTreeItem(): TreeItem {
|
getTreeItem(): TreeItem {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export declare type ResourceType =
|
|||||||
'gitlens:commit' |
|
'gitlens:commit' |
|
||||||
'gitlens:commit-file' |
|
'gitlens:commit-file' |
|
||||||
'gitlens:file-history' |
|
'gitlens:file-history' |
|
||||||
|
'gitlens:folder' |
|
||||||
'gitlens:history' |
|
'gitlens:history' |
|
||||||
'gitlens:message' |
|
'gitlens:message' |
|
||||||
'gitlens:pager' |
|
'gitlens:pager' |
|
||||||
|
|||||||
85
src/views/folderNode.ts
Normal file
85
src/views/folderNode.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
'use strict';
|
||||||
|
import { Arrays, Objects } from '../system';
|
||||||
|
import { TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
||||||
|
import { GitExplorerFilesLayout, IGitExplorerConfig } from '../configuration';
|
||||||
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
|
import { GitUri } from '../gitService';
|
||||||
|
|
||||||
|
export interface IFileExplorerNode extends ExplorerNode {
|
||||||
|
folderName: string;
|
||||||
|
label?: string;
|
||||||
|
priority: boolean;
|
||||||
|
relativePath?: string;
|
||||||
|
root?: Arrays.IHierarchicalItem<IFileExplorerNode>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FolderNode extends ExplorerNode {
|
||||||
|
|
||||||
|
readonly priority: boolean = true;
|
||||||
|
readonly resourceType: ResourceType = 'gitlens:folder';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public readonly repoPath: string,
|
||||||
|
public folderName: string,
|
||||||
|
public relativePath: string | undefined,
|
||||||
|
public readonly root: Arrays.IHierarchicalItem<IFileExplorerNode>,
|
||||||
|
private readonly config: IGitExplorerConfig
|
||||||
|
) {
|
||||||
|
super(new GitUri(Uri.file(repoPath), { repoPath: repoPath, fileName: repoPath }));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChildren(): Promise<(FolderNode | IFileExplorerNode)[]> {
|
||||||
|
if (this.root.descendants === undefined || this.root.children === undefined) return [];
|
||||||
|
|
||||||
|
let children: (FolderNode | IFileExplorerNode)[];
|
||||||
|
|
||||||
|
const nesting = FolderNode.getFileNesting(this.config, this.root.descendants, this.relativePath === undefined);
|
||||||
|
if (nesting !== GitExplorerFilesLayout.List) {
|
||||||
|
children = [];
|
||||||
|
for (const folder of Objects.values(this.root.children)) {
|
||||||
|
if (folder.value === undefined) {
|
||||||
|
children.push(new FolderNode(this.repoPath, folder.name, folder.relativePath, folder, this.config));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
folder.value.relativePath = this.root.relativePath;
|
||||||
|
children.push(folder.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.root.descendants.forEach(n => n.relativePath = this.root.relativePath);
|
||||||
|
children = this.root.descendants;
|
||||||
|
}
|
||||||
|
|
||||||
|
children.sort((a, b) => {
|
||||||
|
return ((a instanceof FolderNode) ? -1 : 1) - ((b instanceof FolderNode) ? -1 : 1) ||
|
||||||
|
(a.priority ? -1 : 1) - (b.priority ? -1 : 1) ||
|
||||||
|
a.label!.localeCompare(b.label!);
|
||||||
|
});
|
||||||
|
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
|
// TODO: Change this to expanded once https://github.com/Microsoft/vscode/issues/30918 is fixed
|
||||||
|
const item = new TreeItem(this.label, TreeItemCollapsibleState.Collapsed);
|
||||||
|
item.contextValue = this.resourceType;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
get label(): string {
|
||||||
|
return this.folderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getFileNesting<T extends IFileExplorerNode>(config: IGitExplorerConfig, children: T[], isRoot: boolean): GitExplorerFilesLayout {
|
||||||
|
const nesting = config.files.layout || GitExplorerFilesLayout.Auto;
|
||||||
|
if (nesting === GitExplorerFilesLayout.Auto) {
|
||||||
|
if (isRoot || config.files.compact) {
|
||||||
|
const nestingThreshold = config.files.threshold || 5;
|
||||||
|
if (children.length <= nestingThreshold) return GitExplorerFilesLayout.List;
|
||||||
|
}
|
||||||
|
return GitExplorerFilesLayout.Tree;
|
||||||
|
}
|
||||||
|
return nesting;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,16 +4,18 @@ import { commands, Event, EventEmitter, ExtensionContext, TextDocumentShowOption
|
|||||||
import { Commands, DiffWithCommandArgs, DiffWithCommandArgsRevision, DiffWithPreviousCommandArgs, DiffWithWorkingCommandArgs, openEditor, OpenFileInRemoteCommandArgs } from '../commands';
|
import { Commands, DiffWithCommandArgs, DiffWithCommandArgsRevision, DiffWithPreviousCommandArgs, DiffWithWorkingCommandArgs, openEditor, OpenFileInRemoteCommandArgs } from '../commands';
|
||||||
import { UriComparer } from '../comparers';
|
import { UriComparer } from '../comparers';
|
||||||
import { ExtensionKey, IConfig } from '../configuration';
|
import { ExtensionKey, IConfig } from '../configuration';
|
||||||
import { CommandContext, setCommandContext } from '../constants';
|
import { CommandContext, setCommandContext, WorkspaceState } from '../constants';
|
||||||
import { BranchHistoryNode, CommitFileNode, CommitNode, ExplorerNode, HistoryNode, MessageNode, RepositoryNode, StashNode } from './explorerNodes';
|
import { BranchHistoryNode, CommitFileNode, CommitNode, ExplorerNode, HistoryNode, MessageNode, RepositoryNode, StashNode } from './explorerNodes';
|
||||||
import { GitService, GitUri, RepoChangedReasons } from '../gitService';
|
import { GitService, GitUri, RepoChangedReasons } from '../gitService';
|
||||||
|
|
||||||
export * from './explorerNodes';
|
export * from './explorerNodes';
|
||||||
|
|
||||||
export type GitExplorerView =
|
export type GitExplorerView =
|
||||||
|
'auto' |
|
||||||
'history' |
|
'history' |
|
||||||
'repository';
|
'repository';
|
||||||
export const GitExplorerView = {
|
export const GitExplorerView = {
|
||||||
|
Auto: 'auto' as GitExplorerView,
|
||||||
History: 'history' as GitExplorerView,
|
History: 'history' as GitExplorerView,
|
||||||
Repository: 'repository' as GitExplorerView
|
Repository: 'repository' as GitExplorerView
|
||||||
};
|
};
|
||||||
@@ -31,7 +33,7 @@ export class GitExplorer implements TreeDataProvider<ExplorerNode> {
|
|||||||
|
|
||||||
private _config: IConfig;
|
private _config: IConfig;
|
||||||
private _root?: ExplorerNode;
|
private _root?: ExplorerNode;
|
||||||
private _view: GitExplorerView = GitExplorerView.Repository;
|
private _view: GitExplorerView | undefined;
|
||||||
|
|
||||||
private _onDidChangeTreeData = new EventEmitter<ExplorerNode>();
|
private _onDidChangeTreeData = new EventEmitter<ExplorerNode>();
|
||||||
public get onDidChangeTreeData(): Event<ExplorerNode> {
|
public get onDidChangeTreeData(): Event<ExplorerNode> {
|
||||||
@@ -62,10 +64,6 @@ export class GitExplorer implements TreeDataProvider<ExplorerNode> {
|
|||||||
context.subscriptions.push(workspace.onDidChangeConfiguration(this.onConfigurationChanged, this));
|
context.subscriptions.push(workspace.onDidChangeConfiguration(this.onConfigurationChanged, this));
|
||||||
|
|
||||||
this.onConfigurationChanged();
|
this.onConfigurationChanged();
|
||||||
|
|
||||||
this._view = this._config.gitExplorer.view;
|
|
||||||
setCommandContext(CommandContext.GitExplorerView, this._view);
|
|
||||||
this._root = this.getRootNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTreeItem(node: ExplorerNode): Promise<TreeItem> {
|
async getTreeItem(node: ExplorerNode): Promise<TreeItem> {
|
||||||
@@ -83,14 +81,14 @@ export class GitExplorer implements TreeDataProvider<ExplorerNode> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getRootNode(editor?: TextEditor): ExplorerNode | undefined {
|
private getRootNode(editor?: TextEditor): ExplorerNode | undefined {
|
||||||
const uri = new GitUri(Uri.file(this.git.repoPath), { repoPath: this.git.repoPath, fileName: this.git.repoPath });
|
|
||||||
|
|
||||||
switch (this._view) {
|
switch (this._view) {
|
||||||
case GitExplorerView.History: return this.getHistoryNode(editor || window.activeTextEditor);
|
case GitExplorerView.History:
|
||||||
case GitExplorerView.Repository: return new RepositoryNode(uri, this.context, this.git);
|
return this.getHistoryNode(editor || window.activeTextEditor);
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
default:
|
||||||
|
const uri = new GitUri(Uri.file(this.git.repoPath), { repoPath: this.git.repoPath, fileName: this.git.repoPath });
|
||||||
|
return new RepositoryNode(uri, this.context, this.git);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getHistoryNode(editor: TextEditor | undefined): ExplorerNode | undefined {
|
private getHistoryNode(editor: TextEditor | undefined): ExplorerNode | undefined {
|
||||||
@@ -116,15 +114,21 @@ export class GitExplorer implements TreeDataProvider<ExplorerNode> {
|
|||||||
private onConfigurationChanged() {
|
private onConfigurationChanged() {
|
||||||
const cfg = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
|
const cfg = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
|
||||||
|
|
||||||
if (!Objects.areEquivalent(cfg.gitExplorer, this._config && this._config.gitExplorer)) {
|
const changed = !Objects.areEquivalent(cfg.gitExplorer, this._config && this._config.gitExplorer);
|
||||||
setTimeout(() => {
|
|
||||||
this._root = this.getRootNode(window.activeTextEditor);
|
|
||||||
this.refresh();
|
|
||||||
}, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._config = cfg;
|
this._config = cfg;
|
||||||
}
|
|
||||||
|
if (changed) {
|
||||||
|
let view = cfg.gitExplorer.view;
|
||||||
|
if (view === GitExplorerView.Auto) {
|
||||||
|
view = this.context.workspaceState.get<GitExplorerView>(WorkspaceState.GitExplorerView, GitExplorerView.Repository);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setView(view);
|
||||||
|
this._root = this.getRootNode(window.activeTextEditor);
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private onRepoChanged(reasons: RepoChangedReasons[]) {
|
private onRepoChanged(reasons: RepoChangedReasons[]) {
|
||||||
if (this._view !== GitExplorerView.Repository) return;
|
if (this._view !== GitExplorerView.Repository) return;
|
||||||
@@ -148,12 +152,26 @@ export class GitExplorer implements TreeDataProvider<ExplorerNode> {
|
|||||||
this.refresh(node);
|
this.refresh(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
switchTo(view: GitExplorerView) {
|
setView(view: GitExplorerView) {
|
||||||
if (this._view === view) return;
|
if (this._view === view) return;
|
||||||
|
|
||||||
|
if (this._config.gitExplorer.view === GitExplorerView.Auto) {
|
||||||
|
this.context.workspaceState.update(WorkspaceState.GitExplorerView, view);
|
||||||
|
}
|
||||||
|
|
||||||
this._view = view;
|
this._view = view;
|
||||||
setCommandContext(CommandContext.GitExplorerView, this._view);
|
setCommandContext(CommandContext.GitExplorerView, this._view);
|
||||||
|
|
||||||
|
if (view !== GitExplorerView.Repository) {
|
||||||
|
this.git.stopWatchingFileSystem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switchTo(view: GitExplorerView) {
|
||||||
|
if (this._view === view) return;
|
||||||
|
|
||||||
|
this.setView(view);
|
||||||
|
|
||||||
this._root = this.getRootNode(window.activeTextEditor);
|
this._root = this.getRootNode(window.activeTextEditor);
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ export class StashNode extends ExplorerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return statuses.map(s => new StashFileNode(s, this.commit, this.context, this.git));
|
const children = statuses.map(s => new StashFileNode(s, this.commit, this.context, this.git));
|
||||||
|
children.sort((a, b) => a.label!.localeCompare(b.label!));
|
||||||
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTreeItem(): TreeItem {
|
getTreeItem(): TreeItem {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } fr
|
|||||||
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
|
||||||
import { CommitFileNode, CommitFileNodeDisplayAs } from './commitFileNode';
|
import { CommitFileNode, CommitFileNodeDisplayAs } from './commitFileNode';
|
||||||
import { ExplorerNode, ResourceType } from './explorerNode';
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
import { getGitStatusIcon, GitBranch, GitLogCommit, GitService, GitUri, IGitStatusFile, StatusFileFormatter } from '../gitService';
|
import { getGitStatusIcon, GitBranch, GitLogCommit, GitService, GitUri, IGitStatusFile, IGitStatusFileWithCommit, IStatusFormatOptions, StatusFileFormatter } from '../gitService';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
export class StatusFileCommitsNode extends ExplorerNode {
|
export class StatusFileCommitsNode extends ExplorerNode {
|
||||||
@@ -11,7 +11,7 @@ export class StatusFileCommitsNode extends ExplorerNode {
|
|||||||
readonly resourceType: ResourceType = 'gitlens:status-file-commits';
|
readonly resourceType: ResourceType = 'gitlens:status-file-commits';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
repoPath: string,
|
public readonly repoPath: string,
|
||||||
public readonly status: IGitStatusFile,
|
public readonly status: IGitStatusFile,
|
||||||
public commits: GitLogCommit[],
|
public commits: GitLogCommit[],
|
||||||
protected readonly context: ExtensionContext,
|
protected readonly context: ExtensionContext,
|
||||||
@@ -26,7 +26,7 @@ export class StatusFileCommitsNode extends ExplorerNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getTreeItem(): Promise<TreeItem> {
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
const item = new TreeItem(StatusFileFormatter.fromTemplate(this.git.config.gitExplorer.commitFileFormat, this.status), TreeItemCollapsibleState.Collapsed);
|
const item = new TreeItem(this.label, TreeItemCollapsibleState.Collapsed);
|
||||||
item.contextValue = this.resourceType;
|
item.contextValue = this.resourceType;
|
||||||
|
|
||||||
const icon = getGitStatusIcon(this.status.status);
|
const icon = getGitStatusIcon(this.status.status);
|
||||||
@@ -41,19 +41,53 @@ export class StatusFileCommitsNode extends ExplorerNode {
|
|||||||
item.command = this.getCommand();
|
item.command = this.getCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only cache the label for a single refresh
|
||||||
|
this._label = undefined;
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _folderName: string | undefined;
|
||||||
|
get folderName() {
|
||||||
|
if (this._folderName === undefined) {
|
||||||
|
this._folderName = path.dirname(this.uri.getRelativePath());
|
||||||
|
}
|
||||||
|
return this._folderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _label: string | undefined;
|
||||||
|
get label() {
|
||||||
|
if (this._label === undefined) {
|
||||||
|
this._label = StatusFileFormatter.fromTemplate(this.git.config.gitExplorer.statusFileFormat,
|
||||||
|
{ ...this.status, commit: this.commit } as IGitStatusFileWithCommit,
|
||||||
|
{ relativePath: this.relativePath } as IStatusFormatOptions);
|
||||||
|
}
|
||||||
|
return this._label;
|
||||||
|
}
|
||||||
|
|
||||||
get commit() {
|
get commit() {
|
||||||
return this.commits[0];
|
return this.commits[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get priority(): boolean {
|
||||||
|
return this.commit.isUncommitted;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _relativePath: string | undefined;
|
||||||
|
get relativePath(): string | undefined {
|
||||||
|
return this._relativePath;
|
||||||
|
}
|
||||||
|
set relativePath(value: string | undefined) {
|
||||||
|
this._relativePath = value;
|
||||||
|
this._label = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
getCommand(): Command | undefined {
|
getCommand(): Command | undefined {
|
||||||
return {
|
return {
|
||||||
title: 'Compare File with Previous Revision',
|
title: 'Compare File with Previous Revision',
|
||||||
command: Commands.DiffWithPrevious,
|
command: Commands.DiffWithPrevious,
|
||||||
arguments: [
|
arguments: [
|
||||||
GitUri.fromFileStatus(this.status, this.uri.repoPath!),
|
GitUri.fromFileStatus(this.status, this.repoPath),
|
||||||
{
|
{
|
||||||
commit: this.commit,
|
commit: this.commit,
|
||||||
line: 0,
|
line: 0,
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import { Arrays, Iterables, Objects } from '../system';
|
import { Arrays, Iterables, Objects } from '../system';
|
||||||
import { ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
import { ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
||||||
|
import { GitExplorerFilesLayout } from '../configuration';
|
||||||
import { ExplorerNode, ResourceType, ShowAllNode } from './explorerNode';
|
import { ExplorerNode, ResourceType, ShowAllNode } from './explorerNode';
|
||||||
import { GitBranch, GitLog, GitLogCommit, GitService, GitStatus, GitUri, IGitStatusFile } from '../gitService';
|
import { FolderNode, IFileExplorerNode } from './folderNode';
|
||||||
|
import { GitBranch, GitLog, GitLogCommit, GitService, GitStatus, GitUri, IGitStatusFileWithCommit } from '../gitService';
|
||||||
import { StatusFileCommitsNode } from './statusFileCommitsNode';
|
import { StatusFileCommitsNode } from './statusFileCommitsNode';
|
||||||
|
import * as path from 'path';
|
||||||
interface IGitStatusFileWithCommit extends IGitStatusFile {
|
|
||||||
commit: GitLogCommit;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StatusFilesNode extends ExplorerNode {
|
export class StatusFilesNode extends ExplorerNode {
|
||||||
|
|
||||||
|
readonly repoPath: string;
|
||||||
readonly resourceType: ResourceType = 'gitlens:status-files';
|
readonly resourceType: ResourceType = 'gitlens:status-files';
|
||||||
|
|
||||||
maxCount: number | undefined = undefined;
|
maxCount: number | undefined = undefined;
|
||||||
@@ -23,48 +23,81 @@ export class StatusFilesNode extends ExplorerNode {
|
|||||||
public readonly branch?: GitBranch
|
public readonly branch?: GitBranch
|
||||||
) {
|
) {
|
||||||
super(new GitUri(Uri.file(status.repoPath), { repoPath: status.repoPath, fileName: status.repoPath }));
|
super(new GitUri(Uri.file(status.repoPath), { repoPath: status.repoPath, fileName: status.repoPath }));
|
||||||
|
this.repoPath = status.repoPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(): Promise<ExplorerNode[]> {
|
async getChildren(): Promise<ExplorerNode[]> {
|
||||||
let statuses: IGitStatusFileWithCommit[];
|
let statuses: IGitStatusFileWithCommit[] = [];
|
||||||
|
|
||||||
|
const repoPath = this.repoPath;
|
||||||
|
|
||||||
let log: GitLog | undefined;
|
let log: GitLog | undefined;
|
||||||
if (this.range !== undefined) {
|
if (this.range !== undefined) {
|
||||||
log = await this.git.getLogForRepo(this.status.repoPath, this.range, this.maxCount);
|
log = await this.git.getLogForRepo(repoPath, this.range, this.maxCount);
|
||||||
if (log === undefined) return [];
|
if (log !== undefined) {
|
||||||
|
statuses = Array.from(Iterables.flatMap(log.commits.values(), c => {
|
||||||
statuses = Array.from(Iterables.flatMap(log.commits.values(), c => {
|
return c.fileStatuses.map(s => {
|
||||||
return c.fileStatuses.map(s => {
|
return { ...s, commit: c } as IGitStatusFileWithCommit;
|
||||||
return { ...s, commit: c } as IGitStatusFileWithCommit;
|
});
|
||||||
});
|
}));
|
||||||
}));
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
statuses = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.status.files.length !== 0) {
|
if (this.status.files.length !== 0 && this.includeWorkingTree) {
|
||||||
statuses.splice(0, 0, ...this.status.files.map(s => {
|
statuses.splice(0, 0, ...this.status.files.map(s => {
|
||||||
return { ...s, commit: new GitLogCommit('file', this.status.repoPath, GitService.uncommittedSha, s.fileName, 'You', new Date(), '', s.status, [s], s.originalFileName, 'HEAD', s.fileName) } as IGitStatusFileWithCommit;
|
return {
|
||||||
|
...s,
|
||||||
|
commit: new GitLogCommit('file', repoPath, GitService.uncommittedSha, s.fileName, 'You', new Date(), '', s.status, [s], s.originalFileName, 'HEAD', s.fileName)
|
||||||
|
} as IGitStatusFileWithCommit;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
statuses.sort((a, b) => b.commit.date.getTime() - a.commit.date.getTime());
|
statuses.sort((a, b) => b.commit.date.getTime() - a.commit.date.getTime());
|
||||||
|
|
||||||
const groups = Arrays.groupBy(statuses, s => s.fileName);
|
const groups = Arrays.groupBy(statuses, s => s.fileName);
|
||||||
|
|
||||||
const children: (StatusFileCommitsNode | ShowAllNode)[] = [
|
let children: IFileExplorerNode[] = [
|
||||||
...Iterables.map(Objects.values<IGitStatusFileWithCommit[]>(groups),
|
...Iterables.map(Objects.values(groups), statuses => new StatusFileCommitsNode(repoPath, statuses[statuses.length - 1], statuses.map(s => s.commit), this.context, this.git, this.branch))
|
||||||
statuses => new StatusFileCommitsNode(this.uri.repoPath!, statuses[statuses.length - 1], statuses.map(s => s.commit), this.context, this.git, this.branch))
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (this.git.config.gitExplorer.files.layout !== GitExplorerFilesLayout.List) {
|
||||||
|
const hierarchy = Arrays.makeHierarchical(children, n => n.uri.getRelativePath().split('/'),
|
||||||
|
(...paths: string[]) => GitService.normalizePath(path.join(...paths)), this.git.config.gitExplorer.files.compact);
|
||||||
|
|
||||||
|
const root = new FolderNode(repoPath, '', undefined, hierarchy, this.git.config.gitExplorer);
|
||||||
|
children = await root.getChildren() as IFileExplorerNode[];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
children.sort((a, b) => (a.priority ? -1 : 1) - (b.priority ? -1 : 1) || a.label!.localeCompare(b.label!));
|
||||||
|
}
|
||||||
|
|
||||||
if (log !== undefined && log.truncated) {
|
if (log !== undefined && log.truncated) {
|
||||||
children.push(new ShowAllNode('Show All Changes', this, this.context));
|
(children as (IFileExplorerNode | ShowAllNode)[]).push(new ShowAllNode('Show All Changes', this, this.context));
|
||||||
}
|
}
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTreeItem(): Promise<TreeItem> {
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
const item = new TreeItem(`Changed Files`, TreeItemCollapsibleState.Collapsed);
|
let files = (this.status.files !== undefined && this.includeWorkingTree) ? this.status.files.length : 0;
|
||||||
|
|
||||||
|
if (this.status.upstream !== undefined) {
|
||||||
|
const stats = await this.git.getChangedFilesCount(this.repoPath, `${this.status.upstream}...`);
|
||||||
|
if (stats !== undefined) {
|
||||||
|
files += stats.files;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const label = `${files} file${files > 1 ? 's' : ''} changed`; // ${this.status.upstream === undefined ? '' : ` (ahead of ${this.status.upstream})`}`;
|
||||||
|
const item = new TreeItem(label, TreeItemCollapsibleState.Collapsed);
|
||||||
item.contextValue = this.resourceType;
|
item.contextValue = this.resourceType;
|
||||||
|
item.iconPath = {
|
||||||
|
dark: this.context.asAbsolutePath(`images/dark/icon-diff.svg`),
|
||||||
|
light: this.context.asAbsolutePath(`images/light/icon-diff.svg`)
|
||||||
|
};
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get includeWorkingTree(): boolean {
|
||||||
|
return this.git.config.gitExplorer.includeWorkingTree;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
import { commands, Disposable, ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
|
||||||
import { ExplorerNode, ResourceType } from './explorerNode';
|
import { ExplorerNode, ResourceType } from './explorerNode';
|
||||||
import { GitService, GitUri } from '../gitService';
|
import { GitService, GitStatus, GitUri } from '../gitService';
|
||||||
import { StatusFilesNode } from './statusFilesNode';
|
import { StatusFilesNode } from './statusFilesNode';
|
||||||
import { StatusUpstreamNode } from './statusUpstreamNode';
|
import { StatusUpstreamNode } from './statusUpstreamNode';
|
||||||
|
|
||||||
|
let _eventDisposable: Disposable | undefined;
|
||||||
|
|
||||||
export class StatusNode extends ExplorerNode {
|
export class StatusNode extends ExplorerNode {
|
||||||
|
|
||||||
readonly resourceType: ResourceType = 'gitlens:status';
|
readonly resourceType: ResourceType = 'gitlens:status';
|
||||||
@@ -30,29 +32,45 @@ export class StatusNode extends ExplorerNode {
|
|||||||
children.push(new StatusUpstreamNode(status, 'ahead', this.context, this.git));
|
children.push(new StatusUpstreamNode(status, 'ahead', this.context, this.git));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.files.length !== 0 || status.state.ahead && this.git.config.insiders) {
|
if (status.state.ahead || (status.files.length !== 0 && this.includeWorkingTree)) {
|
||||||
const range = status.state.ahead
|
const range = status.upstream
|
||||||
? `${status.upstream}..${status.branch}`
|
? `${status.upstream}..${status.branch}`
|
||||||
: undefined;
|
: undefined;
|
||||||
children.splice(0, 0, new StatusFilesNode(status, range, this.context, this.git));
|
children.push(new StatusFilesNode(status, range, this.context, this.git));
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTreeItem(): Promise<TreeItem> {
|
private _status: GitStatus | undefined;
|
||||||
|
|
||||||
|
async getTreeItem(): Promise < TreeItem > {
|
||||||
const status = await this.git.getStatusForRepo(this.uri.repoPath!);
|
const status = await this.git.getStatusForRepo(this.uri.repoPath!);
|
||||||
if (status === undefined) return new TreeItem('No repo status');
|
if (status === undefined) return new TreeItem('No repo status');
|
||||||
|
|
||||||
|
if (_eventDisposable !== undefined) {
|
||||||
|
_eventDisposable.dispose();
|
||||||
|
_eventDisposable = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.includeWorkingTree) {
|
||||||
|
this._status = status;
|
||||||
|
|
||||||
|
_eventDisposable = this.git.onDidChangeFileSystem(this.onFileSystemChanged, this);
|
||||||
|
this.git.startWatchingFileSystem();
|
||||||
|
}
|
||||||
|
|
||||||
let hasChildren = false;
|
let hasChildren = false;
|
||||||
|
const hasWorkingChanges = status.files.length !== 0 && this.includeWorkingTree;
|
||||||
let label = '';
|
let label = '';
|
||||||
let iconSuffix = '';
|
let iconSuffix = '';
|
||||||
if (status.upstream) {
|
if (status.upstream) {
|
||||||
if (!status.state.ahead && !status.state.behind) {
|
if (!status.state.ahead && !status.state.behind) {
|
||||||
label = `${status.branch} is up-to-date with ${status.upstream}`;
|
label = `${status.branch}${hasWorkingChanges ? ' has uncommitted changes and' : ''} is up-to-date with ${status.upstream}`;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
label = `${status.branch} is not up-to-date with ${status.upstream}`;
|
label = `${status.branch}${hasWorkingChanges ? ' has uncommitted changes and' : ''} is not up-to-date with ${status.upstream}`;
|
||||||
|
|
||||||
hasChildren = true;
|
hasChildren = true;
|
||||||
if (status.state.ahead && status.state.behind) {
|
if (status.state.ahead && status.state.behind) {
|
||||||
iconSuffix = '-yellow';
|
iconSuffix = '-yellow';
|
||||||
@@ -66,14 +84,10 @@ export class StatusNode extends ExplorerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
label = `${status.branch} is up-to-date`;
|
label = `${status.branch} ${hasWorkingChanges ? 'has uncommitted changes' : this.includeWorkingTree ? 'has no changes' : 'has nothing to commit'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.git.config.insiders) {
|
const item = new TreeItem(label, (hasChildren || hasWorkingChanges) ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None);
|
||||||
hasChildren = hasChildren || status.files.length !== 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const item = new TreeItem(label, hasChildren ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None);
|
|
||||||
item.contextValue = this.resourceType;
|
item.contextValue = this.resourceType;
|
||||||
|
|
||||||
item.iconPath = {
|
item.iconPath = {
|
||||||
@@ -83,4 +97,21 @@ export class StatusNode extends ExplorerNode {
|
|||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get includeWorkingTree(): boolean {
|
||||||
|
return this.git.config.gitExplorer.includeWorkingTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async onFileSystemChanged(uri: Uri) {
|
||||||
|
const status = await this.git.getStatusForRepo(this.uri.repoPath!);
|
||||||
|
|
||||||
|
// If we haven't changed from having some working changes to none or vice versa then just refresh the node
|
||||||
|
// This is because of https://github.com/Microsoft/vscode/issues/34789
|
||||||
|
if (this._status !== undefined && status !== undefined &&
|
||||||
|
((this._status.files.length === status.files.length) || (this._status.files.length > 0 && status.files.length > 0))) {
|
||||||
|
commands.executeCommand('gitlens.gitExplorer.refreshNode', this);
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.executeCommand('gitlens.gitExplorer.refresh');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -43,8 +43,8 @@ export class StatusUpstreamNode extends ExplorerNode {
|
|||||||
|
|
||||||
async getTreeItem(): Promise<TreeItem> {
|
async getTreeItem(): Promise<TreeItem> {
|
||||||
const label = this.direction === 'ahead'
|
const label = this.direction === 'ahead'
|
||||||
? `${this.status.state.ahead} commit${this.status.state.ahead > 1 ? 's' : ''} ahead (local changes)` // of ${this.status.upstream}`
|
? `${this.status.state.ahead} commit${this.status.state.ahead > 1 ? 's' : ''} (ahead of ${this.status.upstream})`
|
||||||
: `${this.status.state.behind} commit${this.status.state.behind > 1 ? 's' : ''} behind (remote changes)`; // ${this.status.upstream}`;
|
: `${this.status.state.behind} commit${this.status.state.behind > 1 ? 's' : ''} (behind ${this.status.upstream})`;
|
||||||
|
|
||||||
const item = new TreeItem(label, TreeItemCollapsibleState.Collapsed);
|
const item = new TreeItem(label, TreeItemCollapsibleState.Collapsed);
|
||||||
item.contextValue = this.resourceType;
|
item.contextValue = this.resourceType;
|
||||||
|
|||||||
Reference in New Issue
Block a user