From 4ceeafe7ccbaca7c5c0cadc785d15845bb61fb6a Mon Sep 17 00:00:00 2001 From: Christopher Date: Tue, 25 Aug 2020 14:03:11 +0100 Subject: [PATCH] fix: Using custom file system provider over content provider (#1053) --- package.json | 2558 ++++++++++++++++--------------- src/common/types.ts | 3 +- src/extension.ts | 4 +- src/repository.ts | 38 +- src/source_control_manager.ts | 30 +- src/svn.ts | 111 ++ src/svnContentProvider.ts | 158 -- src/svnFileSystemProvider.ts | 212 +++ src/svnRepository.ts | 98 +- src/test/commands.test.ts | 30 +- src/test/extension.test.ts | 2 +- src/test/pathNormalizer.test.ts | 8 +- src/test/repository.test.ts | 8 +- src/test/temp_svn_fs.test.ts | 5 +- src/util.ts | 16 + yarn.lock | 70 +- 16 files changed, 1852 insertions(+), 1499 deletions(-) delete mode 100644 src/svnContentProvider.ts create mode 100644 src/svnFileSystemProvider.ts diff --git a/package.json b/package.json index 84913456..bf4ebbbe 100644 --- a/package.json +++ b/package.json @@ -1,1286 +1,1296 @@ { - "name": "svn-scm", - "displayName": "SVN", - "description": "Integrated Subversion source control", - "version": "2.12.3", - "publisher": "johnstoncode", - "engines": { - "vscode": "^1.44.0" - }, - "private": true, - "enableProposedApi": false, - "icon": "images/subversion.png", - "homepage": "https://github.com/JohnstonCode/svn-scm/blob/master/README.md", - "repository": { - "type": "git", - "url": "https://github.com/JohnstonCode/svn-scm.git" + "name": "svn-scm", + "displayName": "SVN", + "description": "Integrated Subversion source control", + "version": "2.12.3", + "publisher": "johnstoncode", + "engines": { + "vscode": "^1.44.0" + }, + "private": true, + "enableProposedApi": false, + "icon": "images/subversion.png", + "homepage": "https://github.com/JohnstonCode/svn-scm/blob/master/README.md", + "repository": { + "type": "git", + "url": "https://github.com/JohnstonCode/svn-scm.git" + }, + "bugs": { + "url": "https://github.com/JohnstonCode/svn-scm/issues" + }, + "categories": [ + "Other", + "SCM Providers" + ], + "keywords": [ + "multi-root ready", + "scm", + "svn", + "subversion" + ], + "activationEvents": [ + "*" + ], + "main": "./out/extension", + "scripts": { + "build": "yarn run build:ts && yarn run build:css", + "build:css": "yarn node-sass scss/ -o css/ --output-style compressed", + "build:ts": "webpack --mode production", + "compile": "webpack --mode development --watch", + "lint": "eslint \"src/**/*.ts\"", + "lint:fix": "yarn run lint --fix", + "organize": "node ./out/tools/organize.js", + "semantic-release": "semantic-release --yarn", + "style-check": "yarn prettylint 'src/**/*.ts'", + "style-fix": "yarn prettier --write \"src/**/*.ts\"", + "test": "node ./out/test/runTest.js", + "test-compile": "tsc -p ./", + "tools:genReadme": "node ./out/tools/generateConfigSectionForReadme.js", + "vscode:prepublish": "yarn run lint && yarn run build", + "watch:css": "yarn run build:css -w" + }, + "dependencies": {}, + "devDependencies": { + "@semantic-release/changelog": "^5.0.1", + "@semantic-release/git": "^9.0.0", + "@types/glob": "^7.1.3", + "@types/mocha": "^8.0.3", + "@types/node": "^12.11.7", + "@types/semver": "^7.3.3", + "@types/tmp": "0.2.0", + "@types/vscode": "1.44.0", + "@types/xml2js": "^0.4.4", + "@typescript-eslint/eslint-plugin": "^3.9.1", + "@typescript-eslint/parser": "^3.9.1", + "chardet": "^1.2.1", + "dayjs": "^1.8.33", + "decache": "^4.6.0", + "eslint": "^7.7.0", + "eslint-config-prettier": "^6.11.0", + "eslint-plugin-prettier": "^3.1.4", + "glob": "^7.1.4", + "iconv-lite-umd": "0.6.8", + "milligram": "^1.4.1", + "minimatch": "^3.0.4", + "mocha": "^8.1.1", + "node-sass": "^4.14.1", + "original-fs": "^1.0.0", + "ovsx": "^0.1.0-next.9321255", + "prettier": "^2.0.5", + "prettylint": "^1.0.0", + "semantic-release": "^17.1.1", + "semantic-release-vsce": "^3.0.1", + "semver": "^7.2.1", + "tmp": "0.2.1", + "ts-loader": "^8.0.2", + "typescript": "^4.0.2", + "vscode-test": "^1.4.0", + "webpack": "^4.44.1", + "webpack-cli": "^3.3.12", + "xml2js": "^0.4.19" + }, + "config": { + "commitizen": { + "path": "cz-conventional-changelog" + } + }, + "contributes": { + "viewsContainers": { + "activitybar": [ + { + "id": "svnActivity", + "title": "Subversion", + "icon": "icons/subversion-logo.svg" + } + ] }, - "bugs": { - "url": "https://github.com/JohnstonCode/svn-scm/issues" + "views": { + "explorer": [ + { + "id": "svn", + "name": "SVN" + } + ], + "svnActivity": [ + { + "id": "repolog", + "name": "Repositories", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "id": "itemlog", + "name": "File History", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "id": "branchchanges", + "name": "Branch Changes", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + } + ] }, - "categories": [ - "Other", - "SCM Providers" - ], - "keywords": [ - "multi-root ready", - "scm", - "svn", - "subversion" - ], - "activationEvents": [ - "*" + "commands": [ + { + "command": "svn.add", + "title": "Add", + "category": "SVN", + "icon": { + "light": "icons/light/add.svg", + "dark": "icons/dark/add.svg" + } + }, + { + "command": "svn.addToIgnoreExplorer", + "title": "Ignore file/ext from SVN (svn:ignore)", + "category": "SVN" + }, + { + "command": "svn.addToIgnoreSCM", + "title": "Ignore file/ext from SVN (svn:ignore)", + "category": "SVN" + }, + { + "command": "svn.branchchanges.openDiff", + "category": "SVN", + "title": "Open diff" + }, + { + "command": "svn.branchchanges.refresh", + "category": "SVN", + "title": "Refresh branch changes", + "icon": { + "dark": "icons/dark/refresh.svg", + "light": "icons/light/refresh.svg" + } + }, + { + "command": "svn.changelist", + "title": "Set changelist", + "category": "SVN", + "icon": { + "light": "icons/light/changelist.svg", + "dark": "icons/dark/changelist.svg" + } + }, + { + "command": "svn.checkout", + "title": "Checkout", + "category": "SVN" + }, + { + "command": "svn.cleanup", + "title": "Clean up working copy", + "category": "SVN" + }, + { + "command": "svn.close", + "title": "Close repository", + "category": "SVN" + }, + { + "command": "svn.commit", + "title": "Commit Selected", + "category": "SVN", + "icon": { + "light": "icons/light/check.svg", + "dark": "icons/dark/check.svg" + } + }, + { + "command": "svn.commitWithMessage", + "title": "Commit Changes", + "category": "SVN", + "icon": { + "light": "icons/light/check.svg", + "dark": "icons/dark/check.svg" + } + }, + { + "command": "svn.deleteUnversioned", + "title": "Delete selected files", + "category": "SVN" + }, + { + "command": "svn.itemlog.copymsg", + "category": "SVN", + "title": "Copy message" + }, + { + "command": "svn.itemlog.copyrevision", + "category": "SVN", + "title": "Copy revision number" + }, + { + "command": "svn.itemlog.openDiff", + "title": "Open diff", + "category": "SVN" + }, + { + "command": "svn.itemlog.openDiffBase", + "title": "Open diff with BASE", + "category": "SVN" + }, + { + "command": "svn.itemlog.openFileRemote", + "title": "Open this revision", + "category": "SVN" + }, + { + "command": "svn.itemlog.refresh", + "category": "SVN", + "title": "Refresh log for item", + "icon": { + "dark": "icons/dark/refresh.svg", + "light": "icons/light/refresh.svg" + } + }, + { + "command": "svn.log", + "title": "Show commit messages", + "category": "SVN" + }, + { + "command": "svn.openChangeBase", + "title": "Open Changes with BASE", + "category": "SVN", + "icon": { + "light": "icons/light/open-change-base.svg", + "dark": "icons/dark/open-change-base.svg" + } + }, + { + "command": "svn.openChangeHead", + "title": "Open Changes with HEAD", + "category": "SVN", + "icon": { + "light": "icons/light/open-change-head.svg", + "dark": "icons/dark/open-change-head.svg" + } + }, + { + "command": "svn.openChangePrev", + "title": "Open Changes with PREV", + "category": "SVN" + }, + { + "command": "svn.openFile", + "title": "Open File", + "category": "SVN", + "icon": { + "light": "icons/light/open-file.svg", + "dark": "icons/dark/open-file.svg" + } + }, + { + "command": "svn.openHEADFile", + "title": "Open File (HEAD)", + "category": "SVN" + }, + { + "command": "svn.patch", + "title": "Show diff patch for selected", + "category": "SVN" + }, + { + "command": "svn.patchAll", + "title": "Show all diff patch", + "category": "SVN" + }, + { + "command": "svn.patchChangeList", + "title": "Show patch from changelist", + "category": "SVN" + }, + { + "command": "svn.pickCommitMessage", + "title": "Pick a previous commit message", + "category": "SVN", + "icon": { + "light": "icons/light/icon-history.svg", + "dark": "icons/dark/icon-history.svg" + } + }, + { + "command": "svn.refresh", + "title": "Refresh", + "category": "SVN", + "icon": { + "light": "icons/light/refresh.svg", + "dark": "icons/dark/refresh.svg" + } + }, + { + "command": "svn.refreshRemoteChanges", + "title": "Refresh Remote Changes", + "category": "SVN", + "icon": { + "light": "icons/light/refresh.svg", + "dark": "icons/dark/refresh.svg" + } + }, + { + "command": "svn.remove", + "title": "Remove Selected", + "category": "SVN" + }, + { + "command": "svn.removeUnversioned", + "title": "Remove unversioned files", + "category": "SVN" + }, + { + "command": "svn.renameExplorer", + "title": "Rename with SVN", + "category": "SVN" + }, + { + "command": "svn.repolog.addrepolike", + "category": "SVN", + "title": "Add repo-like path", + "icon": { + "dark": "icons/dark/add.svg", + "light": "icons/light/add.svg" + } + }, + { + "command": "svn.repolog.copymsg", + "category": "SVN", + "title": "Copy message" + }, + { + "command": "svn.repolog.copyrevision", + "category": "SVN", + "title": "Copy revision number" + }, + { + "command": "svn.repolog.openDiff", + "category": "SVN", + "title": "Open diff" + }, + { + "command": "svn.repolog.openFileLocal", + "category": "SVN", + "title": "Open WC version of a file" + }, + { + "command": "svn.repolog.openFileRemote", + "category": "SVN", + "title": "Open this revision" + }, + { + "command": "svn.repolog.refresh", + "category": "SVN", + "title": "Refresh log", + "icon": { + "dark": "icons/dark/refresh.svg", + "light": "icons/light/refresh.svg" + } + }, + { + "command": "svn.repolog.remove", + "category": "SVN", + "title": "Remove" + }, + { + "command": "svn.resolve", + "title": "Resolve conflicts for selected", + "category": "SVN", + "icon": { + "light": "icons/light/check.svg", + "dark": "icons/dark/check.svg" + } + }, + { + "command": "svn.resolveAll", + "title": "Resolve all conflicts", + "category": "SVN" + }, + { + "command": "svn.revert", + "title": "Revert Selected File", + "category": "SVN", + "icon": { + "light": "icons/light/clean.svg", + "dark": "icons/dark/clean.svg" + } + }, + { + "command": "svn.revertAll", + "title": "Revert All Changes", + "category": "SVN", + "icon": { + "light": "icons/light/clean.svg", + "dark": "icons/dark/clean.svg" + } + }, + { + "command": "svn.revertChange", + "title": "Revert Change", + "category": "SVN", + "icon": { + "light": "icons/light/clean.svg", + "dark": "icons/dark/clean.svg" + } + }, + { + "command": "svn.revertExplorer", + "title": "Revert with SVN", + "category": "SVN", + "icon": { + "light": "icons/light/clean.svg", + "dark": "icons/dark/clean.svg" + } + }, + { + "command": "svn.searchLogByRevision", + "title": "Search log by revision", + "category": "SVN" + }, + { + "command": "svn.searchLogByText", + "title": "Search log", + "category": "SVN" + }, + { + "command": "svn.switchBranch", + "title": "Switch Branch", + "category": "SVN" + }, + { + "command": "svn.treeview.pullIncomingChange", + "title": "Update selected", + "category": "SVN", + "icon": { + "light": "icons/light/download.svg", + "dark": "icons/dark/download.svg" + } + }, + { + "command": "svn.treeview.refreshProvider", + "title": "Refresh", + "category": "SVN", + "icon": { + "light": "icons/light/refresh.svg", + "dark": "icons/dark/refresh.svg" + } + }, + { + "command": "svn.update", + "title": "Update", + "category": "SVN", + "icon": { + "light": "icons/light/download.svg", + "dark": "icons/dark/download.svg" + } + } ], - "main": "./out/extension", - "scripts": { - "build": "yarn run build:ts && yarn run build:css", - "build:css": "yarn node-sass scss/ -o css/ --output-style compressed", - "build:ts": "webpack --mode production", - "compile": "webpack --mode development --watch", - "lint": "eslint \"src/**/*.ts\"", - "lint:fix": "yarn run lint --fix", - "organize": "node ./out/tools/organize.js", - "semantic-release": "semantic-release --yarn", - "style-check": "yarn prettylint 'src/**/*.ts'", - "style-fix": "yarn prettier --write \"src/**/*.ts\"", - "test": "node ./out/test/runTest.js", - "test-compile": "tsc -p ./", - "tools:genReadme": "node ./out/tools/generateConfigSectionForReadme.js", - "vscode:prepublish": "yarn run lint && yarn run build", - "watch:css": "yarn run build:css -w" - }, - "dependencies": {}, - "devDependencies": { - "@semantic-release/changelog": "^5.0.1", - "@semantic-release/git": "^9.0.0", - "@types/glob": "^7.1.3", - "@types/mocha": "^8.0.3", - "@types/node": "^12.11.7", - "@types/semver": "^7.3.3", - "@types/tmp": "0.2.0", - "@types/vscode": "1.44.0", - "@types/xml2js": "^0.4.4", - "@typescript-eslint/eslint-plugin": "^3.10.0", - "@typescript-eslint/parser": "^3.10.0", - "chardet": "^1.2.1", - "dayjs": "^1.8.34", - "decache": "^4.6.0", - "eslint": "^7.7.0", - "eslint-config-prettier": "^6.11.0", - "eslint-plugin-prettier": "^3.1.4", - "glob": "^7.1.4", - "iconv-lite-umd": "0.6.8", - "milligram": "^1.4.1", - "minimatch": "^3.0.4", - "mocha": "^8.1.1", - "node-sass": "^4.14.1", - "original-fs": "^1.0.0", - "ovsx": "^0.1.0-next.9321255", - "prettier": "^2.1.0", - "prettylint": "^1.0.0", - "semantic-release": "^17.1.1", - "semantic-release-vsce": "^3.0.1", - "semver": "^7.2.1", - "tmp": "0.2.1", - "ts-loader": "^8.0.3", - "typescript": "^4.0.2", - "vscode-test": "^1.4.0", - "webpack": "^4.44.1", - "webpack-cli": "^3.3.12", - "xml2js": "^0.4.19" - }, - "config": { - "commitizen": { - "path": "cz-conventional-changelog" + "menus": { + "commandPalette": [ + { + "command": "svn.add", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.addToIgnoreExplorer", + "when": "false" + }, + { + "command": "svn.branchchanges.openDiff", + "when": "false" + }, + { + "command": "svn.branchchanges.refresh", + "when": "false" + }, + { + "command": "svn.changelist", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.checkout", + "when": "config.svn.enabled" + }, + { + "command": "svn.cleanup", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.close", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.commit", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.commitWithMessage", + "when": "false" + }, + { + "command": "svn.deleteUnversioned", + "when": "false" + }, + { + "command": "svn.itemlog.copymsg", + "when": "false" + }, + { + "command": "svn.itemlog.copyrevision", + "when": "false" + }, + { + "command": "svn.itemlog.openDiff", + "when": "false" + }, + { + "command": "svn.itemlog.openDiffBase", + "when": "false" + }, + { + "command": "svn.itemlog.openFileRemote", + "when": "false" + }, + { + "command": "svn.itemlog.refresh", + "when": "false" + }, + { + "command": "svn.log", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.openChangeBase", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && svnActiveEditorHasChanges" + }, + { + "command": "svn.openChangeHead", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && svnActiveEditorHasChanges" + }, + { + "command": "svn.openFile", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.openHEADFile", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.patch", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.patchAll", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.pickCommitMessage", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.refresh", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.remove", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.removeUnversioned", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && isSvn19orGreater" + }, + { + "command": "svn.renameExplorer", + "when": "false" + }, + { + "command": "svn.repolog.addrepolike", + "when": "false" + }, + { + "command": "svn.repolog.copymsg", + "when": "false" + }, + { + "command": "svn.repolog.copyrevision", + "when": "false" + }, + { + "command": "svn.repolog.openDiff", + "when": "false" + }, + { + "command": "svn.repolog.openFileLocal", + "when": "false" + }, + { + "command": "svn.repolog.openFileRemote", + "when": "false" + }, + { + "command": "svn.repolog.refresh", + "when": "false" + }, + { + "command": "svn.repolog.remove", + "when": "false" + }, + { + "command": "svn.resolve", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.resolveAll", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.revert", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.revertAll", + "when": "false" + }, + { + "command": "svn.revertChange", + "when": "false" + }, + { + "command": "svn.revertExplorer", + "when": "false" + }, + { + "command": "svn.searchLogByRevision", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.searchLogByText", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && isSvn18orGreater" + }, + { + "command": "svn.switchBranch", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.update", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + } + ], + "view/title": [ + { + "command": "svn.treeview.refreshProvider", + "when": "view == svn", + "group": "navigation" + }, + { + "command": "svn.repolog.refresh", + "when": "view == repolog", + "group": "navigation" + }, + { + "command": "svn.repolog.addrepolike", + "when": "view == repolog", + "group": "navigation" + }, + { + "command": "svn.itemlog.refresh", + "when": "view == itemlog", + "group": "navigation" + }, + { + "command": "svn.branchchanges.refresh", + "when": "view == branchchanges", + "group": "navigation" } + ], + "view/item/context": [ + { + "command": "svn.openHEADFile", + "when": "viewItem =~ /incomingChange:(added|modified)/" + }, + { + "command": "svn.openFile", + "when": "viewItem =~ /incomingChange:(modified|deleted)/" + }, + { + "command": "svn.treeview.pullIncomingChange", + "when": "viewItem =~ /incomingChange:*/" + }, + { + "command": "svn.openChangeHead", + "when": "viewItem == incomingChange:modified" + }, + { + "command": "svn.repolog.remove", + "when": "view == repolog && viewItem == userrepo" + }, + { + "command": "svn.itemlog.openFileRemote", + "when": "view == itemlog && viewItem == diffable" + }, + { + "command": "svn.itemlog.openDiff", + "when": "view == itemlog && viewItem == diffable", + "group": "1_diff" + }, + { + "command": "svn.itemlog.openDiffBase", + "when": "view == itemlog && viewItem == diffable", + "group": "1_diff" + }, + { + "command": "svn.itemlog.copymsg", + "when": "view == itemlog && viewItem == diffable" + }, + { + "command": "svn.itemlog.copyrevision", + "when": "view == itemlog && viewItem == diffable" + }, + { + "command": "svn.repolog.openDiff", + "when": "view == repolog && viewItem == diffable" + }, + { + "command": "svn.repolog.openFileRemote", + "when": "view == repolog && viewItem == diffable" + }, + { + "command": "svn.repolog.openFileLocal", + "when": "view == repolog && viewItem == diffable" + }, + { + "command": "svn.repolog.refresh", + "when": "view == repolog && viewItem =~ /.*repo/" + }, + { + "command": "svn.repolog.copymsg", + "when": "view == repolog && viewItem == commit" + }, + { + "command": "svn.repolog.copyrevision", + "when": "view == repolog && viewItem == commit" + } + ], + "scm/title": [ + { + "command": "svn.commitWithMessage", + "group": "navigation", + "when": "config.svn.enabled && scmProvider == svn" + }, + { + "command": "svn.refresh", + "group": "navigation", + "when": "config.svn.enabled && scmProvider == svn" + }, + { + "command": "svn.pickCommitMessage", + "group": "navigation", + "when": "config.svn.enabled && scmProvider == svn" + }, + { + "command": "svn.switchBranch", + "when": "config.svn.enabled && scmProvider == svn" + }, + { + "command": "svn.update", + "when": "config.svn.enabled && scmProvider == svn" + }, + { + "command": "svn.patchAll", + "when": "config.svn.enabled && scmProvider == svn" + }, + { + "command": "svn.resolveAll", + "when": "config.svn.enabled && scmProvider == svn" + }, + { + "command": "svn.log", + "when": "config.svn.enabled && scmProvider == svn" + }, + { + "command": "svn.cleanup", + "when": "config.svn.enabled && scmProvider == svn" + }, + { + "command": "svn.removeUnversioned", + "when": "config.svn.enabled && scmProvider == svn && isSvn19orGreater" + }, + { + "command": "svn.patchChangeList", + "when": "config.svn.enabled && scmProvider == svn" + } + ], + "scm/sourceControl": [ + { + "command": "svn.close", + "group": "navigation", + "when": "scmProvider == svn" + } + ], + "scm/resourceGroup/context": [ + { + "command": "svn.refreshRemoteChanges", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", + "group": "inline" + }, + { + "command": "svn.refreshRemoteChanges", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", + "group": "navigation" + }, + { + "command": "svn.update", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", + "group": "inline" + }, + { + "command": "svn.update", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", + "group": "navigation" + }, + { + "command": "svn.revertAll", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == changes", + "group": "navigation" + }, + { + "command": "svn.revertAll", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == changes", + "group": "inline" + } + ], + "scm/resourceState/context": [ + { + "command": "svn.add", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == unversioned", + "group": "inline" + }, + { + "command": "svn.add", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == unversioned", + "group": "1_modification" + }, + { + "command": "svn.openFile", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != external", + "group": "navigation" + }, + { + "command": "svn.openHEADFile", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external", + "group": "navigation" + }, + { + "command": "svn.openChangeBase", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external", + "group": "navigation" + }, + { + "command": "svn.openChangeHead", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external", + "group": "navigation" + }, + { + "command": "svn.patch", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", + "group": "navigation" + }, + { + "command": "svn.resolve", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == conflicts", + "group": "inline" + }, + { + "command": "svn.resolve", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == conflicts", + "group": "1_modification" + }, + { + "command": "svn.changelist", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", + "group": "inline" + }, + { + "command": "svn.changelist", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", + "group": "1_modification" + }, + { + "command": "svn.commit", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", + "group": "1_modification" + }, + { + "command": "svn.revert", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", + "group": "2_modification" + }, + { + "command": "svn.revert", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", + "group": "inline" + }, + { + "command": "svn.remove", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", + "group": "2_modification" + }, + { + "command": "svn.deleteUnversioned", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == unversioned", + "group": "2_modification" + }, + { + "command": "svn.addToIgnoreSCM", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == unversioned", + "group": "1_modification" + }, + { + "command": "svn.treeview.pullIncomingChange", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", + "group": "inline" + }, + { + "command": "svn.treeview.pullIncomingChange", + "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", + "group": "3_modification" + } + ], + "scm/change/title": [ + { + "command": "svn.revertChange", + "when": "config.svn.enabled && originalResourceScheme == svn" + } + ], + "editor/title": [ + { + "command": "svn.openFile", + "group": "navigation", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme != extension && resourceScheme != merge-conflicts.conflicts-diff" + }, + { + "command": "svn.openChangeBase", + "group": "navigation", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && svnActiveEditorHasChanges && !isInDiffEditor && resourceScheme == file" + }, + { + "command": "svn.openChangeHead", + "group": "navigation", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && svnActiveEditorHasChanges && !isInDiffEditor && resourceScheme == file" + } + ], + "explorer/context": [ + { + "command": "svn.addToIgnoreExplorer", + "group": "9_svn", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.renameExplorer", + "group": "7_modification", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !inputFocus" + }, + { + "command": "svn.changelist", + "group": "9_svn", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, + { + "command": "svn.revertExplorer", + "group": "7_modification", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + } + ] }, - "contributes": { - "viewsContainers": { - "activitybar": [ - { - "id": "svnActivity", - "title": "Subversion", - "icon": "icons/subversion-logo.svg" - } - ] + "configuration": { + "title": "Svn", + "properties": { + "svn.autorefresh": { + "type": "boolean", + "description": "Whether auto refreshing is enabled", + "default": true }, - "views": { - "explorer": [ - { - "id": "svn", - "name": "SVN" - } - ], - "svnActivity": [ - { - "id": "repolog", - "name": "Repositories", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "id": "itemlog", - "name": "File History", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "id": "branchchanges", - "name": "Branch Changes", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - } - ] + "svn.commit.changes.selectedAll": { + "type": "boolean", + "description": "Select all files when commit changes", + "default": true + }, + "svn.commit.checkEmptyMessage": { + "type": "boolean", + "description": "Check empty message before commit", + "default": true + }, + "svn.conflicts.autoResolve": { + "type": "boolean", + "description": "Set file to status resolved after fix conflicts", + "default": false + }, + "svn.default.encoding": { + "type": [ + "string", + "null" + ], + "description": "Encoding of svn output if the output is not utf-8. When this parameter is null, the encoding is automatically detected. Example: 'windows-1252'.", + "default": null + }, + "svn.defaultCheckoutDirectory": { + "type": "string", + "default": null, + "description": "The default location to checkout a svn repository." + }, + "svn.delete.actionForDeletedFiles": { + "type": "string", + "enum": [ + "none", + "prompt", + "remove" + ], + "description": "When a file is deleted, what SVN should do? `none` - Do nothing, `prompt` - Ask the action, `remove` - automatically remove from SVN", + "default": "prompt" + }, + "svn.delete.ignoredRulesForDeletedFiles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Ignored files/rules for `svn.delete.actionForDeletedFiles`(Ex.: file.txt or **/*.txt)", + "default": [] + }, + "svn.detectExternals": { + "type": "boolean", + "default": true, + "description": "Controls whether to automatically detect svn externals." }, - "commands": [ - { - "command": "svn.add", - "title": "Add", - "category": "SVN", - "icon": { - "light": "icons/light/add.svg", - "dark": "icons/dark/add.svg" - } - }, - { - "command": "svn.addToIgnoreExplorer", - "title": "Ignore file/ext from SVN (svn:ignore)", - "category": "SVN" - }, - { - "command": "svn.addToIgnoreSCM", - "title": "Ignore file/ext from SVN (svn:ignore)", - "category": "SVN" - }, - { - "command": "svn.branchchanges.openDiff", - "category": "SVN", - "title": "Open diff" - }, - { - "command": "svn.branchchanges.refresh", - "category": "SVN", - "title": "Refresh branch changes", - "icon": { - "dark": "icons/dark/refresh.svg", - "light": "icons/light/refresh.svg" - } - }, - { - "command": "svn.changelist", - "title": "Set changelist", - "category": "SVN", - "icon": { - "light": "icons/light/changelist.svg", - "dark": "icons/dark/changelist.svg" - } - }, - { - "command": "svn.checkout", - "title": "Checkout", - "category": "SVN" - }, - { - "command": "svn.cleanup", - "title": "Clean up working copy", - "category": "SVN" - }, - { - "command": "svn.close", - "title": "Close repository", - "category": "SVN" - }, - { - "command": "svn.commit", - "title": "Commit Selected", - "category": "SVN", - "icon": { - "light": "icons/light/check.svg", - "dark": "icons/dark/check.svg" - } - }, - { - "command": "svn.commitWithMessage", - "title": "Commit Changes", - "category": "SVN", - "icon": { - "light": "icons/light/check.svg", - "dark": "icons/dark/check.svg" - } - }, - { - "command": "svn.deleteUnversioned", - "title": "Delete selected files", - "category": "SVN" - }, - { - "command": "svn.itemlog.copymsg", - "category": "SVN", - "title": "Copy message" - }, - { - "command": "svn.itemlog.copyrevision", - "category": "SVN", - "title": "Copy revision number" - }, - { - "command": "svn.itemlog.openDiff", - "title": "Open diff", - "category": "SVN" - }, - { - "command": "svn.itemlog.openDiffBase", - "title": "Open diff with BASE", - "category": "SVN" - }, - { - "command": "svn.itemlog.openFileRemote", - "title": "Open this revision", - "category": "SVN" - }, - { - "command": "svn.itemlog.refresh", - "category": "SVN", - "title": "Refresh log for item", - "icon": { - "dark": "icons/dark/refresh.svg", - "light": "icons/light/refresh.svg" - } - }, - { - "command": "svn.log", - "title": "Show commit messages", - "category": "SVN" - }, - { - "command": "svn.openChangeBase", - "title": "Open Changes with BASE", - "category": "SVN", - "icon": { - "light": "icons/light/open-change-base.svg", - "dark": "icons/dark/open-change-base.svg" - } - }, - { - "command": "svn.openChangeHead", - "title": "Open Changes with HEAD", - "category": "SVN", - "icon": { - "light": "icons/light/open-change-head.svg", - "dark": "icons/dark/open-change-head.svg" - } - }, - { - "command": "svn.openChangePrev", - "title": "Open Changes with PREV", - "category": "SVN" - }, - { - "command": "svn.openFile", - "title": "Open File", - "category": "SVN", - "icon": { - "light": "icons/light/open-file.svg", - "dark": "icons/dark/open-file.svg" - } - }, - { - "command": "svn.openHEADFile", - "title": "Open File (HEAD)", - "category": "SVN" - }, - { - "command": "svn.patch", - "title": "Show diff patch for selected", - "category": "SVN" - }, - { - "command": "svn.patchAll", - "title": "Show all diff patch", - "category": "SVN" - }, - { - "command": "svn.patchChangeList", - "title": "Show patch from changelist", - "category": "SVN" - }, - { - "command": "svn.pickCommitMessage", - "title": "Pick a previous commit message", - "category": "SVN", - "icon": { - "light": "icons/light/icon-history.svg", - "dark": "icons/dark/icon-history.svg" - } - }, - { - "command": "svn.refresh", - "title": "Refresh", - "category": "SVN", - "icon": { - "light": "icons/light/refresh.svg", - "dark": "icons/dark/refresh.svg" - } - }, - { - "command": "svn.refreshRemoteChanges", - "title": "Refresh Remote Changes", - "category": "SVN", - "icon": { - "light": "icons/light/refresh.svg", - "dark": "icons/dark/refresh.svg" - } - }, - { - "command": "svn.remove", - "title": "Remove Selected", - "category": "SVN" - }, - { - "command": "svn.removeUnversioned", - "title": "Remove unversioned files", - "category": "SVN" - }, - { - "command": "svn.renameExplorer", - "title": "Rename with SVN", - "category": "SVN" - }, - { - "command": "svn.repolog.addrepolike", - "category": "SVN", - "title": "Add repo-like path", - "icon": { - "dark": "icons/dark/add.svg", - "light": "icons/light/add.svg" - } - }, - { - "command": "svn.repolog.copymsg", - "category": "SVN", - "title": "Copy message" - }, - { - "command": "svn.repolog.copyrevision", - "category": "SVN", - "title": "Copy revision number" - }, - { - "command": "svn.repolog.openDiff", - "category": "SVN", - "title": "Open diff" - }, - { - "command": "svn.repolog.openFileLocal", - "category": "SVN", - "title": "Open WC version of a file" - }, - { - "command": "svn.repolog.openFileRemote", - "category": "SVN", - "title": "Open this revision" - }, - { - "command": "svn.repolog.refresh", - "category": "SVN", - "title": "Refresh log", - "icon": { - "dark": "icons/dark/refresh.svg", - "light": "icons/light/refresh.svg" - } - }, - { - "command": "svn.repolog.remove", - "category": "SVN", - "title": "Remove" - }, - { - "command": "svn.resolve", - "title": "Resolve conflicts for selected", - "category": "SVN", - "icon": { - "light": "icons/light/check.svg", - "dark": "icons/dark/check.svg" - } - }, - { - "command": "svn.resolveAll", - "title": "Resolve all conflicts", - "category": "SVN" - }, - { - "command": "svn.revert", - "title": "Revert Selected File", - "category": "SVN", - "icon": { - "light": "icons/light/clean.svg", - "dark": "icons/dark/clean.svg" - } - }, - { - "command": "svn.revertAll", - "title": "Revert All Changes", - "category": "SVN", - "icon": { - "light": "icons/light/clean.svg", - "dark": "icons/dark/clean.svg" - } - }, - { - "command": "svn.revertChange", - "title": "Revert Change", - "category": "SVN", - "icon": { - "light": "icons/light/clean.svg", - "dark": "icons/dark/clean.svg" - } - }, - { - "command": "svn.revertExplorer", - "title": "Revert with SVN", - "category": "SVN", - "icon": { - "light": "icons/light/clean.svg", - "dark": "icons/dark/clean.svg" - } - }, - { - "command": "svn.searchLogByRevision", - "title": "Search log by revision", - "category": "SVN" - }, - { - "command": "svn.searchLogByText", - "title": "Search log", - "category": "SVN" - }, - { - "command": "svn.switchBranch", - "title": "Switch Branch", - "category": "SVN" - }, - { - "command": "svn.treeview.pullIncomingChange", - "title": "Update selected", - "category": "SVN", - "icon": { - "light": "icons/light/download.svg", - "dark": "icons/dark/download.svg" - } - }, - { - "command": "svn.treeview.refreshProvider", - "title": "Refresh", - "category": "SVN", - "icon": { - "light": "icons/light/refresh.svg", - "dark": "icons/dark/refresh.svg" - } - }, - { - "command": "svn.update", - "title": "Update", - "category": "SVN", - "icon": { - "light": "icons/light/download.svg", - "dark": "icons/dark/download.svg" - } - } - ], - "menus": { - "commandPalette": [ - { - "command": "svn.add", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.addToIgnoreExplorer", - "when": "false" - }, - { - "command": "svn.branchchanges.openDiff", - "when": "false" - }, - { - "command": "svn.branchchanges.refresh", - "when": "false" - }, - { - "command": "svn.changelist", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.checkout", - "when": "config.svn.enabled" - }, - { - "command": "svn.cleanup", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.close", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.commit", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.commitWithMessage", - "when": "false" - }, - { - "command": "svn.deleteUnversioned", - "when": "false" - }, - { - "command": "svn.itemlog.copymsg", - "when": "false" - }, - { - "command": "svn.itemlog.copyrevision", - "when": "false" - }, - { - "command": "svn.itemlog.openDiff", - "when": "false" - }, - { - "command": "svn.itemlog.openDiffBase", - "when": "false" - }, - { - "command": "svn.itemlog.openFileRemote", - "when": "false" - }, - { - "command": "svn.itemlog.refresh", - "when": "false" - }, - { - "command": "svn.log", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.openChangeBase", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && svnActiveEditorHasChanges" - }, - { - "command": "svn.openChangeHead", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && svnActiveEditorHasChanges" - }, - { - "command": "svn.openFile", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.openHEADFile", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.patch", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.patchAll", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.pickCommitMessage", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.refresh", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.remove", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.removeUnversioned", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && isSvn19orGreater" - }, - { - "command": "svn.renameExplorer", - "when": "false" - }, - { - "command": "svn.repolog.addrepolike", - "when": "false" - }, - { - "command": "svn.repolog.copymsg", - "when": "false" - }, - { - "command": "svn.repolog.copyrevision", - "when": "false" - }, - { - "command": "svn.repolog.openDiff", - "when": "false" - }, - { - "command": "svn.repolog.openFileLocal", - "when": "false" - }, - { - "command": "svn.repolog.openFileRemote", - "when": "false" - }, - { - "command": "svn.repolog.refresh", - "when": "false" - }, - { - "command": "svn.repolog.remove", - "when": "false" - }, - { - "command": "svn.resolve", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.resolveAll", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.revert", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.revertAll", - "when": "false" - }, - { - "command": "svn.revertChange", - "when": "false" - }, - { - "command": "svn.revertExplorer", - "when": "false" - }, - { - "command": "svn.searchLogByRevision", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.searchLogByText", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && isSvn18orGreater" - }, - { - "command": "svn.switchBranch", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.update", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - } - ], - "view/title": [ - { - "command": "svn.treeview.refreshProvider", - "when": "view == svn", - "group": "navigation" - }, - { - "command": "svn.repolog.refresh", - "when": "view == repolog", - "group": "navigation" - }, - { - "command": "svn.repolog.addrepolike", - "when": "view == repolog", - "group": "navigation" - }, - { - "command": "svn.itemlog.refresh", - "when": "view == itemlog", - "group": "navigation" - }, - { - "command": "svn.branchchanges.refresh", - "when": "view == branchchanges", - "group": "navigation" - } - ], - "view/item/context": [ - { - "command": "svn.openHEADFile", - "when": "viewItem =~ /incomingChange:(added|modified)/" - }, - { - "command": "svn.openFile", - "when": "viewItem =~ /incomingChange:(modified|deleted)/" - }, - { - "command": "svn.treeview.pullIncomingChange", - "when": "viewItem =~ /incomingChange:*/" - }, - { - "command": "svn.openChangeHead", - "when": "viewItem == incomingChange:modified" - }, - { - "command": "svn.repolog.remove", - "when": "view == repolog && viewItem == userrepo" - }, - { - "command": "svn.itemlog.openFileRemote", - "when": "view == itemlog && viewItem == diffable" - }, - { - "command": "svn.itemlog.openDiff", - "when": "view == itemlog && viewItem == diffable", - "group": "1_diff" - }, - { - "command": "svn.itemlog.openDiffBase", - "when": "view == itemlog && viewItem == diffable", - "group": "1_diff" - }, - { - "command": "svn.itemlog.copymsg", - "when": "view == itemlog && viewItem == diffable" - }, - { - "command": "svn.itemlog.copyrevision", - "when": "view == itemlog && viewItem == diffable" - }, - { - "command": "svn.repolog.openDiff", - "when": "view == repolog && viewItem == diffable" - }, - { - "command": "svn.repolog.openFileRemote", - "when": "view == repolog && viewItem == diffable" - }, - { - "command": "svn.repolog.openFileLocal", - "when": "view == repolog && viewItem == diffable" - }, - { - "command": "svn.repolog.refresh", - "when": "view == repolog && viewItem =~ /.*repo/" - }, - { - "command": "svn.repolog.copymsg", - "when": "view == repolog && viewItem == commit" - }, - { - "command": "svn.repolog.copyrevision", - "when": "view == repolog && viewItem == commit" - } - ], - "scm/title": [ - { - "command": "svn.commitWithMessage", - "group": "navigation", - "when": "config.svn.enabled && scmProvider == svn" - }, - { - "command": "svn.refresh", - "group": "navigation", - "when": "config.svn.enabled && scmProvider == svn" - }, - { - "command": "svn.pickCommitMessage", - "group": "navigation", - "when": "config.svn.enabled && scmProvider == svn" - }, - { - "command": "svn.switchBranch", - "when": "config.svn.enabled && scmProvider == svn" - }, - { - "command": "svn.update", - "when": "config.svn.enabled && scmProvider == svn" - }, - { - "command": "svn.patchAll", - "when": "config.svn.enabled && scmProvider == svn" - }, - { - "command": "svn.resolveAll", - "when": "config.svn.enabled && scmProvider == svn" - }, - { - "command": "svn.log", - "when": "config.svn.enabled && scmProvider == svn" - }, - { - "command": "svn.cleanup", - "when": "config.svn.enabled && scmProvider == svn" - }, - { - "command": "svn.removeUnversioned", - "when": "config.svn.enabled && scmProvider == svn && isSvn19orGreater" - }, - { - "command": "svn.patchChangeList", - "when": "config.svn.enabled && scmProvider == svn" - } - ], - "scm/sourceControl": [ - { - "command": "svn.close", - "group": "navigation", - "when": "scmProvider == svn" - } - ], - "scm/resourceGroup/context": [ - { - "command": "svn.refreshRemoteChanges", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", - "group": "inline" - }, - { - "command": "svn.refreshRemoteChanges", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", - "group": "navigation" - }, - { - "command": "svn.update", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", - "group": "inline" - }, - { - "command": "svn.update", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", - "group": "navigation" - }, - { - "command": "svn.revertAll", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == changes", - "group": "navigation" - }, - { - "command": "svn.revertAll", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == changes", - "group": "inline" - } - ], - "scm/resourceState/context": [ - { - "command": "svn.add", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == unversioned", - "group": "inline" - }, - { - "command": "svn.add", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == unversioned", - "group": "1_modification" - }, - { - "command": "svn.openFile", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != external", - "group": "navigation" - }, - { - "command": "svn.openHEADFile", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external", - "group": "navigation" - }, - { - "command": "svn.openChangeBase", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external", - "group": "navigation" - }, - { - "command": "svn.openChangeHead", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external", - "group": "navigation" - }, - { - "command": "svn.patch", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", - "group": "navigation" - }, - { - "command": "svn.resolve", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == conflicts", - "group": "inline" - }, - { - "command": "svn.resolve", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == conflicts", - "group": "1_modification" - }, - { - "command": "svn.changelist", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", - "group": "inline" - }, - { - "command": "svn.changelist", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", - "group": "1_modification" - }, - { - "command": "svn.commit", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", - "group": "1_modification" - }, - { - "command": "svn.revert", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", - "group": "2_modification" - }, - { - "command": "svn.revert", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", - "group": "inline" - }, - { - "command": "svn.remove", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup != unversioned && scmResourceGroup != external && scmResourceGroup != conflicts && scmResourceGroup != remotechanges", - "group": "2_modification" - }, - { - "command": "svn.deleteUnversioned", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == unversioned", - "group": "2_modification" - }, - { - "command": "svn.addToIgnoreSCM", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == unversioned", - "group": "1_modification" - }, - { - "command": "svn.treeview.pullIncomingChange", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", - "group": "inline" - }, - { - "command": "svn.treeview.pullIncomingChange", - "when": "config.svn.enabled && scmProvider == svn && scmResourceGroup == remotechanges", - "group": "3_modification" - } - ], - "scm/change/title": [ - { - "command": "svn.revertChange", - "when": "config.svn.enabled && originalResourceScheme == svn" - } - ], - "editor/title": [ - { - "command": "svn.openFile", - "group": "navigation", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme != extension && resourceScheme != merge-conflicts.conflicts-diff" - }, - { - "command": "svn.openChangeBase", - "group": "navigation", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && svnActiveEditorHasChanges && !isInDiffEditor && resourceScheme == file" - }, - { - "command": "svn.openChangeHead", - "group": "navigation", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && svnActiveEditorHasChanges && !isInDiffEditor && resourceScheme == file" - } - ], - "explorer/context": [ - { - "command": "svn.addToIgnoreExplorer", - "group": "9_svn", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.renameExplorer", - "group": "7_modification", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0 && explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !inputFocus" - }, - { - "command": "svn.changelist", - "group": "9_svn", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - }, - { - "command": "svn.revertExplorer", - "group": "7_modification", - "when": "config.svn.enabled && svnOpenRepositoryCount != 0" - } + "svn.detectIgnored": { + "type": "boolean", + "default": true, + "description": "Controls whether to automatically detect svn on ignored folders." + }, + "svn.diff.withHead": { + "type": "boolean", + "description": "Show diff changes using latest revision in the repository. Set false to use latest revision in local folder", + "default": true + }, + "svn.enabled": { + "type": "boolean", + "description": "Whether svn is enabled", + "default": true + }, + "svn.experimental.detect_encoding": { + "type": "boolean", + "description": "Try the experimental encoding detection", + "default": false + }, + "svn.experimental.encoding_priority": { + "type": "array", + "description": "Priority of encoding", + "default": [], + "examples": [ + [ + "UTF-8", + "GB18030", + "windows-1251" ] + ] + }, + "svn.gravatar.icon_url": { + "type": "string", + "description": "Url for the gravitar icon using the , and placeholders", + "examples": [ + "https://www.gravatar.com/avatar/.jpg?s=&d=https%3A%2F%2Fui-avatars.com%2Fapi%2F//128" + ], + "default": "https://www.gravatar.com/avatar/.jpg?s=&d=robohash" + }, + "svn.gravatars.enabled": { + "type": "boolean", + "description": "Use garavatar icons in log viewers", + "default": true + }, + "svn.ignoreMissingSvnWarning": { + "type": "boolean", + "description": "Ignores the warning when SVN is missing", + "default": false + }, + "svn.ignoreRepositories": { + "type": [ + "array", + null + ], + "default": null, + "scope": "resource", + "description": "List of SVN repositories to ignore." + }, + "svn.ignoreWorkingCopyIsTooOld": { + "type": "boolean", + "description": "Ignores the warning when working copy is too old", + "default": false + }, + "svn.layout.branchesRegex": { + "type": [ + "string", + "null" + ], + "description": "Regex to detect path for 'branches' in SVN URL, 'null' to disable. Subpath use 'branches/[^/]+/([^/]+)(/.*)?' (Ex.: 'branches/...', 'versions/...')", + "default": "branches/([^/]+)(/.*)?" + }, + "svn.layout.branchesRegexName": { + "type": [ + "number" + ], + "description": "Regex group position for name of branch", + "default": 1 + }, + "svn.layout.showFullName": { + "type": [ + "boolean" + ], + "description": "Set true to show 'branches/' and false to show only ''", + "default": true }, - "configuration": { - "title": "Svn", - "properties": { - "svn.autorefresh": { - "type": "boolean", - "description": "Whether auto refreshing is enabled", - "default": true - }, - "svn.commit.changes.selectedAll": { - "type": "boolean", - "description": "Select all files when commit changes", - "default": true - }, - "svn.commit.checkEmptyMessage": { - "type": "boolean", - "description": "Check empty message before commit", - "default": true - }, - "svn.conflicts.autoResolve": { - "type": "boolean", - "description": "Set file to status resolved after fix conflicts", - "default": false - }, - "svn.default.encoding": { - "type": [ - "string", - "null" - ], - "description": "Encoding of svn output if the output is not utf-8. When this parameter is null, the encoding is automatically detected. Example: 'windows-1252'.", - "default": null - }, - "svn.defaultCheckoutDirectory": { - "type": "string", - "default": null, - "description": "The default location to checkout a svn repository." - }, - "svn.delete.actionForDeletedFiles": { - "type": "string", - "enum": [ - "none", - "prompt", - "remove" - ], - "description": "When a file is deleted, what SVN should do? `none` - Do nothing, `prompt` - Ask the action, `remove` - automatically remove from SVN", - "default": "prompt" - }, - "svn.delete.ignoredRulesForDeletedFiles": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Ignored files/rules for `svn.delete.actionForDeletedFiles`(Ex.: file.txt or **/*.txt)", - "default": [] - }, - "svn.detectExternals": { - "type": "boolean", - "default": true, - "description": "Controls whether to automatically detect svn externals." - }, - "svn.detectIgnored": { - "type": "boolean", - "default": true, - "description": "Controls whether to automatically detect svn on ignored folders." - }, - "svn.diff.withHead": { - "type": "boolean", - "description": "Show diff changes using latest revision in the repository. Set false to use latest revision in local folder", - "default": true - }, - "svn.enabled": { - "type": "boolean", - "description": "Whether svn is enabled", - "default": true - }, - "svn.experimental.detect_encoding": { - "type": "boolean", - "description": "Try the experimental encoding detection", - "default": false - }, - "svn.experimental.encoding_priority": { - "type": "array", - "description": "Priority of encoding", - "default": [], - "examples": [ - [ - "UTF-8", - "GB18030", - "windows-1251" - ] - ] - }, - "svn.gravatar.icon_url": { - "type": "string", - "description": "Url for the gravitar icon using the , and placeholders", - "examples": [ - "https://www.gravatar.com/avatar/.jpg?s=&d=https%3A%2F%2Fui-avatars.com%2Fapi%2F//128" - ], - "default": "https://www.gravatar.com/avatar/.jpg?s=&d=robohash" - }, - "svn.gravatars.enabled": { - "type": "boolean", - "description": "Use garavatar icons in log viewers", - "default": true - }, - "svn.ignoreMissingSvnWarning": { - "type": "boolean", - "description": "Ignores the warning when SVN is missing", - "default": false - }, - "svn.ignoreRepositories": { - "type": [ - "array", - null - ], - "default": null, - "scope": "resource", - "description": "List of SVN repositories to ignore." - }, - "svn.ignoreWorkingCopyIsTooOld": { - "type": "boolean", - "description": "Ignores the warning when working copy is too old", - "default": false - }, - "svn.layout.branchesRegex": { - "type": [ - "string", - "null" - ], - "description": "Regex to detect path for 'branches' in SVN URL, 'null' to disable. Subpath use 'branches/[^/]+/([^/]+)(/.*)?' (Ex.: 'branches/...', 'versions/...')", - "default": "branches/([^/]+)(/.*)?" - }, - "svn.layout.branchesRegexName": { - "type": [ - "number" - ], - "description": "Regex group position for name of branch", - "default": 1 - }, - "svn.layout.showFullName": { - "type": [ - "boolean" - ], - "description": "Set true to show 'branches/' and false to show only ''", - "default": true - }, - "svn.layout.tagRegexName": { - "type": [ - "number" - ], - "description": "Regex group position for name of tag", - "default": 1 - }, - "svn.layout.tagsRegex": { - "type": [ - "string", - "null" - ], - "description": "Regex to detect path for 'tags' in SVN URL, 'null' to disable. Subpath use 'tags/[^/]+/([^/]+)(/.*)?'. (Ex.: 'tags/...', 'stamps/...')", - "default": "tags/([^/]+)(/.*)?" - }, - "svn.layout.trunkRegex": { - "type": [ - "string", - "null" - ], - "description": "Regex to detect path for 'trunk' in SVN URL, 'null' to disable. (Ex.: '(trunk)', '(main)')", - "default": "(trunk)(/.*)?" - }, - "svn.layout.trunkRegexName": { - "type": [ - "number" - ], - "description": "Regex group position for name of trunk", - "default": 1 - }, - "svn.log.length": { - "type": "number", - "minimum": 1, - "description": "Number of commit messages to log", - "default": 50 - }, - "svn.multipleFolders.depth": { - "type": "number", - "minimum": 0, - "description": "Maximum depth to find subfolders using SVN", - "default": 4 - }, - "svn.multipleFolders.enabled": { - "type": "boolean", - "description": "Allow to find subfolders using SVN", - "default": false - }, - "svn.multipleFolders.ignore": { - "type": "array", - "description": "Folders to ignore using SVN", - "default": [ - "**/.git", - "**/.hg", - "**/vendor", - "**/node_modules" - ] - }, - "svn.path": { - "type": [ - "string", - "null" - ], - "description": "Path to the svn executable", - "default": null, - "scope": "machine" - }, - "svn.previousCommitsUser": { - "type": "string", - "description": "Only show previous commits for a given user. Requires svn >= 1.8", - "default": null - }, - "svn.refresh.remoteChanges": { - "type": "boolean", - "description": "Refresh remote changes on refresh command", - "default": false - }, - "svn.remoteChanges.checkFrequency": { - "type": "number", - "description": "Set the interval in seconds to check changed files on remote repository and show in statusbar. 0 to disable", - "default": 300 - }, - "svn.showOutput": { - "type": "boolean", - "description": "Show the output window when the extension starts", - "default": false - }, - "svn.showUpdateMessage": { - "type": "boolean", - "description": "Show the update message when update is run", - "default": true - }, - "svn.sourceControl.changesLeftClick": { - "type": "string", - "enum": [ - "open", - "open diff" - ], - "description": "Set left click functionality on changes resource state", - "default": "open diff" - }, - "svn.sourceControl.combineExternalIfSameServer": { - "type": "boolean", - "default": false, - "description": "Combine the svn external in the main if is from the same server." - }, - "svn.sourceControl.countUnversioned": { - "type": "boolean", - "description": "Allow to count unversioned files in status count", - "default": true - }, - "svn.sourceControl.hideUnversioned": { - "type": "boolean", - "description": "Hide unversioned files in Source Control UI", - "default": false - }, - "svn.sourceControl.ignoreOnCommit": { - "type": "array", - "description": "Changelists to ignore on commit", - "default": [ - "ignore-on-commit" - ] - }, - "svn.sourceControl.ignoreOnStatusCount": { - "type": "array", - "description": "Changelists to ignore on status count", - "default": [ - "ignore-on-commit" - ] - }, - "svn.update.ignoreExternals": { - "type": "boolean", - "description": "Set to ignore externals definitions on update (add --ignore-externals)", - "default": true - } - } + "svn.layout.tagRegexName": { + "type": [ + "number" + ], + "description": "Regex group position for name of tag", + "default": 1 + }, + "svn.layout.tagsRegex": { + "type": [ + "string", + "null" + ], + "description": "Regex to detect path for 'tags' in SVN URL, 'null' to disable. Subpath use 'tags/[^/]+/([^/]+)(/.*)?'. (Ex.: 'tags/...', 'stamps/...')", + "default": "tags/([^/]+)(/.*)?" + }, + "svn.layout.trunkRegex": { + "type": [ + "string", + "null" + ], + "description": "Regex to detect path for 'trunk' in SVN URL, 'null' to disable. (Ex.: '(trunk)', '(main)')", + "default": "(trunk)(/.*)?" + }, + "svn.layout.trunkRegexName": { + "type": [ + "number" + ], + "description": "Regex group position for name of trunk", + "default": 1 + }, + "svn.log.length": { + "type": "number", + "minimum": 1, + "description": "Number of commit messages to log", + "default": 50 + }, + "svn.multipleFolders.depth": { + "type": "number", + "minimum": 0, + "description": "Maximum depth to find subfolders using SVN", + "default": 4 + }, + "svn.multipleFolders.enabled": { + "type": "boolean", + "description": "Allow to find subfolders using SVN", + "default": false + }, + "svn.multipleFolders.ignore": { + "type": "array", + "description": "Folders to ignore using SVN", + "default": [ + "**/.git", + "**/.hg", + "**/vendor", + "**/node_modules" + ] + }, + "svn.path": { + "type": [ + "string", + "null" + ], + "description": "Path to the svn executable", + "default": null, + "scope": "machine" + }, + "svn.previousCommitsUser": { + "type": "string", + "description": "Only show previous commits for a given user. Requires svn >= 1.8", + "default": null + }, + "svn.refresh.remoteChanges": { + "type": "boolean", + "description": "Refresh remote changes on refresh command", + "default": false + }, + "svn.remoteChanges.checkFrequency": { + "type": "number", + "description": "Set the interval in seconds to check changed files on remote repository and show in statusbar. 0 to disable", + "default": 300 + }, + "svn.showOutput": { + "type": "boolean", + "description": "Show the output window when the extension starts", + "default": false + }, + "svn.showUpdateMessage": { + "type": "boolean", + "description": "Show the update message when update is run", + "default": true + }, + "svn.sourceControl.changesLeftClick": { + "type": "string", + "enum": [ + "open", + "open diff" + ], + "description": "Set left click functionality on changes resource state", + "default": "open diff" + }, + "svn.sourceControl.combineExternalIfSameServer": { + "type": "boolean", + "default": false, + "description": "Combine the svn external in the main if is from the same server." + }, + "svn.sourceControl.countUnversioned": { + "type": "boolean", + "description": "Allow to count unversioned files in status count", + "default": true + }, + "svn.sourceControl.hideUnversioned": { + "type": "boolean", + "description": "Hide unversioned files in Source Control UI", + "default": false + }, + "svn.sourceControl.ignoreOnCommit": { + "type": "array", + "description": "Changelists to ignore on commit", + "default": [ + "ignore-on-commit" + ] + }, + "svn.sourceControl.ignoreOnStatusCount": { + "type": "array", + "description": "Changelists to ignore on status count", + "default": [ + "ignore-on-commit" + ] + }, + "svn.update.ignoreExternals": { + "type": "boolean", + "description": "Set to ignore externals definitions on update (add --ignore-externals)", + "default": true } - } + } + }, + "resourceLabelFormatters": [ + { + "scheme": "svn", + "formatting": { + "label": "${path}${authority}", + "separator": "/", + "workspaceSuffix": "Subversion" + } + } + ] + } } diff --git a/src/common/types.ts b/src/common/types.ts index 29d047ab..bae55bc1 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -121,7 +121,8 @@ export enum Operation { Status = "Status", StatusRemote = "StatusRemote", SwitchBranch = "SwitchBranch", - Update = "Update" + Update = "Update", + List = "List" } export interface ISvnResourceGroup extends SourceControlResourceGroup { diff --git a/src/extension.ts b/src/extension.ts index 6b7493b2..e5c69896 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -17,7 +17,6 @@ import { RepoLogProvider } from "./historyView/repoLogProvider"; import * as messages from "./messages"; import { SourceControlManager } from "./source_control_manager"; import { Svn } from "./svn"; -import { SvnContentProvider } from "./svnContentProvider"; import { SvnFinder } from "./svnFinder"; import SvnProvider from "./treeView/dataProviders/svnProvider"; import { toDisposable } from "./util"; @@ -25,6 +24,7 @@ import { BranchChangesProvider } from "./historyView/branchChangesProvider"; import { IsSvn19orGreater } from "./contexts/isSvn19orGreater"; import { IsSvn18orGreater } from "./contexts/isSvn18orGreater"; import { tempSvnFs } from "./temp_svn_fs"; +import { SvnFileSystemProvider } from "./svnFileSystemProvider"; async function init( _context: ExtensionContext, @@ -46,7 +46,7 @@ async function init( disposables.push( sourceControlManager, tempSvnFs, - new SvnContentProvider(sourceControlManager), + new SvnFileSystemProvider(sourceControlManager), new SvnProvider(sourceControlManager), new RepoLogProvider(sourceControlManager), new ItemLogProvider(sourceControlManager), diff --git a/src/repository.ts b/src/repository.ts index 50437dca..d8f627c2 100644 --- a/src/repository.ts +++ b/src/repository.ts @@ -26,7 +26,8 @@ import { SvnDepth, SvnUriAction, ISvnPathChange, - IStoredAuth + IStoredAuth, + ISvnListItem } from "./common/types"; import { debounce, globalSequentialize, memoize, throttle } from "./decorators"; import { exists } from "./fs"; @@ -754,6 +755,15 @@ export class Repository implements IRemoteRepository { }); } + public async showBuffer( + filePath: string | Uri, + revision?: string + ): Promise { + return this.run(Operation.Show, () => { + return this.repository.showBuffer(filePath, revision); + }); + } + public async addFiles(files: string[]) { return this.run(Operation.Add, () => this.repository.addFiles(files)); } @@ -837,6 +847,10 @@ export class Repository implements IRemoteRepository { return this.run(Operation.Patch, () => this.repository.patch(files)); } + public async patchBuffer(files: string[]) { + return this.run(Operation.Patch, () => this.repository.patchBuffer(files)); + } + public async patchChangelist(changelistName: string) { return this.run(Operation.Patch, () => this.repository.patchChangelist(changelistName) @@ -853,18 +867,34 @@ export class Repository implements IRemoteRepository { return this.run(Operation.Log, () => this.repository.plainLog()); } + public async plainLogBuffer() { + return this.run(Operation.Log, () => this.repository.plainLogBuffer()); + } + public async plainLogByRevision(revision: number) { return this.run(Operation.Log, () => this.repository.plainLogByRevision(revision) ); } + public async plainLogByRevisionBuffer(revision: number) { + return this.run(Operation.Log, () => + this.repository.plainLogByRevisionBuffer(revision) + ); + } + public async plainLogByText(search: string) { return this.run(Operation.Log, () => this.repository.plainLogByText(search) ); } + public async plainLogByTextBuffer(search: string) { + return this.run(Operation.Log, () => + this.repository.plainLogByTextBuffer(search) + ); + } + public async log( rfrom: string, rto: string, @@ -922,6 +952,12 @@ export class Repository implements IRemoteRepository { ); } + public async list(filePath: string): Promise { + return this.run(Operation.List, () => { + return this.repository.ls(filePath); + }); + } + public getPathNormalizer(): PathNormalizer { return new PathNormalizer(this.repository.info); } diff --git a/src/source_control_manager.ts b/src/source_control_manager.ts index 477973a6..39237685 100644 --- a/src/source_control_manager.ts +++ b/src/source_control_manager.ts @@ -30,10 +30,13 @@ import { IDisposable, isDescendant, isSvnFolder, - normalizePath + normalizePath, + eventToPromise } from "./util"; import { matchAll } from "./util/globMatch"; +type State = "uninitialized" | "initialized"; + export class SourceControlManager implements IDisposable { private _onDidOpenRepository = new EventEmitter(); public readonly onDidOpenRepository: Event = this @@ -60,6 +63,29 @@ export class SourceControlManager implements IDisposable { private configurationChangeDisposable: Disposable; + private _onDidChangeState = new EventEmitter(); + readonly onDidchangeState = this._onDidChangeState.event; + + private _state: State = "uninitialized"; + get state(): State { + return this._state; + } + + setState(state: State): void { + this._state = state; + this._onDidChangeState.fire(state); + } + + get isInitialized(): Promise { + if (this._state === "initialized") { + return Promise.resolve(); + } + + return eventToPromise( + filterEvent(this.onDidchangeState, s => s === "initialized") + ) as Promise; + } + get repositories(): Repository[] { return this.openRepositories.map(r => r.repository); } @@ -149,6 +175,8 @@ export class SourceControlManager implements IDisposable { this.disposables ); + this.setState("initialized"); + await this.scanWorkspaceFolders(); } diff --git a/src/svn.ts b/src/svn.ts index ea159b7a..1f8f672f 100644 --- a/src/svn.ts +++ b/src/svn.ts @@ -58,6 +58,12 @@ export function cpErrorHandler( }; } +export interface BufferResult { + exitCode: number; + stdout: Buffer; + stderr: string; +} + export class Svn { public version: string; @@ -223,6 +229,111 @@ export class Svn { return { exitCode, stdout: decodedStdout, stderr }; } + public async execBuffer( + cwd: string, + args: any[], + options: ICpOptions = {} + ): Promise { + if (cwd) { + this.lastCwd = cwd; + options.cwd = cwd; + } + + if (options.log !== false) { + const argsOut = args.map(arg => (/ |^$/.test(arg) ? `'${arg}'` : arg)); + this.logOutput( + `[${this.lastCwd.split(/[\\\/]+/).pop()}]$ svn ${argsOut.join(" ")}\n` + ); + } + + if (options.username) { + args.push("--username", options.username); + } + if (options.password) { + args.push("--password", options.password); + } + + if (options.username || options.password) { + // Configuration format: FILE:SECTION:OPTION=[VALUE] + // Disable password store + args.push("--config-option", "config:auth:password-stores="); + // Disable store auth credentials + args.push("--config-option", "servers:global:store-auth-creds=no"); + } + + // Force non interactive environment + args.push("--non-interactive"); + + const defaults: cp.SpawnOptions = { + env: proc.env + }; + if (cwd) { + defaults.cwd = cwd; + } + + defaults.env = Object.assign({}, proc.env, options.env || {}, { + LC_ALL: "en_US.UTF-8", + LANG: "en_US.UTF-8" + }); + + const process = cp.spawn(this.svnPath, args, defaults); + + const disposables: IDisposable[] = []; + + const once = ( + ee: NodeJS.EventEmitter, + name: string, + fn: (...args: any[]) => void + ) => { + ee.once(name, fn); + disposables.push(toDisposable(() => ee.removeListener(name, fn))); + }; + + const on = ( + ee: NodeJS.EventEmitter, + name: string, + fn: (...args: any[]) => void + ) => { + ee.on(name, fn); + disposables.push(toDisposable(() => ee.removeListener(name, fn))); + }; + + const [exitCode, stdout, stderr] = await Promise.all([ + new Promise((resolve, reject) => { + once(process, "error", reject); + once(process, "exit", resolve); + }), + new Promise(resolve => { + const buffers: Buffer[] = []; + on(process.stdout as Readable, "data", (b: Buffer) => buffers.push(b)); + once(process.stdout as Readable, "close", () => + resolve(Buffer.concat(buffers)) + ); + }), + new Promise(resolve => { + const buffers: Buffer[] = []; + on(process.stderr as Readable, "data", (b: Buffer) => buffers.push(b)); + once(process.stderr as Readable, "close", () => + resolve(Buffer.concat(buffers).toString()) + ); + }) + ]); + + dispose(disposables); + + if (options.log !== false && stderr.length > 0) { + const name = this.lastCwd.split(/[\\\/]+/).pop(); + const err = stderr + .split("\n") + .filter((line: string) => line) + .map((line: string) => `[${name}]$ ${line}`) + .join("\n"); + this.logOutput(err); + } + + return { exitCode, stdout, stderr }; + } + public async getRepositoryRoot(path: string) { try { const result = await this.exec(path, ["info", "--xml"]); diff --git a/src/svnContentProvider.ts b/src/svnContentProvider.ts deleted file mode 100644 index 595690d5..00000000 --- a/src/svnContentProvider.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { - Disposable, - Event, - EventEmitter, - TextDocumentContentProvider, - Uri, - window, - workspace -} from "vscode"; -import { - ICache, - ICacheRow, - RepositoryChangeEvent, - SvnUriAction -} from "./common/types"; -import { debounce, throttle } from "./decorators"; -import { SourceControlManager } from "./source_control_manager"; -import { fromSvnUri } from "./uri"; -import { - eventToPromise, - filterEvent, - IDisposable, - isDescendant, - toDisposable -} from "./util"; - -const THREE_MINUTES = 1000 * 60 * 3; -const FIVE_MINUTES = 1000 * 60 * 5; - -export class SvnContentProvider - implements IDisposable, TextDocumentContentProvider { - private _onDidChange = new EventEmitter(); - get onDidChange(): Event { - return this._onDidChange.event; - } - - private changedRepositoryRoots = new Set(); - private cache: ICache = Object.create(null); - private disposables: Disposable[] = []; - - constructor(private sourceControlManager: SourceControlManager) { - this.disposables.push( - sourceControlManager.onDidChangeRepository( - this.onDidChangeRepository, - this - ), - workspace.registerTextDocumentContentProvider("svn", this) - ); - - const interval = setInterval(() => this.cleanup(), FIVE_MINUTES); - this.disposables.push(toDisposable(() => clearInterval(interval))); - } - - private onDidChangeRepository({ repository }: RepositoryChangeEvent): void { - this.changedRepositoryRoots.add(repository.root); - this.eventuallyFireChangeEvents(); - } - - @debounce(1100) - private eventuallyFireChangeEvents(): void { - this.fireChangeEvents(); - } - - @throttle - private async fireChangeEvents(): Promise { - if (!window.state.focused) { - const onDidFocusWindow = filterEvent( - window.onDidChangeWindowState, - e => e.focused - ); - await eventToPromise(onDidFocusWindow); - } - - // Don't check if no has repository changes - if (this.changedRepositoryRoots.size === 0) { - return; - } - - // Use copy to allow new items in parallel - const roots = Array.from(this.changedRepositoryRoots); - this.changedRepositoryRoots.clear(); - - const keys = Object.keys(this.cache); - - cacheLoop: for (const key of keys) { - const uri = this.cache[key].uri; - const fsPath = uri.fsPath; - - for (const root of roots) { - if (isDescendant(root, fsPath)) { - this._onDidChange.fire(uri); - continue cacheLoop; - } - } - } - } - - public async provideTextDocumentContent(uri: Uri): Promise { - try { - const { fsPath, action, extra } = fromSvnUri(uri); - - const repository = this.sourceControlManager.getRepository(fsPath); - - if (!repository) { - return ""; - } - - const cacheKey = uri.toString(); - const timestamp = new Date().getTime(); - const cacheValue: ICacheRow = { uri, timestamp }; - - this.cache[cacheKey] = cacheValue; - - if (action === SvnUriAction.SHOW) { - const ref = extra.ref; - return await repository.show(fsPath, ref); - } - if (action === SvnUriAction.LOG) { - return await repository.plainLog(); - } - if (action === SvnUriAction.LOG_REVISION && extra.revision) { - return await repository.plainLogByRevision(extra.revision); - } - if (action === SvnUriAction.LOG_SEARCH && extra.search) { - return await repository.plainLogByText(extra.search); - } - if (action === SvnUriAction.PATCH) { - return await repository.patch([fsPath]); - } - } catch (error) { - // Dont show error - } - return ""; - } - - private cleanup(): void { - const now = new Date().getTime(); - const cache = Object.create(null); - - Object.keys(this.cache).forEach(key => { - const row = this.cache[key]; - const { fsPath } = fromSvnUri(row.uri); - const isOpen = workspace.textDocuments - .filter(d => d.uri.scheme === "file") - .some(d => d.uri.fsPath === fsPath); - - if (isOpen || now - row.timestamp < THREE_MINUTES) { - cache[row.uri.toString()] = row; - } - }); - - this.cache = cache; - } - - public dispose(): void { - this.disposables.forEach(d => d.dispose()); - } -} diff --git a/src/svnFileSystemProvider.ts b/src/svnFileSystemProvider.ts new file mode 100644 index 00000000..26f6dd2d --- /dev/null +++ b/src/svnFileSystemProvider.ts @@ -0,0 +1,212 @@ +import { + FileSystemProvider, + workspace, + Disposable, + FileStat, + Uri, + FileSystemError, + FileType, + FileChangeEvent, + EventEmitter, + Event, + window, + FileChangeType +} from "vscode"; +import { SourceControlManager } from "./source_control_manager"; +import { fromSvnUri } from "./uri"; +import { SvnUriAction, RepositoryChangeEvent } from "./common/types"; +import { debounce, throttle } from "./decorators"; +import { + filterEvent, + eventToPromise, + isDescendant, + pathEquals, + EmptyDisposable +} from "./util"; + +const THREE_MINUTES = 1000 * 60 * 3; +const FIVE_MINUTES = 1000 * 60 * 5; + +interface CacheRow { + uri: Uri; + timestamp: number; +} + +export class SvnFileSystemProvider implements FileSystemProvider, Disposable { + private disposables: Disposable[] = []; + private cache = new Map(); + + private _onDidChangeFile = new EventEmitter(); + readonly onDidChangeFile: Event = this._onDidChangeFile + .event; + + private changedRepositoryRoots = new Set(); + + constructor(private sourceControlManager: SourceControlManager) { + this.disposables.push( + sourceControlManager.onDidChangeRepository( + this.onDidChangeRepository, + this + ), + workspace.registerFileSystemProvider("svn", this, { + isReadonly: true, + isCaseSensitive: true + }) + ); + + setInterval(() => this.cleanup(), FIVE_MINUTES); + } + + private onDidChangeRepository({ repository }: RepositoryChangeEvent): void { + this.changedRepositoryRoots.add(repository.root); + this.eventuallyFireChangeEvents(); + } + + @debounce(1100) + private eventuallyFireChangeEvents(): void { + this.fireChangeEvents(); + } + + @throttle + private async fireChangeEvents(): Promise { + if (!window.state.focused) { + const onDidFocusWindow = filterEvent( + window.onDidChangeWindowState, + e => e.focused + ); + await eventToPromise(onDidFocusWindow); + } + + const events: FileChangeEvent[] = []; + + for (const { uri } of this.cache.values()) { + const fsPath = uri.fsPath; + + for (const root of this.changedRepositoryRoots) { + if (isDescendant(root, fsPath)) { + events.push({ type: FileChangeType.Changed, uri }); + break; + } + } + } + + if (events.length > 0) { + this._onDidChangeFile.fire(events); + } + + this.changedRepositoryRoots.clear(); + } + + watch(): Disposable { + return EmptyDisposable; + } + + async stat(uri: Uri): Promise { + await this.sourceControlManager.isInitialized; + + const { fsPath } = fromSvnUri(uri); + + const repository = this.sourceControlManager.getRepository(fsPath); + + if (!repository) { + throw FileSystemError.FileNotFound; + } + + let size = 0; + let mtime = new Date().getTime(); + + try { + const listResults = await repository.list(fsPath); + + if (listResults.length) { + size = Number(listResults[0].size) as number; + mtime = Date.parse(listResults[0].commit.date); + } + } catch {} + + return { type: FileType.File, size, mtime, ctime: 0 }; + } + + readDirectory(): Thenable<[string, FileType][]> { + throw new Error("readDirectory is not implemented"); + } + + createDirectory(): void { + throw new Error("createDirectory is not implemented"); + } + + async readFile(uri: Uri): Promise { + await this.sourceControlManager.isInitialized; + + const { fsPath, extra, action } = fromSvnUri(uri); + + const repository = this.sourceControlManager.getRepository(fsPath); + + if (!repository) { + throw FileSystemError.FileNotFound(); + } + + const cacheKey = uri.toString(); + const timestamp = new Date().getTime(); + const cacheValue: CacheRow = { uri: uri, timestamp }; + + this.cache.set(cacheKey, cacheValue); + + try { + if (action === SvnUriAction.SHOW) { + return await repository.showBuffer(fsPath, extra.ref); + } + if (action === SvnUriAction.LOG) { + return await repository.plainLogBuffer(); + } + if (action === SvnUriAction.LOG_REVISION && extra.revision) { + return await repository.plainLogByRevisionBuffer(extra.revision); + } + if (action === SvnUriAction.LOG_SEARCH && extra.search) { + return await repository.plainLogByTextBuffer(extra.search); + } + if (action === SvnUriAction.PATCH) { + console.log("here"); + return await repository.patchBuffer([fsPath]); + } + } catch {} + + return new Uint8Array(0); + } + + writeFile(): void { + throw new Error("writeFile is not implemented"); + } + + delete(): void { + throw new Error("delete is not implemented"); + } + + rename(): void { + throw new Error("rename is not implemented"); + } + + private cleanup(): void { + const now = new Date().getTime(); + const cache = new Map(); + + for (const row of this.cache.values()) { + const { fsPath } = fromSvnUri(row.uri); + const isOpen = workspace.textDocuments + .filter(d => d.uri.scheme === "file") + .some(d => pathEquals(d.uri.fsPath, fsPath)); + + if (isOpen || now - row.timestamp < THREE_MINUTES) { + cache.set(row.uri.toString(), row); + } else { + // TODO: should fire delete events? + } + } + + this.cache = cache; + } + + dispose(): void { + this.disposables.forEach(d => d.dispose()); + } +} diff --git a/src/svnRepository.ts b/src/svnRepository.ts index 89773430..20e489d5 100644 --- a/src/svnRepository.ts +++ b/src/svnRepository.ts @@ -11,7 +11,8 @@ import { Status, SvnDepth, ISvnPathChange, - ISvnPath + ISvnPath, + ISvnListItem } from "./common/types"; import { sequentialize } from "./decorators"; import * as encodeUtil from "./encoding"; @@ -22,7 +23,7 @@ import { parseInfoXml } from "./parser/infoParser"; import { parseSvnList } from "./parser/listParser"; import { parseSvnLog } from "./parser/logParser"; import { parseStatusXml } from "./parser/statusParser"; -import { Svn } from "./svn"; +import { Svn, BufferResult } from "./svn"; import { fixPathSeparator, fixPegRevision, @@ -78,6 +79,16 @@ export class Repository { return this.svn.exec(this.workspaceRoot, args, options); } + public async execBuffer( + args: string[], + options: ICpOptions = {} + ): Promise { + options.username = this.username; + options.password = this.password; + + return this.svn.execBuffer(this.workspaceRoot, args, options); + } + public removeAbsolutePath(file: string) { file = fixPathSeparator(file); @@ -363,6 +374,51 @@ export class Repository { return result.stdout; } + public async showBuffer( + file: string | Uri, + revision?: string + ): Promise { + const args = ["cat"]; + + let uri: Uri; + let filePath: string; + + if (file instanceof Uri) { + uri = file; + filePath = file.toString(true); + } else { + uri = Uri.file(file); + filePath = file; + } + + const isChild = + uri.scheme === "file" && isDescendant(this.workspaceRoot, uri.fsPath); + + let target: string = filePath; + + if (isChild) { + target = this.removeAbsolutePath(target); + } + + if (revision) { + args.push("-r", revision); + if ( + isChild && + !["BASE", "COMMITTED", "PREV"].includes(revision.toUpperCase()) + ) { + const info = await this.getInfo(); + target = info.url + "/" + target.replace(/\\/g, "/"); + // TODO move to SvnRI + } + } + + args.push(target); + + const result = await this.execBuffer(args); + + return result.stdout; + } + public async commitFiles(message: string, files: string[]) { files = files.map(file => this.removeAbsolutePath(file)); @@ -619,6 +675,13 @@ export class Repository { return message; } + public async patchBuffer(files: string[]) { + files = files.map(file => this.removeAbsolutePath(file)); + const result = await this.execBuffer(["diff", "--internal-diff", ...files]); + const message = result.stdout; + return message; + } + public async patchChangelist(changelistName: string) { const result = await this.exec([ "diff", @@ -666,18 +729,43 @@ export class Repository { return result.stdout; } + public async plainLogBuffer(): Promise { + const logLength = configuration.get("log.length") || "50"; + const result = await this.execBuffer([ + "log", + "-r", + "HEAD:1", + "--limit", + logLength + ]); + + return result.stdout; + } + public async plainLogByRevision(revision: number) { const result = await this.exec(["log", "-r", revision.toString()]); return result.stdout; } + public async plainLogByRevisionBuffer(revision: number) { + const result = await this.execBuffer(["log", "-r", revision.toString()]); + + return result.stdout; + } + public async plainLogByText(search: string) { const result = await this.exec(["log", "--search", search]); return result.stdout; } + public async plainLogByTextBuffer(search: string) { + const result = await this.execBuffer(["log", "--search", search]); + + return result.stdout; + } + public async log( rfrom: string, rto: string, @@ -755,6 +843,12 @@ export class Repository { return parseSvnList(result.stdout); } + public async ls(file: string): Promise { + const result = await this.exec(["list", file, "--xml"]); + + return parseSvnList(result.stdout); + } + public async getCurrentIgnore(directory: string) { directory = this.removeAbsolutePath(directory); diff --git a/src/test/commands.test.ts b/src/test/commands.test.ts index caecc305..6ee9489b 100644 --- a/src/test/commands.test.ts +++ b/src/test/commands.test.ts @@ -37,14 +37,14 @@ suite("Commands Tests", () => { testUtil.destroyAllTempPaths(); }); - test("File Open", async function() { + test("File Open", async function () { const file = path.join(checkoutDir.fsPath, "new.txt"); fs.writeFileSync(file, "test"); await commands.executeCommand("svn.fileOpen", Uri.file(file)); }); - test("Add File", async function() { + test("Add File", async function () { const repository = sourceControlManager.getRepository( checkoutDir ) as Repository; @@ -61,7 +61,7 @@ suite("Commands Tests", () => { assert.equal(repository.changes.resourceStates.length, 1); }); - test("Commit Single File", async function() { + test("Commit Single File", async function () { const repository = sourceControlManager.getRepository( checkoutDir ) as Repository; @@ -70,15 +70,15 @@ suite("Commands Tests", () => { await commands.executeCommand("svn.commitWithMessage"); }); - test("Update", async function() { + test("Update", async function () { await commands.executeCommand("svn.update"); }); - test("Show Log", async function() { + test("Show Log", async function () { await commands.executeCommand("svn.log"); }); - test("Open Changes", async function() { + test("Open Changes", async function () { const file = path.join(checkoutDir.fsPath, "new.txt"); fs.writeFileSync(file, "test 2"); const uri = Uri.file(file); @@ -88,7 +88,7 @@ suite("Commands Tests", () => { await commands.executeCommand("svn.openChangeHead", uri); }); - test("Open File", async function() { + test("Open File", async function () { const file = path.join(checkoutDir.fsPath, "new.txt"); const uri = Uri.file(file); @@ -96,7 +96,7 @@ suite("Commands Tests", () => { await commands.executeCommand("svn.openHEADFile", uri); }); - test("Open Diff (Double click o source control)", async function() { + test("Open Diff (Double click o source control)", async function () { const repository = sourceControlManager.getRepository( checkoutDir ) as Repository; @@ -110,7 +110,7 @@ suite("Commands Tests", () => { await commands.executeCommand("svn.openResourceHead", resource); }); - test("Add Changelist", async function() { + test("Add Changelist", async function () { const repository = sourceControlManager.getRepository( checkoutDir ) as Repository; @@ -127,7 +127,7 @@ suite("Commands Tests", () => { assert.ok(repository.changelists.has("changelist-test")); }); - test("Remove Changelist", async function() { + test("Remove Changelist", async function () { const repository = sourceControlManager.getRepository( checkoutDir ) as Repository; @@ -143,11 +143,11 @@ suite("Commands Tests", () => { assert.equal(group.resourceStates.length, 0); }); - test("Show Patch", async function() { + test("Show Patch", async function () { await commands.executeCommand("svn.patch"); }); - test("Commit Selected File", async function() { + test("Commit Selected File", async function () { const repository = sourceControlManager.getRepository( checkoutDir ) as Repository; @@ -165,7 +165,7 @@ suite("Commands Tests", () => { assert.equal(repository.changes.resourceStates.length, 0); }); - test("Commit Multiple", async function() { + test("Commit Multiple", async function () { const file1 = path.join(checkoutDir.fsPath, "file1.txt"); fs.writeFileSync(file1, "test"); await commands.executeCommand("svn.openFile", Uri.file(file1)); @@ -196,7 +196,7 @@ suite("Commands Tests", () => { await commands.executeCommand("svn.commitWithMessage"); }); - test("New Branch", async function() { + test("New Branch", async function () { testUtil.overrideNextShowQuickPick(0); testUtil.overrideNextShowQuickPick(1); testUtil.overrideNextShowInputBox("test"); @@ -212,7 +212,7 @@ suite("Commands Tests", () => { assert.equal(await repository.getCurrentBranch(), "branches/test"); }); - test("Switch Branch", async function() { + test("Switch Branch", async function () { this.timeout(5000); testUtil.overrideNextShowQuickPick(2); await commands.executeCommand("svn.switchBranch"); diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index b6f2b80a..571136ee 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -16,7 +16,7 @@ suite("Extension Tests", () => { // The extension is already activated by vscode before running mocha test framework. // No need to test activate any more. So commenting this case. // tslint:disable-next-line: only-arrow-functions - test("should be able to activate the extension", function(done) { + test("should be able to activate the extension", function (done) { this.timeout(60 * 1000); const extension = vscode.extensions.getExtension( "johnstoncode.svn-scm" diff --git a/src/test/pathNormalizer.test.ts b/src/test/pathNormalizer.test.ts index 84461d60..9c66bc15 100644 --- a/src/test/pathNormalizer.test.ts +++ b/src/test/pathNormalizer.test.ts @@ -23,7 +23,7 @@ suite("SVN URLs parsing", () => { // do nothing }); - test("somedomain", function() { + test("somedomain", function () { assert.equal(nm1.branchRoot.toString(), Uri.parse(ri1.url).toString()); assert.equal( nm1.repoRoot.toString(), @@ -60,7 +60,7 @@ suite("SVN URLs parsing", () => { }; const nm2 = new PathNormalizer(ri2 as ISvnInfo); - test("rootdomain", function() { + test("rootdomain", function () { const p1 = nm2.parse( "/foo/drupal-7/trunk/drupal/sites/all/themes/foo_theme/scss/foo-pdf.scss" ); @@ -89,7 +89,7 @@ suite("SVN URLs parsing", () => { }; const nm3 = new PathNormalizer(ri3 as ISvnInfo); - test("rootbranch", function() { + test("rootbranch", function () { const p4 = nm3.parse("/file.c"); assert.equal(p4.localFullPath!.path, "/home/user/svn/file.c"); }); @@ -106,7 +106,7 @@ suite("SVN URLs parsing", () => { const nm4 = new PathNormalizer(ri4 as ISvnInfo); if (process.platform == "win32") { - test("winpath", function() { + test("winpath", function () { const p4 = nm4.parse("/trunk/file.c"); assert.equal(p4.localFullPath!.fsPath, "x:\\work\\rootd\\file.c"); }); diff --git a/src/test/repository.test.ts b/src/test/repository.test.ts index b27f7b6f..16702b4b 100644 --- a/src/test/repository.test.ts +++ b/src/test/repository.test.ts @@ -33,11 +33,11 @@ suite("Repository Tests", () => { testUtil.destroyAllTempPaths(); }); - test("Empty Open Repository", async function() { + test("Empty Open Repository", async function () { assert.equal(sourceControlManager.repositories.length, 0); }); - test("Try Open Repository", async function() { + test("Try Open Repository", async function () { await sourceControlManager.tryOpenRepository(checkoutDir.fsPath); assert.equal(sourceControlManager.repositories.length, 1); }); @@ -76,7 +76,7 @@ suite("Repository Tests", () => { assert.equal(name, "trunk"); }); - test("Try commit file", async function() { + test("Try commit file", async function () { this.timeout(60000); const repository: Repository | null = sourceControlManager.getRepository( checkoutDir.fsPath @@ -107,7 +107,7 @@ suite("Repository Tests", () => { assert.equal(remoteContent, "test"); }); - test("Try switch branch", async function() { + test("Try switch branch", async function () { this.timeout(60000); const newCheckoutDir = await testUtil.createRepoCheckout( testUtil.getSvnUrl(repoUri) + "/trunk" diff --git a/src/test/temp_svn_fs.test.ts b/src/test/temp_svn_fs.test.ts index 5c0c6ba0..f665d199 100644 --- a/src/test/temp_svn_fs.test.ts +++ b/src/test/temp_svn_fs.test.ts @@ -13,7 +13,10 @@ suite("Test temp svn fs", () => { "test content" ); - assert.equal(revisionUri.fsPath, join('/', '1181ae15a77d83ac0b077051dfed21ed', 'r30_test.js')); + assert.equal( + revisionUri.fsPath, + join("/", "1181ae15a77d83ac0b077051dfed21ed", "r30_test.js") + ); }); test("Temp file is created", async () => { diff --git a/src/util.ts b/src/util.ts index c477a040..79d78640 100644 --- a/src/util.ts +++ b/src/util.ts @@ -205,3 +205,19 @@ export async function isSvnFolder( export function setVscodeContext(key: string, value: any) { commands.executeCommand("setContext", key, value); } + +function isWindowsPath(path: string): boolean { + return /^[a-zA-Z]:\\/.test(path); +} + +export function pathEquals(a: string, b: string): boolean { + // Windows is case insensitive + if (isWindowsPath(a)) { + a = a.toLowerCase(); + b = b.toLowerCase(); + } + + return a === b; +} + +export const EmptyDisposable = toDisposable(() => null); diff --git a/yarn.lock b/yarn.lock index f76f7ec6..a0b0b8c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -346,52 +346,52 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^3.10.0": - version "3.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.0.tgz#40fd53e81639c0d1a515b44e5fdf4c03dfd3cd39" - integrity sha512-Bbeg9JAnSzZ85Y0gpInZscSpifA6SbEgRryaKdP5ZlUjhTKsvZS4GUIE6xAZCjhNTrf4zXXsySo83ZdHL7it0w== +"@typescript-eslint/eslint-plugin@^3.9.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" + integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== dependencies: - "@typescript-eslint/experimental-utils" "3.10.0" + "@typescript-eslint/experimental-utils" "3.10.1" debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@3.10.0": - version "3.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.0.tgz#f97a669a84a78319ab324cd51169d0c52853a360" - integrity sha512-e5ZLSTuXgqC/Gq3QzK2orjlhTZVXzwxDujQmTBOM1NIVBZgW3wiIZjaXuVutk9R4UltFlwC9UD2+bdxsA7yyNg== +"@typescript-eslint/experimental-utils@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" + integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.10.0" - "@typescript-eslint/typescript-estree" "3.10.0" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^3.10.0": - version "3.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.0.tgz#820322d990a82265a78f4c1fc9aae03ce95b76ac" - integrity sha512-iJyf3f2HVwscvJR7ySGMXw2DJgIAPKEz8TeU17XVKzgJRV4/VgCeDFcqLzueRe7iFI2gv+Tln4AV88ZOnsCNXg== +"@typescript-eslint/parser@^3.9.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" + integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.10.0" - "@typescript-eslint/types" "3.10.0" - "@typescript-eslint/typescript-estree" "3.10.0" + "@typescript-eslint/experimental-utils" "3.10.1" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/types@3.10.0": - version "3.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.0.tgz#b81906674eca94a884345ba0bc1aaf6cd4da912a" - integrity sha512-ktUWSa75heQNwH85GRM7qP/UUrXqx9d6yIdw0iLO9/uE1LILW+i+3+B64dUodUS2WFWLzKTlwfi9giqrODibWg== +"@typescript-eslint/types@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" + integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== -"@typescript-eslint/typescript-estree@3.10.0": - version "3.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.0.tgz#65df13579a5e53c12afb4f1c5309589e3855a5de" - integrity sha512-yjuY6rmVHRhcUKgXaSPNVloRueGWpFNhxR5EQLzxXfiFSl1U/+FBqHhbaGwtPPEgCSt61QNhZgiFjWT27bgAyw== +"@typescript-eslint/typescript-estree@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" + integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== dependencies: - "@typescript-eslint/types" "3.10.0" - "@typescript-eslint/visitor-keys" "3.10.0" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/visitor-keys" "3.10.1" debug "^4.1.1" glob "^7.1.6" is-glob "^4.0.1" @@ -399,10 +399,10 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@3.10.0": - version "3.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.0.tgz#6c0cac867e705a42e2c71b359bf6a10a88a28985" - integrity sha512-g4qftk8lWb/rHZe9uEp8oZSvsJhUvR2cfp7F7qE6DyUD2SsovEs8JDQTRP1xHzsD+pERsEpYNqkDgQXW6+ob5A== +"@typescript-eslint/visitor-keys@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" + integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== dependencies: eslint-visitor-keys "^1.1.0" @@ -1872,7 +1872,7 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -dayjs@^1.8.34: +dayjs@^1.8.33: version "1.8.34" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.34.tgz#d3ad33cc43d6b0f24cb8686b90aad2c653708069" integrity sha512-Olb+E6EoMvdPmAMq2QoucuyZycKHjTlBXmRx8Ada+wGtq4SIXuDCdtoaX4KkK0yjf1fJLnwXQURr8gQKWKaybw== @@ -5809,7 +5809,7 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.1.0: +prettier@^2.0.5: version "2.1.0" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.0.tgz#5a9789f767a243118c60f3e56d95cb6544914fbb" integrity sha512-lz28cCbA1cDFHVuY8vvj6QuqOwIpyIfPUYkSl8AZ/vxH8qBXMMjE2knfLHCrZCmUsK/H1bg1P0tOo0dJkTJHvw== @@ -7334,7 +7334,7 @@ trim-off-newlines@^1.0.0: dependencies: glob "^7.1.2" -ts-loader@^8.0.3: +ts-loader@^8.0.2: version "8.0.3" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.3.tgz#56858f4296edf1ed55e01f8520552984d3f0911c" integrity sha512-wsqfnVdB7xQiqhqbz2ZPLGHLPZbHVV5Qn/MNFZkCFxRU1miDyxKORucDGxKtsQJ63Rfza0udiUxWF5nHY6bpdQ==