mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-09 09:42:34 -05:00
Merge vscode 1.67 (#20883)
* Fix initial build breaks from 1.67 merge (#2514) * Update yarn lock files * Update build scripts * Fix tsconfig * Build breaks * WIP * Update yarn lock files * Misc breaks * Updates to package.json * Breaks * Update yarn * Fix breaks * Breaks * Build breaks * Breaks * Breaks * Breaks * Breaks * Breaks * Missing file * Breaks * Breaks * Breaks * Breaks * Breaks * Fix several runtime breaks (#2515) * Missing files * Runtime breaks * Fix proxy ordering issue * Remove commented code * Fix breaks with opening query editor * Fix post merge break * Updates related to setup build and other breaks (#2516) * Fix bundle build issues * Update distro * Fix distro merge and update build JS files * Disable pipeline steps * Remove stats call * Update license name * Make new RPM dependencies a warning * Fix extension manager version checks * Update JS file * Fix a few runtime breaks * Fixes * Fix runtime issues * Fix build breaks * Update notebook tests (part 1) * Fix broken tests * Linting errors * Fix hygiene * Disable lint rules * Bump distro * Turn off smoke tests * Disable integration tests * Remove failing "activate" test * Remove failed test assertion * Disable other broken test * Disable query history tests * Disable extension unit tests * Disable failing tasks
This commit is contained in:
@@ -4,5 +4,4 @@ out/**
|
||||
tsconfig.json
|
||||
build/**
|
||||
extension.webpack.config.js
|
||||
cgmanifest.json
|
||||
yarn.lock
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
var updateGrammar = require('vscode-grammar-updater');
|
||||
|
||||
updateGrammar.update('textmate/git.tmbundle', 'Syntaxes/Git%20Commit%20Message.tmLanguage', './syntaxes/git-commit.tmLanguage.json');
|
||||
updateGrammar.update('textmate/git.tmbundle', 'Syntaxes/Git%20Rebase%20Message.tmLanguage', './syntaxes/git-rebase.tmLanguage.json');
|
||||
updateGrammar.update('textmate/diff.tmbundle', 'Syntaxes/Diff.plist', './syntaxes/diff.tmLanguage.json');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
{
|
||||
"registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"name": "textmate/git.tmbundle",
|
||||
"repositoryUrl": "https://github.com/textmate/git.tmbundle",
|
||||
"commitHash": "5870cf3f8abad3a6637bdf69250b5d2ded427dc4"
|
||||
}
|
||||
},
|
||||
"licenseDetail": [
|
||||
"Copyright (c) 2008 Tim Harper",
|
||||
"",
|
||||
"Permission is hereby granted, free of charge, to any person obtaining",
|
||||
"a copy of this software and associated documentation files (the\"",
|
||||
"Software\"), to deal in the Software without restriction, including",
|
||||
"without limitation the rights to use, copy, modify, merge, publish,",
|
||||
"distribute, sublicense, and/or sell copies of the Software, and to",
|
||||
"permit persons to whom the Software is furnished to do so, subject to",
|
||||
"the following conditions:",
|
||||
"",
|
||||
"The above copyright notice and this permission notice shall be",
|
||||
"included in all copies or substantial portions of the Software.",
|
||||
"",
|
||||
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,",
|
||||
"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF",
|
||||
"MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND",
|
||||
"NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE",
|
||||
"LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
|
||||
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION",
|
||||
"WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
||||
],
|
||||
"license": "MIT",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"name": "textmate/diff.tmbundle",
|
||||
"repositoryUrl": "https://github.com/textmate/diff.tmbundle",
|
||||
"commitHash": "0593bb775eab1824af97ef2172fd38822abd97d7"
|
||||
}
|
||||
},
|
||||
"licenseDetail": [
|
||||
"Copyright (c) textmate-diff.tmbundle project authors",
|
||||
"",
|
||||
"If not otherwise specified (see below), files in this repository fall under the following license:",
|
||||
"",
|
||||
"Permission to copy, use, modify, sell and distribute this",
|
||||
"software is granted. This software is provided \"as is\" without",
|
||||
"express or implied warranty, and with no claim as to its",
|
||||
"suitability for any purpose.",
|
||||
"",
|
||||
"An exception is made for files in readable text which contain their own license information,",
|
||||
"or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added",
|
||||
"to the base-name name of the original file, and an extension of txt, html, or similar. For example",
|
||||
"\"tidy\" is accompanied by \"tidy-license.txt\"."
|
||||
],
|
||||
"license": "TextMate Bundle License",
|
||||
"version": "0.0.0"
|
||||
}
|
||||
],
|
||||
"version": 1
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"comments": {
|
||||
"lineComment": "#",
|
||||
"blockComment": [ "#", " " ]
|
||||
},
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"comments": {
|
||||
"lineComment": "#",
|
||||
"blockComment": [ "#", " " ]
|
||||
},
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"comments": {
|
||||
"lineComment": "#",
|
||||
"blockComment": [ "#", " " ]
|
||||
},
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"comments": {
|
||||
"lineComment": "#",
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,14 @@
|
||||
"vscode": "^1.5.0"
|
||||
},
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"enableProposedApi": true,
|
||||
"enabledApiProposals": [
|
||||
"diffCommand",
|
||||
"contribViewsWelcome",
|
||||
"scmActionButton",
|
||||
"scmSelectedProvider",
|
||||
"scmValidation",
|
||||
"timeline"
|
||||
],
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
@@ -17,19 +24,21 @@
|
||||
"*",
|
||||
"onFileSystem:git"
|
||||
],
|
||||
"extensionDependencies": [
|
||||
"vscode.git-base"
|
||||
],
|
||||
"main": "./out/main",
|
||||
"icon": "resources/icons/git.png",
|
||||
"scripts": {
|
||||
"compile": "gulp compile-extension:git",
|
||||
"watch": "gulp watch-extension:git",
|
||||
"update-emoji": "node ./build/update-emoji.js",
|
||||
"update-grammar": "node ./build/update-grammars.js",
|
||||
"test": "node ../../node_modules/mocha/bin/mocha"
|
||||
},
|
||||
"capabilities": {
|
||||
"virtualWorkspaces": true,
|
||||
"untrustedWorkspaces": {
|
||||
"supported": true
|
||||
"supported": false
|
||||
}
|
||||
},
|
||||
"contributes": {
|
||||
@@ -485,6 +494,11 @@
|
||||
"title": "%command.stashDrop%",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.stashDropAll",
|
||||
"title": "%command.stashDropAll%",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.openDiff",
|
||||
"title": "%command.timelineOpenDiff%",
|
||||
@@ -515,6 +529,26 @@
|
||||
"command": "git.rebaseAbort",
|
||||
"title": "%command.rebaseAbort%",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.closeAllDiffEditors",
|
||||
"title": "%command.closeAllDiffEditors%",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.api.getRepositories",
|
||||
"title": "%command.api.getRepositories%",
|
||||
"category": "Git API"
|
||||
},
|
||||
{
|
||||
"command": "git.api.getRepositoryState",
|
||||
"title": "%command.api.getRepositoryState%",
|
||||
"category": "Git API"
|
||||
},
|
||||
{
|
||||
"command": "git.api.getRemoteSources",
|
||||
"title": "%command.api.getRemoteSources%",
|
||||
"category": "Git API"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
@@ -569,15 +603,15 @@
|
||||
},
|
||||
{
|
||||
"command": "git.openFile",
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && resourceScheme == file && scmActiveResourceHasChanges"
|
||||
},
|
||||
{
|
||||
"command": "git.openHEADFile",
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && resourceScheme == file && scmActiveResourceHasChanges"
|
||||
},
|
||||
{
|
||||
"command": "git.openChange",
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && resourcePath in git.changedResources"
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||
},
|
||||
{
|
||||
"command": "git.stage",
|
||||
@@ -649,7 +683,7 @@
|
||||
},
|
||||
{
|
||||
"command": "git.rename",
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && resourceScheme == file"
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && resourceScheme == file && scmActiveResourceRepository"
|
||||
},
|
||||
{
|
||||
"command": "git.commit",
|
||||
@@ -849,7 +883,7 @@
|
||||
},
|
||||
{
|
||||
"command": "git.ignore",
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && resourceScheme == file && scmActiveResourceRepository"
|
||||
},
|
||||
{
|
||||
"command": "git.stashIncludeUntracked",
|
||||
@@ -879,6 +913,10 @@
|
||||
"command": "git.stashDrop",
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||
},
|
||||
{
|
||||
"command": "git.stashDropAll",
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.openDiff",
|
||||
"when": "false"
|
||||
@@ -898,6 +936,22 @@
|
||||
{
|
||||
"command": "git.timeline.compareWithSelected",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "git.closeAllDiffEditors",
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||
},
|
||||
{
|
||||
"command": "git.api.getRepositories",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "git.api.getRepositoryState",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "git.api.getRemoteSources",
|
||||
"when": "false"
|
||||
}
|
||||
],
|
||||
"scm/title": [
|
||||
@@ -931,6 +985,11 @@
|
||||
"group": "1_header@4",
|
||||
"when": "scmProvider == git"
|
||||
},
|
||||
{
|
||||
"command": "git.fetch",
|
||||
"group": "1_header@5",
|
||||
"when": "scmProvider == git"
|
||||
},
|
||||
{
|
||||
"submenu": "git.commit",
|
||||
"group": "2_main@1",
|
||||
@@ -1324,7 +1383,7 @@
|
||||
{
|
||||
"command": "git.openChange",
|
||||
"group": "navigation",
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && !isInDiffEditor && resourceScheme == file && resourcePath in git.changedResources"
|
||||
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && !isInDiffEditor && resourceScheme == file && scmActiveResourceHasChanges"
|
||||
},
|
||||
{
|
||||
"command": "git.stageSelectedRanges",
|
||||
@@ -1604,6 +1663,10 @@
|
||||
{
|
||||
"command": "git.stashDrop",
|
||||
"group": "stash@7"
|
||||
},
|
||||
{
|
||||
"command": "git.stashDropAll",
|
||||
"group": "stash@8"
|
||||
}
|
||||
],
|
||||
"git.tags": [
|
||||
@@ -2064,6 +2127,12 @@
|
||||
"default": true,
|
||||
"description": "%config.confirmNoVerifyCommit%"
|
||||
},
|
||||
"git.closeDiffOnOperation": {
|
||||
"type": "boolean",
|
||||
"scope": "resource",
|
||||
"default": false,
|
||||
"description": "%config.closeDiffOnOperation%"
|
||||
},
|
||||
"git.openDiffOnClick": {
|
||||
"type": "boolean",
|
||||
"scope": "resource",
|
||||
@@ -2124,6 +2193,11 @@
|
||||
"default": false,
|
||||
"description": "%config.useCommitInputAsStashMessage%"
|
||||
},
|
||||
"git.useIntegratedAskPass": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "%config.useIntegratedAskPass%"
|
||||
},
|
||||
"git.githubAuthentication": {
|
||||
"deprecationMessage": "This setting is now deprecated, please use `github.gitAuthentication` instead."
|
||||
},
|
||||
@@ -2147,6 +2221,12 @@
|
||||
"description": "%config.timeline.showAuthor%",
|
||||
"scope": "window"
|
||||
},
|
||||
"git.timeline.showUncommitted": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "%config.timeline.showUncommitted%",
|
||||
"scope": "window"
|
||||
},
|
||||
"git.showUnpublishedCommitsButton": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -2168,6 +2248,45 @@
|
||||
"scope": "resource",
|
||||
"default": 10000,
|
||||
"description": "%config.statusLimit%"
|
||||
},
|
||||
"git.experimental.installGuide": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"default",
|
||||
"download"
|
||||
],
|
||||
"tags": [
|
||||
"experimental"
|
||||
],
|
||||
"scope": "machine",
|
||||
"description": "%config.experimental.installGuide%",
|
||||
"default": "default"
|
||||
},
|
||||
"git.repositoryScanIgnoredFolders": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": [
|
||||
"node_modules"
|
||||
],
|
||||
"scope": "resource",
|
||||
"markdownDescription": "%config.repositoryScanIgnoredFolders%"
|
||||
},
|
||||
"git.repositoryScanMaxDepth": {
|
||||
"type": "number",
|
||||
"scope": "resource",
|
||||
"default": 1,
|
||||
"markdownDescription": "%config.repositoryScanMaxDepth%"
|
||||
},
|
||||
"git.commandsToLog": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": [],
|
||||
"scope": "resource",
|
||||
"markdownDescription": "%config.commandsToLog%"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2178,7 +2297,8 @@
|
||||
"defaults": {
|
||||
"light": "#587c0c",
|
||||
"dark": "#81b88b",
|
||||
"highContrast": "#1b5225"
|
||||
"highContrast": "#1b5225",
|
||||
"highContrastLight": "#374e06"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2187,7 +2307,8 @@
|
||||
"defaults": {
|
||||
"light": "#895503",
|
||||
"dark": "#E2C08D",
|
||||
"highContrast": "#E2C08D"
|
||||
"highContrast": "#E2C08D",
|
||||
"highContrastLight": "#895503"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2196,7 +2317,8 @@
|
||||
"defaults": {
|
||||
"light": "#ad0707",
|
||||
"dark": "#c74e39",
|
||||
"highContrast": "#c74e39"
|
||||
"highContrast": "#c74e39",
|
||||
"highContrastLight": "#ad0707"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2205,7 +2327,8 @@
|
||||
"defaults": {
|
||||
"light": "#007100",
|
||||
"dark": "#73C991",
|
||||
"highContrast": "#73C991"
|
||||
"highContrast": "#73C991",
|
||||
"highContrastLight": "#007100"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2214,7 +2337,8 @@
|
||||
"defaults": {
|
||||
"light": "#007100",
|
||||
"dark": "#73C991",
|
||||
"highContrast": "#73C991"
|
||||
"highContrast": "#73C991",
|
||||
"highContrastLight": "#007100"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2223,7 +2347,8 @@
|
||||
"defaults": {
|
||||
"light": "#8E8E90",
|
||||
"dark": "#8C8C8C",
|
||||
"highContrast": "#A7A8A9"
|
||||
"highContrast": "#A7A8A9",
|
||||
"highContrastLight": "#8e8e90"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2232,7 +2357,8 @@
|
||||
"defaults": {
|
||||
"light": "#895503",
|
||||
"dark": "#E2C08D",
|
||||
"highContrast": "#E2C08D"
|
||||
"highContrast": "#E2C08D",
|
||||
"highContrastLight": "#895503"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2241,7 +2367,8 @@
|
||||
"defaults": {
|
||||
"light": "#ad0707",
|
||||
"dark": "#c74e39",
|
||||
"highContrast": "#c74e39"
|
||||
"highContrast": "#c74e39",
|
||||
"highContrastLight": "#ad0707"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2250,7 +2377,8 @@
|
||||
"defaults": {
|
||||
"light": "#ad0707",
|
||||
"dark": "#e4676b",
|
||||
"highContrast": "#c74e39"
|
||||
"highContrast": "#c74e39",
|
||||
"highContrastLight": "#ad0707"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2259,82 +2387,11 @@
|
||||
"defaults": {
|
||||
"light": "#1258a7",
|
||||
"dark": "#8db9e2",
|
||||
"highContrast": "#8db9e2"
|
||||
"highContrast": "#8db9e2",
|
||||
"highContrastLight": "#1258a7"
|
||||
}
|
||||
}
|
||||
],
|
||||
"languages": [
|
||||
{
|
||||
"id": "git-commit",
|
||||
"aliases": [
|
||||
"Git Commit Message",
|
||||
"git-commit"
|
||||
],
|
||||
"filenames": [
|
||||
"COMMIT_EDITMSG",
|
||||
"MERGE_MSG"
|
||||
],
|
||||
"configuration": "./languages/git-commit.language-configuration.json"
|
||||
},
|
||||
{
|
||||
"id": "git-rebase",
|
||||
"aliases": [
|
||||
"Git Rebase Message",
|
||||
"git-rebase"
|
||||
],
|
||||
"filenames": [
|
||||
"git-rebase-todo"
|
||||
],
|
||||
"configuration": "./languages/git-rebase.language-configuration.json"
|
||||
},
|
||||
{
|
||||
"id": "diff",
|
||||
"aliases": [
|
||||
"Diff",
|
||||
"diff"
|
||||
],
|
||||
"extensions": [
|
||||
".diff",
|
||||
".patch",
|
||||
".rej"
|
||||
],
|
||||
"configuration": "./languages/diff.language-configuration.json"
|
||||
},
|
||||
{
|
||||
"id": "ignore",
|
||||
"aliases": [
|
||||
"Ignore",
|
||||
"ignore"
|
||||
],
|
||||
"extensions": [
|
||||
".gitignore_global",
|
||||
".gitignore"
|
||||
],
|
||||
"configuration": "./languages/ignore.language-configuration.json"
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
{
|
||||
"language": "git-commit",
|
||||
"scopeName": "text.git-commit",
|
||||
"path": "./syntaxes/git-commit.tmLanguage.json"
|
||||
},
|
||||
{
|
||||
"language": "git-rebase",
|
||||
"scopeName": "text.git-rebase",
|
||||
"path": "./syntaxes/git-rebase.tmLanguage.json"
|
||||
},
|
||||
{
|
||||
"language": "diff",
|
||||
"scopeName": "source.diff",
|
||||
"path": "./syntaxes/diff.tmLanguage.json"
|
||||
},
|
||||
{
|
||||
"language": "ignore",
|
||||
"scopeName": "source.ignore",
|
||||
"path": "./syntaxes/ignore.tmLanguage.json"
|
||||
}
|
||||
],
|
||||
"configurationDefaults": {
|
||||
"[git-commit]": {
|
||||
"editor.rulers": [
|
||||
@@ -2352,10 +2409,30 @@
|
||||
"contents": "%view.workbench.scm.disabled%",
|
||||
"when": "!config.git.enabled"
|
||||
},
|
||||
{
|
||||
"view": "scm",
|
||||
"contents": "%view.workbench.scm.missing.guide%",
|
||||
"when": "config.git.enabled && git.missing && config.git.experimental.installGuide == download"
|
||||
},
|
||||
{
|
||||
"view": "scm",
|
||||
"contents": "%view.workbench.scm.missing.guide.mac%",
|
||||
"when": "config.git.enabled && git.missing && config.git.experimental.installGuide == download && isMac"
|
||||
},
|
||||
{
|
||||
"view": "scm",
|
||||
"contents": "%view.workbench.scm.missing.guide.windows%",
|
||||
"when": "config.git.enabled && git.missing && config.git.experimental.installGuide == download && isWindows"
|
||||
},
|
||||
{
|
||||
"view": "scm",
|
||||
"contents": "%view.workbench.scm.missing.guide.linux%",
|
||||
"when": "config.git.enabled && git.missing && config.git.experimental.installGuide == download && isLinux"
|
||||
},
|
||||
{
|
||||
"view": "scm",
|
||||
"contents": "%view.workbench.scm.missing%",
|
||||
"when": "config.git.enabled && git.missing"
|
||||
"when": "config.git.enabled && git.missing && config.git.experimental.installGuide == default"
|
||||
},
|
||||
{
|
||||
"view": "scm",
|
||||
@@ -2402,19 +2479,19 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vscode/extension-telemetry": "0.4.10",
|
||||
"@vscode/iconv-lite-umd": "0.7.0",
|
||||
"byline": "^5.0.0",
|
||||
"file-type": "16.5.4",
|
||||
"iconv-lite-umd": "0.6.8",
|
||||
"jschardet": "3.0.0",
|
||||
"vscode-extension-telemetry": "0.4.2",
|
||||
"vscode-nls": "^4.0.0",
|
||||
"vscode-uri": "^2.0.0",
|
||||
"which": "^1.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/byline": "4.2.31",
|
||||
"@types/mocha": "^8.2.0",
|
||||
"@types/node": "14.x",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/node": "16.x",
|
||||
"@types/which": "^1.0.28"
|
||||
},
|
||||
"repository": {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"command.cleanAll": "Discard All Changes",
|
||||
"command.cleanAllTracked": "Discard All Tracked Changes",
|
||||
"command.cleanAllUntracked": "Discard All Untracked Changes",
|
||||
"command.closeAllDiffEditors": "Close All Diff Editors",
|
||||
"command.commit": "Commit",
|
||||
"command.commitStaged": "Commit Staged",
|
||||
"command.commitEmpty": "Commit Empty",
|
||||
@@ -78,7 +79,7 @@
|
||||
"command.publish": "Publish Branch...",
|
||||
"command.showOutput": "Show Git Output",
|
||||
"command.ignore": "Add to .gitignore",
|
||||
"command.revealInExplorer": "Reveal in Side Bar",
|
||||
"command.revealInExplorer": "Reveal in Explorer View",
|
||||
"command.rebaseAbort": "Abort Rebase",
|
||||
"command.stashIncludeUntracked": "Stash (Include Untracked)",
|
||||
"command.stash": "Stash",
|
||||
@@ -87,11 +88,15 @@
|
||||
"command.stashApply": "Apply Stash...",
|
||||
"command.stashApplyLatest": "Apply Latest Stash",
|
||||
"command.stashDrop": "Drop Stash...",
|
||||
"command.stashDropAll": "Drop All Stashes...",
|
||||
"command.timelineOpenDiff": "Open Changes",
|
||||
"command.timelineCopyCommitId": "Copy Commit ID",
|
||||
"command.timelineCopyCommitMessage": "Copy Commit Message",
|
||||
"command.timelineSelectForCompare": "Select for Compare",
|
||||
"command.timelineCompareWithSelected": "Compare with Selected",
|
||||
"command.api.getRepositories": "Get Repositories",
|
||||
"command.api.getRepositoryState": "Get Repository State",
|
||||
"command.api.getRemoteSources": "Get Remote Sources",
|
||||
"config.enabled": "Whether git is enabled.",
|
||||
"config.path": "Path and filename of the git executable, e.g. `C:\\Program Files\\Git\\bin\\git.exe` (Windows). This can also be an array of string values containing multiple paths to look up.",
|
||||
"config.autoRepositoryDetection": "Configures when repositories should be automatically detected.",
|
||||
@@ -158,6 +163,14 @@
|
||||
"config.ignoreSubmodules": "Ignore modifications to submodules in the file tree.",
|
||||
"config.ignoredRepositories": "List of git repositories to ignore.",
|
||||
"config.scanRepositories": "List of paths to search for git repositories in.",
|
||||
"config.commandsToLog": {
|
||||
"message": "List of git commands (ex: commit, push) that would have their `stdout` logged to the [git output](command:git.showOutput). If the git command has a client-side hook configured, the client-side hook's `stdout` will also be logged to the [git output](command:git.showOutput).",
|
||||
"comment": [
|
||||
"{Locked='](command:git.showOutput'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"config.showProgress": "Controls whether git actions should show progress.",
|
||||
"config.rebaseWhenSync": "Force git to use rebase when running the sync command.",
|
||||
"config.confirmEmptyCommits": "Always confirm the creation of empty commits for the 'Git: Commit Empty' command.",
|
||||
@@ -170,6 +183,7 @@
|
||||
"config.confirmForcePush": "Controls whether to ask for confirmation before force-pushing.",
|
||||
"config.allowNoVerifyCommit": "Controls whether commits without running pre-commit and commit-msg hooks are allowed.",
|
||||
"config.confirmNoVerifyCommit": "Controls whether to ask for confirmation before committing without verification.",
|
||||
"config.closeDiffOnOperation": "Controls whether the diff editor should be automatically closed when changes are stashed, committed, discarded, staged, or unstaged.",
|
||||
"config.openDiffOnClick": "Controls whether the diff editor should be opened when clicking a change. Otherwise the regular editor will be opened.",
|
||||
"config.supportCancellation": "Controls whether a notification comes up when running the Sync action, which allows the user to cancel the operation.",
|
||||
"config.branchSortOrder": "Controls the sort order for branches.",
|
||||
@@ -181,6 +195,7 @@
|
||||
"config.showCommitInput": "Controls whether to show the commit input in the Git source control panel.",
|
||||
"config.terminalAuthentication": "Controls whether to enable Azure Data Studio to be the authentication handler for git processes spawned in the integrated terminal. Note: terminals need to be restarted to pick up a change in this setting.",
|
||||
"config.timeline.showAuthor": "Controls whether to show the commit author in the Timeline view.",
|
||||
"config.timeline.showUncommitted": "Controls whether to show uncommitted changes in the Timeline view.",
|
||||
"config.timeline.date": "Controls which date to use for items in the Timeline view.",
|
||||
"config.timeline.date.committed": "Use the committed date",
|
||||
"config.timeline.date.authored": "Use the authored date",
|
||||
@@ -190,6 +205,10 @@
|
||||
"config.showUnpublishedCommitsButton.whenEmpty": "Only shows the action button if there are no other changes and there are unpublished commits.",
|
||||
"config.showUnpublishedCommitsButton.never": "Never shows the action button.",
|
||||
"config.statusLimit": "Controls how to limit the number of changes that can be parsed from Git status command. Can be set to 0 for no limit.",
|
||||
"config.experimental.installGuide": "Experimental improvements for the git setup flow.",
|
||||
"config.repositoryScanIgnoredFolders": "List of folders that are ignored while scanning for Git repositories when `#git.autoRepositoryDetection#` is set to `true` or `subFolders`.",
|
||||
"config.repositoryScanMaxDepth": "Controls the depth used when scanning workspace folders for Git repositories when `#git.autoRepositoryDetection#` is set to `true` or `subFolders`. Can be set to `-1` for no limit.",
|
||||
"config.useIntegratedAskPass": "Controls whether GIT_ASKPASS should be overwritten to use the integrated version.",
|
||||
"submenu.explorer": "Git",
|
||||
"submenu.commit": "Commit",
|
||||
"submenu.commit.amend": "Amend",
|
||||
@@ -210,12 +229,86 @@
|
||||
"colors.ignored": "Color for ignored resources.",
|
||||
"colors.conflict": "Color for resources with conflicts.",
|
||||
"colors.submodule": "Color for submodule resources.",
|
||||
"view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use git and source control in Azure Data Studio in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.",
|
||||
"view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||
"view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone Repository](command:git.clone)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||
"view.workbench.scm.folder": "The folder currently open doesn't have a git repository. You can initialize a repository which will enable source control features powered by git.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||
"view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories. You can initialize a repository on a folder which will enable source control features powered by git.\n[Initialize Repository](command:git.init)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||
"view.workbench.scm.emptyWorkspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Add Folder to Workspace](command:workbench.action.addRootFolder)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||
"view.workbench.cloneRepository": "You can clone a repository locally.\n[Clone Repository](command:git.clone 'Clone a repository once the git extension has activated')",
|
||||
"view.workbench.scm.missing": {
|
||||
"message": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use git and source control in Azure Data Studio in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.",
|
||||
"comment": [
|
||||
"{Locked='](command:git.showOutput'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.scm.missing.guide.windows": {
|
||||
"message": "[Download Git for Windows](https://git-scm.com/download/win)\nAfter installing, please [reload](command:workbench.action.reloadWindow) (or [troubleshoot](command:git.showOutput)). Additional source control providers can be installed [from the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22).",
|
||||
"comment": [
|
||||
"{Locked='](command:workbench.action.reloadWindow'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.scm.missing.guide.mac": {
|
||||
"message": "[Download Git for macOS](https://git-scm.com/download/mac)\nAfter installing, please [reload](command:workbench.action.reloadWindow) (or [troubleshoot](command:git.showOutput)). Additional source control providers can be installed [from the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22).",
|
||||
"comment": [
|
||||
"{Locked='](command:workbench.action.reloadWindow'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.scm.missing.guide.linux": {
|
||||
"message": "Source control depends on Git being installed.\n[Download Git for Linux](https://git-scm.com/download/linux)\nAfter installing, please [reload](command:workbench.action.reloadWindow) (or [troubleshoot](command:git.showOutput)). Additional source control providers can be installed [from the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22).",
|
||||
"comment": [
|
||||
"{Locked='](command:workbench.action.reloadWindow'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.scm.missing.guide": "Install Git, a popular source control system, to track code changes and collaborate with others. Learn more in our [Git guides](https://aka.ms/vscode-scm).",
|
||||
"view.workbench.scm.disabled": {
|
||||
"message": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).",
|
||||
"comment": [
|
||||
"{Locked='](command:workbench.action.openSettings?%5B%22git.enabled%22%5D'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.scm.empty": {
|
||||
"message": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone Repository](command:git.clone)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||
"comment": [
|
||||
"{Locked='](command:vscode.openFolder'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.scm.folder": {
|
||||
"message": "The folder currently open doesn't have a git repository. You can initialize a repository which will enable source control features powered by git.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||
"comment": [
|
||||
"{Locked='](command:git.init?%5Btrue%5D'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.scm.workspace": {
|
||||
"message": "The workspace currently open doesn't have any folders containing git repositories. You can initialize a repository on a folder which will enable source control features powered by git.\n[Initialize Repository](command:git.init)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||
"comment": [
|
||||
"{Locked='](command:git.init'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.scm.emptyWorkspace": {
|
||||
"message": "The workspace currently open doesn't have any folders containing git repositories.\n[Add Folder to Workspace](command:workbench.action.addRootFolder)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||
"comment": [
|
||||
"{Locked='](command:workbench.action.addRootFolder'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.cloneRepository": {
|
||||
"message": "You can clone a repository locally.\n[Clone Repository](command:git.clone 'Clone a repository once the git extension has activated')",
|
||||
"comment": [
|
||||
"{Locked='](command:git.clone'}",
|
||||
"Do not translate the 'command:*' part inside of the '(..)'. It is an internal command syntax for Azure Data Studio",
|
||||
"Please make sure there is no space between the right bracket and left parenthesis: ]( this is an internal syntax for links"
|
||||
]
|
||||
},
|
||||
"view.workbench.learnMore": "To learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm)."
|
||||
}
|
||||
|
||||
113
extensions/git/src/actionButton.ts
Normal file
113
extensions/git/src/actionButton.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, Event, EventEmitter, SourceControlActionButton, Uri, workspace } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Repository, Operation } from './repository';
|
||||
import { dispose } from './util';
|
||||
import { Branch } from './api/git';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
interface ActionButtonState {
|
||||
readonly HEAD: Branch | undefined;
|
||||
readonly isSyncRunning: boolean;
|
||||
readonly repositoryHasNoChanges: boolean;
|
||||
}
|
||||
|
||||
export class ActionButtonCommand {
|
||||
private _onDidChange = new EventEmitter<void>();
|
||||
get onDidChange(): Event<void> { return this._onDidChange.event; }
|
||||
|
||||
private _state: ActionButtonState;
|
||||
private get state() { return this._state; }
|
||||
private set state(state: ActionButtonState) {
|
||||
if (JSON.stringify(this._state) !== JSON.stringify(state)) {
|
||||
this._state = state;
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
}
|
||||
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(readonly repository: Repository) {
|
||||
this._state = { HEAD: undefined, isSyncRunning: false, repositoryHasNoChanges: false };
|
||||
|
||||
repository.onDidRunGitStatus(this.onDidRunGitStatus, this, this.disposables);
|
||||
repository.onDidChangeOperations(this.onDidChangeOperations, this, this.disposables);
|
||||
}
|
||||
|
||||
get button(): SourceControlActionButton | undefined {
|
||||
if (!this.state.HEAD || !this.state.HEAD.name || !this.state.HEAD.commit) { return undefined; }
|
||||
|
||||
const config = workspace.getConfiguration('git', Uri.file(this.repository.root));
|
||||
const showActionButton = config.get<string>('showUnpublishedCommitsButton', 'whenEmpty');
|
||||
const postCommitCommand = config.get<string>('postCommitCommand');
|
||||
const noPostCommitCommand = postCommitCommand !== 'sync' && postCommitCommand !== 'push';
|
||||
|
||||
let actionButton: SourceControlActionButton | undefined;
|
||||
if (showActionButton === 'always' || (showActionButton === 'whenEmpty' && this.state.repositoryHasNoChanges && noPostCommitCommand)) {
|
||||
if (this.state.HEAD.upstream) {
|
||||
if (this.state.HEAD.ahead) {
|
||||
const config = workspace.getConfiguration('git', Uri.file(this.repository.root));
|
||||
const rebaseWhenSync = config.get<string>('rebaseWhenSync');
|
||||
|
||||
const ahead = `${this.state.HEAD.ahead}$(arrow-up)`;
|
||||
const behind = this.state.HEAD.behind ? `${this.state.HEAD.behind}$(arrow-down) ` : '';
|
||||
const icon = this.state.isSyncRunning ? '$(sync~spin)' : '$(sync)';
|
||||
|
||||
actionButton = {
|
||||
command: {
|
||||
command: this.state.isSyncRunning ? '' : rebaseWhenSync ? 'git.syncRebase' : 'git.sync',
|
||||
title: localize('scm button sync title', "{0} {1}{2}", icon, behind, ahead),
|
||||
tooltip: this.state.isSyncRunning ?
|
||||
localize('syncing changes', "Synchronizing Changes...")
|
||||
: this.repository.syncTooltip,
|
||||
arguments: [this.repository.sourceControl],
|
||||
},
|
||||
description: localize('scm button sync description', "{0} Sync Changes {1}{2}", icon, behind, ahead)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
actionButton = {
|
||||
command: {
|
||||
command: this.state.isSyncRunning ? '' : 'git.publish',
|
||||
title: localize('scm button publish title', "$(cloud-upload) Publish Branch"),
|
||||
tooltip: this.state.isSyncRunning ?
|
||||
localize('scm button publish branch running', "Publishing Branch...") :
|
||||
localize('scm button publish branch', "Publish Branch"),
|
||||
arguments: [this.repository.sourceControl],
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return actionButton;
|
||||
}
|
||||
|
||||
private onDidChangeOperations(): void {
|
||||
const isSyncRunning = this.repository.operations.isRunning(Operation.Sync) ||
|
||||
this.repository.operations.isRunning(Operation.Push) ||
|
||||
this.repository.operations.isRunning(Operation.Pull);
|
||||
|
||||
this.state = { ...this.state, isSyncRunning };
|
||||
}
|
||||
|
||||
private onDidRunGitStatus(): void {
|
||||
this.state = {
|
||||
...this.state,
|
||||
HEAD: this.repository.HEAD,
|
||||
repositoryHasNoChanges:
|
||||
this.repository.indexGroup.resourceStates.length === 0 &&
|
||||
this.repository.mergeGroup.resourceStates.length === 0 &&
|
||||
this.repository.untrackedGroup.resourceStates.length === 0 &&
|
||||
this.repository.workingTreeGroup.resourceStates.length === 0
|
||||
};
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposables = dispose(this.disposables);
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,13 @@
|
||||
|
||||
import { Model } from '../model';
|
||||
import { Repository as BaseRepository, Resource } from '../repository';
|
||||
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, ForcePushMode, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, RefType, RemoteSourceProvider, CredentialsProvider, BranchQuery, PushErrorHandler, PublishEvent, FetchOptions, ICloneOptions } from './git'; // {{SQL CARBON EDIT}} add ICloneOptions
|
||||
import { Event, SourceControlInputBox, Uri, SourceControl, Disposable, commands, CancellationToken } from 'vscode'; // {{SQL CARBON EDIT}} add CancellationToken
|
||||
import { mapEvent } from '../util';
|
||||
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, ForcePushMode, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, RefType, CredentialsProvider, BranchQuery, PushErrorHandler, PublishEvent, FetchOptions, RemoteSourceProvider, RemoteSourcePublisher, ICloneOptions } from './git'; // {{SQL CARBON EDIT}} add ICloneOptions
|
||||
import { Event, SourceControlInputBox, Uri, SourceControl, Disposable, commands, CancellationToken } from 'vscode';
|
||||
import { combinedDisposable, mapEvent } from '../util';
|
||||
import { toGitUri } from '../uri';
|
||||
import { pickRemoteSource, PickRemoteSourceOptions } from '../remoteSource';
|
||||
import { GitExtensionImpl } from './extension';
|
||||
import { GitBaseApi } from '../git-base';
|
||||
import { PickRemoteSourceOptions } from './git-base';
|
||||
|
||||
class ApiInputBox implements InputBox {
|
||||
set value(value: string) { this._inputBox.value = value; }
|
||||
@@ -67,7 +68,7 @@ export class ApiRepository implements Repository {
|
||||
return this._repository.apply(patch, reverse);
|
||||
}
|
||||
|
||||
getConfigs(): Promise<{ key: string; value: string; }[]> {
|
||||
getConfigs(): Promise<{ key: string; value: string }[]> {
|
||||
return this._repository.getConfigs();
|
||||
}
|
||||
|
||||
@@ -83,11 +84,11 @@ export class ApiRepository implements Repository {
|
||||
return this._repository.getGlobalConfig(key);
|
||||
}
|
||||
|
||||
getObjectDetails(treeish: string, path: string): Promise<{ mode: string; object: string; size: number; }> {
|
||||
getObjectDetails(treeish: string, path: string): Promise<{ mode: string; object: string; size: number }> {
|
||||
return this._repository.getObjectDetails(treeish, path);
|
||||
}
|
||||
|
||||
detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string }> {
|
||||
detectObjectType(object: string): Promise<{ mimetype: string; encoding?: string }> {
|
||||
return this._repository.detectObjectType(object);
|
||||
}
|
||||
|
||||
@@ -103,6 +104,14 @@ export class ApiRepository implements Repository {
|
||||
return this._repository.getCommit(ref);
|
||||
}
|
||||
|
||||
add(paths: string[]) {
|
||||
return this._repository.add(paths.map(p => Uri.file(p)));
|
||||
}
|
||||
|
||||
revert(paths: string[]) {
|
||||
return this._repository.revert(paths.map(p => Uri.file(p)));
|
||||
}
|
||||
|
||||
clean(paths: string[]) {
|
||||
return this._repository.clean(paths.map(p => Uri.file(p)));
|
||||
}
|
||||
@@ -173,6 +182,14 @@ export class ApiRepository implements Repository {
|
||||
return this._repository.getMergeBase(ref1, ref2);
|
||||
}
|
||||
|
||||
tag(name: string, upstream: string): Promise<void> {
|
||||
return this._repository.tag(name, upstream);
|
||||
}
|
||||
|
||||
deleteTag(name: string): Promise<void> {
|
||||
return this._repository.deleteTag(name);
|
||||
}
|
||||
|
||||
status(): Promise<void> {
|
||||
return this._repository.status();
|
||||
}
|
||||
@@ -288,7 +305,18 @@ export class ApiImpl implements API {
|
||||
}
|
||||
|
||||
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable {
|
||||
return this._model.registerRemoteSourceProvider(provider);
|
||||
const disposables: Disposable[] = [];
|
||||
|
||||
if (provider.publishRepository) {
|
||||
disposables.push(this._model.registerRemoteSourcePublisher(provider as RemoteSourcePublisher));
|
||||
}
|
||||
disposables.push(GitBaseApi.getAPI().registerRemoteSourceProvider(provider));
|
||||
|
||||
return combinedDisposable(disposables);
|
||||
}
|
||||
|
||||
registerRemoteSourcePublisher(publisher: RemoteSourcePublisher): Disposable {
|
||||
return this._model.registerRemoteSourcePublisher(publisher);
|
||||
}
|
||||
|
||||
registerCredentialsProvider(provider: CredentialsProvider): Disposable {
|
||||
@@ -375,11 +403,7 @@ export function registerAPICommands(extension: GitExtensionImpl): Disposable {
|
||||
}));
|
||||
|
||||
disposables.push(commands.registerCommand('git.api.getRemoteSources', (opts?: PickRemoteSourceOptions) => {
|
||||
if (!extension.model) {
|
||||
return;
|
||||
}
|
||||
|
||||
return pickRemoteSource(extension.model, opts as any);
|
||||
return commands.executeCommand('git-base.api.getRemoteSources', opts);
|
||||
}));
|
||||
|
||||
return Disposable.from(...disposables);
|
||||
|
||||
60
extensions/git/src/api/git-base.d.ts
vendored
Normal file
60
extensions/git/src/api/git-base.d.ts
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, Event, ProviderResult, Uri } from 'vscode';
|
||||
export { ProviderResult } from 'vscode';
|
||||
|
||||
export interface API {
|
||||
pickRemoteSource(options: PickRemoteSourceOptions): Promise<string | PickRemoteSourceResult | undefined>;
|
||||
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable;
|
||||
}
|
||||
|
||||
export interface GitBaseExtension {
|
||||
|
||||
readonly enabled: boolean;
|
||||
readonly onDidChangeEnablement: Event<boolean>;
|
||||
|
||||
/**
|
||||
* Returns a specific API version.
|
||||
*
|
||||
* Throws error if git-base extension is disabled. You can listed to the
|
||||
* [GitBaseExtension.onDidChangeEnablement](#GitBaseExtension.onDidChangeEnablement)
|
||||
* event to know when the extension becomes enabled/disabled.
|
||||
*
|
||||
* @param version Version number.
|
||||
* @returns API instance
|
||||
*/
|
||||
getAPI(version: 1): API;
|
||||
}
|
||||
|
||||
export interface PickRemoteSourceOptions {
|
||||
readonly providerLabel?: (provider: RemoteSourceProvider) => string;
|
||||
readonly urlLabel?: string;
|
||||
readonly providerName?: string;
|
||||
readonly branch?: boolean; // then result is PickRemoteSourceResult
|
||||
}
|
||||
|
||||
export interface PickRemoteSourceResult {
|
||||
readonly url: string;
|
||||
readonly branch?: string;
|
||||
}
|
||||
|
||||
export interface RemoteSource {
|
||||
readonly name: string;
|
||||
readonly description?: string;
|
||||
readonly url: string | string[];
|
||||
}
|
||||
|
||||
export interface RemoteSourceProvider {
|
||||
readonly name: string;
|
||||
/**
|
||||
* Codicon name
|
||||
*/
|
||||
readonly icon?: string;
|
||||
readonly supportsQuery?: boolean;
|
||||
|
||||
getBranches?(url: string): ProviderResult<string[]>;
|
||||
getRemoteSources(query?: string): ProviderResult<RemoteSource[]>;
|
||||
}
|
||||
12
extensions/git/src/api/git.d.ts
vendored
12
extensions/git/src/api/git.d.ts
vendored
@@ -172,6 +172,8 @@ export interface Repository {
|
||||
show(ref: string, path: string): Promise<string>;
|
||||
getCommit(ref: string): Promise<Commit>;
|
||||
|
||||
add(paths: string[]): Promise<void>;
|
||||
revert(paths: string[]): Promise<void>;
|
||||
clean(paths: string[]): Promise<void>;
|
||||
|
||||
apply(patch: string, reverse?: boolean): Promise<void>;
|
||||
@@ -198,6 +200,9 @@ export interface Repository {
|
||||
|
||||
getMergeBase(ref1: string, ref2: string): Promise<string>;
|
||||
|
||||
tag(name: string, upstream: string): Promise<void>;
|
||||
deleteTag(name: string): Promise<void>;
|
||||
|
||||
status(): Promise<void>;
|
||||
checkout(treeish: string): Promise<void>;
|
||||
|
||||
@@ -231,6 +236,12 @@ export interface RemoteSourceProvider {
|
||||
publishRepository?(repository: Repository): Promise<void>;
|
||||
}
|
||||
|
||||
export interface RemoteSourcePublisher {
|
||||
readonly name: string;
|
||||
readonly icon?: string; // codicon name
|
||||
publishRepository(repository: Repository): Promise<void>;
|
||||
}
|
||||
|
||||
export interface Credentials {
|
||||
readonly username: string;
|
||||
readonly password: string;
|
||||
@@ -273,6 +284,7 @@ export interface API {
|
||||
init(root: Uri): Promise<Repository | null>;
|
||||
openRepository(root: Uri): Promise<Repository | null>
|
||||
|
||||
registerRemoteSourcePublisher(publisher: RemoteSourcePublisher): Disposable;
|
||||
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable;
|
||||
registerCredentialsProvider(provider: CredentialsProvider): Disposable;
|
||||
registerPushErrorHandler(handler: PushErrorHandler): Disposable;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
VSCODE_GIT_ASKPASS_PIPE=`mktemp`
|
||||
ELECTRON_RUN_AS_NODE="1" VSCODE_GIT_ASKPASS_PIPE="$VSCODE_GIT_ASKPASS_PIPE" "$VSCODE_GIT_ASKPASS_NODE" "$VSCODE_GIT_ASKPASS_MAIN" $*
|
||||
ELECTRON_RUN_AS_NODE="1" VSCODE_GIT_ASKPASS_PIPE="$VSCODE_GIT_ASKPASS_PIPE" "$VSCODE_GIT_ASKPASS_NODE" "$VSCODE_GIT_ASKPASS_MAIN" $VSCODE_GIT_ASKPASS_EXTRA_ARGS $*
|
||||
cat $VSCODE_GIT_ASKPASS_PIPE
|
||||
rm $VSCODE_GIT_ASKPASS_PIPE
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { window, InputBoxOptions, Uri, OutputChannel, Disposable, workspace } from 'vscode';
|
||||
import { IDisposable, EmptyDisposable, toDisposable } from './util';
|
||||
import { IDisposable, EmptyDisposable, toDisposable, logTimestamp } from './util';
|
||||
import * as path from 'path';
|
||||
import { IIPCHandler, IIPCServer, createIPCServer } from './ipc/ipcServer';
|
||||
import { CredentialsProvider, Credentials } from './api/git';
|
||||
@@ -19,7 +19,7 @@ export class Askpass implements IIPCHandler {
|
||||
try {
|
||||
return new Askpass(await createIPCServer(context));
|
||||
} catch (err) {
|
||||
outputChannel.appendLine(`[error] Failed to create git askpass IPC: ${err}`);
|
||||
outputChannel.appendLine(`${logTimestamp()} [error] Failed to create git askpass IPC: ${err}`);
|
||||
return new Askpass();
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ export class Askpass implements IIPCHandler {
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ request, host }: { request: string, host: string }): Promise<string> {
|
||||
async handle({ request, host }: { request: string; host: string }): Promise<string> {
|
||||
const config = workspace.getConfiguration('git', null);
|
||||
const enabled = config.get<boolean>('enabled');
|
||||
|
||||
@@ -72,19 +72,26 @@ export class Askpass implements IIPCHandler {
|
||||
return await window.showInputBox(options) || '';
|
||||
}
|
||||
|
||||
getEnv(): { [key: string]: string; } {
|
||||
getEnv(): { [key: string]: string } {
|
||||
if (!this.ipc) {
|
||||
return {
|
||||
GIT_ASKPASS: path.join(__dirname, 'askpass-empty.sh')
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
let env: { [key: string]: string } = {
|
||||
...this.ipc.getEnv(),
|
||||
GIT_ASKPASS: path.join(__dirname, 'askpass.sh'),
|
||||
VSCODE_GIT_ASKPASS_NODE: process.execPath,
|
||||
VSCODE_GIT_ASKPASS_EXTRA_ARGS: (process.versions['electron'] && process.versions['microsoft-build']) ? '--ms-enable-electron-run-as-node' : '',
|
||||
VSCODE_GIT_ASKPASS_MAIN: path.join(__dirname, 'askpass-main.js')
|
||||
};
|
||||
|
||||
const config = workspace.getConfiguration('git');
|
||||
if (config.get<boolean>('useIntegratedAskPass')) {
|
||||
env.GIT_ASKPASS = path.join(__dirname, 'askpass.sh');
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
registerCredentialsProvider(provider: CredentialsProvider): Disposable {
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { Command, commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider } from 'vscode';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
import TelemetryReporter from '@vscode/extension-telemetry';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Branch, ForcePushMode, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourceProvider } from './api/git';
|
||||
import { Branch, ForcePushMode, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourcePublisher } from './api/git';
|
||||
import { Git, Stash } from './git';
|
||||
import { Model } from './model';
|
||||
import { Repository, Resource, ResourceGroupType } from './repository';
|
||||
import { applyLineChanges, getModifiedRange, intersectDiffWithRange, invertLineChange, toLineRanges } from './staging';
|
||||
import { fromGitUri, toGitUri, isGitUri } from './uri';
|
||||
import { grep, isDescendant, pathEquals } from './util';
|
||||
import { grep, isDescendant, logTimestamp, pathEquals, relativePath } from './util';
|
||||
import { Log, LogLevel } from './log';
|
||||
import { GitTimelineItem } from './timelineProvider';
|
||||
import { ApiRepository } from './api/api1';
|
||||
@@ -186,7 +186,7 @@ function command(commandId: string, options: ScmCommandOptions = {}): Function {
|
||||
// 'image/bmp'
|
||||
// ];
|
||||
|
||||
async function categorizeResourceByResolution(resources: Resource[]): Promise<{ merge: Resource[], resolved: Resource[], unresolved: Resource[], deletionConflicts: Resource[] }> {
|
||||
async function categorizeResourceByResolution(resources: Resource[]): Promise<{ merge: Resource[]; resolved: Resource[]; unresolved: Resource[]; deletionConflicts: Resource[] }> {
|
||||
const selection = resources.filter(s => s instanceof Resource) as Resource[];
|
||||
const merge = selection.filter(s => s.resourceGroupType === ResourceGroupType.Merge);
|
||||
const isBothAddedOrModified = (s: Resource) => s.type === Status.BOTH_MODIFIED || s.type === Status.BOTH_ADDED;
|
||||
@@ -282,7 +282,7 @@ interface PushOptions {
|
||||
remote?: string;
|
||||
refspec?: string;
|
||||
setUpstream?: boolean;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class CommandErrorOutputTextDocumentContentProvider implements TextDocumentContentProvider {
|
||||
@@ -353,7 +353,7 @@ export class CommandCenter {
|
||||
}
|
||||
|
||||
Log.logLevel = choice.logLevel;
|
||||
this.outputChannel.appendLine(localize('changed', "Log level changed to: {0}", LogLevel[Log.logLevel]));
|
||||
this.outputChannel.appendLine(localize('changed', "{0} Log level changed to: {1}", logTimestamp(), LogLevel[Log.logLevel]));
|
||||
}
|
||||
|
||||
@command('git.refresh', { repository: true })
|
||||
@@ -392,7 +392,7 @@ export class CommandCenter {
|
||||
|
||||
async cloneRepository(url?: string, parentPath?: string, options: { recursive?: boolean } = {}): Promise<void> {
|
||||
if (!url || typeof url !== 'string') {
|
||||
url = await pickRemoteSource(this.model, {
|
||||
url = await pickRemoteSource({
|
||||
providerLabel: provider => localize('clonefrom', "Clone from {0}", provider.name),
|
||||
urlLabel: localize('repourl', "Clone from URL")
|
||||
});
|
||||
@@ -544,7 +544,7 @@ export class CommandCenter {
|
||||
} else {
|
||||
const placeHolder = localize('init', "Pick workspace folder to initialize git repo in");
|
||||
const pick = { label: localize('choose', "Choose Folder...") };
|
||||
const items: { label: string, folder?: WorkspaceFolder }[] = [
|
||||
const items: { label: string; folder?: WorkspaceFolder }[] = [
|
||||
...workspace.workspaceFolders.map(folder => ({ label: folder.name, description: folder.uri.fsPath, folder })),
|
||||
pick
|
||||
];
|
||||
@@ -686,6 +686,10 @@ export class CommandCenter {
|
||||
}
|
||||
|
||||
const activeTextEditor = window.activeTextEditor;
|
||||
// Must extract these now because opening a new document will change the activeTextEditor reference
|
||||
const previousVisibleRange = activeTextEditor?.visibleRanges[0];
|
||||
const previousURI = activeTextEditor?.document.uri;
|
||||
const previousSelection = activeTextEditor?.selection;
|
||||
|
||||
for (const uri of uris) {
|
||||
const opts: TextDocumentShowOptions = {
|
||||
@@ -702,18 +706,21 @@ export class CommandCenter {
|
||||
const document = window.activeTextEditor?.document;
|
||||
|
||||
// If the document doesn't match what we opened then don't attempt to select the range
|
||||
if (document?.uri.toString() !== uri.toString()) {
|
||||
// Additioanlly if there was no previous document we don't have information to select a range
|
||||
if (document?.uri.toString() !== uri.toString() || !activeTextEditor || !previousURI || !previousSelection) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if active text editor has same path as other editor. we cannot compare via
|
||||
// URI.toString() here because the schemas can be different. Instead we just go by path.
|
||||
if (activeTextEditor && activeTextEditor.document.uri.path === uri.path && document) {
|
||||
if (previousURI.path === uri.path && document) {
|
||||
// preserve not only selection but also visible range
|
||||
opts.selection = activeTextEditor.selection;
|
||||
const previousVisibleRanges = activeTextEditor.visibleRanges;
|
||||
opts.selection = previousSelection;
|
||||
const editor = await window.showTextDocument(document, opts);
|
||||
editor.revealRange(previousVisibleRanges[0]);
|
||||
// This should always be defined but just in case
|
||||
if (previousVisibleRange) {
|
||||
editor.revealRange(previousVisibleRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -796,7 +803,7 @@ export class CommandCenter {
|
||||
return;
|
||||
}
|
||||
|
||||
const from = path.relative(repository.root, fromUri.fsPath);
|
||||
const from = relativePath(repository.root, fromUri.fsPath);
|
||||
let to = await window.showInputBox({
|
||||
value: from,
|
||||
valueSelection: [from.length - path.basename(from).length, from.length]
|
||||
@@ -813,14 +820,14 @@ export class CommandCenter {
|
||||
|
||||
@command('git.stage')
|
||||
async stage(...resourceStates: SourceControlResourceState[]): Promise<void> {
|
||||
this.outputChannel.appendLine(`git.stage ${resourceStates.length}`);
|
||||
this.outputChannel.appendLine(`${logTimestamp()} git.stage ${resourceStates.length}`);
|
||||
|
||||
resourceStates = resourceStates.filter(s => !!s);
|
||||
|
||||
if (resourceStates.length === 0 || (resourceStates[0] && !(resourceStates[0].resourceUri instanceof Uri))) {
|
||||
const resource = this.getSCMResource();
|
||||
|
||||
this.outputChannel.appendLine(`git.stage.getSCMResource ${resource ? resource.resourceUri.toString() : null}`);
|
||||
this.outputChannel.appendLine(`${logTimestamp()} git.stage.getSCMResource ${resource ? resource.resourceUri.toString() : null}`);
|
||||
|
||||
if (!resource) {
|
||||
return;
|
||||
@@ -863,7 +870,7 @@ export class CommandCenter {
|
||||
const untracked = selection.filter(s => s.resourceGroupType === ResourceGroupType.Untracked);
|
||||
const scmResources = [...workingTree, ...untracked, ...resolved, ...unresolved];
|
||||
|
||||
this.outputChannel.appendLine(`git.stage.scmResources ${scmResources.length}`);
|
||||
this.outputChannel.appendLine(`${logTimestamp()} git.stage.scmResources ${scmResources.length}`);
|
||||
if (!scmResources.length) {
|
||||
return;
|
||||
}
|
||||
@@ -1676,7 +1683,7 @@ export class CommandCenter {
|
||||
return this._checkout(repository, { detached: true, treeish });
|
||||
}
|
||||
|
||||
private async _checkout(repository: Repository, opts?: { detached?: boolean, treeish?: string }): Promise<boolean> {
|
||||
private async _checkout(repository: Repository, opts?: { detached?: boolean; treeish?: string }): Promise<boolean> {
|
||||
if (typeof opts?.treeish === 'string') {
|
||||
await repository.checkout(opts?.treeish, opts);
|
||||
return true;
|
||||
@@ -2128,7 +2135,7 @@ export class CommandCenter {
|
||||
}
|
||||
|
||||
const branchName = repository.HEAD.name;
|
||||
const message = localize('confirm publish branch', "The branch '{0}' has no upstream branch. Would you like to publish this branch?", branchName);
|
||||
const message = localize('confirm publish branch', "The branch '{0}' has no remote branch. Would you like to publish this branch?", branchName);
|
||||
const yes = localize('ok', "OK");
|
||||
const pick = await window.showWarningMessage(message, { modal: true }, yes);
|
||||
|
||||
@@ -2215,7 +2222,7 @@ export class CommandCenter {
|
||||
|
||||
@command('git.addRemote', { repository: true })
|
||||
async addRemote(repository: Repository): Promise<string | undefined> {
|
||||
const url = await pickRemoteSource(this.model, {
|
||||
const url = await pickRemoteSource({
|
||||
providerLabel: provider => localize('addfrom', "Add remote from {0}", provider.name),
|
||||
urlLabel: localize('addFrom', "Add remote from URL")
|
||||
});
|
||||
@@ -2278,7 +2285,7 @@ export class CommandCenter {
|
||||
return;
|
||||
} else if (!HEAD.upstream) {
|
||||
const branchName = HEAD.name;
|
||||
const message = localize('confirm publish branch', "The branch '{0}' has no upstream branch. Would you like to publish this branch?", branchName);
|
||||
const message = localize('confirm publish branch', "The branch '{0}' has no remote branch. Would you like to publish this branch?", branchName);
|
||||
const yes = localize('ok', "OK");
|
||||
const pick = await window.showWarningMessage(message, { modal: true }, yes);
|
||||
|
||||
@@ -2296,7 +2303,7 @@ export class CommandCenter {
|
||||
const shouldPrompt = !isReadonly && config.get<boolean>('confirmSync') === true;
|
||||
|
||||
if (shouldPrompt) {
|
||||
const message = localize('sync is unpredictable', "This action will push and pull commits to and from '{0}/{1}'.", HEAD.upstream.remote, HEAD.upstream.name);
|
||||
const message = localize('sync is unpredictable', "This action will pull and push commits from and to '{0}/{1}'.", HEAD.upstream.remote, HEAD.upstream.name);
|
||||
const yes = localize('ok', "OK");
|
||||
const neverAgain = localize('never again', "OK, Don't Show Again");
|
||||
const pick = await window.showWarningMessage(message, { modal: true }, yes, neverAgain);
|
||||
@@ -2360,19 +2367,19 @@ export class CommandCenter {
|
||||
const remotes = repository.remotes;
|
||||
|
||||
if (remotes.length === 0) {
|
||||
const providers = this.model.getRemoteProviders().filter(p => !!p.publishRepository);
|
||||
const publishers = this.model.getRemoteSourcePublishers();
|
||||
|
||||
if (providers.length === 0) {
|
||||
if (publishers.length === 0) {
|
||||
window.showWarningMessage(localize('no remotes to publish', "Your repository has no remotes configured to publish to."));
|
||||
return;
|
||||
}
|
||||
|
||||
let provider: RemoteSourceProvider;
|
||||
let publisher: RemoteSourcePublisher;
|
||||
|
||||
if (providers.length === 1) {
|
||||
provider = providers[0];
|
||||
if (publishers.length === 1) {
|
||||
publisher = publishers[0];
|
||||
} else {
|
||||
const picks = providers
|
||||
const picks = publishers
|
||||
.map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('publish to', "Publish to {0}", provider.name), alwaysShow: true, provider }));
|
||||
const placeHolder = localize('pick provider', "Pick a provider to publish the branch '{0}' to:", branchName);
|
||||
const choice = await window.showQuickPick(picks, { placeHolder });
|
||||
@@ -2381,10 +2388,10 @@ export class CommandCenter {
|
||||
return;
|
||||
}
|
||||
|
||||
provider = choice.provider;
|
||||
publisher = choice.provider;
|
||||
}
|
||||
|
||||
await provider.publishRepository!(new ApiRepository(repository));
|
||||
await publisher.publishRepository(new ApiRepository(repository));
|
||||
this.model.firePublishEvent(repository, branchName);
|
||||
|
||||
return;
|
||||
@@ -2596,6 +2603,29 @@ export class CommandCenter {
|
||||
await repository.dropStash(stash.index);
|
||||
}
|
||||
|
||||
@command('git.stashDropAll', { repository: true })
|
||||
async stashDropAll(repository: Repository): Promise<void> {
|
||||
const stashes = await repository.getStashes();
|
||||
|
||||
if (stashes.length === 0) {
|
||||
window.showInformationMessage(localize('no stashes', "There are no stashes in the repository."));
|
||||
return;
|
||||
}
|
||||
|
||||
// request confirmation for the operation
|
||||
const yes = localize('yes', "Yes");
|
||||
const question = stashes.length === 1 ?
|
||||
localize('drop one stash', "Are you sure you want to drop ALL stashes? There is 1 stash that will be subject to pruning, and MAY BE IMPOSSIBLE TO RECOVER.") :
|
||||
localize('drop all stashes', "Are you sure you want to drop ALL stashes? There are {0} stashes that will be subject to pruning, and MAY BE IMPOSSIBLE TO RECOVER.", stashes.length);
|
||||
|
||||
const result = await window.showWarningMessage(question, yes);
|
||||
if (result !== yes) {
|
||||
return;
|
||||
}
|
||||
|
||||
await repository.dropStash();
|
||||
}
|
||||
|
||||
private async pickStash(repository: Repository, placeHolder: string): Promise<Stash | undefined> {
|
||||
const stashes = await repository.getStashes();
|
||||
|
||||
@@ -2640,12 +2670,12 @@ export class CommandCenter {
|
||||
else if (item.previousRef === 'HEAD' && item.ref === '~') {
|
||||
title = localize('git.title.index', '{0} (Index)', basename);
|
||||
} else {
|
||||
title = localize('git.title.diffRefs', '{0} ({1}) ⟷ {0} ({2})', basename, item.shortPreviousRef, item.shortRef);
|
||||
title = localize('git.title.diffRefs', '{0} ({1}) ↔ {0} ({2})', basename, item.shortPreviousRef, item.shortRef);
|
||||
}
|
||||
|
||||
return {
|
||||
command: 'vscode.diff',
|
||||
title: 'Open Comparison',
|
||||
title: localize('git.timeline.openDiffCommand', "Open Comparison"),
|
||||
arguments: [toGitUri(uri, item.previousRef), item.ref === '' ? uri : toGitUri(uri, item.ref), title, options]
|
||||
};
|
||||
}
|
||||
@@ -2668,7 +2698,7 @@ export class CommandCenter {
|
||||
env.clipboard.writeText(item.message);
|
||||
}
|
||||
|
||||
private _selectedForCompare: { uri: Uri, item: GitTimelineItem } | undefined;
|
||||
private _selectedForCompare: { uri: Uri; item: GitTimelineItem } | undefined;
|
||||
|
||||
@command('git.timeline.selectForCompare', { repository: false })
|
||||
async timelineSelectForCompare(item: TimelineItem, uri: Uri | undefined, _source: string) {
|
||||
@@ -2710,7 +2740,7 @@ export class CommandCenter {
|
||||
}
|
||||
|
||||
|
||||
const title = localize('git.title.diff', '{0} ⟷ {1}', leftTitle, rightTitle);
|
||||
const title = localize('git.title.diff', '{0} ↔ {1}', leftTitle, rightTitle);
|
||||
await commands.executeCommand('vscode.diff', selected.ref === '' ? uri : toGitUri(uri, selected.ref), item.ref === '' ? uri : toGitUri(uri, item.ref), title);
|
||||
}
|
||||
|
||||
@@ -2723,6 +2753,17 @@ export class CommandCenter {
|
||||
}
|
||||
}
|
||||
|
||||
@command('git.closeAllDiffEditors', { repository: true })
|
||||
closeDiffEditors(repository: Repository): void {
|
||||
const resources = [
|
||||
...repository.indexGroup.resourceStates.map(r => r.resourceUri.fsPath),
|
||||
...repository.workingTreeGroup.resourceStates.map(r => r.resourceUri.fsPath),
|
||||
...repository.untrackedGroup.resourceStates.map(r => r.resourceUri.fsPath)
|
||||
];
|
||||
|
||||
repository.closeDiffEditors(resources, resources, true);
|
||||
}
|
||||
|
||||
private createCommand(id: string, key: string, method: Function, options: ScmCommandOptions): (...args: any[]) => any {
|
||||
const result = (...args: any[]) => {
|
||||
let result: Promise<any>;
|
||||
@@ -2813,7 +2854,7 @@ export class CommandCenter {
|
||||
type = 'warning';
|
||||
options.modal = false;
|
||||
break;
|
||||
case GitErrorCodes.AuthenticationFailed:
|
||||
case GitErrorCodes.AuthenticationFailed: {
|
||||
const regex = /Authentication failed for '(.*)'/i;
|
||||
const match = regex.exec(err.stderr || String(err));
|
||||
|
||||
@@ -2821,12 +2862,13 @@ export class CommandCenter {
|
||||
? localize('auth failed specific', "Failed to authenticate to git remote:\n\n{0}", match[1])
|
||||
: localize('auth failed', "Failed to authenticate to git remote.");
|
||||
break;
|
||||
}
|
||||
case GitErrorCodes.NoUserNameConfigured:
|
||||
case GitErrorCodes.NoUserEmailConfigured:
|
||||
message = localize('missing user info', "Make sure you configure your 'user.name' and 'user.email' in git.");
|
||||
choices.set(localize('learn more', "Learn More"), () => commands.executeCommand('vscode.open', Uri.parse('https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup')));
|
||||
choices.set(localize('learn more', "Learn More"), () => commands.executeCommand('vscode.open', Uri.parse('https://aka.ms/vscode-setup-git')));
|
||||
break;
|
||||
default:
|
||||
default: {
|
||||
const hint = (err.stderr || err.message || String(err))
|
||||
.replace(/^error: /mi, '')
|
||||
.replace(/^> husky.*$/mi, '')
|
||||
@@ -2839,6 +2881,7 @@ export class CommandCenter {
|
||||
: localize('git error', "Git error");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!message) {
|
||||
@@ -2870,10 +2913,10 @@ export class CommandCenter {
|
||||
private getSCMResource(uri?: Uri): Resource | undefined {
|
||||
uri = uri ? uri : (window.activeTextEditor && window.activeTextEditor.document.uri);
|
||||
|
||||
this.outputChannel.appendLine(`git.getSCMResource.uri ${uri && uri.toString()}`);
|
||||
this.outputChannel.appendLine(`${logTimestamp()} git.getSCMResource.uri ${uri && uri.toString()}`);
|
||||
|
||||
for (const r of this.model.repositories.map(r => r.root)) {
|
||||
this.outputChannel.appendLine(`repo root ${r}`);
|
||||
this.outputChannel.appendLine(`${logTimestamp()} repo root ${r}`);
|
||||
}
|
||||
|
||||
if (!uri) {
|
||||
@@ -2927,7 +2970,7 @@ export class CommandCenter {
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [] as { repository: Repository, resources: Uri[] }[]);
|
||||
}, [] as { repository: Repository; resources: Uri[] }[]);
|
||||
|
||||
const promises = groups
|
||||
.map(({ repository, resources }) => fn(repository as Repository, isSingleResource ? resources[0] : resources));
|
||||
|
||||
@@ -16,7 +16,7 @@ class GitIgnoreDecorationProvider implements FileDecorationProvider {
|
||||
private static Decoration: FileDecoration = { color: new ThemeColor('gitDecoration.ignoredResourceForeground') };
|
||||
|
||||
readonly onDidChangeFileDecorations: Event<Uri[]>;
|
||||
private queue = new Map<string, { repository: Repository; queue: Map<string, PromiseSource<FileDecoration | undefined>>; }>();
|
||||
private queue = new Map<string, { repository: Repository; queue: Map<string, PromiseSource<FileDecoration | undefined>> }>();
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(private model: Model) {
|
||||
|
||||
30
extensions/git/src/git-base.ts
Normal file
30
extensions/git/src/git-base.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { extensions } from 'vscode';
|
||||
import { API as GitBaseAPI, GitBaseExtension } from './api/git-base';
|
||||
|
||||
export class GitBaseApi {
|
||||
|
||||
private static _gitBaseApi: GitBaseAPI | undefined;
|
||||
|
||||
static getAPI(): GitBaseAPI {
|
||||
if (!this._gitBaseApi) {
|
||||
const gitBaseExtension = extensions.getExtension<GitBaseExtension>('vscode.git-base')!.exports;
|
||||
const onDidChangeGitBaseExtensionEnablement = (enabled: boolean) => {
|
||||
this._gitBaseApi = enabled ? gitBaseExtension.getAPI(1) : undefined;
|
||||
};
|
||||
|
||||
gitBaseExtension.onDidChangeEnablement(onDidChangeGitBaseExtensionEnablement);
|
||||
onDidChangeGitBaseExtensionEnablement(gitBaseExtension.enabled);
|
||||
|
||||
if (!this._gitBaseApi) {
|
||||
throw new Error('vscode.git-base extension is not enabled.');
|
||||
}
|
||||
}
|
||||
|
||||
return this._gitBaseApi;
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,13 @@ import { promises as fs, exists, realpath } from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import * as cp from 'child_process';
|
||||
import { fileURLToPath } from 'url';
|
||||
import * as which from 'which';
|
||||
import { EventEmitter } from 'events';
|
||||
import * as iconv from 'iconv-lite-umd';
|
||||
import * as iconv from '@vscode/iconv-lite-umd';
|
||||
import * as filetype from 'file-type';
|
||||
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter, Versions } from './util';
|
||||
import { CancellationToken, Uri } from 'vscode';
|
||||
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter, Versions, isWindows } from './util';
|
||||
import { CancellationToken, ConfigurationChangeEvent, Uri, workspace } from 'vscode'; // {{SQL CARBON EDIT}} remove Progress
|
||||
import { detectEncoding } from './encoding';
|
||||
import { Ref, RefType, Branch, Remote, ForcePushMode, GitErrorCodes, LogOptions, Change, Status, CommitOptions, BranchQuery, ICloneOptions } from './api/git'; // {{SQL CARBON EDIT}} add ICloneOptions
|
||||
import * as byline from 'byline';
|
||||
@@ -20,7 +21,6 @@ import { StringDecoder } from 'string_decoder';
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/65693
|
||||
const MAX_CLI_LENGTH = 30000;
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
export interface IGit {
|
||||
path: string;
|
||||
@@ -84,7 +84,7 @@ function findGitDarwin(onValidate: (path: string) => boolean): Promise<IGit> {
|
||||
return e('git not found');
|
||||
}
|
||||
|
||||
const path = gitPathBuffer.toString().replace(/^\s+|\s+$/g, '');
|
||||
const path = gitPathBuffer.toString().trim();
|
||||
|
||||
function getVersion(path: string) {
|
||||
if (!onValidate(path)) {
|
||||
@@ -368,6 +368,7 @@ export class Git {
|
||||
readonly userAgent: string;
|
||||
readonly version: string;
|
||||
private env: any;
|
||||
private commandsToLog: string[] = [];
|
||||
|
||||
private _onOutput = new EventEmitter();
|
||||
get onOutput(): EventEmitter { return this._onOutput; }
|
||||
@@ -377,13 +378,25 @@ export class Git {
|
||||
this.version = options.version;
|
||||
this.userAgent = options.userAgent;
|
||||
this.env = options.env || {};
|
||||
|
||||
const onConfigurationChanged = (e?: ConfigurationChangeEvent) => {
|
||||
if (e !== undefined && !e.affectsConfiguration('git.commandsToLog')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const config = workspace.getConfiguration('git');
|
||||
this.commandsToLog = config.get<string[]>('commandsToLog', []);
|
||||
};
|
||||
|
||||
workspace.onDidChangeConfiguration(onConfigurationChanged, this);
|
||||
onConfigurationChanged();
|
||||
}
|
||||
|
||||
compareGitVersionTo(version: string): -1 | 0 | 1 {
|
||||
return Versions.compare(Versions.fromString(this.version), Versions.fromString(version));
|
||||
}
|
||||
|
||||
open(repository: string, dotGit: string): Repository {
|
||||
open(repository: string, dotGit: { path: string; commonPath?: string }): Repository {
|
||||
return new Repository(this, repository, dotGit);
|
||||
}
|
||||
|
||||
@@ -456,7 +469,7 @@ export class Git {
|
||||
}
|
||||
|
||||
async getRepositoryRoot(repositoryPath: string): Promise<string> {
|
||||
const result = await this.exec(repositoryPath, ['rev-parse', '--show-toplevel'], { log: false });
|
||||
const result = await this.exec(repositoryPath, ['rev-parse', '--show-toplevel']);
|
||||
|
||||
// Keep trailing spaces which are part of the directory name
|
||||
const repoPath = path.normalize(result.stdout.trimLeft().replace(/[\r\n]+$/, ''));
|
||||
@@ -467,6 +480,7 @@ export class Git {
|
||||
const repoUri = Uri.file(repoPath);
|
||||
const pathUri = Uri.file(repositoryPath);
|
||||
if (repoUri.authority.length !== 0 && pathUri.authority.length === 0) {
|
||||
// eslint-disable-next-line code-no-look-behind-regex
|
||||
let match = /(?<=^\/?)([a-zA-Z])(?=:\/)/.exec(pathUri.path);
|
||||
if (match !== null) {
|
||||
const [, letter] = match;
|
||||
@@ -495,15 +509,25 @@ export class Git {
|
||||
return repoPath;
|
||||
}
|
||||
|
||||
async getRepositoryDotGit(repositoryPath: string): Promise<string> {
|
||||
const result = await this.exec(repositoryPath, ['rev-parse', '--git-dir']);
|
||||
let dotGitPath = result.stdout.trim();
|
||||
async getRepositoryDotGit(repositoryPath: string): Promise<{ path: string; commonPath?: string }> {
|
||||
const result = await this.exec(repositoryPath, ['rev-parse', '--git-dir', '--git-common-dir']);
|
||||
let [dotGitPath, commonDotGitPath] = result.stdout.split('\n').map(r => r.trim());
|
||||
|
||||
if (!path.isAbsolute(dotGitPath)) {
|
||||
dotGitPath = path.join(repositoryPath, dotGitPath);
|
||||
}
|
||||
dotGitPath = path.normalize(dotGitPath);
|
||||
|
||||
return path.normalize(dotGitPath);
|
||||
if (commonDotGitPath) {
|
||||
if (!path.isAbsolute(commonDotGitPath)) {
|
||||
commonDotGitPath = path.join(repositoryPath, commonDotGitPath);
|
||||
}
|
||||
commonDotGitPath = path.normalize(commonDotGitPath);
|
||||
|
||||
return { path: dotGitPath, commonPath: commonDotGitPath !== dotGitPath ? commonDotGitPath : undefined };
|
||||
}
|
||||
|
||||
return { path: dotGitPath };
|
||||
}
|
||||
|
||||
async exec(cwd: string, args: string[], options: SpawnOptions = {}): Promise<IExecutionResult<string>> {
|
||||
@@ -517,7 +541,16 @@ export class Git {
|
||||
|
||||
stream(cwd: string, args: string[], options: SpawnOptions = {}): cp.ChildProcess {
|
||||
options = assign({ cwd }, options || {});
|
||||
return this.spawn(args, options);
|
||||
const child = this.spawn(args, options);
|
||||
|
||||
if (options.log !== false) {
|
||||
const startTime = Date.now();
|
||||
child.on('exit', (_) => {
|
||||
this.log(`> git ${args.join(' ')} [${Date.now() - startTime}ms]\n`);
|
||||
});
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
private async _exec(args: string[], options: SpawnOptions = {}): Promise<IExecutionResult<string>> {
|
||||
@@ -531,10 +564,22 @@ export class Git {
|
||||
child.stdin!.end(options.input, 'utf8');
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
const bufferResult = await exec(child, options.cancellationToken);
|
||||
|
||||
if (options.log !== false && bufferResult.stderr.length > 0) {
|
||||
this.log(`${bufferResult.stderr}\n`);
|
||||
if (options.log !== false) {
|
||||
// command
|
||||
this.log(`> git ${args.join(' ')} [${Date.now() - startTime}ms]\n`);
|
||||
|
||||
// stdout
|
||||
if (bufferResult.stdout.length > 0 && args.find(a => this.commandsToLog.includes(a))) {
|
||||
this.log(`${bufferResult.stdout}\n`);
|
||||
}
|
||||
|
||||
// stderr
|
||||
if (bufferResult.stderr.length > 0) {
|
||||
this.log(`${bufferResult.stderr}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
let encoding = options.encoding || 'utf8';
|
||||
@@ -581,17 +626,27 @@ export class Git {
|
||||
GIT_PAGER: 'cat'
|
||||
});
|
||||
|
||||
if (options.cwd) {
|
||||
options.cwd = sanitizePath(options.cwd);
|
||||
}
|
||||
|
||||
if (options.log !== false) {
|
||||
this.log(`> git ${args.join(' ')}\n`);
|
||||
const cwd = this.getCwd(options);
|
||||
if (cwd) {
|
||||
options.cwd = sanitizePath(cwd);
|
||||
}
|
||||
|
||||
return cp.spawn(this.path, args, options);
|
||||
}
|
||||
|
||||
private getCwd(options: SpawnOptions): string | undefined {
|
||||
const cwd = options.cwd;
|
||||
if (typeof cwd === 'undefined' || typeof cwd === 'string') {
|
||||
return cwd;
|
||||
}
|
||||
|
||||
if (cwd.protocol === 'file:') {
|
||||
return fileURLToPath(cwd);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private log(output: string): void {
|
||||
this._onOutput.emit('log', output);
|
||||
}
|
||||
@@ -818,7 +873,7 @@ export class Repository {
|
||||
constructor(
|
||||
private _git: Git,
|
||||
private repositoryRoot: string,
|
||||
readonly dotGit: string
|
||||
readonly dotGit: { path: string; commonPath?: string }
|
||||
) { }
|
||||
|
||||
get git(): Git {
|
||||
@@ -858,7 +913,7 @@ export class Repository {
|
||||
return result.stdout.trim();
|
||||
}
|
||||
|
||||
async getConfigs(scope: string): Promise<{ key: string; value: string; }[]> {
|
||||
async getConfigs(scope: string): Promise<{ key: string; value: string }[]> {
|
||||
const args = ['config'];
|
||||
|
||||
if (scope) {
|
||||
@@ -960,7 +1015,7 @@ export class Repository {
|
||||
return stdout;
|
||||
}
|
||||
|
||||
async getObjectDetails(treeish: string, path: string): Promise<{ mode: string, object: string, size: number }> {
|
||||
async getObjectDetails(treeish: string, path: string): Promise<{ mode: string; object: string; size: number }> {
|
||||
if (!treeish) { // index
|
||||
const elements = await this.lsfiles(path);
|
||||
|
||||
@@ -998,7 +1053,7 @@ export class Repository {
|
||||
async getGitRelativePath(ref: string, relativePath: string): Promise<string> {
|
||||
const relativePathLowercase = relativePath.toLowerCase();
|
||||
const dirname = path.posix.dirname(relativePath) + '/';
|
||||
const elements: { file: string; }[] = ref ? await this.lstree(ref, dirname) : await this.lsfiles(dirname);
|
||||
const elements: { file: string }[] = ref ? await this.lstree(ref, dirname) : await this.lsfiles(dirname);
|
||||
const element = elements.filter(file => file.file.toLowerCase() === relativePathLowercase)[0];
|
||||
|
||||
if (!element) {
|
||||
@@ -1008,7 +1063,7 @@ export class Repository {
|
||||
return element.file;
|
||||
}
|
||||
|
||||
async detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string }> {
|
||||
async detectObjectType(object: string): Promise<{ mimetype: string; encoding?: string }> {
|
||||
const child = await this.stream(['show', '--textconv', object]);
|
||||
const buffer = await readBytes(child.stdout!, 4100);
|
||||
|
||||
@@ -1195,7 +1250,7 @@ export class Repository {
|
||||
break;
|
||||
|
||||
// Rename contains two paths, the second one is what the file is renamed/copied to.
|
||||
case 'R':
|
||||
case 'R': {
|
||||
if (index >= entries.length) {
|
||||
break;
|
||||
}
|
||||
@@ -1214,7 +1269,7 @@ export class Repository {
|
||||
});
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
default:
|
||||
// Unknown status
|
||||
break entriesLoop;
|
||||
@@ -1308,7 +1363,7 @@ export class Repository {
|
||||
await this.exec(['update-index', add, '--cacheinfo', mode, hash, path]);
|
||||
}
|
||||
|
||||
async checkout(treeish: string, paths: string[], opts: { track?: boolean, detached?: boolean } = Object.create(null)): Promise<void> {
|
||||
async checkout(treeish: string, paths: string[], opts: { track?: boolean; detached?: boolean } = Object.create(null)): Promise<void> {
|
||||
const args = ['checkout', '-q'];
|
||||
|
||||
if (opts.track) {
|
||||
@@ -1570,7 +1625,7 @@ export class Repository {
|
||||
await this.exec(args);
|
||||
}
|
||||
|
||||
async fetch(options: { remote?: string, ref?: string, all?: boolean, prune?: boolean, depth?: number, silent?: boolean, readonly cancellationToken?: CancellationToken } = {}): Promise<void> {
|
||||
async fetch(options: { remote?: string; ref?: string; all?: boolean; prune?: boolean; depth?: number; silent?: boolean; readonly cancellationToken?: CancellationToken } = {}): Promise<void> {
|
||||
const args = ['fetch'];
|
||||
const spawnOptions: SpawnOptions = {
|
||||
cancellationToken: options.cancellationToken,
|
||||
@@ -1793,10 +1848,13 @@ export class Repository {
|
||||
}
|
||||
|
||||
async dropStash(index?: number): Promise<void> {
|
||||
const args = ['stash', 'drop'];
|
||||
const args = ['stash'];
|
||||
|
||||
if (typeof index === 'number') {
|
||||
args.push('drop');
|
||||
args.push(`stash@{${index}}`);
|
||||
} else {
|
||||
args.push('clear');
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -1810,11 +1868,17 @@ export class Repository {
|
||||
}
|
||||
}
|
||||
|
||||
getStatus(opts?: { limit?: number, ignoreSubmodules?: boolean }): Promise<{ status: IFileStatus[]; didHitLimit: boolean; }> {
|
||||
return new Promise<{ status: IFileStatus[]; didHitLimit: boolean; }>((c, e) => {
|
||||
getStatus(opts?: { limit?: number; ignoreSubmodules?: boolean; untrackedChanges?: 'mixed' | 'separate' | 'hidden' }): Promise<{ status: IFileStatus[]; statusLength: number; didHitLimit: boolean }> {
|
||||
return new Promise<{ status: IFileStatus[]; statusLength: number; didHitLimit: boolean }>((c, e) => {
|
||||
const parser = new GitStatusParser();
|
||||
const env = { GIT_OPTIONAL_LOCKS: '0' };
|
||||
const args = ['status', '-z', '-u'];
|
||||
const args = ['status', '-z'];
|
||||
|
||||
if (opts?.untrackedChanges === 'hidden') {
|
||||
args.push('-uno');
|
||||
} else {
|
||||
args.push('-uall');
|
||||
}
|
||||
|
||||
if (opts?.ignoreSubmodules) {
|
||||
args.push('--ignore-submodules');
|
||||
@@ -1835,10 +1899,10 @@ export class Repository {
|
||||
}));
|
||||
}
|
||||
|
||||
c({ status: parser.status, didHitLimit: false });
|
||||
c({ status: parser.status, statusLength: parser.status.length, didHitLimit: false });
|
||||
};
|
||||
|
||||
const limit = opts?.limit ?? 5000;
|
||||
const limit = opts?.limit ?? 10000;
|
||||
const onStdoutData = (raw: string) => {
|
||||
parser.update(raw);
|
||||
|
||||
@@ -1847,7 +1911,7 @@ export class Repository {
|
||||
child.stdout!.removeListener('data', onStdoutData);
|
||||
child.kill();
|
||||
|
||||
c({ status: parser.status.slice(0, limit), didHitLimit: true });
|
||||
c({ status: parser.status.slice(0, limit), statusLength: parser.status.length, didHitLimit: true });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1891,7 +1955,7 @@ export class Repository {
|
||||
.map(([ref]) => ({ name: ref, type: RefType.Head } as Branch));
|
||||
}
|
||||
|
||||
async getRefs(opts?: { sort?: 'alphabetically' | 'committerdate', contains?: string, pattern?: string, count?: number }): Promise<Ref[]> {
|
||||
async getRefs(opts?: { sort?: 'alphabetically' | 'committerdate'; contains?: string; pattern?: string; count?: number }): Promise<Ref[]> {
|
||||
const args = ['for-each-ref'];
|
||||
|
||||
if (opts?.count) {
|
||||
@@ -1989,8 +2053,10 @@ export class Repository {
|
||||
if (this._git.compareGitVersionTo('1.9.0') === -1) {
|
||||
args.push('--format=%(refname)%00%(upstream:short)%00%(objectname)');
|
||||
supportsAheadBehind = false;
|
||||
} else {
|
||||
} else if (this._git.compareGitVersionTo('2.16.0') === -1) {
|
||||
args.push('--format=%(refname)%00%(upstream:short)%00%(objectname)%00%(upstream:track)');
|
||||
} else {
|
||||
args.push('--format=%(refname)%00%(upstream:short)%00%(objectname)%00%(upstream:track)%00%(upstream:remotename)%00%(upstream:remoteref)');
|
||||
}
|
||||
|
||||
if (/^refs\/(head|remotes)\//i.test(name)) {
|
||||
@@ -2001,7 +2067,7 @@ export class Repository {
|
||||
|
||||
const result = await this.exec(args);
|
||||
const branches: Branch[] = result.stdout.trim().split('\n').map<Branch | undefined>(line => {
|
||||
let [branchName, upstream, ref, status] = line.trim().split('\0');
|
||||
let [branchName, upstream, ref, status, remoteName, upstreamRef] = line.trim().split('\0');
|
||||
|
||||
if (branchName.startsWith('refs/heads/')) {
|
||||
branchName = branchName.substring(11);
|
||||
@@ -2018,8 +2084,8 @@ export class Repository {
|
||||
type: RefType.Head,
|
||||
name: branchName,
|
||||
upstream: upstream ? {
|
||||
name: upstream.substring(index + 1),
|
||||
remote: upstream.substring(0, index)
|
||||
name: upstreamRef ? upstreamRef.substring(11) : upstream.substring(index + 1),
|
||||
remote: remoteName ? remoteName : upstream.substring(0, index)
|
||||
} : undefined,
|
||||
commit: ref || undefined,
|
||||
ahead: Number(ahead) || 0,
|
||||
|
||||
@@ -61,7 +61,7 @@ export async function createIPCServer(context?: string): Promise<IIPCServer> {
|
||||
|
||||
export interface IIPCServer extends Disposable {
|
||||
readonly ipcHandlePath: string | undefined;
|
||||
getEnv(): { [key: string]: string; };
|
||||
getEnv(): { [key: string]: string };
|
||||
registerHandler(name: string, handler: IIPCHandler): Disposable;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ class IPCServer implements IIPCServer, Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
getEnv(): { [key: string]: string; } {
|
||||
getEnv(): { [key: string]: string } {
|
||||
return { VSCODE_GIT_IPC_HANDLE: this.ipcHandlePath };
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ import { CommandCenter } from './commands';
|
||||
import { GitFileSystemProvider } from './fileSystemProvider';
|
||||
import { GitDecorations } from './decorationProvider';
|
||||
import { Askpass } from './askpass';
|
||||
import { toDisposable, filterEvent, eventToPromise } from './util';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
import { toDisposable, filterEvent, eventToPromise, logTimestamp } from './util';
|
||||
import TelemetryReporter from '@vscode/extension-telemetry';
|
||||
import { GitExtension } from './api/git';
|
||||
import { GitProtocolHandler } from './protocolHandler';
|
||||
import { GitExtensionImpl } from './api/extension';
|
||||
@@ -25,7 +25,7 @@ import { GitTimelineProvider } from './timelineProvider';
|
||||
import { registerAPICommands } from './api/api1';
|
||||
import { TerminalEnvironmentManager } from './terminal';
|
||||
|
||||
const deactivateTasks: { (): Promise<any>; }[] = [];
|
||||
const deactivateTasks: { (): Promise<any> }[] = [];
|
||||
|
||||
export async function deactivate(): Promise<any> {
|
||||
for (const task of deactivateTasks) {
|
||||
@@ -46,7 +46,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
|
||||
}
|
||||
|
||||
const info = await findGit(pathHints, gitPath => {
|
||||
outputChannel.appendLine(localize('validating', "Validating found git in: {0}", gitPath));
|
||||
outputChannel.appendLine(localize('validating', "{0} Validating found git in: {1}", logTimestamp(), gitPath));
|
||||
if (excludes.length === 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
|
||||
const normalized = path.normalize(gitPath).replace(/[\r\n]+$/, '');
|
||||
const skip = excludes.some(e => normalized.startsWith(e));
|
||||
if (skip) {
|
||||
outputChannel.appendLine(localize('skipped', "Skipped found git in: {0}", gitPath));
|
||||
outputChannel.appendLine(localize('skipped', "{0} Skipped found git in: {1}", logTimestamp(), gitPath));
|
||||
}
|
||||
return !skip;
|
||||
});
|
||||
@@ -73,7 +73,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
|
||||
version: info.version,
|
||||
env: environment,
|
||||
});
|
||||
const model = new Model(git, askpass, context.globalState, outputChannel);
|
||||
const model = new Model(git, askpass, context.globalState, outputChannel, telemetryReporter);
|
||||
disposables.push(model);
|
||||
|
||||
const onRepository = () => commands.executeCommand('setContext', 'gitOpenRepositoryCount', `${model.repositories.length}`);
|
||||
@@ -81,7 +81,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
|
||||
model.onDidCloseRepository(onRepository, null, disposables);
|
||||
onRepository();
|
||||
|
||||
outputChannel.appendLine(localize('using git', "Using git {0} from {1}", info.version, info.path));
|
||||
outputChannel.appendLine(localize('using git', "{0} Using git {1} from {2}", logTimestamp(), info.version, info.path));
|
||||
|
||||
const onOutput = (str: string) => {
|
||||
const lines = str.split(/\r?\n/mg);
|
||||
@@ -90,7 +90,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
|
||||
lines.pop();
|
||||
}
|
||||
|
||||
outputChannel.appendLine(lines.join('\n'));
|
||||
outputChannel.appendLine(`${logTimestamp()} ${lines.join('\n')}`);
|
||||
};
|
||||
git.onOutput.addListener('log', onOutput);
|
||||
disposables.push(toDisposable(() => git.onOutput.removeListener('log', onOutput)));
|
||||
@@ -152,7 +152,7 @@ async function warnAboutMissingGit(): Promise<void> {
|
||||
);
|
||||
|
||||
if (choice === download) {
|
||||
commands.executeCommand('vscode.open', Uri.parse('https://git-scm.com/'));
|
||||
commands.executeCommand('vscode.open', Uri.parse('https://aka.ms/vscode-download-git'));
|
||||
} else if (choice === neverShowAgain) {
|
||||
await config.update('ignoreMissingGitWarning', true, true);
|
||||
}
|
||||
@@ -166,7 +166,7 @@ export async function _activate(context: ExtensionContext): Promise<GitExtension
|
||||
commands.registerCommand('git.showOutput', () => outputChannel.show());
|
||||
disposables.push(outputChannel);
|
||||
|
||||
const { name, version, aiKey } = require('../package.json') as { name: string, version: string, aiKey: string };
|
||||
const { name, version, aiKey } = require('../package.json') as { name: string; version: string; aiKey: string };
|
||||
const telemetryReporter = new TelemetryReporter(name, version, aiKey);
|
||||
deactivateTasks.push(() => telemetryReporter.dispose());
|
||||
|
||||
@@ -193,6 +193,11 @@ export async function _activate(context: ExtensionContext): Promise<GitExtension
|
||||
// console.warn(err.message); {{SQL CARBON EDIT}} turn-off Git missing prompt
|
||||
// outputChannel.appendLine(err.message); {{SQL CARBON EDIT}} turn-off Git missing prompt
|
||||
|
||||
/* __GDPR__
|
||||
"git.missing" : {}
|
||||
*/
|
||||
telemetryReporter.sendTelemetryEvent('git.missing');
|
||||
|
||||
commands.executeCommand('setContext', 'git.missing', true);
|
||||
// warnAboutMissingGit(); {{SQL CARBON EDIT}} turn-off Git missing prompt
|
||||
|
||||
|
||||
@@ -4,19 +4,21 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, OutputChannel, commands } from 'vscode';
|
||||
import TelemetryReporter from '@vscode/extension-telemetry';
|
||||
import { Repository, RepositoryState } from './repository';
|
||||
import { memoize, sequentialize, debounce } from './decorators';
|
||||
import { dispose, anyEvent, filterEvent, isDescendant, pathEquals, toDisposable, eventToPromise } from './util';
|
||||
import { dispose, anyEvent, filterEvent, isDescendant, pathEquals, toDisposable, eventToPromise, logTimestamp } from './util';
|
||||
import { Git } from './git';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { fromGitUri } from './uri';
|
||||
import { APIState as State, RemoteSourceProvider, CredentialsProvider, PushErrorHandler, PublishEvent } from './api/git';
|
||||
import { APIState as State, CredentialsProvider, PushErrorHandler, PublishEvent, RemoteSourcePublisher } from './api/git';
|
||||
import { Askpass } from './askpass';
|
||||
import { IRemoteSourceProviderRegistry } from './remoteProvider';
|
||||
import { IPushErrorHandlerRegistry } from './pushError';
|
||||
import { ApiRepository } from './api/api1';
|
||||
import { IRemoteSourcePublisherRegistry } from './remotePublisher';
|
||||
import { Log, LogLevel } from './log';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -48,7 +50,7 @@ interface OpenRepository extends Disposable {
|
||||
repository: Repository;
|
||||
}
|
||||
|
||||
export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRegistry {
|
||||
export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerRegistry {
|
||||
|
||||
private _onDidOpenRepository = new EventEmitter<Repository>();
|
||||
readonly onDidOpenRepository: Event<Repository> = this._onDidOpenRepository.event;
|
||||
@@ -95,19 +97,20 @@ export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRe
|
||||
return eventToPromise(filterEvent(this.onDidChangeState, s => s === 'initialized')) as Promise<any>;
|
||||
}
|
||||
|
||||
private remoteSourceProviders = new Set<RemoteSourceProvider>();
|
||||
private remoteSourcePublishers = new Set<RemoteSourcePublisher>();
|
||||
|
||||
private _onDidAddRemoteSourceProvider = new EventEmitter<RemoteSourceProvider>();
|
||||
readonly onDidAddRemoteSourceProvider = this._onDidAddRemoteSourceProvider.event;
|
||||
private _onDidAddRemoteSourcePublisher = new EventEmitter<RemoteSourcePublisher>();
|
||||
readonly onDidAddRemoteSourcePublisher = this._onDidAddRemoteSourcePublisher.event;
|
||||
|
||||
private _onDidRemoveRemoteSourceProvider = new EventEmitter<RemoteSourceProvider>();
|
||||
readonly onDidRemoveRemoteSourceProvider = this._onDidRemoveRemoteSourceProvider.event;
|
||||
private _onDidRemoveRemoteSourcePublisher = new EventEmitter<RemoteSourcePublisher>();
|
||||
readonly onDidRemoveRemoteSourcePublisher = this._onDidRemoveRemoteSourcePublisher.event;
|
||||
|
||||
private showRepoOnHomeDriveRootWarning = true;
|
||||
private pushErrorHandlers = new Set<PushErrorHandler>();
|
||||
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private outputChannel: OutputChannel) {
|
||||
constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private outputChannel: OutputChannel, private telemetryReporter: TelemetryReporter) {
|
||||
workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables);
|
||||
window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables);
|
||||
workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.disposables);
|
||||
@@ -133,25 +136,36 @@ export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRe
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the first level of each workspace folder, looking
|
||||
* for git repositories.
|
||||
* Scans each workspace folder, looking for git repositories. By
|
||||
* default it scans one level deep but that can be changed using
|
||||
* the git.repositoryScanMaxDepth setting.
|
||||
*/
|
||||
private async scanWorkspaceFolders(): Promise<void> {
|
||||
const config = workspace.getConfiguration('git');
|
||||
const autoRepositoryDetection = config.get<boolean | 'subFolders' | 'openEditors'>('autoRepositoryDetection');
|
||||
|
||||
// Log repository scan settings
|
||||
if (Log.logLevel <= LogLevel.Trace) {
|
||||
this.outputChannel.appendLine(`${logTimestamp()} Trace: autoRepositoryDetection="${autoRepositoryDetection}"`);
|
||||
}
|
||||
|
||||
if (autoRepositoryDetection !== true && autoRepositoryDetection !== 'subFolders') {
|
||||
return;
|
||||
}
|
||||
|
||||
await Promise.all((workspace.workspaceFolders || []).map(async folder => {
|
||||
const root = folder.uri.fsPath;
|
||||
const children = await new Promise<string[]>((c, e) => fs.readdir(root, (err, r) => err ? e(err) : c(r)));
|
||||
const subfolders = new Set(children.filter(child => child !== '.git').map(child => path.join(root, child)));
|
||||
|
||||
// Workspace folder children
|
||||
const repositoryScanMaxDepth = (workspace.isTrusted ? workspace.getConfiguration('git', folder.uri) : config).get<number>('repositoryScanMaxDepth', 1);
|
||||
const repositoryScanIgnoredFolders = (workspace.isTrusted ? workspace.getConfiguration('git', folder.uri) : config).get<string[]>('repositoryScanIgnoredFolders', []);
|
||||
|
||||
const subfolders = new Set(await this.traverseWorkspaceFolder(root, repositoryScanMaxDepth, repositoryScanIgnoredFolders));
|
||||
|
||||
// Repository scan folders
|
||||
const scanPaths = (workspace.isTrusted ? workspace.getConfiguration('git', folder.uri) : config).get<string[]>('scanRepositories') || [];
|
||||
for (const scanPath of scanPaths) {
|
||||
if (scanPath !== '.git') {
|
||||
if (scanPath === '.git') {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -167,6 +181,31 @@ export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRe
|
||||
}));
|
||||
}
|
||||
|
||||
private async traverseWorkspaceFolder(workspaceFolder: string, maxDepth: number, repositoryScanIgnoredFolders: string[]): Promise<string[]> {
|
||||
const result: string[] = [];
|
||||
const foldersToTravers = [{ path: workspaceFolder, depth: 0 }];
|
||||
|
||||
while (foldersToTravers.length > 0) {
|
||||
const currentFolder = foldersToTravers.shift()!;
|
||||
|
||||
if (currentFolder.depth < maxDepth || maxDepth === -1) {
|
||||
const children = await fs.promises.readdir(currentFolder.path, { withFileTypes: true });
|
||||
const childrenFolders = children
|
||||
.filter(dirent =>
|
||||
dirent.isDirectory() && dirent.name !== '.git' &&
|
||||
!repositoryScanIgnoredFolders.find(f => pathEquals(dirent.name, f)))
|
||||
.map(dirent => path.join(currentFolder.path, dirent.name));
|
||||
|
||||
result.push(...childrenFolders);
|
||||
foldersToTravers.push(...childrenFolders.map(folder => {
|
||||
return { path: folder, depth: currentFolder.depth + 1 };
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private onPossibleGitRepositoryChange(uri: Uri): void {
|
||||
const config = workspace.getConfiguration('git');
|
||||
const autoRepositoryDetection = config.get<boolean | 'subFolders' | 'openEditors'>('autoRepositoryDetection');
|
||||
@@ -271,7 +310,7 @@ export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRe
|
||||
// Check if the folder is a bare repo: if it has a file named HEAD && `rev-parse --show -cdup` is empty
|
||||
try {
|
||||
fs.accessSync(path.join(repoPath, 'HEAD'), fs.constants.F_OK);
|
||||
const result = await this.git.exec(repoPath, ['-C', repoPath, 'rev-parse', '--show-cdup'], { log: false });
|
||||
const result = await this.git.exec(repoPath, ['-C', repoPath, 'rev-parse', '--show-cdup']);
|
||||
if (result.stderr.trim() === '' && result.stdout.trim() === '') {
|
||||
return;
|
||||
}
|
||||
@@ -296,14 +335,32 @@ export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRe
|
||||
return;
|
||||
}
|
||||
|
||||
// On Window, opening a git repository from the root of the HOMEDRIVE poses a security risk.
|
||||
// We will only a open git repository from the root of the HOMEDRIVE if the user explicitly
|
||||
// opens the HOMEDRIVE as a folder. Only show the warning once during repository discovery.
|
||||
if (process.platform === 'win32' && process.env.HOMEDRIVE && pathEquals(`${process.env.HOMEDRIVE}\\`, repositoryRoot)) {
|
||||
const isRepoInWorkspaceFolders = (workspace.workspaceFolders ?? []).find(f => pathEquals(f.uri.fsPath, repositoryRoot))!!;
|
||||
|
||||
if (!isRepoInWorkspaceFolders) {
|
||||
if (this.showRepoOnHomeDriveRootWarning) {
|
||||
window.showWarningMessage(localize('repoOnHomeDriveRootWarning', "Unable to automatically open the git repository at '{0}'. To open that git repository, open it directly as a folder in VS Code.", repositoryRoot));
|
||||
this.showRepoOnHomeDriveRootWarning = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const dotGit = await this.git.getRepositoryDotGit(repositoryRoot);
|
||||
const repository = new Repository(this.git.open(repositoryRoot, dotGit), this, this, this.globalState, this.outputChannel);
|
||||
const repository = new Repository(this.git.open(repositoryRoot, dotGit), this, this, this.globalState, this.outputChannel, this.telemetryReporter);
|
||||
|
||||
this.open(repository);
|
||||
await repository.status();
|
||||
repository.status(); // do not await this, we want SCM to know about the repo asap
|
||||
} catch (ex) {
|
||||
// noop
|
||||
this.outputChannel.appendLine(`Opening repository for path='${repoPath}' failed; ex=${ex}`);
|
||||
if (Log.logLevel <= LogLevel.Trace) {
|
||||
this.outputChannel.appendLine(`${logTimestamp()} Trace: Opening repository for path='${repoPath}' failed; ex=${ex}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +386,7 @@ export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRe
|
||||
}
|
||||
|
||||
private open(repository: Repository): void {
|
||||
this.outputChannel.appendLine(`Open repository: ${repository.root}`);
|
||||
this.outputChannel.appendLine(`${logTimestamp()} Open repository: ${repository.root}`);
|
||||
|
||||
const onDidDisappearRepository = filterEvent(repository.onDidChangeState, state => state === RepositoryState.Disposed);
|
||||
const disappearListener = onDidDisappearRepository(() => dispose());
|
||||
@@ -386,7 +443,7 @@ export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRe
|
||||
return;
|
||||
}
|
||||
|
||||
this.outputChannel.appendLine(`Close repository: ${repository.root}`);
|
||||
this.outputChannel.appendLine(`${logTimestamp()} Close repository: ${repository.root}`);
|
||||
openRepository.dispose();
|
||||
}
|
||||
|
||||
@@ -496,24 +553,24 @@ export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRe
|
||||
return undefined;
|
||||
}
|
||||
|
||||
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable {
|
||||
this.remoteSourceProviders.add(provider);
|
||||
this._onDidAddRemoteSourceProvider.fire(provider);
|
||||
registerRemoteSourcePublisher(publisher: RemoteSourcePublisher): Disposable {
|
||||
this.remoteSourcePublishers.add(publisher);
|
||||
this._onDidAddRemoteSourcePublisher.fire(publisher);
|
||||
|
||||
return toDisposable(() => {
|
||||
this.remoteSourceProviders.delete(provider);
|
||||
this._onDidRemoveRemoteSourceProvider.fire(provider);
|
||||
this.remoteSourcePublishers.delete(publisher);
|
||||
this._onDidRemoveRemoteSourcePublisher.fire(publisher);
|
||||
});
|
||||
}
|
||||
|
||||
getRemoteSourcePublishers(): RemoteSourcePublisher[] {
|
||||
return [...this.remoteSourcePublishers.values()];
|
||||
}
|
||||
|
||||
registerCredentialsProvider(provider: CredentialsProvider): Disposable {
|
||||
return this.askpass.registerCredentialsProvider(provider);
|
||||
}
|
||||
|
||||
getRemoteProviders(): RemoteSourceProvider[] {
|
||||
return [...this.remoteSourceProviders.values()];
|
||||
}
|
||||
|
||||
registerPushErrorHandler(handler: PushErrorHandler): Disposable {
|
||||
this.pushErrorHandlers.add(handler);
|
||||
return toDisposable(() => this.pushErrorHandlers.delete(handler));
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, Event } from 'vscode';
|
||||
import { RemoteSourceProvider } from './api/git';
|
||||
import { RemoteSourcePublisher } from './api/git';
|
||||
|
||||
export interface IRemoteSourceProviderRegistry {
|
||||
readonly onDidAddRemoteSourceProvider: Event<RemoteSourceProvider>;
|
||||
readonly onDidRemoveRemoteSourceProvider: Event<RemoteSourceProvider>;
|
||||
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable;
|
||||
getRemoteProviders(): RemoteSourceProvider[];
|
||||
export interface IRemoteSourcePublisherRegistry {
|
||||
readonly onDidAddRemoteSourcePublisher: Event<RemoteSourcePublisher>;
|
||||
readonly onDidRemoveRemoteSourcePublisher: Event<RemoteSourcePublisher>;
|
||||
|
||||
getRemoteSourcePublishers(): RemoteSourcePublisher[];
|
||||
registerRemoteSourcePublisher(publisher: RemoteSourcePublisher): Disposable;
|
||||
}
|
||||
@@ -3,180 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { QuickPickItem, window, QuickPick } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { RemoteSourceProvider, RemoteSource } from './api/git';
|
||||
import { Model } from './model';
|
||||
import { throttle, debounce } from './decorators';
|
||||
import { PickRemoteSourceOptions, PickRemoteSourceResult } from './api/git-base';
|
||||
import { GitBaseApi } from './git-base';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
async function getQuickPickResult<T extends QuickPickItem>(quickpick: QuickPick<T>): Promise<T | undefined> {
|
||||
const result = await new Promise<T | undefined>(c => {
|
||||
quickpick.onDidAccept(() => c(quickpick.selectedItems[0]));
|
||||
quickpick.onDidHide(() => c(undefined));
|
||||
quickpick.show();
|
||||
});
|
||||
|
||||
quickpick.hide();
|
||||
return result;
|
||||
}
|
||||
|
||||
class RemoteSourceProviderQuickPick {
|
||||
|
||||
private quickpick: QuickPick<QuickPickItem & { remoteSource?: RemoteSource }>;
|
||||
|
||||
constructor(private provider: RemoteSourceProvider) {
|
||||
this.quickpick = window.createQuickPick();
|
||||
this.quickpick.ignoreFocusOut = true;
|
||||
|
||||
if (provider.supportsQuery) {
|
||||
this.quickpick.placeholder = localize('type to search', "Repository name (type to search)");
|
||||
this.quickpick.onDidChangeValue(this.onDidChangeValue, this);
|
||||
} else {
|
||||
this.quickpick.placeholder = localize('type to filter', "Repository name");
|
||||
}
|
||||
}
|
||||
|
||||
@debounce(300)
|
||||
private onDidChangeValue(): void {
|
||||
this.query();
|
||||
}
|
||||
|
||||
@throttle
|
||||
private async query(): Promise<void> {
|
||||
this.quickpick.busy = true;
|
||||
|
||||
try {
|
||||
const remoteSources = await this.provider.getRemoteSources(this.quickpick.value) || [];
|
||||
|
||||
if (remoteSources.length === 0) {
|
||||
this.quickpick.items = [{
|
||||
label: localize('none found', "No remote repositories found."),
|
||||
alwaysShow: true
|
||||
}];
|
||||
} else {
|
||||
this.quickpick.items = remoteSources.map(remoteSource => ({
|
||||
label: remoteSource.name,
|
||||
description: remoteSource.description || (typeof remoteSource.url === 'string' ? remoteSource.url : remoteSource.url[0]),
|
||||
remoteSource,
|
||||
alwaysShow: true
|
||||
}));
|
||||
}
|
||||
} catch (err) {
|
||||
this.quickpick.items = [{ label: localize('error', "$(error) Error: {0}", err.message), alwaysShow: true }];
|
||||
console.error(err);
|
||||
} finally {
|
||||
this.quickpick.busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
async pick(): Promise<RemoteSource | undefined> {
|
||||
this.query();
|
||||
const result = await getQuickPickResult(this.quickpick);
|
||||
return result?.remoteSource;
|
||||
}
|
||||
}
|
||||
|
||||
export interface PickRemoteSourceOptions {
|
||||
readonly providerLabel?: (provider: RemoteSourceProvider) => string;
|
||||
readonly urlLabel?: string;
|
||||
readonly providerName?: string;
|
||||
readonly branch?: boolean; // then result is PickRemoteSourceResult
|
||||
}
|
||||
|
||||
export interface PickRemoteSourceResult {
|
||||
readonly url: string;
|
||||
readonly branch?: string;
|
||||
}
|
||||
|
||||
export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions & { branch?: false | undefined }): Promise<string | undefined>;
|
||||
export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions & { branch: true }): Promise<PickRemoteSourceResult | undefined>;
|
||||
export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions = {}): Promise<string | PickRemoteSourceResult | undefined> {
|
||||
const quickpick = window.createQuickPick<(QuickPickItem & { provider?: RemoteSourceProvider, url?: string })>();
|
||||
quickpick.ignoreFocusOut = true;
|
||||
|
||||
if (options.providerName) {
|
||||
const provider = model.getRemoteProviders()
|
||||
.filter(provider => provider.name === options.providerName)[0];
|
||||
|
||||
if (provider) {
|
||||
return await pickProviderSource(provider, options);
|
||||
}
|
||||
}
|
||||
|
||||
const providers = model.getRemoteProviders()
|
||||
.map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + (options.providerLabel ? options.providerLabel(provider) : provider.name), alwaysShow: true, provider }));
|
||||
|
||||
quickpick.placeholder = providers.length === 0
|
||||
? localize('provide url', "Provide repository URL")
|
||||
: localize('provide url or pick', "Provide repository URL or pick a repository source.");
|
||||
|
||||
const updatePicks = (value?: string) => {
|
||||
if (value) {
|
||||
quickpick.items = [{
|
||||
label: options.urlLabel ?? localize('url', "URL"),
|
||||
description: value,
|
||||
alwaysShow: true,
|
||||
url: value
|
||||
},
|
||||
...providers];
|
||||
} else {
|
||||
quickpick.items = providers;
|
||||
}
|
||||
};
|
||||
|
||||
quickpick.onDidChangeValue(updatePicks);
|
||||
updatePicks();
|
||||
|
||||
const result = await getQuickPickResult(quickpick);
|
||||
|
||||
if (result) {
|
||||
if (result.url) {
|
||||
return result.url;
|
||||
} else if (result.provider) {
|
||||
return await pickProviderSource(result.provider, options);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async function pickProviderSource(provider: RemoteSourceProvider, options: PickRemoteSourceOptions = {}): Promise<string | PickRemoteSourceResult | undefined> {
|
||||
const quickpick = new RemoteSourceProviderQuickPick(provider);
|
||||
const remote = await quickpick.pick();
|
||||
|
||||
let url: string | undefined;
|
||||
|
||||
if (remote) {
|
||||
if (typeof remote.url === 'string') {
|
||||
url = remote.url;
|
||||
} else if (remote.url.length > 0) {
|
||||
url = await window.showQuickPick(remote.url, { ignoreFocusOut: true, placeHolder: localize('pick url', "Choose a URL to clone from.") });
|
||||
}
|
||||
}
|
||||
|
||||
if (!url || !options.branch) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (!provider.getBranches) {
|
||||
return { url };
|
||||
}
|
||||
|
||||
const branches = await provider.getBranches(url);
|
||||
|
||||
if (!branches) {
|
||||
return { url };
|
||||
}
|
||||
|
||||
const branch = await window.showQuickPick(branches, {
|
||||
placeHolder: localize('branch name', "Branch name")
|
||||
});
|
||||
|
||||
if (!branch) {
|
||||
return { url };
|
||||
}
|
||||
|
||||
return { url, branch };
|
||||
export async function pickRemoteSource(options: PickRemoteSourceOptions & { branch?: false | undefined }): Promise<string | undefined>;
|
||||
export async function pickRemoteSource(options: PickRemoteSourceOptions & { branch: true }): Promise<PickRemoteSourceResult | undefined>;
|
||||
export async function pickRemoteSource(options: PickRemoteSourceOptions = {}): Promise<string | PickRemoteSourceResult | undefined> {
|
||||
return GitBaseApi.getAPI().pickRemoteSource(options);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, OutputChannel, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands } from 'vscode';
|
||||
import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, OutputChannel, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands, Tab, TabInputTextDiff, TabInputNotebookDiff, RelativePattern } from 'vscode';
|
||||
import TelemetryReporter from '@vscode/extension-telemetry';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Branch, Change, ForcePushMode, GitErrorCodes, LogOptions, Ref, RefType, Remote, Status, CommitOptions, BranchQuery, FetchOptions } from './api/git';
|
||||
import { AutoFetcher } from './autofetch';
|
||||
@@ -13,12 +14,13 @@ import { debounce, memoize, throttle } from './decorators';
|
||||
import { Commit, GitError, Repository as BaseRepository, Stash, Submodule, LogFileOptions } from './git';
|
||||
import { StatusBarCommands } from './statusbar';
|
||||
import { toGitUri } from './uri';
|
||||
import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, IDisposable, isDescendant, onceEvent } from './util';
|
||||
import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, IDisposable, isDescendant, logTimestamp, onceEvent, pathEquals, relativePath } from './util';
|
||||
import { IFileWatcher, watch } from './watch';
|
||||
import { Log, LogLevel } from './log';
|
||||
import { IRemoteSourceProviderRegistry } from './remoteProvider';
|
||||
import { IPushErrorHandlerRegistry } from './pushError';
|
||||
import { ApiRepository } from './api/api1';
|
||||
import { IRemoteSourcePublisherRegistry } from './remotePublisher';
|
||||
import { ActionButtonCommand } from './actionButton';
|
||||
|
||||
const timeout = (millis: number) => new Promise(c => setTimeout(c, millis));
|
||||
|
||||
@@ -516,8 +518,8 @@ class FileEventLogger {
|
||||
}
|
||||
|
||||
this.eventDisposable = combinedDisposable([
|
||||
this.onWorkspaceWorkingTreeFileChange(uri => this.outputChannel.appendLine(`[debug] [wt] Change: ${uri.fsPath}`)),
|
||||
this.onDotGitFileChange(uri => this.outputChannel.appendLine(`[debug] [.git] Change: ${uri.fsPath}`))
|
||||
this.onWorkspaceWorkingTreeFileChange(uri => this.outputChannel.appendLine(`${logTimestamp()} [debug] [wt] Change: ${uri.fsPath}`)),
|
||||
this.onDotGitFileChange(uri => this.outputChannel.appendLine(`${logTimestamp()} [debug] [.git] Change: ${uri.fsPath}`))
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -539,10 +541,12 @@ class DotGitWatcher implements IFileWatcher {
|
||||
private repository: Repository,
|
||||
private outputChannel: OutputChannel
|
||||
) {
|
||||
const rootWatcher = watch(repository.dotGit);
|
||||
const rootWatcher = watch(repository.dotGit.path);
|
||||
this.disposables.push(rootWatcher);
|
||||
|
||||
const filteredRootWatcher = filterEvent(rootWatcher.event, uri => !/\/\.git(\/index\.lock)?$/.test(uri.path));
|
||||
// Ignore changes to the "index.lock" file, and watchman fsmonitor hook (https://git-scm.com/docs/githooks#_fsmonitor_watchman) cookie files.
|
||||
// Watchman creates a cookie file inside the git directory whenever a query is run (https://facebook.github.io/watchman/docs/cookies.html).
|
||||
const filteredRootWatcher = filterEvent(rootWatcher.event, uri => !/\/\.git(\/index\.lock)?$|\/\.watchman-cookie-/.test(uri.path));
|
||||
this.event = anyEvent(filteredRootWatcher, this.emitter.event);
|
||||
|
||||
repository.onDidRunGitStatus(this.updateTransientWatchers, this, this.disposables);
|
||||
@@ -559,7 +563,7 @@ class DotGitWatcher implements IFileWatcher {
|
||||
this.transientDisposables = dispose(this.transientDisposables);
|
||||
|
||||
const { name, remote } = this.repository.HEAD.upstream;
|
||||
const upstreamPath = path.join(this.repository.dotGit, 'refs', 'remotes', remote, name);
|
||||
const upstreamPath = path.join(this.repository.dotGit.commonPath ?? this.repository.dotGit.path, 'refs', 'remotes', remote, name);
|
||||
|
||||
try {
|
||||
const upstreamWatcher = watch(upstreamPath);
|
||||
@@ -567,7 +571,7 @@ class DotGitWatcher implements IFileWatcher {
|
||||
upstreamWatcher.event(this.emitter.fire, this.emitter, this.transientDisposables);
|
||||
} catch (err) {
|
||||
if (Log.logLevel <= LogLevel.Error) {
|
||||
this.outputChannel.appendLine(`Warning: Failed to watch ref '${upstreamPath}', is most likely packed.`);
|
||||
this.outputChannel.appendLine(`${logTimestamp()} Warning: Failed to watch ref '${upstreamPath}', is most likely packed.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -664,7 +668,7 @@ class ResourceCommandResolver {
|
||||
case Status.MODIFIED:
|
||||
case Status.UNTRACKED:
|
||||
case Status.IGNORED:
|
||||
case Status.INTENT_TO_ADD:
|
||||
case Status.INTENT_TO_ADD: {
|
||||
const uriString = resource.resourceUri.toString();
|
||||
const [indexStatus] = this.repository.indexGroup.resourceStates.filter(r => r.resourceUri.toString() === uriString);
|
||||
|
||||
@@ -673,7 +677,7 @@ class ResourceCommandResolver {
|
||||
}
|
||||
|
||||
return resource.resourceUri;
|
||||
|
||||
}
|
||||
case Status.BOTH_ADDED:
|
||||
case Status.BOTH_MODIFIED:
|
||||
return resource.resourceUri;
|
||||
@@ -838,7 +842,7 @@ export class Repository implements Disposable {
|
||||
return this.repository.root;
|
||||
}
|
||||
|
||||
get dotGit(): string {
|
||||
get dotGit(): { path: string; commonPath?: string } {
|
||||
return this.repository.dotGit;
|
||||
}
|
||||
|
||||
@@ -850,42 +854,42 @@ export class Repository implements Disposable {
|
||||
|
||||
constructor(
|
||||
private readonly repository: BaseRepository,
|
||||
remoteSourceProviderRegistry: IRemoteSourceProviderRegistry,
|
||||
private pushErrorHandlerRegistry: IPushErrorHandlerRegistry,
|
||||
remoteSourcePublisherRegistry: IRemoteSourcePublisherRegistry,
|
||||
globalState: Memento,
|
||||
outputChannel: OutputChannel
|
||||
outputChannel: OutputChannel,
|
||||
private telemetryReporter: TelemetryReporter
|
||||
) {
|
||||
const workspaceWatcher = workspace.createFileSystemWatcher('**');
|
||||
this.disposables.push(workspaceWatcher);
|
||||
const repositoryWatcher = workspace.createFileSystemWatcher(new RelativePattern(Uri.file(repository.root), '**'));
|
||||
this.disposables.push(repositoryWatcher);
|
||||
|
||||
const onWorkspaceFileChange = anyEvent(workspaceWatcher.onDidChange, workspaceWatcher.onDidCreate, workspaceWatcher.onDidDelete);
|
||||
const onWorkspaceRepositoryFileChange = filterEvent(onWorkspaceFileChange, uri => isDescendant(repository.root, uri.fsPath));
|
||||
const onWorkspaceWorkingTreeFileChange = filterEvent(onWorkspaceRepositoryFileChange, uri => !/\/\.git($|\/)/.test(uri.path));
|
||||
const onRepositoryFileChange = anyEvent(repositoryWatcher.onDidChange, repositoryWatcher.onDidCreate, repositoryWatcher.onDidDelete);
|
||||
const onRepositoryWorkingTreeFileChange = filterEvent(onRepositoryFileChange, uri => !/\.git($|\/)/.test(relativePath(repository.root, uri.fsPath)));
|
||||
|
||||
let onDotGitFileChange: Event<Uri>;
|
||||
let onRepositoryDotGitFileChange: Event<Uri>;
|
||||
|
||||
try {
|
||||
const dotGitFileWatcher = new DotGitWatcher(this, outputChannel);
|
||||
onDotGitFileChange = dotGitFileWatcher.event;
|
||||
onRepositoryDotGitFileChange = dotGitFileWatcher.event;
|
||||
this.disposables.push(dotGitFileWatcher);
|
||||
} catch (err) {
|
||||
if (Log.logLevel <= LogLevel.Error) {
|
||||
outputChannel.appendLine(`Failed to watch '${this.dotGit}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`);
|
||||
outputChannel.appendLine(`${logTimestamp()} Failed to watch path:'${this.dotGit.path}' or commonPath:'${this.dotGit.commonPath}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`);
|
||||
}
|
||||
|
||||
onDotGitFileChange = filterEvent(onWorkspaceRepositoryFileChange, uri => /\/\.git($|\/)/.test(uri.path));
|
||||
onRepositoryDotGitFileChange = filterEvent(onRepositoryFileChange, uri => /\.git($|\/)/.test(uri.path));
|
||||
}
|
||||
|
||||
// FS changes should trigger `git status`:
|
||||
// - any change inside the repository working tree
|
||||
// - any change whithin the first level of the `.git` folder, except the folder itself and `index.lock`
|
||||
const onFileChange = anyEvent(onWorkspaceWorkingTreeFileChange, onDotGitFileChange);
|
||||
const onFileChange = anyEvent(onRepositoryWorkingTreeFileChange, onRepositoryDotGitFileChange);
|
||||
onFileChange(this.onFileChange, this, this.disposables);
|
||||
|
||||
// Relevate repository changes should trigger virtual document change events
|
||||
onDotGitFileChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
|
||||
onRepositoryDotGitFileChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
|
||||
|
||||
this.disposables.push(new FileEventLogger(onWorkspaceWorkingTreeFileChange, onDotGitFileChange, outputChannel));
|
||||
this.disposables.push(new FileEventLogger(onRepositoryWorkingTreeFileChange, onRepositoryDotGitFileChange, outputChannel));
|
||||
|
||||
const root = Uri.file(repository.root);
|
||||
this._sourceControl = scm.createSourceControl('git', 'Git', root);
|
||||
@@ -959,11 +963,16 @@ export class Repository implements Disposable {
|
||||
}
|
||||
}, null, this.disposables);
|
||||
|
||||
const statusBar = new StatusBarCommands(this, remoteSourceProviderRegistry);
|
||||
const statusBar = new StatusBarCommands(this, remoteSourcePublisherRegistry);
|
||||
this.disposables.push(statusBar);
|
||||
statusBar.onDidChange(() => this._sourceControl.statusBarCommands = statusBar.commands, null, this.disposables);
|
||||
this._sourceControl.statusBarCommands = statusBar.commands;
|
||||
|
||||
const actionButton = new ActionButtonCommand(this);
|
||||
this.disposables.push(actionButton);
|
||||
actionButton.onDidChange(() => this._sourceControl.actionButton = actionButton.button);
|
||||
this._sourceControl.actionButton = actionButton.button;
|
||||
|
||||
const progressManager = new ProgressManager(this);
|
||||
this.disposables.push(progressManager);
|
||||
|
||||
@@ -1069,7 +1078,7 @@ export class Repository implements Disposable {
|
||||
return await this.repository.getCommitTemplate();
|
||||
}
|
||||
|
||||
getConfigs(): Promise<{ key: string; value: string; }[]> {
|
||||
getConfigs(): Promise<{ key: string; value: string }[]> {
|
||||
return this.run(Operation.Config, () => this.repository.getConfigs('local'));
|
||||
}
|
||||
|
||||
@@ -1150,8 +1159,11 @@ export class Repository implements Disposable {
|
||||
return this.run(Operation.HashObject, () => this.repository.hashObject(data));
|
||||
}
|
||||
|
||||
async add(resources: Uri[], opts?: { update?: boolean; }): Promise<void> {
|
||||
await this.run(Operation.Add, () => this.repository.add(resources.map(r => r.fsPath), opts));
|
||||
async add(resources: Uri[], opts?: { update?: boolean }): Promise<void> {
|
||||
await this.run(Operation.Add, async () => {
|
||||
await this.repository.add(resources.map(r => r.fsPath), opts);
|
||||
this.closeDiffEditors([], [...resources.map(r => r.fsPath)]);
|
||||
});
|
||||
}
|
||||
|
||||
async rm(resources: Uri[]): Promise<void> {
|
||||
@@ -1159,16 +1171,28 @@ export class Repository implements Disposable {
|
||||
}
|
||||
|
||||
async stage(resource: Uri, contents: string): Promise<void> {
|
||||
const relativePath = path.relative(this.repository.root, resource.fsPath).replace(/\\/g, '/');
|
||||
await this.run(Operation.Stage, () => this.repository.stage(relativePath, contents));
|
||||
const path = relativePath(this.repository.root, resource.fsPath).replace(/\\/g, '/');
|
||||
await this.run(Operation.Stage, async () => {
|
||||
await this.repository.stage(path, contents);
|
||||
this.closeDiffEditors([], [...resource.fsPath]);
|
||||
});
|
||||
this._onDidChangeOriginalResource.fire(resource);
|
||||
}
|
||||
|
||||
async revert(resources: Uri[]): Promise<void> {
|
||||
await this.run(Operation.RevertFiles, () => this.repository.revert('HEAD', resources.map(r => r.fsPath)));
|
||||
await this.run(Operation.RevertFiles, async () => {
|
||||
await this.repository.revert('HEAD', resources.map(r => r.fsPath));
|
||||
this.closeDiffEditors([...resources.length !== 0 ?
|
||||
resources.map(r => r.fsPath) :
|
||||
this.indexGroup.resourceStates.map(r => r.resourceUri.fsPath)], []);
|
||||
});
|
||||
}
|
||||
|
||||
async commit(message: string | undefined, opts: CommitOptions = Object.create(null)): Promise<void> {
|
||||
const indexResources = [...this.indexGroup.resourceStates.map(r => r.resourceUri.fsPath)];
|
||||
const workingGroupResources = opts.all && opts.all !== 'tracked' ?
|
||||
[...this.workingTreeGroup.resourceStates.map(r => r.resourceUri.fsPath)] : [];
|
||||
|
||||
if (this.rebaseCommit) {
|
||||
await this.run(Operation.RebaseContinue, async () => {
|
||||
if (opts.all) {
|
||||
@@ -1177,6 +1201,7 @@ export class Repository implements Disposable {
|
||||
}
|
||||
|
||||
await this.repository.rebaseContinue();
|
||||
this.closeDiffEditors(indexResources, workingGroupResources);
|
||||
});
|
||||
} else {
|
||||
await this.run(Operation.Commit, async () => {
|
||||
@@ -1193,6 +1218,7 @@ export class Repository implements Disposable {
|
||||
}
|
||||
|
||||
await this.repository.commit(message, opts);
|
||||
this.closeDiffEditors(indexResources, workingGroupResources);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1236,9 +1262,35 @@ export class Repository implements Disposable {
|
||||
await this.repository.clean(toClean);
|
||||
await this.repository.checkout('', toCheckout);
|
||||
await this.repository.updateSubmodules(submodulesToUpdate);
|
||||
|
||||
this.closeDiffEditors([], [...toClean, ...toCheckout]);
|
||||
});
|
||||
}
|
||||
|
||||
closeDiffEditors(indexResources: string[], workingTreeResources: string[], ignoreSetting: boolean = false): void {
|
||||
const config = workspace.getConfiguration('git', Uri.file(this.root));
|
||||
if (!config.get<boolean>('closeDiffOnOperation', false) && !ignoreSetting) { return; }
|
||||
|
||||
const diffEditorTabsToClose: Tab[] = [];
|
||||
|
||||
for (const tab of window.tabGroups.all.map(g => g.tabs).flat()) {
|
||||
const { input } = tab;
|
||||
if (input instanceof TabInputTextDiff || input instanceof TabInputNotebookDiff) {
|
||||
if (input.modified.scheme === 'git' && indexResources.some(r => pathEquals(r, input.modified.fsPath))) {
|
||||
// Index
|
||||
diffEditorTabsToClose.push(tab);
|
||||
}
|
||||
if (input.modified.scheme === 'file' && input.original.scheme === 'git' && workingTreeResources.some(r => pathEquals(r, input.modified.fsPath))) {
|
||||
// Working Tree
|
||||
diffEditorTabsToClose.push(tab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close editors
|
||||
window.tabGroups.close(diffEditorTabsToClose, true);
|
||||
}
|
||||
|
||||
async branch(name: string, _checkout: boolean, _ref?: string): Promise<void> {
|
||||
await this.run(Operation.Branch, () => this.repository.branch(name, _checkout, _ref));
|
||||
}
|
||||
@@ -1287,11 +1339,11 @@ export class Repository implements Disposable {
|
||||
await this.run(Operation.DeleteTag, () => this.repository.deleteTag(name));
|
||||
}
|
||||
|
||||
async checkout(treeish: string, opts?: { detached?: boolean; }): Promise<void> {
|
||||
async checkout(treeish: string, opts?: { detached?: boolean }): Promise<void> {
|
||||
await this.run(Operation.Checkout, () => this.repository.checkout(treeish, [], opts));
|
||||
}
|
||||
|
||||
async checkoutTracking(treeish: string, opts: { detached?: boolean; } = {}): Promise<void> {
|
||||
async checkoutTracking(treeish: string, opts: { detached?: boolean } = {}): Promise<void> {
|
||||
await this.run(Operation.CheckoutTracking, () => this.repository.checkout(treeish, [], { ...opts, track: true }));
|
||||
}
|
||||
|
||||
@@ -1324,7 +1376,7 @@ export class Repository implements Disposable {
|
||||
}
|
||||
|
||||
@throttle
|
||||
async fetchDefault(options: { silent?: boolean; } = {}): Promise<void> {
|
||||
async fetchDefault(options: { silent?: boolean } = {}): Promise<void> {
|
||||
await this._fetch({ silent: options.silent });
|
||||
}
|
||||
|
||||
@@ -1342,7 +1394,7 @@ export class Repository implements Disposable {
|
||||
await this._fetch(options);
|
||||
}
|
||||
|
||||
private async _fetch(options: { remote?: string, ref?: string, all?: boolean, prune?: boolean, depth?: number, silent?: boolean; } = {}): Promise<void> {
|
||||
private async _fetch(options: { remote?: string; ref?: string; all?: boolean; prune?: boolean; depth?: number; silent?: boolean } = {}): Promise<void> {
|
||||
if (!options.prune) {
|
||||
const config = workspace.getConfiguration('git', Uri.file(this.root));
|
||||
const prune = config.get<boolean>('pruneOnFetch');
|
||||
@@ -1543,16 +1595,16 @@ export class Repository implements Disposable {
|
||||
|
||||
async show(ref: string, filePath: string): Promise<string> {
|
||||
return await this.run(Operation.Show, async () => {
|
||||
const relativePath = path.relative(this.repository.root, filePath).replace(/\\/g, '/');
|
||||
const path = relativePath(this.repository.root, filePath).replace(/\\/g, '/');
|
||||
const configFiles = workspace.getConfiguration('files', Uri.file(filePath));
|
||||
const defaultEncoding = configFiles.get<string>('encoding');
|
||||
const autoGuessEncoding = configFiles.get<boolean>('autoGuessEncoding');
|
||||
|
||||
try {
|
||||
return await this.repository.bufferString(`${ref}:${relativePath}`, defaultEncoding, autoGuessEncoding);
|
||||
return await this.repository.bufferString(`${ref}:${path}`, defaultEncoding, autoGuessEncoding);
|
||||
} catch (err) {
|
||||
if (err.gitErrorCode === GitErrorCodes.WrongCase) {
|
||||
const gitRelativePath = await this.repository.getGitRelativePath(ref, relativePath);
|
||||
const gitRelativePath = await this.repository.getGitRelativePath(ref, path);
|
||||
return await this.repository.bufferString(`${ref}:${gitRelativePath}`, defaultEncoding, autoGuessEncoding);
|
||||
}
|
||||
|
||||
@@ -1563,16 +1615,16 @@ export class Repository implements Disposable {
|
||||
|
||||
async buffer(ref: string, filePath: string): Promise<Buffer> {
|
||||
return this.run(Operation.Show, () => {
|
||||
const relativePath = path.relative(this.repository.root, filePath).replace(/\\/g, '/');
|
||||
return this.repository.buffer(`${ref}:${relativePath}`);
|
||||
const path = relativePath(this.repository.root, filePath).replace(/\\/g, '/');
|
||||
return this.repository.buffer(`${ref}:${path}`);
|
||||
});
|
||||
}
|
||||
|
||||
getObjectDetails(ref: string, filePath: string): Promise<{ mode: string, object: string, size: number; }> {
|
||||
getObjectDetails(ref: string, filePath: string): Promise<{ mode: string; object: string; size: number }> {
|
||||
return this.run(Operation.GetObjectDetails, () => this.repository.getObjectDetails(ref, filePath));
|
||||
}
|
||||
|
||||
detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string; }> {
|
||||
detectObjectType(object: string): Promise<{ mimetype: string; encoding?: string }> {
|
||||
return this.run(Operation.Show, () => this.repository.detectObjectType(object));
|
||||
}
|
||||
|
||||
@@ -1585,7 +1637,15 @@ export class Repository implements Disposable {
|
||||
}
|
||||
|
||||
async createStash(message?: string, includeUntracked?: boolean): Promise<void> {
|
||||
return await this.run(Operation.Stash, () => this.repository.createStash(message, includeUntracked));
|
||||
const indexResources = [...this.indexGroup.resourceStates.map(r => r.resourceUri.fsPath)];
|
||||
const workingGroupResources = [
|
||||
...this.workingTreeGroup.resourceStates.map(r => r.resourceUri.fsPath),
|
||||
...includeUntracked ? this.untrackedGroup.resourceStates.map(r => r.resourceUri.fsPath) : []];
|
||||
|
||||
return await this.run(Operation.Stash, async () => {
|
||||
this.repository.createStash(message, includeUntracked);
|
||||
this.closeDiffEditors(indexResources, workingGroupResources);
|
||||
});
|
||||
}
|
||||
|
||||
async popStash(index?: number): Promise<void> {
|
||||
@@ -1608,7 +1668,7 @@ export class Repository implements Disposable {
|
||||
return await this.run(Operation.Ignore, async () => {
|
||||
const ignoreFile = `${this.repository.root}${path.sep}.gitignore`;
|
||||
const textToAppend = files
|
||||
.map(uri => path.relative(this.repository.root, uri.fsPath).replace(/\\/g, '/'))
|
||||
.map(uri => relativePath(this.repository.root, uri.fsPath).replace(/\\/g, '/'))
|
||||
.join('\n');
|
||||
|
||||
const document = await new Promise(c => fs.exists(ignoreFile, c))
|
||||
@@ -1798,11 +1858,23 @@ export class Repository implements Disposable {
|
||||
@throttle
|
||||
private async updateModelState(): Promise<void> {
|
||||
const scopedConfig = workspace.getConfiguration('git', Uri.file(this.repository.root));
|
||||
const untrackedChanges = scopedConfig.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges');
|
||||
const ignoreSubmodules = scopedConfig.get<boolean>('ignoreSubmodules');
|
||||
|
||||
const limit = scopedConfig.get<number>('statusLimit', 5000);
|
||||
const limit = scopedConfig.get<number>('statusLimit', 10000);
|
||||
|
||||
const { status, didHitLimit } = await this.repository.getStatus({ limit, ignoreSubmodules });
|
||||
const { status, statusLength, didHitLimit } = await this.repository.getStatus({ limit, ignoreSubmodules, untrackedChanges });
|
||||
|
||||
if (didHitLimit) {
|
||||
/* __GDPR__
|
||||
"statusLimit" : {
|
||||
"ignoreSubmodules": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"limit": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
|
||||
"statusLength": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
|
||||
}
|
||||
*/
|
||||
this.telemetryReporter.sendTelemetryEvent('statusLimit', { ignoreSubmodules: String(ignoreSubmodules) }, { limit, statusLength });
|
||||
}
|
||||
|
||||
const config = workspace.getConfiguration('git');
|
||||
const shouldIgnore = config.get<boolean>('ignoreLimitWarning') === true;
|
||||
@@ -1873,8 +1945,6 @@ export class Repository implements Disposable {
|
||||
this._submodules = submodules!;
|
||||
this.rebaseCommit = rebaseCommit;
|
||||
|
||||
|
||||
const untrackedChanges = scopedConfig.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges');
|
||||
const index: Resource[] = [];
|
||||
const workingTree: Resource[] = [];
|
||||
const merge: Resource[] = [];
|
||||
@@ -1923,37 +1993,6 @@ export class Repository implements Disposable {
|
||||
return undefined;
|
||||
});
|
||||
|
||||
let actionButton: SourceControl['actionButton'];
|
||||
if (HEAD !== undefined) {
|
||||
const config = workspace.getConfiguration('git', Uri.file(this.repository.root));
|
||||
const showActionButton = config.get<string>('showUnpublishedCommitsButton', 'whenEmpty');
|
||||
|
||||
if (showActionButton === 'always' || (showActionButton === 'whenEmpty' && workingTree.length === 0 && index.length === 0 && untracked.length === 0 && merge.length === 0)) {
|
||||
if (HEAD.name && HEAD.commit) {
|
||||
if (HEAD.upstream) {
|
||||
if (HEAD.ahead) {
|
||||
const rebaseWhenSync = config.get<string>('rebaseWhenSync');
|
||||
|
||||
actionButton = {
|
||||
command: rebaseWhenSync ? 'git.syncRebase' : 'git.sync',
|
||||
title: localize('scm button sync title', ' Sync Changes $(sync){0}{1}', HEAD.behind ? `${HEAD.behind}$(arrow-down) ` : '', `${HEAD.ahead}$(arrow-up)`),
|
||||
tooltip: this.syncTooltip,
|
||||
arguments: [this._sourceControl],
|
||||
};
|
||||
}
|
||||
} else {
|
||||
actionButton = {
|
||||
command: 'git.publish',
|
||||
title: localize('scm button publish title', "$(cloud-upload) Publish Changes"),
|
||||
tooltip: localize('scm button publish tooltip', "Publish Changes"),
|
||||
arguments: [this._sourceControl],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._sourceControl.actionButton = actionButton;
|
||||
|
||||
// set resource groups
|
||||
this.mergeGroup.resourceStates = merge;
|
||||
this.indexGroup.resourceStates = index;
|
||||
@@ -1963,9 +2002,6 @@ export class Repository implements Disposable {
|
||||
// set count badge
|
||||
this.setCountBadge();
|
||||
|
||||
// Update context key with changed resources
|
||||
commands.executeCommand('setContext', 'git.changedResources', [...merge, ...index, ...workingTree, ...untracked].map(r => r.resourceUri.fsPath.toString()));
|
||||
|
||||
this._onDidChangeStatus.fire();
|
||||
|
||||
this._sourceControl.commitTemplate = await this.getInputTemplate();
|
||||
|
||||
@@ -49,7 +49,7 @@ export function applyLineChanges(original: TextDocument, modified: TextDocument,
|
||||
return result.join('');
|
||||
}
|
||||
|
||||
export function toLineRanges(selections: Selection[], textDocument: TextDocument): Range[] {
|
||||
export function toLineRanges(selections: readonly Selection[], textDocument: TextDocument): Range[] {
|
||||
const lineRanges = selections.map(s => {
|
||||
const startLine = textDocument.lineAt(s.start.line);
|
||||
const endLine = textDocument.lineAt(s.end.line);
|
||||
@@ -109,12 +109,28 @@ export function intersectDiffWithRange(textDocument: TextDocument, diff: LineCha
|
||||
if (diff.modifiedEndLineNumber === 0) {
|
||||
return diff;
|
||||
} else {
|
||||
return {
|
||||
originalStartLineNumber: diff.originalStartLineNumber,
|
||||
originalEndLineNumber: diff.originalEndLineNumber,
|
||||
modifiedStartLineNumber: intersection.start.line + 1,
|
||||
modifiedEndLineNumber: intersection.end.line + 1
|
||||
};
|
||||
const modifiedStartLineNumber = intersection.start.line + 1;
|
||||
const modifiedEndLineNumber = intersection.end.line + 1;
|
||||
|
||||
// heuristic: same number of lines on both sides, let's assume line by line
|
||||
if (diff.originalEndLineNumber - diff.originalStartLineNumber === diff.modifiedEndLineNumber - diff.modifiedStartLineNumber) {
|
||||
const delta = modifiedStartLineNumber - diff.modifiedStartLineNumber;
|
||||
const length = modifiedEndLineNumber - modifiedStartLineNumber;
|
||||
|
||||
return {
|
||||
originalStartLineNumber: diff.originalStartLineNumber + delta,
|
||||
originalEndLineNumber: diff.originalStartLineNumber + delta + length,
|
||||
modifiedStartLineNumber,
|
||||
modifiedEndLineNumber
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
originalStartLineNumber: diff.originalStartLineNumber,
|
||||
originalEndLineNumber: diff.originalEndLineNumber,
|
||||
modifiedStartLineNumber,
|
||||
modifiedEndLineNumber
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import { Disposable, Command, EventEmitter, Event, workspace, Uri } from 'vscode
|
||||
import { Repository, Operation } from './repository';
|
||||
import { anyEvent, dispose, filterEvent } from './util';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Branch, RemoteSourceProvider } from './api/git';
|
||||
import { IRemoteSourceProviderRegistry } from './remoteProvider';
|
||||
import { Branch, RemoteSourcePublisher } from './api/git';
|
||||
import { IRemoteSourcePublisherRegistry } from './remotePublisher';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -44,7 +44,7 @@ interface SyncStatusBarState {
|
||||
readonly isSyncRunning: boolean;
|
||||
readonly hasRemotes: boolean;
|
||||
readonly HEAD: Branch | undefined;
|
||||
readonly remoteSourceProviders: RemoteSourceProvider[];
|
||||
readonly remoteSourcePublishers: RemoteSourcePublisher[];
|
||||
}
|
||||
|
||||
class SyncStatusBar {
|
||||
@@ -60,21 +60,20 @@ class SyncStatusBar {
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
|
||||
constructor(private repository: Repository, private remoteSourceProviderRegistry: IRemoteSourceProviderRegistry) {
|
||||
constructor(private repository: Repository, private remoteSourcePublisherRegistry: IRemoteSourcePublisherRegistry) {
|
||||
this._state = {
|
||||
enabled: true,
|
||||
isSyncRunning: false,
|
||||
hasRemotes: false,
|
||||
HEAD: undefined,
|
||||
remoteSourceProviders: this.remoteSourceProviderRegistry.getRemoteProviders()
|
||||
.filter(p => !!p.publishRepository)
|
||||
remoteSourcePublishers: remoteSourcePublisherRegistry.getRemoteSourcePublishers()
|
||||
};
|
||||
|
||||
repository.onDidRunGitStatus(this.onDidRunGitStatus, this, this.disposables);
|
||||
repository.onDidChangeOperations(this.onDidChangeOperations, this, this.disposables);
|
||||
|
||||
anyEvent(remoteSourceProviderRegistry.onDidAddRemoteSourceProvider, remoteSourceProviderRegistry.onDidRemoveRemoteSourceProvider)
|
||||
(this.onDidChangeRemoteSourceProviders, this, this.disposables);
|
||||
anyEvent(remoteSourcePublisherRegistry.onDidAddRemoteSourcePublisher, remoteSourcePublisherRegistry.onDidRemoveRemoteSourcePublisher)
|
||||
(this.onDidChangeRemoteSourcePublishers, this, this.disposables);
|
||||
|
||||
const onEnablementChange = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.enableStatusBarSync'));
|
||||
onEnablementChange(this.updateEnablement, this, this.disposables);
|
||||
@@ -104,11 +103,10 @@ class SyncStatusBar {
|
||||
};
|
||||
}
|
||||
|
||||
private onDidChangeRemoteSourceProviders(): void {
|
||||
private onDidChangeRemoteSourcePublishers(): void {
|
||||
this.state = {
|
||||
...this.state,
|
||||
remoteSourceProviders: this.remoteSourceProviderRegistry.getRemoteProviders()
|
||||
.filter(p => !!p.publishRepository)
|
||||
remoteSourcePublishers: this.remoteSourcePublisherRegistry.getRemoteSourcePublishers()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -118,12 +116,12 @@ class SyncStatusBar {
|
||||
}
|
||||
|
||||
if (!this.state.hasRemotes) {
|
||||
if (this.state.remoteSourceProviders.length === 0) {
|
||||
if (this.state.remoteSourcePublishers.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tooltip = this.state.remoteSourceProviders.length === 1
|
||||
? localize('publish to', "Publish to {0}", this.state.remoteSourceProviders[0].name)
|
||||
const tooltip = this.state.remoteSourcePublishers.length === 1
|
||||
? localize('publish to', "Publish to {0}", this.state.remoteSourcePublishers[0].name)
|
||||
: localize('publish to...', "Publish to...");
|
||||
|
||||
return {
|
||||
@@ -154,7 +152,7 @@ class SyncStatusBar {
|
||||
} else {
|
||||
icon = '$(cloud-upload)';
|
||||
command = 'git.publish';
|
||||
tooltip = localize('publish changes', "Publish Changes");
|
||||
tooltip = localize('publish branch', "Publish Branch");
|
||||
}
|
||||
} else {
|
||||
command = '';
|
||||
@@ -188,8 +186,8 @@ export class StatusBarCommands {
|
||||
private checkoutStatusBar: CheckoutStatusBar;
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(repository: Repository, remoteSourceProviderRegistry: IRemoteSourceProviderRegistry) {
|
||||
this.syncStatusBar = new SyncStatusBar(repository, remoteSourceProviderRegistry);
|
||||
constructor(repository: Repository, remoteSourcePublisherRegistry: IRemoteSourcePublisherRegistry) {
|
||||
this.syncStatusBar = new SyncStatusBar(repository, remoteSourcePublisherRegistry);
|
||||
this.checkoutStatusBar = new CheckoutStatusBar(repository);
|
||||
this.onDidChange = anyEvent(this.syncStatusBar.onDidChange, this.checkoutStatusBar.onDidChange);
|
||||
}
|
||||
|
||||
@@ -42,13 +42,12 @@ suite('git smoke test', function () {
|
||||
suiteSetup(async function () {
|
||||
fs.writeFileSync(file('app.js'), 'hello', 'utf8');
|
||||
fs.writeFileSync(file('index.pug'), 'hello', 'utf8');
|
||||
cp.execSync('git init', { cwd });
|
||||
cp.execSync('git init -b main', { cwd });
|
||||
cp.execSync('git config user.name testuser', { cwd });
|
||||
cp.execSync('git config user.email monacotools@microsoft.com', { cwd });
|
||||
cp.execSync('git config commit.gpgsign false', { cwd });
|
||||
cp.execSync('git add .', { cwd });
|
||||
cp.execSync('git commit -m "initial commit"', { cwd });
|
||||
cp.execSync('git branch -m main', { cwd });
|
||||
|
||||
// make sure git is activated
|
||||
const ext = extensions.getExtension<GitExtension>('vscode.git');
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
import { CancellationToken, ConfigurationChangeEvent, Disposable, env, Event, EventEmitter, ThemeIcon, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider, Uri, workspace } from 'vscode';
|
||||
import { CancellationToken, ConfigurationChangeEvent, Disposable, env, Event, EventEmitter, MarkdownString, ThemeIcon, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider, Uri, workspace } from 'vscode';
|
||||
import { Model } from './model';
|
||||
import { Repository, Resource } from './repository';
|
||||
import { debounce } from './decorators';
|
||||
@@ -50,6 +50,20 @@ export class GitTimelineItem extends TimelineItem {
|
||||
return this.shortenRef(this.previousRef);
|
||||
}
|
||||
|
||||
setItemDetails(author: string, email: string | undefined, date: string, message: string): void {
|
||||
this.tooltip = new MarkdownString('', true);
|
||||
|
||||
if (email) {
|
||||
const emailTitle = localize('git.timeline.email', "Email");
|
||||
this.tooltip.appendMarkdown(`$(account) [**${author}**](mailto:${email} "${emailTitle} ${author}")\n\n`);
|
||||
} else {
|
||||
this.tooltip.appendMarkdown(`$(account) **${author}**\n\n`);
|
||||
}
|
||||
|
||||
this.tooltip.appendMarkdown(`$(history) ${date}\n\n`);
|
||||
this.tooltip.appendMarkdown(message);
|
||||
}
|
||||
|
||||
private shortenRef(ref: string): string {
|
||||
if (ref === '' || ref === '~' || ref === 'HEAD') {
|
||||
return ref;
|
||||
@@ -155,6 +169,9 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
|
||||
const dateType = config.get<'committed' | 'authored'>('date');
|
||||
const showAuthor = config.get<boolean>('showAuthor');
|
||||
const showUncommitted = config.get<boolean>('showUncommitted');
|
||||
|
||||
const openComparison = localize('git.timeline.openComparison', "Open Comparison");
|
||||
|
||||
const items = commits.map<GitTimelineItem>((c, i) => {
|
||||
const date = dateType === 'authored' ? c.authorDate : c.commitDate;
|
||||
@@ -166,12 +183,13 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
if (showAuthor) {
|
||||
item.description = c.authorName;
|
||||
}
|
||||
item.detail = `${c.authorName} (${c.authorEmail}) — ${c.hash.substr(0, 8)}\n${dateFormatter.format(date)}\n\n${message}`;
|
||||
|
||||
item.setItemDetails(c.authorName!, c.authorEmail, dateFormatter.format(date), message);
|
||||
|
||||
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
|
||||
if (cmd) {
|
||||
item.command = {
|
||||
title: 'Open Comparison',
|
||||
title: openComparison,
|
||||
command: cmd.command,
|
||||
arguments: cmd.arguments,
|
||||
};
|
||||
@@ -191,12 +209,12 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
|
||||
item.iconPath = new ThemeIcon('git-commit');
|
||||
item.description = '';
|
||||
item.detail = localize('git.timeline.detail', '{0} — {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format(date), Resource.getStatusText(index.type));
|
||||
item.setItemDetails(you, undefined, dateFormatter.format(date), Resource.getStatusText(index.type));
|
||||
|
||||
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
|
||||
if (cmd) {
|
||||
item.command = {
|
||||
title: 'Open Comparison',
|
||||
title: openComparison,
|
||||
command: cmd.command,
|
||||
arguments: cmd.arguments,
|
||||
};
|
||||
@@ -205,26 +223,27 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
items.splice(0, 0, item);
|
||||
}
|
||||
|
||||
const working = repo.workingTreeGroup.resourceStates.find(r => r.resourceUri.fsPath === uri.fsPath);
|
||||
if (working) {
|
||||
const date = new Date();
|
||||
if (showUncommitted) {
|
||||
const working = repo.workingTreeGroup.resourceStates.find(r => r.resourceUri.fsPath === uri.fsPath);
|
||||
if (working) {
|
||||
const date = new Date();
|
||||
|
||||
const item = new GitTimelineItem('', index ? '~' : 'HEAD', localize('git.timeline.uncommitedChanges', 'Uncommitted Changes'), date.getTime(), 'working', 'git:file:working');
|
||||
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
|
||||
item.iconPath = new ThemeIcon('git-commit');
|
||||
item.description = '';
|
||||
item.detail = localize('git.timeline.detail', '{0} — {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format(date), Resource.getStatusText(working.type));
|
||||
const item = new GitTimelineItem('', index ? '~' : 'HEAD', localize('git.timeline.uncommitedChanges', 'Uncommitted Changes'), date.getTime(), 'working', 'git:file:working');
|
||||
item.iconPath = new ThemeIcon('circle-outline');
|
||||
item.description = '';
|
||||
item.setItemDetails(you, undefined, dateFormatter.format(date), Resource.getStatusText(working.type));
|
||||
|
||||
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
|
||||
if (cmd) {
|
||||
item.command = {
|
||||
title: 'Open Comparison',
|
||||
command: cmd.command,
|
||||
arguments: cmd.arguments,
|
||||
};
|
||||
const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri);
|
||||
if (cmd) {
|
||||
item.command = {
|
||||
title: openComparison,
|
||||
command: cmd.command,
|
||||
arguments: cmd.arguments,
|
||||
};
|
||||
}
|
||||
|
||||
items.splice(0, 0, item);
|
||||
}
|
||||
|
||||
items.splice(0, 0, item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,12 +255,12 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
|
||||
private ensureProviderRegistration() {
|
||||
if (this.providerDisposable === undefined) {
|
||||
this.providerDisposable = workspace.registerTimelineProvider(['file', 'git', 'vscode-remote', 'gitlens-git'], this);
|
||||
this.providerDisposable = workspace.registerTimelineProvider(['file', 'git', 'vscode-remote', 'gitlens-git', 'vscode-local-history'], this);
|
||||
}
|
||||
}
|
||||
|
||||
private onConfigurationChanged(e: ConfigurationChangeEvent) {
|
||||
if (e.affectsConfiguration('git.timeline.date') || e.affectsConfiguration('git.timeline.showAuthor')) {
|
||||
if (e.affectsConfiguration('git.timeline.date') || e.affectsConfiguration('git.timeline.showAuthor') || e.affectsConfiguration('git.timeline.showUncommitted')) {
|
||||
this.fireChanged();
|
||||
}
|
||||
}
|
||||
|
||||
8
extensions/git/src/typings/refs.d.ts
vendored
8
extensions/git/src/typings/refs.d.ts
vendored
@@ -1,8 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||
/// <reference path='../../../../src/vs/vscode.proposed.d.ts'/>
|
||||
/// <reference path="../../../types/lib.textEncoder.d.ts" />
|
||||
@@ -4,15 +4,22 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event, Disposable, EventEmitter } from 'vscode';
|
||||
import { dirname, sep } from 'path';
|
||||
import { dirname, sep, relative } from 'path';
|
||||
import { Readable } from 'stream';
|
||||
import { promises as fs, createReadStream } from 'fs';
|
||||
import * as byline from 'byline';
|
||||
|
||||
export const isMacintosh = process.platform === 'darwin';
|
||||
export const isWindows = process.platform === 'win32';
|
||||
|
||||
export function log(...args: any[]): void {
|
||||
console.log.apply(console, ['git:', ...args]);
|
||||
}
|
||||
|
||||
export function logTimestamp(): string {
|
||||
return `[${new Date().toISOString()}]`;
|
||||
}
|
||||
|
||||
export interface IDisposable {
|
||||
dispose(): void;
|
||||
}
|
||||
@@ -168,7 +175,7 @@ export async function mkdirp(path: string, mode?: number): Promise<boolean> {
|
||||
}
|
||||
|
||||
export function uniqueFilter<T>(keyFn: (t: T) => string): (t: T) => boolean {
|
||||
const seen: { [key: string]: boolean; } = Object.create(null);
|
||||
const seen: { [key: string]: boolean } = Object.create(null);
|
||||
|
||||
return element => {
|
||||
const key = keyFn(element);
|
||||
@@ -280,8 +287,14 @@ export function detectUnicodeEncoding(buffer: Buffer): Encoding | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
function isWindowsPath(path: string): boolean {
|
||||
return /^[a-zA-Z]:\\/.test(path);
|
||||
function normalizePath(path: string): string {
|
||||
// Windows & Mac are currently being handled
|
||||
// as case insensitive file systems in VS Code.
|
||||
if (isWindows || isMacintosh) {
|
||||
return path.toLowerCase();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
export function isDescendant(parent: string, descendant: string): boolean {
|
||||
@@ -293,23 +306,26 @@ export function isDescendant(parent: string, descendant: string): boolean {
|
||||
parent += sep;
|
||||
}
|
||||
|
||||
// Windows is case insensitive
|
||||
if (isWindowsPath(parent)) {
|
||||
parent = parent.toLowerCase();
|
||||
descendant = descendant.toLowerCase();
|
||||
}
|
||||
|
||||
return descendant.startsWith(parent);
|
||||
return normalizePath(descendant).startsWith(normalizePath(parent));
|
||||
}
|
||||
|
||||
export function pathEquals(a: string, b: string): boolean {
|
||||
// Windows is case insensitive
|
||||
if (isWindowsPath(a)) {
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
return normalizePath(a) === normalizePath(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the `repository.root` compute the relative path while trying to preserve
|
||||
* the casing of the resource URI. The `repository.root` segment of the path can
|
||||
* have a casing mismatch if the folder/workspace is being opened with incorrect
|
||||
* casing.
|
||||
*/
|
||||
export function relativePath(from: string, to: string): string {
|
||||
if (isDescendant(from, to) && from.length < to.length) {
|
||||
return to.substring(from.length + 1);
|
||||
}
|
||||
|
||||
return a === b;
|
||||
// Fallback to `path.relative`
|
||||
return relative(from, to);
|
||||
}
|
||||
|
||||
export function* splitInChunks(array: string[], maxChunkLength: number): IterableIterator<string[]> {
|
||||
@@ -379,7 +395,7 @@ export class Limiter<T> {
|
||||
}
|
||||
}
|
||||
|
||||
type Completion<T> = { success: true, value: T } | { success: false, err: any };
|
||||
type Completion<T> = { success: true; value: T } | { success: false; err: any };
|
||||
|
||||
export class PromiseSource<T> {
|
||||
|
||||
|
||||
@@ -3,23 +3,20 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event, EventEmitter, Uri } from 'vscode';
|
||||
import { join } from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { IDisposable } from './util';
|
||||
import { Event, RelativePattern, Uri, workspace } from 'vscode';
|
||||
import { IDisposable, anyEvent } from './util';
|
||||
|
||||
export interface IFileWatcher extends IDisposable {
|
||||
readonly event: Event<Uri>;
|
||||
}
|
||||
|
||||
export function watch(location: string): IFileWatcher {
|
||||
const dotGitWatcher = fs.watch(location);
|
||||
const onDotGitFileChangeEmitter = new EventEmitter<Uri>();
|
||||
dotGitWatcher.on('change', (_, e) => onDotGitFileChangeEmitter.fire(Uri.file(join(location, e as string))));
|
||||
dotGitWatcher.on('error', err => console.error(err));
|
||||
const watcher = workspace.createFileSystemWatcher(new RelativePattern(location, '*'));
|
||||
|
||||
return new class implements IFileWatcher {
|
||||
event = onDotGitFileChangeEmitter.event;
|
||||
dispose() { dotGitWatcher.close(); }
|
||||
event = anyEvent(watcher.onDidCreate, watcher.onDidChange, watcher.onDidDelete);
|
||||
dispose() {
|
||||
watcher.dispose();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
{
|
||||
"information_for_contributors": [
|
||||
"This file has been converted from https://github.com/textmate/diff.tmbundle/blob/master/Syntaxes/Diff.plist",
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/textmate/diff.tmbundle/commit/0593bb775eab1824af97ef2172fd38822abd97d7",
|
||||
"name": "Diff",
|
||||
"scopeName": "source.diff",
|
||||
"patterns": [
|
||||
{
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.separator.diff"
|
||||
}
|
||||
},
|
||||
"match": "^((\\*{15})|(={67})|(-{3}))$\\n?",
|
||||
"name": "meta.separator.diff"
|
||||
},
|
||||
{
|
||||
"match": "^\\d+(,\\d+)*(a|d|c)\\d+(,\\d+)*$\\n?",
|
||||
"name": "meta.diff.range.normal"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.range.diff"
|
||||
},
|
||||
"2": {
|
||||
"name": "meta.toc-list.line-number.diff"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.definition.range.diff"
|
||||
}
|
||||
},
|
||||
"match": "^(@@)\\s*(.+?)\\s*(@@)($\\n?)?",
|
||||
"name": "meta.diff.range.unified"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"3": {
|
||||
"name": "punctuation.definition.range.diff"
|
||||
},
|
||||
"4": {
|
||||
"name": "punctuation.definition.range.diff"
|
||||
},
|
||||
"6": {
|
||||
"name": "punctuation.definition.range.diff"
|
||||
},
|
||||
"7": {
|
||||
"name": "punctuation.definition.range.diff"
|
||||
}
|
||||
},
|
||||
"match": "^(((\\-{3}) .+ (\\-{4}))|((\\*{3}) .+ (\\*{4})))$\\n?",
|
||||
"name": "meta.diff.range.context"
|
||||
},
|
||||
{
|
||||
"match": "^diff --git a/.*$\\n?",
|
||||
"name": "meta.diff.header.git"
|
||||
},
|
||||
{
|
||||
"match": "^diff (-|\\S+\\s+\\S+).*$\\n?",
|
||||
"name": "meta.diff.header.command"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"4": {
|
||||
"name": "punctuation.definition.from-file.diff"
|
||||
},
|
||||
"6": {
|
||||
"name": "punctuation.definition.from-file.diff"
|
||||
},
|
||||
"7": {
|
||||
"name": "punctuation.definition.from-file.diff"
|
||||
}
|
||||
},
|
||||
"match": "(^(((-{3}) .+)|((\\*{3}) .+))$\\n?|^(={4}) .+(?= - ))",
|
||||
"name": "meta.diff.header.from-file"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"2": {
|
||||
"name": "punctuation.definition.to-file.diff"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.definition.to-file.diff"
|
||||
},
|
||||
"4": {
|
||||
"name": "punctuation.definition.to-file.diff"
|
||||
}
|
||||
},
|
||||
"match": "(^(\\+{3}) .+$\\n?| (-) .* (={4})$\\n?)",
|
||||
"name": "meta.diff.header.to-file"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"3": {
|
||||
"name": "punctuation.definition.inserted.diff"
|
||||
},
|
||||
"6": {
|
||||
"name": "punctuation.definition.inserted.diff"
|
||||
}
|
||||
},
|
||||
"match": "^(((>)( .*)?)|((\\+).*))$\\n?",
|
||||
"name": "markup.inserted.diff"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.changed.diff"
|
||||
}
|
||||
},
|
||||
"match": "^(!).*$\\n?",
|
||||
"name": "markup.changed.diff"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"3": {
|
||||
"name": "punctuation.definition.deleted.diff"
|
||||
},
|
||||
"6": {
|
||||
"name": "punctuation.definition.deleted.diff"
|
||||
}
|
||||
},
|
||||
"match": "^(((<)( .*)?)|((-).*))$\\n?",
|
||||
"name": "markup.deleted.diff"
|
||||
},
|
||||
{
|
||||
"begin": "^(#)",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.comment.diff"
|
||||
}
|
||||
},
|
||||
"comment": "Git produces unified diffs with embedded comments\"",
|
||||
"end": "\\n",
|
||||
"name": "comment.line.number-sign.diff"
|
||||
},
|
||||
{
|
||||
"match": "^index [0-9a-f]{7,40}\\.\\.[0-9a-f]{7,40}.*$\\n?",
|
||||
"name": "meta.diff.index.git"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "punctuation.separator.key-value.diff"
|
||||
},
|
||||
"2": {
|
||||
"name": "meta.toc-list.file-name.diff"
|
||||
}
|
||||
},
|
||||
"match": "^Index(:) (.+)$\\n?",
|
||||
"name": "meta.diff.index"
|
||||
},
|
||||
{
|
||||
"match": "^Only in .*: .*$\\n?",
|
||||
"name": "meta.diff.only-in"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
{
|
||||
"information_for_contributors": [
|
||||
"This file has been converted from https://github.com/textmate/git.tmbundle/blob/master/Syntaxes/Git%20Commit%20Message.tmLanguage",
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/textmate/git.tmbundle/commit/93897a78c6e52bef13dadc0d4091d203c5facb40",
|
||||
"name": "Git Commit Message",
|
||||
"scopeName": "text.git-commit",
|
||||
"patterns": [
|
||||
{
|
||||
"begin": "\\A(?!# Please enter the commit message)",
|
||||
"end": "^(?=# Please enter the commit message)",
|
||||
"name": "meta.scope.message.git-commit",
|
||||
"patterns": [
|
||||
{
|
||||
"begin": "\\A(?=#)",
|
||||
"end": "^(?!#)",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comment"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "^(?!# Please enter the commit message)",
|
||||
"end": "^(?=# Please enter the commit message)",
|
||||
"patterns": [
|
||||
{
|
||||
"begin": "\\G",
|
||||
"end": "^(?!\\G)",
|
||||
"name": "meta.scope.subject.git-commit",
|
||||
"patterns": [
|
||||
{
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "keyword.other.$2.git-commit"
|
||||
}
|
||||
},
|
||||
"match": "\\G((fixup|squash)!)\\s*"
|
||||
},
|
||||
{
|
||||
"match": ".{73,}$",
|
||||
"name": "invalid.illegal.line-too-long.git-commit"
|
||||
},
|
||||
{
|
||||
"match": ".{51,}$",
|
||||
"name": "invalid.deprecated.line-too-long.git-commit"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "^(?!# Please enter the commit message)",
|
||||
"end": "^(?=# Please enter the commit message)",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comment"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "^(?=# Please enter the commit message)",
|
||||
"end": "\\z",
|
||||
"name": "meta.scope.metadata.git-commit",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#metadata"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"comment": {
|
||||
"begin": "^(#)",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.comment.git-commit"
|
||||
}
|
||||
},
|
||||
"end": "\\n",
|
||||
"name": "comment.line.number-sign.git-commit"
|
||||
},
|
||||
"metadata": {
|
||||
"patterns": [
|
||||
{
|
||||
"begin": "(?=^# Changes to be committed:)",
|
||||
"end": "(?!\\G)((?=^# \\w)|(?!^#))",
|
||||
"patterns": [
|
||||
{
|
||||
"begin": "(^[ \\t]+)?(?=#)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "punctuation.whitespace.comment.leading.git-commit"
|
||||
}
|
||||
},
|
||||
"contentName": "comment.line.number-sign.git-commit",
|
||||
"end": "(?!\\G)^",
|
||||
"patterns": [
|
||||
{
|
||||
"match": "\\G#",
|
||||
"name": "punctuation.definition.comment.git-commit"
|
||||
},
|
||||
{
|
||||
"match": "((modified|renamed):.*)$\\n?",
|
||||
"name": "markup.changed.git-commit"
|
||||
},
|
||||
{
|
||||
"match": "(new file:.*)$\\n?",
|
||||
"name": "markup.inserted.git-commit"
|
||||
},
|
||||
{
|
||||
"match": "(deleted:.*)$\\n?",
|
||||
"name": "markup.deleted.git-commit"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"include": "#comment"
|
||||
},
|
||||
{
|
||||
"begin": "(?=diff\\ \\-\\-git)",
|
||||
"comment": "diff presented at the end of the commit message when using commit -v.",
|
||||
"contentName": "source.diff",
|
||||
"end": "\\z",
|
||||
"name": "meta.embedded.diff.git-commit",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "source.diff"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
{
|
||||
"information_for_contributors": [
|
||||
"This file has been converted from https://github.com/textmate/git.tmbundle/blob/master/Syntaxes/Git%20Rebase%20Message.tmLanguage",
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/textmate/git.tmbundle/commit/5870cf3f8abad3a6637bdf69250b5d2ded427dc4",
|
||||
"name": "Git Rebase Message",
|
||||
"scopeName": "text.git-rebase",
|
||||
"patterns": [
|
||||
{
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.comment.git-rebase"
|
||||
}
|
||||
},
|
||||
"match": "^\\s*(#).*$\\n?",
|
||||
"name": "comment.line.number-sign.git-rebase"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "support.function.git-rebase"
|
||||
},
|
||||
"2": {
|
||||
"name": "constant.sha.git-rebase"
|
||||
},
|
||||
"3": {
|
||||
"name": "meta.commit-message.git-rebase"
|
||||
}
|
||||
},
|
||||
"match": "^\\s*(pick|p|reword|r|edit|e|squash|s|fixup|f|drop|d)\\s+([0-9a-f]+)\\s+(.*)$",
|
||||
"name": "meta.commit-command.git-rebase"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "support.function.git-rebase"
|
||||
},
|
||||
"2": {
|
||||
"patterns": [
|
||||
{
|
||||
"include": "source.shell"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"match": "^\\s*(exec|x)\\s+(.*)$",
|
||||
"name": "meta.commit-command.git-rebase"
|
||||
},
|
||||
{
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "support.function.git-rebase"
|
||||
}
|
||||
},
|
||||
"match": "^\\s*(break|b)\\s*$",
|
||||
"name": "meta.commit-command.git-rebase"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "Ignore",
|
||||
"scopeName": "source.ignore",
|
||||
"patterns": [
|
||||
{
|
||||
"match": "^#.*",
|
||||
"name": "comment.line.number-sign.ignore"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
This is the summary line. It can't be too long.
|
||||
After I can write a much more detailed description without quite the same restrictions on length.
|
||||
|
||||
# Please enter the commit message for your changes. Lines starting
|
||||
# with '#' will be ignored, and an empty message aborts the commit.
|
||||
# On branch master
|
||||
# Your branch is up-to-date with 'origin/master'.
|
||||
#
|
||||
# Changes to be committed:
|
||||
# deleted: README.md
|
||||
# modified: index.less
|
||||
# new file: spec/COMMIT_EDITMSG
|
||||
#
|
||||
@@ -1,7 +0,0 @@
|
||||
diff --git a/helloworld.txt b/helloworld.txt
|
||||
index e4f37c4..557db03 100644
|
||||
--- a/helloworld.txt
|
||||
+++ b/helloworld.txt
|
||||
@@ -1 +1 @@
|
||||
-Hello world
|
||||
+Hello World
|
||||
@@ -1,15 +0,0 @@
|
||||
pick 1fc6c95 Patch A
|
||||
squash fa39187 Something to add to patch A
|
||||
pick 7b36971 Something to move before patch B
|
||||
pick 6b2481b Patch B
|
||||
fixup c619268 A fix for Patch B
|
||||
edit dd1475d Something I want to split
|
||||
reword 4ca2acc i cant' typ goods
|
||||
|
||||
# Commands:
|
||||
# p, pick = use commit
|
||||
# r, reword = use commit, but edit the commit message
|
||||
# e, edit = use commit, but stop for amending
|
||||
# s, squash = use commit, but meld into previous commit
|
||||
# f, fixup = like "squash", but discard this commit's log message
|
||||
# x, exec = run command (the rest of the line) using shell
|
||||
@@ -1,255 +0,0 @@
|
||||
[
|
||||
{
|
||||
"c": "This is the summary line. It can't be too long.",
|
||||
"t": "text.git-commit meta.scope.message.git-commit meta.scope.subject.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "After I can write a much more detailed description without quite the same restrictions on length.",
|
||||
"t": "text.git-commit meta.scope.message.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " Please enter the commit message for your changes. Lines starting",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " with '#' will be ignored, and an empty message aborts the commit.",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " On branch master",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " Your branch is up-to-date with 'origin/master'.",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " Changes to be committed:",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "\t",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "deleted: README.md",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit markup.deleted.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "markup.deleted: #CE9178",
|
||||
"light_plus": "markup.deleted: #A31515",
|
||||
"dark_vs": "markup.deleted: #CE9178",
|
||||
"light_vs": "markup.deleted: #A31515",
|
||||
"hc_black": "markup.deleted: #CE9178"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "\t",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "modified: index.less",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit markup.changed.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "markup.changed: #569CD6",
|
||||
"light_plus": "markup.changed: #0451A5",
|
||||
"dark_vs": "markup.changed: #569CD6",
|
||||
"light_vs": "markup.changed: #0451A5",
|
||||
"hc_black": "markup.changed: #569CD6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "\t",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "new file: spec/COMMIT_EDITMSG",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit markup.inserted.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "markup.inserted: #B5CEA8",
|
||||
"light_plus": "markup.inserted: #098658",
|
||||
"dark_vs": "markup.inserted: #B5CEA8",
|
||||
"light_vs": "markup.inserted: #098658",
|
||||
"hc_black": "markup.inserted: #B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-commit meta.scope.metadata.git-commit comment.line.number-sign.git-commit punctuation.definition.comment.git-commit",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,167 +0,0 @@
|
||||
[
|
||||
{
|
||||
"c": "diff --git a/helloworld.txt b/helloworld.txt",
|
||||
"t": "source.diff meta.diff.header.git",
|
||||
"r": {
|
||||
"dark_plus": "meta.diff.header: #569CD6",
|
||||
"light_plus": "meta.diff.header: #000080",
|
||||
"dark_vs": "meta.diff.header: #569CD6",
|
||||
"light_vs": "meta.diff.header: #000080",
|
||||
"hc_black": "meta.diff.header: #000080"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "index e4f37c4..557db03 100644",
|
||||
"t": "source.diff meta.diff.index.git",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "---",
|
||||
"t": "source.diff meta.diff.header.from-file punctuation.definition.from-file.diff",
|
||||
"r": {
|
||||
"dark_plus": "meta.diff.header: #569CD6",
|
||||
"light_plus": "meta.diff.header: #000080",
|
||||
"dark_vs": "meta.diff.header: #569CD6",
|
||||
"light_vs": "meta.diff.header: #000080",
|
||||
"hc_black": "meta.diff.header: #000080"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " a/helloworld.txt",
|
||||
"t": "source.diff meta.diff.header.from-file",
|
||||
"r": {
|
||||
"dark_plus": "meta.diff.header: #569CD6",
|
||||
"light_plus": "meta.diff.header: #000080",
|
||||
"dark_vs": "meta.diff.header: #569CD6",
|
||||
"light_vs": "meta.diff.header: #000080",
|
||||
"hc_black": "meta.diff.header: #000080"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "+++",
|
||||
"t": "source.diff meta.diff.header.to-file punctuation.definition.to-file.diff",
|
||||
"r": {
|
||||
"dark_plus": "meta.diff.header: #569CD6",
|
||||
"light_plus": "meta.diff.header: #000080",
|
||||
"dark_vs": "meta.diff.header: #569CD6",
|
||||
"light_vs": "meta.diff.header: #000080",
|
||||
"hc_black": "meta.diff.header: #000080"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " b/helloworld.txt",
|
||||
"t": "source.diff meta.diff.header.to-file",
|
||||
"r": {
|
||||
"dark_plus": "meta.diff.header: #569CD6",
|
||||
"light_plus": "meta.diff.header: #000080",
|
||||
"dark_vs": "meta.diff.header: #569CD6",
|
||||
"light_vs": "meta.diff.header: #000080",
|
||||
"hc_black": "meta.diff.header: #000080"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "@@",
|
||||
"t": "source.diff meta.diff.range.unified punctuation.definition.range.diff",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "source.diff meta.diff.range.unified",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "-1 +1",
|
||||
"t": "source.diff meta.diff.range.unified meta.toc-list.line-number.diff",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "source.diff meta.diff.range.unified",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "@@",
|
||||
"t": "source.diff meta.diff.range.unified punctuation.definition.range.diff",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "-",
|
||||
"t": "source.diff markup.deleted.diff punctuation.definition.deleted.diff",
|
||||
"r": {
|
||||
"dark_plus": "markup.deleted: #CE9178",
|
||||
"light_plus": "markup.deleted: #A31515",
|
||||
"dark_vs": "markup.deleted: #CE9178",
|
||||
"light_vs": "markup.deleted: #A31515",
|
||||
"hc_black": "markup.deleted: #CE9178"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "Hello world",
|
||||
"t": "source.diff markup.deleted.diff",
|
||||
"r": {
|
||||
"dark_plus": "markup.deleted: #CE9178",
|
||||
"light_plus": "markup.deleted: #A31515",
|
||||
"dark_vs": "markup.deleted: #CE9178",
|
||||
"light_vs": "markup.deleted: #A31515",
|
||||
"hc_black": "markup.deleted: #CE9178"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "+",
|
||||
"t": "source.diff markup.inserted.diff punctuation.definition.inserted.diff",
|
||||
"r": {
|
||||
"dark_plus": "markup.inserted: #B5CEA8",
|
||||
"light_plus": "markup.inserted: #098658",
|
||||
"dark_vs": "markup.inserted: #B5CEA8",
|
||||
"light_vs": "markup.inserted: #098658",
|
||||
"hc_black": "markup.inserted: #B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "Hello World",
|
||||
"t": "source.diff markup.inserted.diff",
|
||||
"r": {
|
||||
"dark_plus": "markup.inserted: #B5CEA8",
|
||||
"light_plus": "markup.inserted: #098658",
|
||||
"dark_vs": "markup.inserted: #B5CEA8",
|
||||
"light_vs": "markup.inserted: #098658",
|
||||
"hc_black": "markup.inserted: #B5CEA8"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,541 +0,0 @@
|
||||
[
|
||||
{
|
||||
"c": "pick",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase support.function.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "support.function.git-rebase: #9CDCFE",
|
||||
"light_plus": "support.function.git-rebase: #0451A5",
|
||||
"dark_vs": "support.function.git-rebase: #9CDCFE",
|
||||
"light_vs": "support.function.git-rebase: #0451A5",
|
||||
"hc_black": "support.function.git-rebase: #D4D4D4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "1fc6c95",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_plus": "constant.sha.git-rebase: #098658",
|
||||
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_vs": "constant.sha.git-rebase: #098658",
|
||||
"hc_black": "constant.sha.git-rebase: #B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "Patch A",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase meta.commit-message.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "squash",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase support.function.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "support.function.git-rebase: #9CDCFE",
|
||||
"light_plus": "support.function.git-rebase: #0451A5",
|
||||
"dark_vs": "support.function.git-rebase: #9CDCFE",
|
||||
"light_vs": "support.function.git-rebase: #0451A5",
|
||||
"hc_black": "support.function.git-rebase: #D4D4D4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "fa39187",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_plus": "constant.sha.git-rebase: #098658",
|
||||
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_vs": "constant.sha.git-rebase: #098658",
|
||||
"hc_black": "constant.sha.git-rebase: #B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "Something to add to patch A",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase meta.commit-message.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "pick",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase support.function.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "support.function.git-rebase: #9CDCFE",
|
||||
"light_plus": "support.function.git-rebase: #0451A5",
|
||||
"dark_vs": "support.function.git-rebase: #9CDCFE",
|
||||
"light_vs": "support.function.git-rebase: #0451A5",
|
||||
"hc_black": "support.function.git-rebase: #D4D4D4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "7b36971",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_plus": "constant.sha.git-rebase: #098658",
|
||||
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_vs": "constant.sha.git-rebase: #098658",
|
||||
"hc_black": "constant.sha.git-rebase: #B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "Something to move before patch B",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase meta.commit-message.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "pick",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase support.function.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "support.function.git-rebase: #9CDCFE",
|
||||
"light_plus": "support.function.git-rebase: #0451A5",
|
||||
"dark_vs": "support.function.git-rebase: #9CDCFE",
|
||||
"light_vs": "support.function.git-rebase: #0451A5",
|
||||
"hc_black": "support.function.git-rebase: #D4D4D4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "6b2481b",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_plus": "constant.sha.git-rebase: #098658",
|
||||
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_vs": "constant.sha.git-rebase: #098658",
|
||||
"hc_black": "constant.sha.git-rebase: #B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "Patch B",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase meta.commit-message.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "fixup",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase support.function.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "support.function.git-rebase: #9CDCFE",
|
||||
"light_plus": "support.function.git-rebase: #0451A5",
|
||||
"dark_vs": "support.function.git-rebase: #9CDCFE",
|
||||
"light_vs": "support.function.git-rebase: #0451A5",
|
||||
"hc_black": "support.function.git-rebase: #D4D4D4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "c619268",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_plus": "constant.sha.git-rebase: #098658",
|
||||
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_vs": "constant.sha.git-rebase: #098658",
|
||||
"hc_black": "constant.sha.git-rebase: #B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "A fix for Patch B",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase meta.commit-message.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "edit",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase support.function.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "support.function.git-rebase: #9CDCFE",
|
||||
"light_plus": "support.function.git-rebase: #0451A5",
|
||||
"dark_vs": "support.function.git-rebase: #9CDCFE",
|
||||
"light_vs": "support.function.git-rebase: #0451A5",
|
||||
"hc_black": "support.function.git-rebase: #D4D4D4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "dd1475d",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_plus": "constant.sha.git-rebase: #098658",
|
||||
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_vs": "constant.sha.git-rebase: #098658",
|
||||
"hc_black": "constant.sha.git-rebase: #B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "Something I want to split",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase meta.commit-message.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "reword",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase support.function.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "support.function.git-rebase: #9CDCFE",
|
||||
"light_plus": "support.function.git-rebase: #0451A5",
|
||||
"dark_vs": "support.function.git-rebase: #9CDCFE",
|
||||
"light_vs": "support.function.git-rebase: #0451A5",
|
||||
"hc_black": "support.function.git-rebase: #D4D4D4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "4ca2acc",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase constant.sha.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_plus": "constant.sha.git-rebase: #098658",
|
||||
"dark_vs": "constant.sha.git-rebase: #B5CEA8",
|
||||
"light_vs": "constant.sha.git-rebase: #098658",
|
||||
"hc_black": "constant.sha.git-rebase: #B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "i cant' typ goods",
|
||||
"t": "text.git-rebase meta.commit-command.git-rebase meta.commit-message.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase punctuation.definition.comment.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " Commands:",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase punctuation.definition.comment.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " p, pick = use commit",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase punctuation.definition.comment.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " r, reword = use commit, but edit the commit message",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase punctuation.definition.comment.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " e, edit = use commit, but stop for amending",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase punctuation.definition.comment.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " s, squash = use commit, but meld into previous commit",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase punctuation.definition.comment.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " f, fixup = like \"squash\", but discard this commit's log message",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "#",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase punctuation.definition.comment.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " x, exec = run command (the rest of the line) using shell",
|
||||
"t": "text.git-rebase comment.line.number-sign.git-rebase",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1 +0,0 @@
|
||||
--ui tdd out/test
|
||||
@@ -8,6 +8,14 @@
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
"src/**/*",
|
||||
"../../src/vscode-dts/vscode.d.ts",
|
||||
"../../src/vscode-dts/vscode.proposed.diffCommand.d.ts",
|
||||
"../../src/vscode-dts/vscode.proposed.scmActionButton.d.ts",
|
||||
"../../src/vscode-dts/vscode.proposed.scmSelectedProvider.d.ts",
|
||||
"../../src/vscode-dts/vscode.proposed.scmValidation.d.ts",
|
||||
"../../src/vscode-dts/vscode.proposed.tabs.d.ts",
|
||||
"../../src/vscode-dts/vscode.proposed.timeline.d.ts",
|
||||
"../types/lib.textEncoder.d.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -14,26 +14,36 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/mocha@^8.2.0":
|
||||
version "8.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.3.tgz#bbeb55fbc73f28ea6de601fbfa4613f58d785323"
|
||||
integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==
|
||||
"@types/mocha@^9.1.1":
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4"
|
||||
integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==
|
||||
|
||||
"@types/node@*":
|
||||
version "8.0.51"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb"
|
||||
integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ==
|
||||
|
||||
"@types/node@14.x":
|
||||
version "14.14.43"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8"
|
||||
integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ==
|
||||
"@types/node@16.x":
|
||||
version "16.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae"
|
||||
integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==
|
||||
|
||||
"@types/which@^1.0.28":
|
||||
version "1.0.28"
|
||||
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6"
|
||||
integrity sha1-AW44dim4gXvtZT/jLqtdESecjfY=
|
||||
|
||||
"@vscode/extension-telemetry@0.4.10":
|
||||
version "0.4.10"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.4.10.tgz#be960c05bdcbea0933866346cf244acad6cac910"
|
||||
integrity sha512-XgyUoWWRQExTmd9DynIIUQo1NPex/zIeetdUAXeBjVuW9ioojM1TcDaSqOa/5QLC7lx+oEXwSU1r0XSBgzyz6w==
|
||||
|
||||
"@vscode/iconv-lite-umd@0.7.0":
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz#d2f1e0664ee6036408f9743fee264ea0699b0e48"
|
||||
integrity sha512-bRRFxLfg5dtAyl5XyiVWz/ZBPahpOpPrNYnnHpOpUZvam4tKH35wdhP4Kj6PbM0+KdliOsPzbGWpkxcdpNB/sg==
|
||||
|
||||
byline@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1"
|
||||
@@ -48,10 +58,6 @@ file-type@16.5.4:
|
||||
strtok3 "^6.2.4"
|
||||
token-types "^4.1.1"
|
||||
|
||||
iconv-lite-umd@0.6.8:
|
||||
version "0.6.8"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0"
|
||||
integrity sha512-zvXJ5gSwMC9JD3wDzH8CoZGc1pbiJn12Tqjk8BXYCnYz3hYL5GRjHW8LEykjXhV9WgNGI4rgpgHcbIiBfrRq6A==
|
||||
|
||||
ieee754@^1.2.1:
|
||||
version "1.2.1"
|
||||
@@ -62,7 +68,6 @@ inherits@^2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
@@ -127,11 +132,6 @@ util-deprecate@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
vscode-extension-telemetry@0.4.2:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.4.2.tgz#6ef847a80c9cfc207eb15e3a254f235acebb65a5"
|
||||
integrity sha512-y0f51mVoFxHIzULQNCC26TBFIKdEC7uckS3tFoK++OOOl8mU2LlOxgmbd52T/SXoXNg5aI7xqs+4V2ug5ITvKw==
|
||||
|
||||
vscode-nls@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"
|
||||
|
||||
Reference in New Issue
Block a user