Compare commits

...

183 Commits

Author SHA1 Message Date
Anthony Dresser
1f3e59c9f9 added default config for timeSeries since it is not the same (#1852) 2018-07-06 13:21:12 -07:00
Karl Burtram
1956078c8c Update config.json 2018-07-06 12:50:06 -07:00
Leila Lali
11230f59fc vbump sqlops version (#1862) 2018-07-06 09:43:06 -07:00
Karl Burtram
21bad7a01f Refresh agent dashboard panel after create\update\delete operations (#1861)
* Edit alert WIP

* A couple alert edit bugs

* Hook up dashboard refresh notification

* Hook onchange event to other agent service calls

* Switch update handler to scalar value

* Add null check on handler callback
2018-07-06 08:57:30 -07:00
Aditya Bist
6f9a27ecc7 Agent - UI changes (#1859)
* fixed regressions, added separator

* finished operator dialog UI
2018-07-05 20:31:54 -07:00
Matt Irvine
c504113d13 Update card layout to give more icon space (#1858) 2018-07-05 14:58:46 -07:00
Karl Burtram
c92ff60592 Update Agent extension package-lock.json (#1857)
* Update Agent extension package-lock.json

* Try removing the pacakge-lock file
2018-07-05 14:30:55 -07:00
Karl Burtram
e9013d1a2a Bump SQL Tools Service to 1.5.0-alpha.3 2018-07-05 13:34:27 -07:00
Matt Irvine
9c4580fe40 Add grouping feature for model view forms (#1853) 2018-07-05 11:36:29 -07:00
Anthony Dresser
cb060cb5db add row status on status bar for queries (#1841) 2018-07-05 10:43:24 -07:00
Karl Burtram
6c3d85cc45 New Operator, Alert and Proxy request handlers (#1846)
* Add agent dialog class

* Rename agent dialog data classes

* Alert dialog data updates

* Create operator and proxy handlers
2018-07-05 08:26:03 -07:00
Aditya Bist
14ae89e87c added common action bar with context based actions for all pages (#1842) 2018-07-03 20:32:04 -07:00
Karl Burtram
24c48f025d Add Delete Alert action implementation (#1840)
* Delete alert WIP 1

* Add agent delete methods

* Add Delete implementation for Jobs, Operators, and Proxies
2018-07-03 19:58:02 -07:00
Anthony Dresser
f0a556f004 add quote to string escape (#1838) 2018-07-03 16:37:44 -07:00
Karl Burtram
fd4d6abb4d Update CHANGELOG.md 2018-07-03 14:01:52 -07:00
Anthony Dresser
41cc839380 add themeing to profiler (#1826) 2018-07-03 13:34:20 -07:00
Karl Burtram
c2a4380b96 Rename Agent dialog classes to remove "Create" (#1837)
* Remove Create from agent dialog names

* Move actions class into common directory
2018-07-03 13:30:16 -07:00
Aditya Bist
6f402ac79f Agent : New Step dialog (#1834)
* added file browser tree to API and dialog

* added callbacks for selected files

* added file browser to step dialog

* remove commented code

* fixed file name bug
2018-07-03 13:07:02 -07:00
Karl Burtram
bf7c1306b1 Agent Tab panel visibility check base class (#1829)
* Agent Tab panel visibility check base class

* Add context menu to tab panel tables for Edit and Delete
2018-07-03 12:42:37 -07:00
Matt Irvine
c1509cf09d Update button icon when icon path changes (#1833) 2018-07-03 11:58:43 -07:00
Anthony Dresser
014bca031c add logic to clean up providers when appropriate (#1824) 2018-07-03 11:49:57 -07:00
Anthony Dresser
4f864fd5bd add escape formatting (#1825) 2018-07-03 11:49:17 -07:00
JASM2007
2da67567e4 Update mssql.JSON (#1803)
I modified lots of snippets to include the database name so that the user can additionally tab through the database name. I made some quality of life change for the user.  I normalized and standardized snippets to look more like one user created the file rather than each script taking on various flavors from the contributors. I tried to write the comments in the snippets in the same style at the majority of the snippets.  I added highlighting in key areas that were missing it or were not replacing the comments. Additionally there was no snippets for sqlCreateIndex and sqlCreateTempTable which I find standard for SQL users.  Let me know your thoughts! No trying to offend anyone if I changed your code.
2018-07-03 08:42:56 -07:00
Karl Burtram
5b19d2b1fc Fill out controls for Alert, Operator and Proxy dialogs (#1827)
* Clean up alert dialog

* Fill in controls for operator and proxy dialogs
2018-07-03 07:34:39 -07:00
Karl Burtram
a6837dcd40 Remove "client" folder in Agent extension (#1820)
* Remove "client" folder in Agent extension

* Alert dialog cleanups
2018-07-02 14:47:00 -07:00
Matt Irvine
af80751a1f Fix linked account error message typo (#1823) 2018-07-02 14:14:10 -07:00
Matt Irvine
dd02597c3b Fix display problems with model view icon components (#1822) 2018-07-02 14:03:22 -07:00
Matt Irvine
2926a3cbd8 Update query editor connection display when connecting via API (#1819) 2018-07-02 13:10:19 -07:00
Matt
b02bb3bfd4 Fixes implicit any type - issue #1814 (#1815) 2018-07-02 09:09:40 -07:00
Karl Burtram
67a4683bb1 Bump Agent and Profiler extension versions (#1812) 2018-06-30 23:02:00 -07:00
Peter Schneider
9baee1c22c Changed the stored procedure call to work on case sensitive instances (#1809) 2018-06-30 15:48:15 -07:00
Karl Burtram
8cb67b4f9d Add Alert, Operator and Proxy panel tabs (#1811)
* Add Create Alert dialog

* Add Job Alerts view

* Stage WIP

* Add Proxy View component

* Hook up proxy and operator view callbacks

* Style cleanup

* Add additonal columns to views
2018-06-30 15:31:40 -07:00
Matt Irvine
0cd47bc328 Fix webview editor height issue (#1808) 2018-06-29 19:13:22 -07:00
Kevin Cunnane
07fb58d5e1 Fixes #1804 Dashboard Home tab should be overrideable for other connection providers (#1805)
- Adds new isHomeTab property. If set, this indicates a tab should override the default home tab.
2018-06-29 18:49:56 -07:00
Anthony Dresser
2d80d5e611 Add connection info to title (#1645)
* add connection info to the file label

* formatting

* first attempt at title shortening

* add user to title shortening

* add settings to control connection info in title

* formatting

* move setting
2018-06-29 17:04:09 -07:00
Anthony Dresser
4bd63b615b fix table highlighting issues (#1802) 2018-06-29 17:03:01 -07:00
Kevin Cunnane
335f667507 Fix null ref error when no database or server node are in object tree (#1790)
- Also fixed minor issue where `var` was used instead of `let` in a related file, since this is discouraged in our codebase.
2018-06-29 16:49:46 -07:00
Madeline MacDonald
1819036d7d Profiler Keybindings (#1801)
* Added default new profiler keybinding. Exposed profiler.start and profiler.stop so they can be used with keybindings

* Changing where session state gets set

* Cleaning up unnecessary code
2018-06-29 16:34:40 -07:00
Kevin Cunnane
4f76f116ac Ensure dashboard tabs only show for supported providers (#1798)
- Fixes #1764, fixes #1765
- Fixes bug where configModifiers were passed in the dashboard service in some places, and a different object with incompatible / missing fields in a different one. Now it always passes in the owner object, and this should have the required fields
 - Note: this doesn't fix the problem where the code does not fail to build, which I would have expected to be the case.
- Adds "provider" as an option for TabConfig including in the schema
- Filter by "provider" type when loading tabs. If provider is not set for a tab, will assume "MSSQL" since it's the default provider. This is a design decision - without this, we would either have to disable tabs that don't show this or have them incorrectly show for non-MSSQL provider types

Notes:

Does not override behavior for individual widgets, which still get the current provider set as their provider if not specified. This seems to be required so should be fine.
We will fix tasks/widgets that aren't supported by a provider showing up in a separate PR, since it's a different issue
2018-06-29 16:04:57 -07:00
Matt Irvine
1eba7c7d2a Fix model view input box bugs (#1797) 2018-06-29 14:20:06 -07:00
Karl Burtram
83234dd52c Update SQL Tools Service to 1.5.0-alpha.1 2018-06-29 11:09:24 -07:00
Aditya Bist
bae23b7fce Agent: UI/UX finishes and clean up (#1768)
* changed columnw widths

* fixed scrolling for prev run job history list

* fixed all resizing and scrolling issues in agent

* removed commented code

* code review comments
2018-06-28 10:12:02 -07:00
Matt Irvine
3db61eaa82 Add sqlservices wizard sample (#1769) 2018-06-28 10:06:48 -07:00
Matt Irvine
5cf85a0361 Display page number, title, and description in wizard page headers (#1766) 2018-06-27 16:26:26 -07:00
Anthony Dresser
ffe27f5bde Tab outline in dashboard (#1742)
* add border to dashboard tabs

* formatting
2018-06-27 14:33:58 -07:00
Anthony Dresser
78bcd9d54c bump slickgrid (#1758) 2018-06-27 14:29:18 -07:00
Anthony Dresser
1a9797f0ff Change default settings to remove error (#1741)
* change default settings

* formatting
2018-06-27 13:59:36 -07:00
Karl Burtram
0de94ff8a4 Add "Schedule Picker" dialog (#1759)
* Merge master

* Add pick schedule dialog 1

* Add Pick Schedule button to create job dialog

* Cleanup Pick Schedule dialog

* Hook-up onClose event for Pick Schedule

* Code review feedback
2018-06-27 13:42:08 -07:00
Kevin Cunnane
472233d9a7 Providers without metadata service or serverInfo shouldn't break dashboard (#1761)
- Fix a number of issues that arose while testing a provider without a metadata service or serverInfo object returned via DMP calls. These should be optional services/features and we should be resilient to them not existing. In most places we already have these checks
- This does not cover a number of "improvement" scenarios, such as filtering extension tabs by provider, and defaulting any tabs that don't specify a provider to be MSSQL. This and some other features to ensure things make sense will be implemented in separate PRs but this unblocked the scenario
2018-06-27 13:40:37 -07:00
Aditya Bist
f69e31b0d5 Jobs/new step (#1734)
* added jobs view toolbar

* create job command and dialog stub

* add tab content and wire up the provider

* fix the steps tab error

* create job dialog 6/15 changes

* general tab done

* success action and retries completed

* added failure action dropdown

* add notification tab checkbox events

* added AgentJobStepInfo objects in sqlops

* create job dialog - 0618 update 1

* added model save function

* width for controls and initial state for notification tab controls

* refresh master and changes to work with latest code

* fixed next and prev button positions

* new step dialog ui finished

* implemented parse button

* fix package file

* add validation and sub-items collections

* hook up the step creation dialog - step 1

* merged master

* fixed step issue, step can me made now
2018-06-26 19:11:59 -07:00
Karl Burtram
60b696cc31 Fix casing for resourceprovider module require (#1731)
* Fix casing for resourceprovider module require

* Rename files to avoid build output recasing on macos
2018-06-26 18:37:31 -07:00
Leila Lali
549037f744 fixing model view issues (#1737)
* fixing model view issues
2018-06-26 16:40:41 -07:00
Karl Burtram
ca5e1e6133 Fix a couple references to VS Code in UI (#1730) 2018-06-26 15:30:11 -07:00
Aditya Bist
3e3ff163db Jobs - New step (WIP) (#1711)
* added jobs view toolbar

* create job command and dialog stub

* add tab content and wire up the provider

* fix the steps tab error

* create job dialog 6/15 changes

* general tab done

* success action and retries completed

* added failure action dropdown

* add notification tab checkbox events

* added AgentJobStepInfo objects in sqlops

* create job dialog - 0618 update 1

* added model save function

* width for controls and initial state for notification tab controls

* refresh master and changes to work with latest code

* fixed next and prev button positions

* new step dialog ui finished

* implemented parse button

* fix package file

* add validation and sub-items collections

* hook up the step creation dialog - step 1

* merged master
2018-06-26 11:09:41 -07:00
Matt Irvine
ca755365ce Fix dialog/wizard undefined connectionInfo bug (#1725) 2018-06-25 18:26:25 -07:00
Matt Irvine
ea979de19f Disable wizard/dialog next/done buttons when page not valid (#1708) 2018-06-25 12:25:48 -07:00
Anthony Dresser
473ddfcdf1 Modifying angular bootstrap to add injection at the module level (#1691)
* work on fixing injection

* change bootstrapping method

* add a catch for testing

* remove unneeded code
2018-06-22 16:09:13 -07:00
Leila Lali
a627285a4c Feature/selectable card component (#1703)
* added selectable card

* creating new card type
2018-06-22 14:25:21 -07:00
Alan Ren
322847469d fix dropdown component issue (#1709)
* fix dropdown component issue

* handle enable property default
2018-06-21 18:00:07 -07:00
Matt Irvine
6c5fac997f Add dialog close validation (#1704) 2018-06-21 16:55:47 -07:00
Leila Lali
1871fd383e Feature/form improvements (#1707)
* adding more options for form

* added form requied and info for item
2018-06-21 15:26:52 -07:00
Matt Irvine
f5b147ca4b Add info/warning/error messages for wizards and dialogs (#1696) 2018-06-21 11:55:23 -07:00
Anthony Dresser
9d2b206156 Accessibility enhancements (#1678)
* adds aria-label to inputs for connection

* formatting

* add ariaLabels to all checkboxes/inputboxes/dropdowns

* fix labels on database dropdown action

* fix compile errors

* remove unnecessary code
2018-06-20 16:56:19 -07:00
Karl Burtram
a372c76e07 Update SQL Ops to 0.31.1 for July iteration 2018-06-20 12:52:37 -07:00
Karl Burtram
b1ce07d3ae Add SQL CARBON EDIT tag in product class (#1690) 2018-06-20 12:42:32 -07:00
Karl Burtram
bc09fb30d8 Updaet readme for June release (#1684) 2018-06-19 22:27:32 -07:00
Leila Lali
c13f219318 form should not default to100% by default (#1679) 2018-06-19 14:12:04 -07:00
Madeline MacDonald
6b018c5d06 Profiler toolbar fixes + creating connections (#1677)
* Fixing button enabling, connection selection

* Fixing spacing
2018-06-19 13:54:47 -07:00
Anthony Dresser
e69158d9b2 Swallow error on context view when disposing children (#1663)
* swallow error on context view  when disposing children

* fix edit comment
2018-06-19 12:22:25 -07:00
Madeline MacDonald
520cfb780a Profiler notifications (#1648)
* adding lost events flag to events available notification

* Initial changes to support notifications for stopped session and lost events

* Updated localized strings & send stop notification box

* reordering imports

* vbump sqltools & dataprotocolclient, fix notification wording
2018-06-19 11:23:01 -07:00
Leila Lali
e686fed209 fixing the table, form dialog tab layout issues (#1671) 2018-06-19 10:55:23 -07:00
Karl Burtram
80ab19ac23 Add screenshot to Profiler extension readme (#1670)
* Add screenshot to Profiler extension readme

* Fix up the readme text a little
2018-06-19 10:09:34 -07:00
Matt Irvine
25228fa58e Fix edit data limit dropdown position (#1667) 2018-06-18 20:27:25 -04:00
Karl Burtram
676d35090f Fix Release Notes link to refer to correct location (#1665)
* Fix Release Notes link to refer to correct location

* Fix typo
2018-06-18 20:18:24 -04:00
Karl Burtram
e1a36a356c Add Profiler extension to recommended list (#1662) 2018-06-18 19:30:16 -04:00
Matt Irvine
3274c0b734 Make height and width optional for model view components (#1657) 2018-06-18 16:27:57 -07:00
Karl Burtram
9c95e1289f Bump SQL Ops to 0.30.6 2018-06-18 15:37:17 -07:00
Karl Burtram
ef29871b62 Pickup SQL Tools Service 1.4.0-alpha.45 (#1649) 2018-06-18 13:06:00 -07:00
Leila Lali
a2a87f8d2b fixed two layout issues in model view components (#1647) 2018-06-18 12:23:54 -07:00
Matt Irvine
83c01c6bcb Fix edit data revert row bugs (#1634)
* Clean up edit data revert behavior

* Unify escape and revert row edit data handling

* Revert unedited new row when clicking off of it

* Make delete work when adding new row
2018-06-18 12:17:16 -07:00
Aditya Bist
c1d850804c Agent: Added highlighting for jobs (#1588)
* added highlighting for jobs

* cleaner code with theme compatibility
2018-06-18 10:55:40 -07:00
Aditya Bist
6590d5f58a fixed refresh and removed unused imports (#1633) 2018-06-18 10:54:15 -07:00
Leila Lali
a225925bc4 fixed several model view issues (#1640)
* fixed several model view issues
2018-06-15 16:59:12 -07:00
Matt Irvine
ab39f1f44f Use theme color for model view button text (#1639) 2018-06-15 15:29:15 -07:00
Madeline MacDonald
8d89364d72 Displaying all event data (#1635)
* Displaying all event data

* Fixing viewing blank text panels and highlighting

* add aria-label for insights dialog (#1629)

* Displaying all event data

* Fixing viewing blank text panels and highlighting

* descriptive comments, removing redundant code
2018-06-15 14:16:42 -07:00
Madeline MacDonald
af2bc859d1 Profiler toolbar changes (#1615)
* Clear event view pane when starting new session

* Removing debug logging

* Handling pause button

* Cleaning up comments from previous commit

* Fixing comments from PR

* Fixing a comment I forgot to delete

* Bumping dataprotocolclient version

* Bumping sqltoolsservice & sqlops-dataprotocolclient version
2018-06-15 13:39:46 -07:00
Anthony Dresser
8e72fdaa52 add aria-label for insights dialog (#1629) 2018-06-14 15:40:57 -07:00
Matt Irvine
e9661f90d0 Prevent components from being defined multiple times (#1627) 2018-06-13 16:51:06 -07:00
Leila Lali
30b111034d added option to mode view input box to create the input as text area (#1630)
* added option to create input as multi line

* added min and max for input box
2018-06-13 16:32:34 -07:00
Leila Lali
df18359309 fixed the issue with disabling the select box (#1625) 2018-06-13 15:23:59 -07:00
Matt Irvine
03857e0afd Update SQL select box styler (#1619) 2018-06-12 17:38:02 -07:00
Matt Irvine
eaf1e08752 Fix bug where select box selection could not be changed by mouse (#1616) 2018-06-12 14:48:58 -07:00
Leila Lali
d39ceffa94 fixed the issue with displaying licenses (#1610) 2018-06-12 13:41:59 -07:00
Anthony Dresser
406b171c66 add a check for when the task is not valid (#1607) 2018-06-12 10:48:49 -07:00
Aditya Bist
6d89b9e203 Agent: Previous Runs chart functionality (#1564)
* added basic prev run chart functionality

* removed dead code

* resizing columns generates charts again
2018-06-12 09:28:40 -07:00
Karl Burtram
733bb69d25 Add Agent Service configuration request methods (#1608)
* WIP 1

* WIP 2

* Add Agent Service configuration request methods

* Fix typo

* Tabify sqlops.d.ts.
2018-06-11 16:32:18 -07:00
Leila Lali
4609694141 added Declarative table to model view controls (#1593)
* added Declarative table to model view controls
2018-06-11 12:40:17 -07:00
Anthony Dresser
3be0c5130a Fixes accessibility for grid (#1592)
* adds neccessary code to read cell value for table cells

* formatting
2018-06-11 12:06:06 -07:00
Abbie Petchtes
e50b512580 fix keyboard issues in editable dropdown (#1600) 2018-06-11 09:28:27 -07:00
Karl Burtram
eb62d054de Update package.json 2018-06-08 18:05:16 -07:00
Aditya Bist
e870a309c0 Agent: Filtering & Sorting (#1441)
* have a working filter

* fixed error details when filtering

* filtering with styling done

* fix transition styling

* fixed more styling issues

* optimized errors when switching pages

* added sorting functionality

* removed dead code

* fixed styling issues when sorting

* added sorting with styling for every column

* code review comments

* fixed styling issue when a bigger filter was applied, followed by a smaller one and then cleared

* use absolute paths in imports

* fixed issues with styling when sorting is performed on a filtered dataset
2018-06-08 17:08:01 -07:00
Leila Lali
3afd3b0ff3 fixed the compile error (#1601) 2018-06-08 15:47:29 -07:00
Matt Irvine
e3a2ed95d4 Add wizard navigation validator (#1587) 2018-06-08 15:32:37 -07:00
Matt Irvine
20c4f085c8 Fix custom UI validation bugs (#1583) 2018-06-08 15:32:21 -07:00
Leila Lali
02af7e9299 Feature/model view list (#1551)
* fixed the issue with drop down styling

* added list box to model view library
2018-06-08 13:51:02 -07:00
Abbie Petchtes
0ae9b36d93 fix colors issues in dashboard (#1591) 2018-06-08 11:55:31 -07:00
Matt Irvine
2bbb2842e5 Fix model view component updateProperties implementation (#1586) 2018-06-08 09:41:00 -07:00
Matt Irvine
a5b4eeb932 Add loading spinner component (#1580) 2018-06-07 17:54:48 -07:00
Anthony Dresser
44de602e52 readd check on start up for tabs (#1585) 2018-06-07 17:20:28 -07:00
Anthony Dresser
63fb4e2827 Bootstrap Service Abstract injection (#1534)
* change to generic injection

* formatting

* fixed missed merge

* change to keep a record of the services per selector

* formatting

* adding back in tests

* apply back tests

* remove fundamentally broken test
2018-06-07 16:19:26 -07:00
Anthony Dresser
0a839c7321 Agent layout fixes (#1559)
* added layout to agent

* formatting

* formatting
2018-06-07 14:57:50 -07:00
Anthony Dresser
e9747a61ac fix error if close insight before laoded (#1557) 2018-06-07 09:23:52 -07:00
Anthony Dresser
43c3bf4d24 Fix dashboard refresh (#1556)
* better handling of selecting the first ab

* formatting
2018-06-07 09:23:38 -07:00
Matt Irvine
0bf642d200 Update sqlservices example for new webview messages API (#1569) 2018-06-06 17:29:50 -07:00
Abbie Petchtes
b2b69376c4 address comments on support button icon (#1568)
* support icon button

* formatting

* fix dropdown css and set attribute for model view editor

* address comments

* fixing conflict
2018-06-06 14:15:11 -07:00
Abbie Petchtes
38ad60478c Support icon for button.component (#1565)
* support icon button

* formatting

* fix dropdown css and set attribute for model view editor
2018-06-06 14:05:36 -07:00
Matt Irvine
cf6a7198f9 Fix error when calling layout on single-tab dialog (#1552) 2018-06-05 16:07:36 -07:00
Anthony Dresser
ac8a926a70 added progress indication for database navigation in dashboard (#1529) 2018-06-05 11:38:00 -07:00
Anthony Dresser
aef7244939 add more specific label for dropdown (#1544) 2018-06-05 11:36:19 -07:00
Anthony Dresser
628e2adc64 change role of query buttons to button (#1543) 2018-06-05 11:35:59 -07:00
Matt Irvine
0c58f09e59 Merge VS Code 1.23.1 (#1520) 2018-06-05 11:24:51 -07:00
Abbie Petchtes
e3baf5c443 Fix model view editor where switching between different type of editors remove the dom (#1546)
* fix model view editor where switching between different type of editors destroy the dom

* address comments
2018-06-04 14:41:17 -07:00
Leila Lali
f70bf590cd fixed the layout issue in model view containers (#1548)
* fixed the layout issue in model view containers

* fixed the sample
2018-06-04 14:25:41 -07:00
Leila Lali
473a414bc3 added table componenet (#1542) 2018-06-04 12:04:05 -07:00
Abbie Petchtes
9ad4ec6464 Support view model toolbar (#1533)
* support view model toolbar

* add EULA

* formatting

* address comment
2018-06-04 10:11:32 -07:00
Aditya Bist
a15c315a1c updated version after insider build release (#1538) 2018-06-01 15:42:24 -07:00
Anthony Dresser
58036bb364 Mssql edition context (#1537)
* added sql server edition context

* formatting

* change context key to engine edition
2018-06-01 14:43:15 -07:00
Aditya Bist
8a3509e006 removed discontinued red bar from error detail (#1521) 2018-05-31 13:17:46 -07:00
Aditya Bist
1d3ead4031 fixed crash because of extra detect changes call (#1519) 2018-05-31 12:04:49 -07:00
Anthony Dresser
498bb47d7f Add progress indicator for dashboard scripting (#1511)
* add progress indicator for dashboard scripting

* formatting
2018-05-31 12:04:00 -07:00
Lance Klinger
f2df9f3917 Fix for double clicking column handle in results table where the column width would not update correctly when the longest row item is the top item in the viewPort (#1504) 2018-05-31 12:03:33 -07:00
Madeline MacDonald
0414ab6e6a Fixing launching new profiler from object explorer (#1514) 2018-05-30 16:39:11 -07:00
Matt Irvine
14a7a5534f Add API for extensions to get data protocol providers (#1518) 2018-05-30 16:37:11 -07:00
Karl Burtram
edc60e0ad1 Fix nullref exception showing query plan panel (#1516) 2018-05-30 14:30:14 -07:00
Abbie Petchtes
1a97e3de06 fix webview component css and add webview example (#1517) 2018-05-30 13:48:08 -07:00
Leila Lali
f5b1bd0bc2 fixed the issue with tab layout inside the dialog pane (#1515) 2018-05-30 13:02:19 -07:00
Aditya Bist
05d7e24e66 Agent UI fixes (#1510)
* added ellipses for long job names

* fixed resizing crash in jobs history page

* added some more ui fixes

* changed minWidths to widths

* code review comments
2018-05-30 10:53:36 -07:00
Leila Lali
83842ee9e1 fixed the path to fix the linux build error (#1512) 2018-05-30 09:53:30 -07:00
Leila Lali
a13039b14b added group container (#1508) 2018-05-29 13:08:13 -07:00
Leila Lali
8fce79f385 fixed the selector name for model view components (#1488) 2018-05-24 15:20:24 -07:00
Matt Irvine
2efea63000 Bump version to 0.30.3 2018-05-24 14:30:02 -07:00
Abbie Petchtes
c208abf0c5 Fix view model editor and webview component (#1483)
* destroy viewmodel when editor is closed and add example

* support retainContextWhenHidden option for webview component

* fix breaking change from master

* dispose html element during dispose

* add more comments
2018-05-24 13:54:41 -07:00
Anthony Dresser
1359354387 Angular Individual Service Injection - Decouple bootstrap service (#1457)
* change services to be individually injected into angular

* messing around with injection

* change angular bootstrapping to factory style

* formatting

* formatting

* fix imports

* fix build errors

* fix testsw

* fix tests

* fix compile errors
2018-05-23 16:51:02 -07:00
Abbie Petchtes
cd0f9b71c5 Fix view model editor layout (#1473)
* flex container should be as big as the parent container

* add example
2018-05-23 11:20:28 -07:00
Anthony Dresser
04ec9caad1 Remove Jquery references (#1461)
* modify key codes

* formatting

* change string event type

* code clean up
2018-05-23 10:59:28 -07:00
Leila Lali
259306a8db fixed the issue with setting form's width (#1472) 2018-05-23 10:23:03 -07:00
Abbie Petchtes
36a8991682 Feature/webview for model view (#1463)
* support webview for view model

* formatting

* remove unused imports
2018-05-23 09:51:44 -07:00
Leila Lali
1461929f86 added text component (#1462)
* added text component
2018-05-22 16:12:02 -07:00
Leila Lali
4bfc549927 model view drop down now support editable and not editable list (#1460)
* model view drop down now support editable and not editable list
2018-05-22 13:12:53 -07:00
Matt Irvine
40db0d6f6f Only allow model view components to be added once (#1458) 2018-05-22 13:06:00 -07:00
Karl Burtram
6aac0b6056 Initial Profiler extension scaffolding (#1451)
* Copy agent to profiler extension

* A few mote edits
2018-05-21 16:40:22 -07:00
Matt Irvine
8e234d9b2d Enable basic wizard API (#1450) 2018-05-21 15:19:21 -07:00
Abbie Petchtes
70819252a9 Add support for model view editor (#1442)
* Add proposed API for model view editors

* Initial working model view editor

* Add extension demo

* Revert "Add extension demo"

This reverts commit 10d3b720ad347919dd5668a339da8e96e26b2b82.

* view model editor and add the support for register content

* clean up the code

* fix editor issues where you register more than one content

* formating

* remove unused imports

* addressed comments

* address comments2

* address comment3
2018-05-21 12:46:13 -07:00
Leila Lali
ba264d8311 added radio button model view component (#1439)
* added radio button model view component
2018-05-21 11:45:27 -07:00
Karl Burtram
5de002e5c1 Change VS Code to SQL Ops Studio in screen reader dialog (#1448) 2018-05-21 10:45:39 -07:00
Karl Burtram
0b771abad2 Bump SQL Tools to 1.4.0-alpha.35 (#1447) 2018-05-18 16:27:04 -07:00
Anthony Dresser
00041c8ecd nump slickgrid (#1428) 2018-05-18 13:52:38 -07:00
Anthony Dresser
0225d6d9f9 adds tab accessibility (#1433) 2018-05-18 13:52:22 -07:00
Matt Irvine
fb4260d71c Bump tools service for recent fixes (#1434) 2018-05-17 09:55:01 -07:00
Karl Burtram
fa253158f4 Update SQL Ops to 0.30.2 (#1437) 2018-05-16 18:28:28 -07:00
Leila Lali
45e3c6ae49 added register content method to dialog and tab (#1415)
* added register content method to dialog and tab
2018-05-16 09:09:41 -07:00
Matt Irvine
d526fe0f7f Fire model view close event when destroyed (#1427) 2018-05-15 17:35:31 -07:00
Kevin Cunnane
5707b58fda Make Webview support (#1429)
This is needed to enable testing of webview-based experiences.

This was made an official API in the latest VSCode release, so on next merge this will be standard anyhow.
2018-05-15 16:37:52 -07:00
Matt Irvine
1a9f72dfe0 Rearrange done and cancel buttons and dispose dialogs correctly (#1420) 2018-05-15 15:39:27 -07:00
Karl Burtram
078f3a2b54 Add BETWEEN and REVERT to keyword colorization list (#1421) 2018-05-15 12:05:59 -07:00
Kevin Cunnane
5bcfb9ab32 Minor fix: callback data can be anything, shouldn't restrict to string (#1404) 2018-05-14 17:20:56 -07:00
Matt Irvine
9bd45cf66a Add default model view input types and validation (#1397) 2018-05-14 16:20:19 -07:00
Cory Rivera
89c48bbe75 Add option for using generic SQL queries to filter EditData rows via a query editor pane. (#1329) 2018-05-14 12:27:55 -07:00
Abbie Petchtes
6b549696c5 Bug/keyboard issue in manange linked account (#1400)
* add message and add account button when the linked account is empty

* fix account dialog tests

* address comment
2018-05-14 11:25:13 -07:00
Matt Irvine
3aaf8a24bf Fix form layout spacing (#1401) 2018-05-14 11:06:50 -07:00
Kevin Cunnane
41ffd6e8ae Add action list to cards with callback (#1392)
- Add the ActionDescriptor functionality. This is a table of information with actionable links
- Also add optional status indicator which shows a color. In the future, would like to extend to have icon in this space as an alternative.
- Fixed 1 issue with account management UI throwing an error on cancel
2018-05-11 10:59:42 -07:00
Abbie Petchtes
c0a6f3e012 fix theming issue in table widget (#1391) 2018-05-11 09:52:58 -07:00
Abbie Petchtes
eae8de0373 Add grid.viewAsChart and grid.goToNextGrid keyboard shortcuts for editor (#1390)
* adding shortcuts for view as chart and go to next grid

* small fix

* refactor query output functions out of gridParentComponents

* Revert "refactor query output functions out of gridParentComponents"

This reverts commit 51addcac76d2a21df150a8d95f54f061aab6ac7a.
2018-05-11 09:38:14 -07:00
Anthony Dresser
23ec6ac567 Change angular panel display behavior (#1344)
* got it working

* remove unneeded code

* formatting

* added scrollable, dashboard tabs don't scroll correctly though

* fix all bugs I could find

* address comments
2018-05-10 09:27:41 -07:00
Matt Irvine
f4cfb4a5ef Fire done/cancel click events when dialog is closed (#1379) 2018-05-09 13:17:02 -07:00
Abbie Petchtes
80a9c82813 Fix high contrast issues in task viewlet and panel (#1381)
* fix high contrast issues in task and panel

* change the panelTitle.inactiveForeground color in light theme

* remove opacity when the panel is active and inactive
2018-05-09 12:32:03 -07:00
Leila Lali
bcd6178d67 added properties to inputbox and form to be able to change style fro… (#1371)
* added properties to inputbox and form to be able to change style from extension
* moved registerModelViewProvider from dashboard to ui namespace
2018-05-09 10:58:23 -07:00
Matt Irvine
f10e281ffc Add validation to model view components (#1356) 2018-05-08 14:15:26 -07:00
Karl Burtram
c2b32fd64a Bump SQL Ops to 0.30.1 (#1369) 2018-05-08 13:02:14 -07:00
Karl Burtram
80f150dfb4 Update README for May release (#1359) 2018-05-07 09:27:38 -07:00
Aditya Bist
a5c5fcbde1 fixed tabbing for jobs history page (#1353) 2018-05-05 11:10:44 -07:00
Abbie Petchtes
0d76e845d5 update server reports extension screenshot (#1354) 2018-05-04 15:09:20 -07:00
Abbie Petchtes
979d50eb0e Add left nav bar for server reports extension (#1345)
* add left nav bar for server reports extension

* change monitor icon

* change performance icons
2018-05-04 14:57:01 -07:00
3907 changed files with 93941 additions and 52809 deletions

9
.gitattributes vendored Normal file
View File

@@ -0,0 +1,9 @@
* text=auto
LICENSE.txt eol=crlf
ThirdPartyNotices.txt eol=crlf
*.bat eol=crlf
*.cmd eol=crlf
*.ps1 eol=lf
*.sh eol=lf

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@ node_modules/
out/
out-build/
out-editor/
out-editor-esm/
out-editor-min/
out-monaco-editor-core/
out-vscode/

View File

@@ -32,8 +32,6 @@ addons:
before_install:
- git submodule update --init --recursive
- git clone --depth 1 https://github.com/creationix/nvm.git ./.nvm
- source ./.nvm/nvm.sh
- nvm install 8.9.1
- nvm use 8.9.1
- npm i -g yarn

View File

@@ -1,9 +1,9 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// See https://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"eg2.tslint",
"dbaeumer.vscode-eslint",
"msjsdiag.debugger-for-chrome"
]
}
}

View File

@@ -38,5 +38,6 @@
}
}
],
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.tsdk": "node_modules/typescript/lib",
"git.ignoreLimitWarning": true
}

View File

@@ -1,5 +1,33 @@
# Change Log
## Version 0.30.6
* Release date: June 20, 2018
* Release status: Public Preview
## What's new in this version
* **SQL Server Profiler for SQL Operations Studio *Preview*** extension initial release
* The new **SQL Data Warehouse** extension includes rich customizable dashboard widgets surfacing insights to your data warehouse. This unlocks key scenarios around managing and tuning your data warehouse to ensure it is optimized for consistent performance.
* **Edit Data "Filtering and Sorting"** support
* **SQL Server Agent for SQL Operations Studio *Preview*** extension enhancements for Jobs and Job History views
* Improved **Wizard & Dialog UI Builder Framework** extensibility APIs
* Update VS Code Platform source code integrating [March 2018 (1.22)](https://code.visualstudio.com/updates/v1_22) and [April 2018 (1.23)](https://code.visualstudio.com/updates/v1_23) releases
* Fix GitHub Issues
## Version 0.29.3
* Release date: May 7, 2018
* Release status: Public Preview
## What's new in this version
The May release is focused on stabilization and bug fixes leading up to the Build conference. This build contains the following highlights.
* Announcing **Redgate SQL Search** extension available in Extension Manager
* Community Localization available for 10 languages: **German, Spanish, French, Italian, Japanese, Korean, Portuguese, Russian, Simplified Chinese and Traditional Chinese!**
* Reduced telemetry collection, improved [opt-out](https://github.com/Microsoft/sqlopsstudio/wiki/How-to-Disable-Telemetry-Reporting) experience and in-product links to [Privacy Statement](https://privacy.microsoft.com/en-us/privacystatement)
* Extension Manager has improved Marketplace experience to easily discover community extensions
* SQL Agent extension Jobs and Job History view improvement
* Updates for **whoisactive** and **Server Reports** extensions
* Continue to fix GitHub issues
## Version 0.28.6
* Release date: April 25, 2018
* Release status: Public Preview

View File

@@ -4,11 +4,11 @@ MICROSOFT SQL OPERATIONS STUDIO
Microsoft Corporation ("Microsoft") grants you a nonexclusive, perpetual,
royalty-free right to use, copy, and modify the software code provided by us
("Software Code"). You may not sublicense the Software Code or any use of it
(except to your affiliates and to vendors to perform work on your behalf)
through distribution, network access, service agreement, lease, rental, or
otherwise. Unless applicable law gives you more rights, Microsoft reserves all
other rights not expressly granted herein, whether by implication, estoppel or
("Software Code"). You may not sublicense the Software Code or any use of it
(except to your affiliates and to vendors to perform work on your behalf)
through distribution, network access, service agreement, lease, rental, or
otherwise. Unless applicable law gives you more rights, Microsoft reserves all
other rights not expressly granted herein, whether by implication, estoppel or
otherwise.
THE SOFTWARE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY

View File

@@ -808,5 +808,389 @@
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
"SOFTWARE"
]
},
{
"name": "mdn-data",
"version": "1.1.12",
"repositoryURL": "https://github.com/mdn/data",
"license": "MPL",
"licenseDetail": [
"Mozilla Public License Version 2.0",
"",
"Copyright (c) 2018 Mozilla Corporation",
"",
"==================================",
"",
"1. Definitions",
"--------------",
"",
"1.1. \"Contributor\"",
" means each individual or legal entity that creates, contributes to",
" the creation of, or owns Covered Software.",
"",
"1.2. \"Contributor Version\"",
" means the combination of the Contributions of others (if any) used",
" by a Contributor and that particular Contributor's Contribution.",
"",
"1.3. \"Contribution\"",
" means Covered Software of a particular Contributor.",
"",
"1.4. \"Covered Software\"",
" means Source Code Form to which the initial Contributor has attached",
" the notice in Exhibit A, the Executable Form of such Source Code",
" Form, and Modifications of such Source Code Form, in each case",
" including portions thereof.",
"",
"1.5. \"Incompatible With Secondary Licenses\"",
" means",
"",
" (a) that the initial Contributor has attached the notice described",
" in Exhibit B to the Covered Software; or",
"",
" (b) that the Covered Software was made available under the terms of",
" version 1.1 or earlier of the License, but not also under the",
" terms of a Secondary License.",
"",
"1.6. \"Executable Form\"",
" means any form of the work other than Source Code Form.",
"",
"1.7. \"Larger Work\"",
" means a work that combines Covered Software with other material, in",
" a separate file or files, that is not Covered Software.",
"",
"1.8. \"License\"",
" means this document.",
"",
"1.9. \"Licensable\"",
" means having the right to grant, to the maximum extent possible,",
" whether at the time of the initial grant or subsequently, any and",
" all of the rights conveyed by this License.",
"",
"1.10. \"Modifications\"",
" means any of the following:",
"",
" (a) any file in Source Code Form that results from an addition to,",
" deletion from, or modification of the contents of Covered",
" Software; or",
"",
" (b) any new file in Source Code Form that contains any Covered",
" Software.",
"",
"1.11. \"Patent Claims\" of a Contributor",
" means any patent claim(s), including without limitation, method,",
" process, and apparatus claims, in any patent Licensable by such",
" Contributor that would be infringed, but for the grant of the",
" License, by the making, using, selling, offering for sale, having",
" made, import, or transfer of either its Contributions or its",
" Contributor Version.",
"",
"1.12. \"Secondary License\"",
" means either the GNU General Public License, Version 2.0, the GNU",
" Lesser General Public License, Version 2.1, the GNU Affero General",
" Public License, Version 3.0, or any later versions of those",
" licenses.",
"",
"1.13. \"Source Code Form\"",
" means the form of the work preferred for making modifications.",
"",
"1.14. \"You\" (or \"Your\")",
" means an individual or a legal entity exercising rights under this",
" License. For legal entities, \"You\" includes any entity that",
" controls, is controlled by, or is under common control with You. For",
" purposes of this definition, \"control\" means (a) the power, direct",
" or indirect, to cause the direction or management of such entity,",
" whether by contract or otherwise, or (b) ownership of more than",
" fifty percent (50%) of the outstanding shares or beneficial",
" ownership of such entity.",
"",
"2. License Grants and Conditions",
"--------------------------------",
"",
"2.1. Grants",
"",
"Each Contributor hereby grants You a world-wide, royalty-free,",
"non-exclusive license:",
"",
"(a) under intellectual property rights (other than patent or trademark)",
" Licensable by such Contributor to use, reproduce, make available,",
" modify, display, perform, distribute, and otherwise exploit its",
" Contributions, either on an unmodified basis, with Modifications, or",
" as part of a Larger Work; and",
"",
"(b) under Patent Claims of such Contributor to make, use, sell, offer",
" for sale, have made, import, and otherwise transfer either its",
" Contributions or its Contributor Version.",
"",
"2.2. Effective Date",
"",
"The licenses granted in Section 2.1 with respect to any Contribution",
"become effective for each Contribution on the date the Contributor first",
"distributes such Contribution.",
"",
"2.3. Limitations on Grant Scope",
"",
"The licenses granted in this Section 2 are the only rights granted under",
"this License. No additional rights or licenses will be implied from the",
"distribution or licensing of Covered Software under this License.",
"Notwithstanding Section 2.1(b) above, no patent license is granted by a",
"Contributor:",
"",
"(a) for any code that a Contributor has removed from Covered Software;",
" or",
"",
"(b) for infringements caused by: (i) Your and any other third party's",
" modifications of Covered Software, or (ii) the combination of its",
" Contributions with other software (except as part of its Contributor",
" Version); or",
"",
"(c) under Patent Claims infringed by Covered Software in the absence of",
" its Contributions.",
"",
"This License does not grant any rights in the trademarks, service marks,",
"or logos of any Contributor (except as may be necessary to comply with",
"the notice requirements in Section 3.4).",
"",
"2.4. Subsequent Licenses",
"",
"No Contributor makes additional grants as a result of Your choice to",
"distribute the Covered Software under a subsequent version of this",
"License (see Section 10.2) or under the terms of a Secondary License (if",
"permitted under the terms of Section 3.3).",
"",
"2.5. Representation",
"",
"Each Contributor represents that the Contributor believes its",
"Contributions are its original creation(s) or it has sufficient rights",
"to grant the rights to its Contributions conveyed by this License.",
"",
"2.6. Fair Use",
"",
"This License is not intended to limit any rights You have under",
"applicable copyright doctrines of fair use, fair dealing, or other",
"equivalents.",
"",
"2.7. Conditions",
"",
"Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted",
"in Section 2.1.",
"",
"3. Responsibilities",
"-------------------",
"",
"3.1. Distribution of Source Form",
"",
"All distribution of Covered Software in Source Code Form, including any",
"Modifications that You create or to which You contribute, must be under",
"the terms of this License. You must inform recipients that the Source",
"Code Form of the Covered Software is governed by the terms of this",
"License, and how they can obtain a copy of this License. You may not",
"attempt to alter or restrict the recipients' rights in the Source Code",
"Form.",
"",
"3.2. Distribution of Executable Form",
"",
"If You distribute Covered Software in Executable Form then:",
"",
"(a) such Covered Software must also be made available in Source Code",
" Form, as described in Section 3.1, and You must inform recipients of",
" the Executable Form how they can obtain a copy of such Source Code",
" Form by reasonable means in a timely manner, at a charge no more",
" than the cost of distribution to the recipient; and",
"",
"(b) You may distribute such Executable Form under the terms of this",
" License, or sublicense it under different terms, provided that the",
" license for the Executable Form does not attempt to limit or alter",
" the recipients' rights in the Source Code Form under this License.",
"",
"3.3. Distribution of a Larger Work",
"",
"You may create and distribute a Larger Work under terms of Your choice,",
"provided that You also comply with the requirements of this License for",
"the Covered Software. If the Larger Work is a combination of Covered",
"Software with a work governed by one or more Secondary Licenses, and the",
"Covered Software is not Incompatible With Secondary Licenses, this",
"License permits You to additionally distribute such Covered Software",
"under the terms of such Secondary License(s), so that the recipient of",
"the Larger Work may, at their option, further distribute the Covered",
"Software under the terms of either this License or such Secondary",
"License(s).",
"",
"3.4. Notices",
"",
"You may not remove or alter the substance of any license notices",
"(including copyright notices, patent notices, disclaimers of warranty,",
"or limitations of liability) contained within the Source Code Form of",
"the Covered Software, except that You may alter any license notices to",
"the extent required to remedy known factual inaccuracies.",
"",
"3.5. Application of Additional Terms",
"",
"You may choose to offer, and to charge a fee for, warranty, support,",
"indemnity or liability obligations to one or more recipients of Covered",
"Software. However, You may do so only on Your own behalf, and not on",
"behalf of any Contributor. You must make it absolutely clear that any",
"such warranty, support, indemnity, or liability obligation is offered by",
"You alone, and You hereby agree to indemnify every Contributor for any",
"liability incurred by such Contributor as a result of warranty, support,",
"indemnity or liability terms You offer. You may include additional",
"disclaimers of warranty and limitations of liability specific to any",
"jurisdiction.",
"",
"4. Inability to Comply Due to Statute or Regulation",
"---------------------------------------------------",
"",
"If it is impossible for You to comply with any of the terms of this",
"License with respect to some or all of the Covered Software due to",
"statute, judicial order, or regulation then You must: (a) comply with",
"the terms of this License to the maximum extent possible; and (b)",
"describe the limitations and the code they affect. Such description must",
"be placed in a text file included with all distributions of the Covered",
"Software under this License. Except to the extent prohibited by statute",
"or regulation, such description must be sufficiently detailed for a",
"recipient of ordinary skill to be able to understand it.",
"",
"5. Termination",
"--------------",
"",
"5.1. The rights granted under this License will terminate automatically",
"if You fail to comply with any of its terms. However, if You become",
"compliant, then the rights granted under this License from a particular",
"Contributor are reinstated (a) provisionally, unless and until such",
"Contributor explicitly and finally terminates Your grants, and (b) on an",
"ongoing basis, if such Contributor fails to notify You of the",
"non-compliance by some reasonable means prior to 60 days after You have",
"come back into compliance. Moreover, Your grants from a particular",
"Contributor are reinstated on an ongoing basis if such Contributor",
"notifies You of the non-compliance by some reasonable means, this is the",
"first time You have received notice of non-compliance with this License",
"from such Contributor, and You become compliant prior to 30 days after",
"Your receipt of the notice.",
"",
"5.2. If You initiate litigation against any entity by asserting a patent",
"infringement claim (excluding declaratory judgment actions,",
"counter-claims, and cross-claims) alleging that a Contributor Version",
"directly or indirectly infringes any patent, then the rights granted to",
"You by any and all Contributors for the Covered Software under Section",
"2.1 of this License shall terminate.",
"",
"5.3. In the event of termination under Sections 5.1 or 5.2 above, all",
"end user license agreements (excluding distributors and resellers) which",
"have been validly granted by You or Your distributors under this License",
"prior to termination shall survive termination.",
"",
"************************************************************************",
"* *",
"* 6. Disclaimer of Warranty *",
"* ------------------------- *",
"* *",
"* Covered Software is provided under this License on an \"as is\" *",
"* basis, without warranty of any kind, either expressed, implied, or *",
"* statutory, including, without limitation, warranties that the *",
"* Covered Software is free of defects, merchantable, fit for a *",
"* particular purpose or non-infringing. The entire risk as to the *",
"* quality and performance of the Covered Software is with You. *",
"* Should any Covered Software prove defective in any respect, You *",
"* (not any Contributor) assume the cost of any necessary servicing, *",
"* repair, or correction. This disclaimer of warranty constitutes an *",
"* essential part of this License. No use of any Covered Software is *",
"* authorized under this License except under this disclaimer. *",
"* *",
"************************************************************************",
"",
"************************************************************************",
"* *",
"* 7. Limitation of Liability *",
"* -------------------------- *",
"* *",
"* Under no circumstances and under no legal theory, whether tort *",
"* (including negligence), contract, or otherwise, shall any *",
"* Contributor, or anyone who distributes Covered Software as *",
"* permitted above, be liable to You for any direct, indirect, *",
"* special, incidental, or consequential damages of any character *",
"* including, without limitation, damages for lost profits, loss of *",
"* goodwill, work stoppage, computer failure or malfunction, or any *",
"* and all other commercial damages or losses, even if such party *",
"* shall have been informed of the possibility of such damages. This *",
"* limitation of liability shall not apply to liability for death or *",
"* personal injury resulting from such party's negligence to the *",
"* extent applicable law prohibits such limitation. Some *",
"* jurisdictions do not allow the exclusion or limitation of *",
"* incidental or consequential damages, so this exclusion and *",
"* limitation may not apply to You. *",
"* *",
"************************************************************************",
"",
"8. Litigation",
"-------------",
"",
"Any litigation relating to this License may be brought only in the",
"courts of a jurisdiction where the defendant maintains its principal",
"place of business and such litigation shall be governed by laws of that",
"jurisdiction, without reference to its conflict-of-law provisions.",
"Nothing in this Section shall prevent a party's ability to bring",
"cross-claims or counter-claims.",
"",
"9. Miscellaneous",
"----------------",
"",
"This License represents the complete agreement concerning the subject",
"matter hereof. If any provision of this License is held to be",
"unenforceable, such provision shall be reformed only to the extent",
"necessary to make it enforceable. Any law or regulation which provides",
"that the language of a contract shall be construed against the drafter",
"shall not be used to construe this License against a Contributor.",
"",
"10. Versions of the License",
"---------------------------",
"",
"10.1. New Versions",
"",
"Mozilla Foundation is the license steward. Except as provided in Section",
"10.3, no one other than the license steward has the right to modify or",
"publish new versions of this License. Each version will be given a",
"distinguishing version number.",
"",
"10.2. Effect of New Versions",
"",
"You may distribute the Covered Software under the terms of the version",
"of the License under which You originally received the Covered Software,",
"or under the terms of any subsequent version published by the license",
"steward.",
"",
"10.3. Modified Versions",
"",
"If you create software not governed by this License, and you want to",
"create a new license for such software, you may create and use a",
"modified version of this License if you rename the license and remove",
"any references to the name of the license steward (except to note that",
"such modified license differs from this License).",
"",
"10.4. Distributing Source Code Form that is Incompatible With Secondary",
"Licenses",
"",
"If You choose to distribute Source Code Form that is Incompatible With",
"Secondary Licenses under the terms of this version of the License, the",
"notice described in Exhibit B of this License must be attached.",
"",
"Exhibit A - Source Code Form License Notice",
"-------------------------------------------",
"",
" This Source Code Form is subject to the terms of the Mozilla Public",
" License, v. 2.0. If a copy of the MPL was not distributed with this",
" file, You can obtain one at http://mozilla.org/MPL/2.0/.",
"",
"If it is not possible or desirable to put the notice in a particular",
"file, then You may include the notice in a location (such as a LICENSE",
"file in a relevant directory) where a recipient would be likely to look",
"for such a notice.",
"",
"You may add additional accurate notices of copyright ownership.",
"",
"Exhibit B - \"Incompatible With Secondary Licenses\" Notice",
"---------------------------------------------------------",
"",
" This Source Code Form is \"Incompatible With Secondary Licenses\", as",
" defined by the Mozilla Public License, v. 2.0."
]
}
]

View File

@@ -4,16 +4,16 @@
SQL Operations Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
**Download SQL Operations Studio March Public Preview**
**Download SQL Operations Studio June Public Preview**
Platform | Link
-- | --
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=872717
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=872718
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=872719
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=872720
Linux DEB | https://go.microsoft.com/fwlink/?linkid=872722
Linux RPM | https://go.microsoft.com/fwlink/?linkid=872721
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=875602
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=875603
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=875604
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=875605
Linux RPM | https://go.microsoft.com/fwlink/?linkid=875606
Linux DEB | https://go.microsoft.com/fwlink/?linkid=875607
Go to our [download page](https://aka.ms/sqlopsstudio) for more specific instructions.
@@ -61,6 +61,7 @@ The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.micro
## Contributions and "thank you"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* lanceklinger `Fix for double clicking column handle in results table #1504`
* westerncj for `Removed duplicate contribution from README.md (#753)`
* ntovas for `Fix for duplicate extensions shown in "Save File" dialog. (#779)`
* SebastianPfliegel for `Add cursor snippet (#475)`
@@ -74,7 +75,18 @@ We would like to thank all our users who raised issues, and in particular the fo
* SebastianPfliegel `Remove sqlExtensionHelp (#312)`
* olljanat for `Implemented npm version check (#314)`
* Adam Mechanic for helping with the `whoisactive` extension
* All community localization contributors *(will get list of individuals next month)*
* All community localization contributors
* French: Adrien Clerbois, ANAS BELABBES, Antoine Griffard, Arian Papillon, Eric Macarez, Eric Van Thorre, Jérémy LANDON, Matthias GROSPERRIN, Maxime COQUEREL, Olivier Guinart, thierry DEMAN-BARCELÒ, Thomas Potier
* Italian: Aldo Donetti, Alessandro Alpi, Andrea Dottor, Bruni Luca, Gianluca Hotz, Luca Nardi, Luigi Bruno, Marco Dal Pino, Mirco Vanini, Pasquale Ceglie, Riccardo Cappello, Sergio Govoni, Stefano Demiliani
* German: Anna Henke-Gunvaldson, Ben Weissman, David Ullmer, J.M. ., Kai Modo, Konstantin Staschill, Kostja Klein, Lennart Trunk, Markus Ehrenmüller-Jensen, Mascha Kroenlein, Matthias Knoll, Mourad Louha, Thomas Hütter, Wolfgang Straßer
* Spanish: Alberto Poblacion, Andy Gonzalez, Carlos Mendible, Christian Araujo, Daniel D, Eickhel Mendoza, Ernesto Cardenas, Ivan Toledo Ivanovic, Fran Diaz, JESUS GIL, Jorge Serrano Pérez, José Saturnino Pimentel Juárez, Mauricio Hidalgo, Pablo Iglesias, Rikhardo Estrada Rdez, Thierry DEMAN, YOLANDA CUESTA ALTIERI
* Japanese: Fujio Kojima, Kazushi KAMEGAWA, Masayoshi Yamada, Masayuki Ozawa , Seiji Momoto, Takashi Kanai, Takayoshi Tanaka, Yoshihisa Ozaki, 庄垣内治
* Chinese (simplified): DAN YE, Joel Yang, Lynne Dong, RyanYu Zhang, Sheng Jiang, Wei Zhang, Zhiliang Xu
* Chinese (Traditional): Bruce Chen, Chiayi Yen, Kevin Yang, Winnie Lin, 保哥 Will, 謝政廷
* Korean: Do-Kyun Kim, Evelyn Kim, Helen Jung, Hong Jmee, jeongwoo choi, Jun Hyoung Lee, Jungsun Kim정선, Justin Yoo, Kavrith mucha, Kiwoong Youm, MinGyu Ju, MVP_JUNO BEA, Sejun Kim, SOONMAN KWON, sung man ko, Yeongrak Choi, younggun kim, Youngjae Kim, 소영 이
* Russian: Andrey Veselov, Anton Fontanov, Anton Savin, Elena Ostrovskaia, Igor Babichev, Maxim Zelensky, Rodion Fedechkin, Tasha T, Vladimir Zyryanov
* Portuguese Brazil: Daniel de Sousa, Diogo Duarte, Douglas Correa, Douglas Eccker, José Emanuel Mendes, Marcelo Fernandes, Marcondes Alexandre, Roberto Fonseca, Rodrigo Crespi
And of course we'd like to thank the authors of all upstream dependencies. Please see a full list in the [ThirdPartyNotices.txt](https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/ThirdPartyNotices.txt)

View File

@@ -11,7 +11,6 @@ install:
build_script:
- yarn
- .\node_modules\.bin\gulp electron
- .\node_modules\.bin\tsc -p .\src\tsconfig.monaco.json --noEmit
- npm run compile
test_script:

View File

@@ -1,12 +1,12 @@
[
{
"name": "ms-vscode.node-debug",
"version": "1.21.8",
"version": "1.23.3",
"repo": "https://github.com/Microsoft/vscode-node-debug"
},
{
"name": "ms-vscode.node-debug2",
"version": "1.21.2",
"version": "1.23.5",
"repo": "https://github.com/Microsoft/vscode-node-debug2"
}
]
]

View File

@@ -3,12 +3,15 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var gulp = require('gulp');
var path = require('path');
var util = require('./lib/util');
var common = require('./lib/optimize');
var es = require('event-stream');
var File = require('vinyl');
const gulp = require('gulp');
const path = require('path');
const util = require('./lib/util');
const common = require('./lib/optimize');
const es = require('event-stream');
const File = require('vinyl');
const i18n = require('./lib/i18n');
const standalone = require('./lib/standalone');
const cp = require('child_process');
var root = path.dirname(__dirname);
var sha1 = util.getVersion(root);
@@ -71,6 +74,8 @@ function editorLoaderConfig() {
return result;
}
const languages = i18n.defaultLanguages.concat([]); // i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages : []);
gulp.task('clean-optimized-editor', util.rimraf('out-editor'));
gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-client-build'], common.optimizeTask({
entryPoints: editorEntryPoints,
@@ -81,14 +86,36 @@ gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-client-build'],
header: BUNDLED_FILE_HEADER,
bundleInfo: true,
out: 'out-editor',
languages: undefined
languages: languages
}));
gulp.task('clean-minified-editor', util.rimraf('out-editor-min'));
gulp.task('minify-editor', ['clean-minified-editor', 'optimize-editor'], common.minifyTask('out-editor'));
gulp.task('clean-editor-esm', util.rimraf('out-editor-esm'));
gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro'], function () {
standalone.createESMSourcesAndResources({
entryPoints: [
'vs/editor/editor.main',
'vs/editor/editor.worker'
],
outFolder: './out-editor-esm/src',
outResourcesFolder: './out-monaco-editor-core/esm',
redirects: {
'vs/base/browser/ui/octiconLabel/octiconLabel': 'vs/base/browser/ui/octiconLabel/octiconLabel.mock',
'vs/nls': 'vs/nls.mock',
}
});
});
gulp.task('compile-editor-esm', ['extract-editor-esm', 'clean-editor-distro'], function () {
const result = cp.spawnSync(`node`, [`../node_modules/.bin/tsc`], {
cwd: path.join(__dirname, '../out-editor-esm')
});
console.log(result.stdout.toString());
});
gulp.task('clean-editor-distro', util.rimraf('out-monaco-editor-core'));
gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-editor'], function () {
gulp.task('editor-distro', ['clean-editor-distro', 'compile-editor-esm', 'minify-editor', 'optimize-editor'], function () {
return es.merge(
// other assets
es.merge(
@@ -97,6 +124,17 @@ gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-ed
gulp.src('src/vs/monaco.d.ts')
).pipe(gulp.dest('out-monaco-editor-core')),
// place the .d.ts in the esm folder
gulp.src('src/vs/monaco.d.ts')
.pipe(es.through(function (data) {
this.emit('data', new File({
path: data.path.replace(/monaco\.d\.ts/, 'editor.api.d.ts'),
base: data.base,
contents: data.contents
}));
}))
.pipe(gulp.dest('out-monaco-editor-core/esm/vs/editor')),
// package.json
gulp.src('build/monaco/package.json')
.pipe(es.through(function (data) {
@@ -208,3 +246,60 @@ function filterStream(testFunc) {
this.emit('data', data);
});
}
//#region monaco type checking
function createTscCompileTask(watch) {
return () => {
const createReporter = require('./lib/reporter').createReporter;
return new Promise((resolve, reject) => {
const args = ['./node_modules/.bin/tsc', '-p', './src/tsconfig.monaco.json', '--noEmit'];
if (watch) {
args.push('-w');
}
const child = cp.spawn(`node`, args, {
cwd: path.join(__dirname, '..'),
// stdio: [null, 'pipe', 'inherit']
});
let errors = [];
let reporter = createReporter();
let report;
let magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings
child.stdout.on('data', data => {
let str = String(data);
str = str.replace(magic, '').trim();
if (str.indexOf('Starting compilation') >= 0 || str.indexOf('File change detected') >= 0) {
errors.length = 0;
report = reporter.end(false);
} else if (str.indexOf('Compilation complete') >= 0) {
report.end();
} else if (str) {
let match = /(.*\(\d+,\d+\): )(.*: )(.*)/.exec(str);
if (match) {
// trying to massage the message so that it matches the gulp-tsb error messages
// e.g. src/vs/base/common/strings.ts(663,5): error TS2322: Type '1234' is not assignable to type 'string'.
let fullpath = path.join(root, match[1]);
let message = match[3];
// @ts-ignore
reporter(fullpath + message);
} else {
// @ts-ignore
reporter(str);
}
}
});
child.on('exit', resolve);
child.on('error', reject);
});
};
}
gulp.task('monaco-typecheck-watch', createTscCompileTask(true));
gulp.task('monaco-typecheck', createTscCompileTask(false));
//#endregion

View File

@@ -21,6 +21,7 @@ const nlsDev = require('vscode-nls-dev');
const root = path.dirname(__dirname);
const commit = util.getVersion(root);
const i18n = require('./lib/i18n');
const plumber = require('gulp-plumber');
const extensionsPath = path.join(path.dirname(__dirname), 'extensions');
@@ -82,6 +83,13 @@ const tasks = compilations.map(function (tsconfigFile) {
const input = es.through();
const tsFilter = filter(['**/*.ts', '!**/lib/lib*.d.ts', '!**/node_modules/**'], { restore: true });
const output = input
.pipe(plumber({
errorHandler: function (err) {
if (err && !err.__reporter__) {
reporter(err);
}
}
}))
.pipe(tsFilter)
.pipe(util.loadSourcemaps())
.pipe(compilation())

View File

@@ -46,10 +46,9 @@ const indentationFilter = [
'!src/vs/nls.js',
'!src/vs/css.js',
'!src/vs/loader.js',
'!src/vs/base/common/marked/raw.marked.js',
'!src/vs/base/common/winjs.base.raw.js',
'!src/vs/base/common/marked/marked.js',
'!src/vs/base/common/winjs.base.js',
'!src/vs/base/node/terminateProcess.sh',
'!src/vs/base/node/ps-win.ps1',
'!test/assert.js',
// except specific folders
@@ -62,6 +61,7 @@ const indentationFilter = [
// except multiple specific files
'!**/package.json',
'!**/yarn.lock',
'!**/yarn-error.log',
// except multiple specific folders
'!**/octicons/**',
@@ -104,8 +104,9 @@ const copyrightFilter = [
'!build/**/*.init',
'!resources/linux/snap/snapcraft.yaml',
'!resources/win32/bin/code.js',
'!extensions/markdown/media/tomorrow.css',
'!extensions/html/server/src/modes/typescript/*'
'!extensions/markdown-language-features/media/tomorrow.css',
'!extensions/html-language-features/server/src/modes/typescript/*',
'!extensions/*/server/bin/*'
];
const eslintFilter = [
@@ -116,8 +117,8 @@ const eslintFilter = [
'!src/vs/nls.js',
'!src/vs/css.build.js',
'!src/vs/nls.build.js',
'!src/**/winjs.base.raw.js',
'!src/**/raw.marked.js',
'!src/**/winjs.base.js',
'!src/**/marked.js',
'!**/test/**'
];
@@ -132,15 +133,15 @@ const tslintFilter = [
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!extensions/**/*.test.ts',
'!extensions/html/server/lib/jquery.d.ts'
'!extensions/html-language-features/server/lib/jquery.d.ts'
];
const copyrightHeader = [
const copyrightHeaderLines = [
'/*---------------------------------------------------------------------------------------------',
' * Copyright (c) Microsoft Corporation. All rights reserved.',
' * Licensed under the Source EULA. See License.txt in the project root for license information.',
' *--------------------------------------------------------------------------------------------*/'
].join('\n');
];
gulp.task('eslint', () => {
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
@@ -202,12 +203,17 @@ function hygiene(some) {
tsfmt.processString(file.path, file.contents.toString('utf8'), {
verify: false,
tsfmt: true,
// verbose: true
// verbose: true,
// keep checkJS happy
editorconfig: undefined,
replace: undefined,
tsconfig: undefined,
tslint: undefined
tsconfigFile: undefined,
tslint: undefined,
tslintFile: undefined,
tsfmtFile: undefined,
vscode: undefined,
vscodeFile: undefined
}).then(result => {
let original = result.src.replace(/\r\n/gm, '\n');
let formatted = result.dest.replace(/\r\n/gm, '\n');

View File

@@ -77,7 +77,8 @@ const vsce = require('vsce');
const sqlBuiltInExtensions = [
// Add SQL built-in extensions here.
// the extension will be excluded from SQLOps package and will have separate vsix packages
'agent'
'agent',
'profiler'
];
const vscodeEntryPoints = _.flatten([
@@ -90,18 +91,19 @@ const vscodeEntryPoints = _.flatten([
const vscodeResources = [
'out-build/main.js',
'out-build/cli.js',
'out-build/driver.js',
'out-build/bootstrap.js',
'out-build/bootstrap-amd.js',
'out-build/paths.js',
'out-build/vs/**/*.{svg,png,cur,html}',
'out-build/vs/base/common/performance.js',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,ps-win.ps1}',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh}',
'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
'out-build/vs/workbench/browser/media/*-theme.css',
'out-build/vs/workbench/electron-browser/bootstrap/**',
'out-build/vs/workbench/parts/debug/**/*.json',
'out-build/vs/workbench/parts/execution/**/*.scpt',
'out-build/vs/workbench/parts/html/browser/webview-pre.js',
'out-build/vs/workbench/parts/webview/electron-browser/webview-pre.js',
'out-build/vs/**/markdown.css',
'out-build/vs/workbench/parts/tasks/**/*.json',
'out-build/vs/workbench/parts/terminal/electron-browser/terminalProcess.js',
@@ -110,6 +112,7 @@ const vscodeResources = [
'out-build/vs/workbench/services/files/**/*.md',
'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js',
'out-build/vs/code/electron-browser/issue/issueReporter.js',
'out-build/vs/code/electron-browser/processExplorer/processExplorer.js',
// {{SQL CARBON EDIT}}
'out-build/sql/workbench/electron-browser/splashscreen/*',
'out-build/sql/**/*.{svg,png,cur,html}',
@@ -347,7 +350,7 @@ function packageTask(platform, arch, opts) {
const packageJsonStream = gulp.src(['package.json'], { base: '.' })
.pipe(json({ name, version }));
const settingsSearchBuildId = getBuildNumber();
const settingsSearchBuildId = getSettingsSearchBuildId(packageJson);
const date = new Date().toISOString();
const productJsonStream = gulp.src(['product.json'], { base: '.' })
.pipe(json({ commit, date, checksums, settingsSearchBuildId }));
@@ -389,6 +392,7 @@ function packageTask(platform, arch, opts) {
.pipe(util.cleanNodeModule('core-js', ['**/**'], undefined))
.pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined))
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
.pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']))
.pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar'));
@@ -578,14 +582,12 @@ gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () =
}
if (!fs.existsSync(allConfigDetailsPath)) {
console.error(`configuration file at ${allConfigDetailsPath} does not exist`);
return;
throw new Error(`configuration file at ${allConfigDetailsPath} does not exist`);
}
const settingsSearchBuildId = getBuildNumber();
const settingsSearchBuildId = getSettingsSearchBuildId(packageJson);
if (!settingsSearchBuildId) {
console.error('Failed to compute build number');
return;
throw new Error('Failed to compute build number');
}
return gulp.src(allConfigDetailsPath)
@@ -597,76 +599,18 @@ gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () =
}));
});
function getBuildNumber() {
const previous = getPreviousVersion(packageJson.version);
if (!previous) {
return 0;
}
function getSettingsSearchBuildId(packageJson) {
const previous = util.getPreviousVersion(packageJson.version);
try {
const out = cp.execSync(`git rev-list ${previous}..HEAD --count`);
const count = parseInt(out.toString());
return versionStringToNumber(packageJson.version) * 1e4 + count;
return util.versionStringToNumber(packageJson.version) * 1e4 + count;
} catch (e) {
console.error('Could not determine build number: ' + e.toString());
return 0;
throw new Error('Could not determine build number: ' + e.toString());
}
}
/**
* Given 1.17.2, return 1.17.1
* 1.18.0 => 1.17.2.
* 2.0.0 => 1.18.0 (or the highest 1.x)
*/
function getPreviousVersion(versionStr) {
function tagExists(tagName) {
try {
cp.execSync(`git rev-parse ${tagName}`, { stdio: 'ignore' });
return true;
} catch (e) {
return false;
}
}
function getLastTagFromBase(semverArr, componentToTest) {
const baseVersion = semverArr.join('.');
if (!tagExists(baseVersion)) {
console.error('Failed to find tag for base version, ' + baseVersion);
return null;
}
let goodTag;
do {
goodTag = semverArr.join('.');
semverArr[componentToTest]++;
} while (tagExists(semverArr.join('.')));
return goodTag;
}
const semverArr = versionStr.split('.');
if (semverArr[2] > 0) {
semverArr[2]--;
return semverArr.join('.');
} else if (semverArr[1] > 0) {
semverArr[1]--;
return getLastTagFromBase(semverArr, 2);
} else {
semverArr[0]--;
return getLastTagFromBase(semverArr, 1);
}
}
function versionStringToNumber(versionStr) {
const semverRegex = /(\d+)\.(\d+)\.(\d+)/;
const match = versionStr.match(semverRegex);
if (!match) {
return 0;
}
return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10);
}
// This task is only run for the MacOS build
gulp.task('generate-vscode-configuration', () => {
return new Promise((resolve, reject) => {
@@ -698,9 +642,6 @@ gulp.task('generate-vscode-configuration', () => {
clearTimeout(timer);
reject(err);
});
}).catch(e => {
// Don't fail the build
console.error(e.toString());
});
});

View File

@@ -21,29 +21,6 @@ const rpmDependencies = require('../resources/linux/rpm/dependencies.json');
const linuxPackageRevision = Math.floor(new Date().getTime() / 1000);
const flatpakManifest = {
appId: product.darwinBundleIdentifier, // We need a reverse-url style identifier.
sdk: 'org.freedesktop.Sdk',
runtime: 'org.freedesktop.Sdk',
runtimeVersion: '1.4',
base: 'io.atom.electron.BaseApp',
baseFlatpakref: 'https://s3-us-west-2.amazonaws.com/electron-flatpak.endlessm.com/electron-base-app-master.flatpakref',
command: product.applicationName,
symlinks: [
['/share/' + product.applicationName + '/bin/' + product.applicationName, '/bin/' + product.applicationName],
],
finishArgs: [
'--share=ipc', '--socket=x11', // Allow showing X11 windows.
'--share=network', // Network access (e.g. for installing extension).
'--filesystem=host', // Allow access to the whole file system.
'--device=dri', // Allow OpenGL rendering.
'--filesystem=/tmp', // Needed for Chromium's single instance check.
'--socket=pulseaudio', // Some extensions may want to play sounds...
'--talk-name=org.freedesktop.Notifications', // ...or pop up notifications.
],
};
function getDebPackageArch(arch) {
return { x64: 'amd64', ia32: 'i386', arm: 'armhf' }[arch];
}
@@ -336,10 +313,3 @@ gulp.task('vscode-linux-arm-prepare-snap', ['clean-vscode-linux-arm-snap'], prep
gulp.task('vscode-linux-ia32-build-snap', ['vscode-linux-ia32-prepare-snap'], buildSnapPackage('ia32'));
gulp.task('vscode-linux-x64-build-snap', ['vscode-linux-x64-prepare-snap'], buildSnapPackage('x64'));
gulp.task('vscode-linux-arm-build-snap', ['vscode-linux-arm-prepare-snap'], buildSnapPackage('arm'));
gulp.task('vscode-linux-ia32-prepare-flatpak', ['clean-vscode-linux-ia32-flatpak'], prepareFlatpak('ia32'));
gulp.task('vscode-linux-x64-prepare-flatpak', ['clean-vscode-linux-x64-flatpak'], prepareFlatpak('x64'));
gulp.task('vscode-linux-arm-prepare-flatpak', ['clean-vscode-linux-arm-flatpak'], prepareFlatpak('arm'));
gulp.task('vscode-linux-ia32-flatpak', ['vscode-linux-ia32-prepare-flatpak'], buildFlatpak('ia32'));
gulp.task('vscode-linux-x64-flatpak', ['vscode-linux-x64-prepare-flatpak'], buildFlatpak('x64'));
gulp.task('vscode-linux-arm-flatpak', ['vscode-linux-arm-prepare-flatpak'], buildFlatpak('arm'));

View File

@@ -22,11 +22,12 @@ var rootDir = path.join(__dirname, '../../src');
var options = require('../../src/tsconfig.json').compilerOptions;
options.verbose = false;
options.sourceMap = true;
if (process.env['VSCODE_NO_SOURCEMAP']) {
if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry
options.sourceMap = false;
}
options.rootDir = rootDir;
options.sourceRoot = util.toFileUri(rootDir);
options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 'CRLF' : 'LF';
function createCompile(build, emitError) {
var opts = _.clone(options);
opts.inlineSources = !!build;

View File

@@ -30,6 +30,7 @@ if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry
}
options.rootDir = rootDir;
options.sourceRoot = util.toFileUri(rootDir);
options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 'CRLF' : 'LF';
function createCompile(build: boolean, emitError?: boolean): (token?: util.ICancellationToken) => NodeJS.ReadWriteStream {
const opts = _.clone(options);

View File

@@ -37,9 +37,8 @@ exports.defaultLanguages = [
// languages requested by the community to non-stable builds
exports.extraLanguages = [
{ id: 'pt-br', folderName: 'ptb' },
// {{SQL CARBON EDIT}}
// { id: 'hu', folderName: 'hun' },
// { id: 'tr', folderName: 'trk' }
{ id: 'hu', folderName: 'hun' },
{ id: 'tr', folderName: 'trk' }
];
// non built-in extensions also that are transifex and need to be part of the language packs
var externalExtensionsWithTranslations = {
@@ -528,6 +527,7 @@ function getResource(sourceFile) {
else if (/^vs\/workbench/.test(sourceFile)) {
return { name: 'vs/workbench', project: workbenchProject };
}
// {{SQL CARBON EDIT}}
else if (/^sql/.test(sourceFile)) {
return { name: 'sql', project: sqlopsProject };
}
@@ -1052,7 +1052,10 @@ function createI18nFile(originalFilePath, messages) {
var key = _a[_i];
result[key] = messages[key];
}
var content = JSON.stringify(result, null, '\t').replace(/\r\n/g, '\n');
var content = JSON.stringify(result, null, '\t');
if (process.platform === 'win32') {
content = content.replace(/\n/g, '\r\n');
}
return new File({
path: path.join(originalFilePath + '.i18n.json'),
contents: Buffer.from(content, 'utf8')
@@ -1086,7 +1089,7 @@ function prepareI18nPackFiles(externalExtensions, resultingTranslationPaths, pse
extPack = extensionsPacks[resource] = { version: i18nPackVersion, contents: {} };
}
var externalId = externalExtensions[resource];
if (!externalId) {
if (!externalId) { // internal extension: remove 'extensions/extensionId/' segnent
var secondSlash = path.indexOf('/', firstSlash + 1);
extPack.contents[path.substr(secondSlash + 1)] = file.messages;
}

View File

@@ -130,10 +130,18 @@
"name": "vs/workbench/parts/update",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/url",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/watermark",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/webview",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/welcome",
"project": "vscode-workbench"
@@ -146,6 +154,10 @@
"name": "vs/workbench/services/configuration",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/configurationResolver",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/crashReporter",
"project": "vscode-workbench"
@@ -201,6 +213,10 @@
{
"name": "vs/workbench/services/decorations",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/preferences",
"project": "vscode-preferences"
}
]
}

View File

@@ -1179,7 +1179,10 @@ function createI18nFile(originalFilePath: string, messages: any): File {
result[key] = messages[key];
}
let content = JSON.stringify(result, null, '\t').replace(/\r\n/g, '\n');
let content = JSON.stringify(result, null, '\t');
if (process.platform === 'win32') {
content = content.replace(/\n/g, '\r\n');
}
return new File({
path: path.join(originalFilePath + '.i18n.json'),
contents: Buffer.from(content, 'utf8')

View File

@@ -150,13 +150,16 @@ function isImportNode(node) {
.filter(function (d) { return d.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport; })
.map(function (d) { return d.importClause.namedBindings.name; })
.concat(importEqualsDeclarations.map(function (d) { return d.name; }))
// find read-only references to `nls`
.map(function (n) { return service.getReferencesAtPosition(filename, n.pos + 1); })
.flatten()
.filter(function (r) { return !r.isWriteAccess; })
// find the deepest call expressions AST nodes that contain those references
.map(function (r) { return collect(sourceFile, function (n) { return isCallExpressionWithinTextSpanCollectStep(r.textSpan, n); }); })
.map(function (a) { return lazy(a).last(); })
.filter(function (n) { return !!n; })
.map(function (n) { return n; })
// only `localize` calls
.filter(function (n) { return n.expression.kind === ts.SyntaxKind.PropertyAccessExpression && n.expression.name.getText() === 'localize'; });
// `localize` named imports
var allLocalizeImportDeclarations = importDeclarations

View File

@@ -34,7 +34,13 @@ catch (err) {
}
function log() {
var errors = _.flatten(allErrors);
errors.map(function (err) { return util.log(util.colors.red('Error') + ": " + err); });
var seen = new Set();
errors.map(function (err) {
if (!seen.has(err)) {
seen.add(err);
util.log(util.colors.red('Error') + ": " + err);
}
});
var regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/;
var messages = errors
.map(function (err) { return regex.exec(err); })
@@ -67,8 +73,13 @@ function createReporter() {
return es.through(null, function () {
onEnd();
if (emitError && errors.length > 0) {
log();
this.emit('error');
errors.__logged__ = true;
if (!errors.__logged__) {
log();
}
var err = new Error("Found " + errors.length + " errors");
err.__reporter__ = true;
this.emit('error', err);
}
else {
this.emit('end');
@@ -80,4 +91,3 @@ function createReporter() {
return ReportFunc;
}
exports.createReporter = createReporter;
;

View File

@@ -11,7 +11,7 @@ import * as util from 'gulp-util';
import * as fs from 'fs';
import * as path from 'path';
const allErrors: Error[][] = [];
const allErrors: string[][] = [];
let startTime: number = null;
let count = 0;
@@ -42,7 +42,14 @@ try {
function log(): void {
const errors = _.flatten(allErrors);
errors.map(err => util.log(`${util.colors.red('Error')}: ${err}`));
const seen = new Set<string>();
errors.map(err => {
if (!seen.has(err)) {
seen.add(err);
util.log(`${util.colors.red('Error')}: ${err}`);
}
});
const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/;
const messages = errors
@@ -61,17 +68,17 @@ function log(): void {
}
export interface IReporter {
(err: Error): void;
(err: string): void;
hasErrors(): boolean;
end(emitError: boolean): NodeJS.ReadWriteStream;
}
export function createReporter(): IReporter {
const errors: Error[] = [];
const errors: string[] = [];
allErrors.push(errors);
class ReportFunc {
constructor(err: Error) {
constructor(err: string) {
errors.push(err);
}
@@ -87,8 +94,15 @@ export function createReporter(): IReporter {
onEnd();
if (emitError && errors.length > 0) {
log();
this.emit('error');
(errors as any).__logged__ = true;
if (!(errors as any).__logged__) {
log();
}
const err = new Error(`Found ${errors.length} errors`);
(err as any).__reporter__ = true;
this.emit('error', err);
} else {
this.emit('end');
}
@@ -97,4 +111,4 @@ export function createReporter(): IReporter {
}
return <IReporter><any>ReportFunc;
};
}

265
build/lib/standalone.js Normal file
View File

@@ -0,0 +1,265 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript");
var fs = require("fs");
var path = require("path");
var REPO_ROOT = path.join(__dirname, '../../');
var SRC_DIR = path.join(REPO_ROOT, 'src');
var OUT_EDITOR = path.join(REPO_ROOT, 'out-editor');
function createESMSourcesAndResources(options) {
var OUT_FOLDER = path.join(REPO_ROOT, options.outFolder);
var OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder);
var in_queue = Object.create(null);
var queue = [];
var enqueue = function (module) {
if (in_queue[module]) {
return;
}
in_queue[module] = true;
queue.push(module);
};
var seenDir = {};
var createDirectoryRecursive = function (dir) {
if (seenDir[dir]) {
return;
}
var lastSlash = dir.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = dir.lastIndexOf('\\');
}
if (lastSlash !== -1) {
createDirectoryRecursive(dir.substring(0, lastSlash));
}
seenDir[dir] = true;
try {
fs.mkdirSync(dir);
}
catch (err) { }
};
seenDir[REPO_ROOT] = true;
var toggleComments = function (fileContents) {
var lines = fileContents.split(/\r\n|\r|\n/);
var mode = 0;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (mode === 0) {
if (/\/\/ ESM-comment-begin/.test(line)) {
mode = 1;
continue;
}
if (/\/\/ ESM-uncomment-begin/.test(line)) {
mode = 2;
continue;
}
continue;
}
if (mode === 1) {
if (/\/\/ ESM-comment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = '// ' + line;
continue;
}
if (mode === 2) {
if (/\/\/ ESM-uncomment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) {
return indent;
});
}
}
return lines.join('\n');
};
var write = function (filePath, contents) {
var absoluteFilePath;
if (/\.ts$/.test(filePath)) {
absoluteFilePath = path.join(OUT_FOLDER, filePath);
}
else {
absoluteFilePath = path.join(OUT_RESOURCES_FOLDER, filePath);
}
createDirectoryRecursive(path.dirname(absoluteFilePath));
if (/(\.ts$)|(\.js$)/.test(filePath)) {
contents = toggleComments(contents.toString());
}
fs.writeFileSync(absoluteFilePath, contents);
};
options.entryPoints.forEach(function (entryPoint) { return enqueue(entryPoint); });
while (queue.length > 0) {
var module_1 = queue.shift();
if (transportCSS(options, module_1, enqueue, write)) {
continue;
}
if (transportResource(options, module_1, enqueue, write)) {
continue;
}
if (transportDTS(options, module_1, enqueue, write)) {
continue;
}
var filename = void 0;
if (options.redirects[module_1]) {
filename = path.join(SRC_DIR, options.redirects[module_1] + '.ts');
}
else {
filename = path.join(SRC_DIR, module_1 + '.ts');
}
var fileContents = fs.readFileSync(filename).toString();
var info = ts.preProcessFile(fileContents);
for (var i = info.importedFiles.length - 1; i >= 0; i--) {
var importedFilename = info.importedFiles[i].fileName;
var pos = info.importedFiles[i].pos;
var end = info.importedFiles[i].end;
var importedFilepath = void 0;
if (/^vs\/css!/.test(importedFilename)) {
importedFilepath = importedFilename.substr('vs/css!'.length) + '.css';
}
else {
importedFilepath = importedFilename;
}
if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) {
importedFilepath = path.join(path.dirname(module_1), importedFilepath);
}
enqueue(importedFilepath);
var relativePath = void 0;
if (importedFilepath === path.dirname(module_1)) {
relativePath = '../' + path.basename(path.dirname(module_1));
}
else if (importedFilepath === path.dirname(path.dirname(module_1))) {
relativePath = '../../' + path.basename(path.dirname(path.dirname(module_1)));
}
else {
relativePath = path.relative(path.dirname(module_1), importedFilepath);
}
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}
fileContents = (fileContents.substring(0, pos + 1)
+ relativePath
+ fileContents.substring(end + 1));
}
fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) {
return "import * as " + m1 + " from " + m2 + ";";
});
fileContents = fileContents.replace(/Thenable/g, 'PromiseLike');
write(module_1 + '.ts', fileContents);
}
var esm_opts = {
"compilerOptions": {
"outDir": path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER),
"rootDir": "src",
"module": "es6",
"target": "es5",
"experimentalDecorators": true,
"lib": [
"dom",
"es5",
"es2015.collection",
"es2015.promise"
],
"types": []
}
};
fs.writeFileSync(path.join(path.dirname(OUT_FOLDER), 'tsconfig.json'), JSON.stringify(esm_opts, null, '\t'));
var monacodts = fs.readFileSync(path.join(SRC_DIR, 'vs/monaco.d.ts')).toString();
fs.writeFileSync(path.join(OUT_FOLDER, 'vs/monaco.d.ts'), monacodts);
}
exports.createESMSourcesAndResources = createESMSourcesAndResources;
function transportCSS(options, module, enqueue, write) {
if (!/\.css/.test(module)) {
return false;
}
var filename = path.join(SRC_DIR, module);
var fileContents = fs.readFileSync(filename).toString();
var inlineResources = 'base64'; // see https://github.com/Microsoft/monaco-editor/issues/148
var inlineResourcesLimit = 300000; //3000; // see https://github.com/Microsoft/monaco-editor/issues/336
var newContents = _rewriteOrInlineUrls(filename, fileContents, inlineResources === 'base64', inlineResourcesLimit);
write(module, newContents);
return true;
function _rewriteOrInlineUrls(originalFileFSPath, contents, forceBase64, inlineByteLimit) {
return _replaceURL(contents, function (url) {
var imagePath = path.join(path.dirname(module), url);
var fileContents = fs.readFileSync(path.join(SRC_DIR, imagePath));
if (fileContents.length < inlineByteLimit) {
var MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png';
var DATA = ';base64,' + fileContents.toString('base64');
if (!forceBase64 && /\.svg$/.test(url)) {
// .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris
var newText = fileContents.toString()
.replace(/"/g, '\'')
.replace(/</g, '%3C')
.replace(/>/g, '%3E')
.replace(/&/g, '%26')
.replace(/#/g, '%23')
.replace(/\s+/g, ' ');
var encodedData = ',' + newText;
if (encodedData.length < DATA.length) {
DATA = encodedData;
}
}
return '"data:' + MIME + DATA + '"';
}
enqueue(imagePath);
return url;
});
}
function _replaceURL(contents, replacer) {
// Use ")" as the terminator as quotes are oftentimes not used at all
return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, function (_) {
var matches = [];
for (var _i = 1; _i < arguments.length; _i++) {
matches[_i - 1] = arguments[_i];
}
var url = matches[0];
// Eliminate starting quotes (the initial whitespace is not captured)
if (url.charAt(0) === '"' || url.charAt(0) === '\'') {
url = url.substring(1);
}
// The ending whitespace is captured
while (url.length > 0 && (url.charAt(url.length - 1) === ' ' || url.charAt(url.length - 1) === '\t')) {
url = url.substring(0, url.length - 1);
}
// Eliminate ending quotes
if (url.charAt(url.length - 1) === '"' || url.charAt(url.length - 1) === '\'') {
url = url.substring(0, url.length - 1);
}
if (!_startsWith(url, 'data:') && !_startsWith(url, 'http://') && !_startsWith(url, 'https://')) {
url = replacer(url);
}
return 'url(' + url + ')';
});
}
function _startsWith(haystack, needle) {
return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle;
}
}
function transportResource(options, module, enqueue, write) {
if (!/\.svg/.test(module)) {
return false;
}
write(module, fs.readFileSync(path.join(SRC_DIR, module)));
return true;
}
function transportDTS(options, module, enqueue, write) {
if (options.redirects[module] && fs.existsSync(path.join(SRC_DIR, options.redirects[module] + '.ts'))) {
return false;
}
if (!fs.existsSync(path.join(SRC_DIR, module + '.d.ts'))) {
return false;
}
write(module + '.d.ts', fs.readFileSync(path.join(SRC_DIR, module + '.d.ts')));
var filename;
if (options.redirects[module]) {
write(module + '.js', fs.readFileSync(path.join(SRC_DIR, options.redirects[module] + '.js')));
}
else {
write(module + '.js', fs.readFileSync(path.join(SRC_DIR, module + '.js')));
}
return true;
}

305
build/lib/standalone.ts Normal file
View File

@@ -0,0 +1,305 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as ts from 'typescript';
import * as fs from 'fs';
import * as path from 'path';
const REPO_ROOT = path.join(__dirname, '../../');
const SRC_DIR = path.join(REPO_ROOT, 'src');
const OUT_EDITOR = path.join(REPO_ROOT, 'out-editor');
export interface IOptions {
entryPoints: string[];
outFolder: string;
outResourcesFolder: string;
redirects: { [module: string]: string; };
}
export function createESMSourcesAndResources(options: IOptions): void {
const OUT_FOLDER = path.join(REPO_ROOT, options.outFolder);
const OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder);
let in_queue: { [module: string]: boolean; } = Object.create(null);
let queue: string[] = [];
const enqueue = (module: string) => {
if (in_queue[module]) {
return;
}
in_queue[module] = true;
queue.push(module);
};
const seenDir: { [key: string]: boolean; } = {};
const createDirectoryRecursive = (dir: string) => {
if (seenDir[dir]) {
return;
}
let lastSlash = dir.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = dir.lastIndexOf('\\');
}
if (lastSlash !== -1) {
createDirectoryRecursive(dir.substring(0, lastSlash));
}
seenDir[dir] = true;
try { fs.mkdirSync(dir); } catch (err) { }
};
seenDir[REPO_ROOT] = true;
const toggleComments = (fileContents: string) => {
let lines = fileContents.split(/\r\n|\r|\n/);
let mode = 0;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (mode === 0) {
if (/\/\/ ESM-comment-begin/.test(line)) {
mode = 1;
continue;
}
if (/\/\/ ESM-uncomment-begin/.test(line)) {
mode = 2;
continue;
}
continue;
}
if (mode === 1) {
if (/\/\/ ESM-comment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = '// ' + line;
continue;
}
if (mode === 2) {
if (/\/\/ ESM-uncomment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) {
return indent;
});
}
}
return lines.join('\n');
};
const write = (filePath: string, contents: string | Buffer) => {
let absoluteFilePath: string;
if (/\.ts$/.test(filePath)) {
absoluteFilePath = path.join(OUT_FOLDER, filePath);
} else {
absoluteFilePath = path.join(OUT_RESOURCES_FOLDER, filePath);
}
createDirectoryRecursive(path.dirname(absoluteFilePath));
if (/(\.ts$)|(\.js$)/.test(filePath)) {
contents = toggleComments(contents.toString());
}
fs.writeFileSync(absoluteFilePath, contents);
};
options.entryPoints.forEach((entryPoint) => enqueue(entryPoint));
while (queue.length > 0) {
const module = queue.shift();
if (transportCSS(options, module, enqueue, write)) {
continue;
}
if (transportResource(options, module, enqueue, write)) {
continue;
}
if (transportDTS(options, module, enqueue, write)) {
continue;
}
let filename: string;
if (options.redirects[module]) {
filename = path.join(SRC_DIR, options.redirects[module] + '.ts');
} else {
filename = path.join(SRC_DIR, module + '.ts');
}
let fileContents = fs.readFileSync(filename).toString();
const info = ts.preProcessFile(fileContents);
for (let i = info.importedFiles.length - 1; i >= 0; i--) {
const importedFilename = info.importedFiles[i].fileName;
const pos = info.importedFiles[i].pos;
const end = info.importedFiles[i].end;
let importedFilepath: string;
if (/^vs\/css!/.test(importedFilename)) {
importedFilepath = importedFilename.substr('vs/css!'.length) + '.css';
} else {
importedFilepath = importedFilename;
}
if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) {
importedFilepath = path.join(path.dirname(module), importedFilepath);
}
enqueue(importedFilepath);
let relativePath: string;
if (importedFilepath === path.dirname(module)) {
relativePath = '../' + path.basename(path.dirname(module));
} else if (importedFilepath === path.dirname(path.dirname(module))) {
relativePath = '../../' + path.basename(path.dirname(path.dirname(module)));
} else {
relativePath = path.relative(path.dirname(module), importedFilepath);
}
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}
fileContents = (
fileContents.substring(0, pos + 1)
+ relativePath
+ fileContents.substring(end + 1)
);
}
fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) {
return `import * as ${m1} from ${m2};`;
});
fileContents = fileContents.replace(/Thenable/g, 'PromiseLike');
write(module + '.ts', fileContents);
}
const esm_opts = {
"compilerOptions": {
"outDir": path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER),
"rootDir": "src",
"module": "es6",
"target": "es5",
"experimentalDecorators": true,
"lib": [
"dom",
"es5",
"es2015.collection",
"es2015.promise"
],
"types": [
]
}
};
fs.writeFileSync(path.join(path.dirname(OUT_FOLDER), 'tsconfig.json'), JSON.stringify(esm_opts, null, '\t'));
const monacodts = fs.readFileSync(path.join(SRC_DIR, 'vs/monaco.d.ts')).toString();
fs.writeFileSync(path.join(OUT_FOLDER, 'vs/monaco.d.ts'), monacodts);
}
function transportCSS(options: IOptions, module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean {
if (!/\.css/.test(module)) {
return false;
}
const filename = path.join(SRC_DIR, module);
const fileContents = fs.readFileSync(filename).toString();
const inlineResources = 'base64'; // see https://github.com/Microsoft/monaco-editor/issues/148
const inlineResourcesLimit = 300000;//3000; // see https://github.com/Microsoft/monaco-editor/issues/336
const newContents = _rewriteOrInlineUrls(filename, fileContents, inlineResources === 'base64', inlineResourcesLimit);
write(module, newContents);
return true;
function _rewriteOrInlineUrls(originalFileFSPath: string, contents: string, forceBase64: boolean, inlineByteLimit: number): string {
return _replaceURL(contents, (url) => {
let imagePath = path.join(path.dirname(module), url);
let fileContents = fs.readFileSync(path.join(SRC_DIR, imagePath));
if (fileContents.length < inlineByteLimit) {
const MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png';
let DATA = ';base64,' + fileContents.toString('base64');
if (!forceBase64 && /\.svg$/.test(url)) {
// .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris
let newText = fileContents.toString()
.replace(/"/g, '\'')
.replace(/</g, '%3C')
.replace(/>/g, '%3E')
.replace(/&/g, '%26')
.replace(/#/g, '%23')
.replace(/\s+/g, ' ');
let encodedData = ',' + newText;
if (encodedData.length < DATA.length) {
DATA = encodedData;
}
}
return '"data:' + MIME + DATA + '"';
}
enqueue(imagePath);
return url;
});
}
function _replaceURL(contents: string, replacer: (url: string) => string): string {
// Use ")" as the terminator as quotes are oftentimes not used at all
return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, (_: string, ...matches: string[]) => {
var url = matches[0];
// Eliminate starting quotes (the initial whitespace is not captured)
if (url.charAt(0) === '"' || url.charAt(0) === '\'') {
url = url.substring(1);
}
// The ending whitespace is captured
while (url.length > 0 && (url.charAt(url.length - 1) === ' ' || url.charAt(url.length - 1) === '\t')) {
url = url.substring(0, url.length - 1);
}
// Eliminate ending quotes
if (url.charAt(url.length - 1) === '"' || url.charAt(url.length - 1) === '\'') {
url = url.substring(0, url.length - 1);
}
if (!_startsWith(url, 'data:') && !_startsWith(url, 'http://') && !_startsWith(url, 'https://')) {
url = replacer(url);
}
return 'url(' + url + ')';
});
}
function _startsWith(haystack: string, needle: string): boolean {
return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle;
}
}
function transportResource(options: IOptions, module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean {
if (!/\.svg/.test(module)) {
return false;
}
write(module, fs.readFileSync(path.join(SRC_DIR, module)));
return true;
}
function transportDTS(options: IOptions, module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean {
if (options.redirects[module] && fs.existsSync(path.join(SRC_DIR, options.redirects[module] + '.ts'))) {
return false;
}
if (!fs.existsSync(path.join(SRC_DIR, module + '.d.ts'))) {
return false;
}
write(module + '.d.ts', fs.readFileSync(path.join(SRC_DIR, module + '.d.ts')));
let filename: string;
if (options.redirects[module]) {
write(module + '.js', fs.readFileSync(path.join(SRC_DIR, options.redirects[module] + '.js')));
} else {
write(module + '.js', fs.readFileSync(path.join(SRC_DIR, module + '.js')));
}
return true;
}

View File

@@ -0,0 +1,56 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
var assert = require("assert");
var util = require("../util");
function getMockTagExists(tags) {
return function (tag) { return tags.indexOf(tag) >= 0; };
}
suite('util tests', function () {
test('getPreviousVersion - patch', function () {
assert.equal(util.getPreviousVersion('1.2.3', getMockTagExists(['1.2.2', '1.2.1', '1.2.0', '1.1.0'])), '1.2.2');
});
test('getPreviousVersion - patch invalid', function () {
try {
util.getPreviousVersion('1.2.2', getMockTagExists(['1.2.0', '1.1.0']));
}
catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
test('getPreviousVersion - minor', function () {
assert.equal(util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.2', '1.1.3'])), '1.1.3');
assert.equal(util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.0.0'])), '1.1.0');
});
test('getPreviousVersion - minor gap', function () {
assert.equal(util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.3'])), '1.1.1');
});
test('getPreviousVersion - minor invalid', function () {
try {
util.getPreviousVersion('1.2.0', getMockTagExists(['1.0.0']));
}
catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
test('getPreviousVersion - major', function () {
assert.equal(util.getPreviousVersion('2.0.0', getMockTagExists(['1.0.0', '1.1.0', '1.2.0', '1.2.1', '1.2.2'])), '1.2.2');
});
test('getPreviousVersion - major invalid', function () {
try {
util.getPreviousVersion('3.0.0', getMockTagExists(['1.0.0']));
}
catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
});

View File

@@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert = require('assert');
import util = require('../util');
function getMockTagExists(tags: string[]) {
return (tag: string) => tags.indexOf(tag) >= 0;
}
suite('util tests', () => {
test('getPreviousVersion - patch', () => {
assert.equal(
util.getPreviousVersion('1.2.3', getMockTagExists(['1.2.2', '1.2.1', '1.2.0', '1.1.0'])),
'1.2.2'
);
});
test('getPreviousVersion - patch invalid', () => {
try {
util.getPreviousVersion('1.2.2', getMockTagExists(['1.2.0', '1.1.0']));
} catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
test('getPreviousVersion - minor', () => {
assert.equal(
util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.2', '1.1.3'])),
'1.1.3'
);
assert.equal(
util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.0.0'])),
'1.1.0'
);
});
test('getPreviousVersion - minor gap', () => {
assert.equal(
util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.3'])),
'1.1.1'
);
});
test('getPreviousVersion - minor invalid', () => {
try {
util.getPreviousVersion('1.2.0', getMockTagExists(['1.0.0']));
} catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
test('getPreviousVersion - major', () => {
assert.equal(
util.getPreviousVersion('2.0.0', getMockTagExists(['1.0.0', '1.1.0', '1.2.0', '1.2.1', '1.2.2'])),
'1.2.2'
);
});
test('getPreviousVersion - major invalid', () => {
try {
util.getPreviousVersion('3.0.0', getMockTagExists(['1.0.0']));
} catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
});

View File

@@ -71,7 +71,7 @@ var TranslationRemindRuleWalker = /** @class */ (function (_super) {
}
});
if (!resourceDefined) {
this.addFailureAtNode(node, "Please add '" + resource + "' to ./builds/lib/i18n.resources.json file to use translations here.");
this.addFailureAtNode(node, "Please add '" + resource + "' to ./build/lib/i18n.resources.json file to use translations here.");
}
};
TranslationRemindRuleWalker.NLS_MODULE = 'vs/nls';

View File

@@ -67,7 +67,7 @@ class TranslationRemindRuleWalker extends Lint.RuleWalker {
});
if (!resourceDefined) {
this.addFailureAtNode(node, `Please add '${resource}' to ./builds/lib/i18n.resources.json file to use translations here.`);
this.addFailureAtNode(node, `Please add '${resource}' to ./build/lib/i18n.resources.json file to use translations here.`);
}
}
}

View File

@@ -14,6 +14,7 @@ var fs = require("fs");
var _rimraf = require("rimraf");
var git = require("./git");
var VinylFile = require("vinyl");
var cp = require("child_process");
var NoCancellationToken = { isCancellationRequested: function () { return false; } };
function incremental(streamProvider, initial, supportsCancellation) {
var input = es.through();
@@ -210,3 +211,68 @@ function filter(fn) {
return result;
}
exports.filter = filter;
function tagExists(tagName) {
try {
cp.execSync("git rev-parse " + tagName, { stdio: 'ignore' });
return true;
}
catch (e) {
return false;
}
}
/**
* Returns the version previous to the given version. Throws if a git tag for that version doesn't exist.
* Given 1.17.2, return 1.17.1
* 1.18.0 => 1.17.2. (or the highest 1.17.x)
* 2.0.0 => 1.18.0 (or the highest 1.x)
*/
function getPreviousVersion(versionStr, _tagExists) {
if (_tagExists === void 0) { _tagExists = tagExists; }
function getLatestTagFromBase(semverArr, componentToTest) {
var baseVersion = semverArr.join('.');
if (!_tagExists(baseVersion)) {
throw new Error('Failed to find git tag for base version, ' + baseVersion);
}
var goodTag;
do {
goodTag = semverArr.join('.');
semverArr[componentToTest]++;
} while (_tagExists(semverArr.join('.')));
return goodTag;
}
var semverArr = versionStringToNumberArray(versionStr);
if (semverArr[2] > 0) {
semverArr[2]--;
var previous = semverArr.join('.');
if (!_tagExists(previous)) {
throw new Error('Failed to find git tag for previous version, ' + previous);
}
return previous;
}
else if (semverArr[1] > 0) {
semverArr[1]--;
return getLatestTagFromBase(semverArr, 2);
}
else {
semverArr[0]--;
// Find 1.x.0 for latest x
var latestMinorVersion = getLatestTagFromBase(semverArr, 1);
// Find 1.x.y for latest y
return getLatestTagFromBase(versionStringToNumberArray(latestMinorVersion), 2);
}
}
exports.getPreviousVersion = getPreviousVersion;
function versionStringToNumberArray(versionStr) {
return versionStr
.split('.')
.map(function (s) { return parseInt(s); });
}
function versionStringToNumber(versionStr) {
var semverRegex = /(\d+)\.(\d+)\.(\d+)/;
var match = versionStr.match(semverRegex);
if (!match) {
throw new Error('Version string is not properly formatted: ' + versionStr);
}
return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10);
}
exports.versionStringToNumber = versionStringToNumber;

View File

@@ -17,6 +17,7 @@ import * as git from './git';
import * as VinylFile from 'vinyl';
import { ThroughStream } from 'through';
import * as sm from 'source-map';
import * as cp from 'child_process';
export interface ICancellationToken {
isCancellationRequested(): boolean;
@@ -268,4 +269,74 @@ export function filter(fn: (data: any) => boolean): FilterStream {
result.restore = es.through();
return result;
}
}
function tagExists(tagName: string): boolean {
try {
cp.execSync(`git rev-parse ${tagName}`, { stdio: 'ignore' });
return true;
} catch (e) {
return false;
}
}
/**
* Returns the version previous to the given version. Throws if a git tag for that version doesn't exist.
* Given 1.17.2, return 1.17.1
* 1.18.0 => 1.17.2. (or the highest 1.17.x)
* 2.0.0 => 1.18.0 (or the highest 1.x)
*/
export function getPreviousVersion(versionStr: string, _tagExists = tagExists) {
function getLatestTagFromBase(semverArr: number[], componentToTest: number): string {
const baseVersion = semverArr.join('.');
if (!_tagExists(baseVersion)) {
throw new Error('Failed to find git tag for base version, ' + baseVersion);
}
let goodTag;
do {
goodTag = semverArr.join('.');
semverArr[componentToTest]++;
} while (_tagExists(semverArr.join('.')));
return goodTag;
}
const semverArr = versionStringToNumberArray(versionStr);
if (semverArr[2] > 0) {
semverArr[2]--;
const previous = semverArr.join('.');
if (!_tagExists(previous)) {
throw new Error('Failed to find git tag for previous version, ' + previous);
}
return previous;
} else if (semverArr[1] > 0) {
semverArr[1]--;
return getLatestTagFromBase(semverArr, 2);
} else {
semverArr[0]--;
// Find 1.x.0 for latest x
const latestMinorVersion = getLatestTagFromBase(semverArr, 1);
// Find 1.x.y for latest y
return getLatestTagFromBase(versionStringToNumberArray(latestMinorVersion), 2);
}
}
function versionStringToNumberArray(versionStr: string): number[] {
return versionStr
.split('.')
.map(s => parseInt(s));
}
export function versionStringToNumber(versionStr: string) {
const semverRegex = /(\d+)\.(\d+)\.(\d+)/;
const match = versionStr.match(semverRegex);
if (!match) {
throw new Error('Version string is not properly formatted: ' + versionStr);
}
return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10);
}

View File

@@ -1,6 +1,6 @@
The Source EULA
Copyright (c) 2016 Microsoft Corporation
Copyright (c) 2016 - present Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -32,7 +32,7 @@ END OF winjs NOTICES AND INFORMATION
%% string_scorer version 0.1.20 (https://github.com/joshaven/string_score)
=========================================
This software is released under the Source EULA:
This software is released under the MIT license:
Copyright (c) Joshaven Potter
@@ -60,7 +60,7 @@ END OF string_scorer NOTICES AND INFORMATION
%% chjj-marked NOTICES AND INFORMATION BEGIN HERE
=========================================
The Source EULA
The MIT License (MIT)
Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)

View File

@@ -171,9 +171,7 @@ function format(text) {
function getRuleProvider(options) {
// Share this between multiple formatters using the same options.
// This represents the bulk of the space the formatter uses.
var ruleProvider = new ts.formatting.RulesProvider();
ruleProvider.ensureUpToDate(options);
return ruleProvider;
return ts.formatting.getFormatContext(options);
}
function applyEdits(text, edits) {
// Apply edits in reverse on the existing text
@@ -210,7 +208,8 @@ function createReplacer(data) {
};
}
function generateDeclarationFile(out, inputFiles, recipe) {
var lines = recipe.split(/\r\n|\n|\r/);
var endl = /\r\n/.test(recipe) ? '\r\n' : '\n';
var lines = recipe.split(endl);
var result = [];
lines.forEach(function (line) {
var m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
@@ -278,12 +277,11 @@ function generateDeclarationFile(out, inputFiles, recipe) {
}
result.push(line);
});
var resultTxt = result.join('\n');
var resultTxt = result.join(endl);
resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri');
resultTxt = resultTxt.replace(/\bEvent</g, 'IEvent<');
resultTxt = resultTxt.replace(/\bTPromise</g, 'Promise<');
resultTxt = format(resultTxt);
resultTxt = resultTxt.replace(/\r\n/g, '\n');
return resultTxt;
}
function getFilesToWatch(out) {
@@ -314,10 +312,13 @@ function run(out, inputFiles) {
var result = generateDeclarationFile(out, inputFiles, recipe);
var currentContent = fs.readFileSync(DECLARATION_PATH).toString();
log('Finished monaco.d.ts generation');
var one = currentContent.replace(/\r\n/gm, '\n');
var other = result.replace(/\r\n/gm, '\n');
var isTheSame = one === other;
return {
content: result,
filePath: DECLARATION_PATH,
isTheSame: currentContent === result
isTheSame: isTheSame
};
}
exports.run = run;

View File

@@ -24,15 +24,15 @@ function logErr(message: any, ...rest: any[]): void {
util.log(util.colors.red('[monaco.d.ts]'), message, ...rest);
}
function moduleIdToPath(out:string, moduleId:string): string {
function moduleIdToPath(out: string, moduleId: string): string {
if (/\.d\.ts/.test(moduleId)) {
return path.join(SRC, moduleId);
}
return path.join(OUT_ROOT, out, moduleId) + '.d.ts';
}
let SOURCE_FILE_MAP: {[moduleId:string]:ts.SourceFile;} = {};
function getSourceFile(out:string, inputFiles: { [file: string]: string; }, moduleId:string): ts.SourceFile {
let SOURCE_FILE_MAP: { [moduleId: string]: ts.SourceFile; } = {};
function getSourceFile(out: string, inputFiles: { [file: string]: string; }, moduleId: string): ts.SourceFile {
if (!SOURCE_FILE_MAP[moduleId]) {
let filePath = path.normalize(moduleIdToPath(out, moduleId));
@@ -53,7 +53,7 @@ function getSourceFile(out:string, inputFiles: { [file: string]: string; }, modu
type TSTopLevelDeclaration = ts.InterfaceDeclaration | ts.EnumDeclaration | ts.ClassDeclaration | ts.TypeAliasDeclaration | ts.FunctionDeclaration | ts.ModuleDeclaration;
type TSTopLevelDeclare = TSTopLevelDeclaration | ts.VariableStatement;
function isDeclaration(a:TSTopLevelDeclare): a is TSTopLevelDeclaration {
function isDeclaration(a: TSTopLevelDeclare): a is TSTopLevelDeclaration {
return (
a.kind === ts.SyntaxKind.InterfaceDeclaration
|| a.kind === ts.SyntaxKind.EnumDeclaration
@@ -64,7 +64,7 @@ function isDeclaration(a:TSTopLevelDeclare): a is TSTopLevelDeclaration {
);
}
function visitTopLevelDeclarations(sourceFile:ts.SourceFile, visitor:(node:TSTopLevelDeclare)=>boolean): void {
function visitTopLevelDeclarations(sourceFile: ts.SourceFile, visitor: (node: TSTopLevelDeclare) => boolean): void {
let stop = false;
let visit = (node: ts.Node): void => {
@@ -100,8 +100,8 @@ function visitTopLevelDeclarations(sourceFile:ts.SourceFile, visitor:(node:TSTop
}
function getAllTopLevelDeclarations(sourceFile:ts.SourceFile): TSTopLevelDeclare[] {
let all:TSTopLevelDeclare[] = [];
function getAllTopLevelDeclarations(sourceFile: ts.SourceFile): TSTopLevelDeclare[] {
let all: TSTopLevelDeclare[] = [];
visitTopLevelDeclarations(sourceFile, (node) => {
if (node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ModuleDeclaration) {
let interfaceDeclaration = <ts.InterfaceDeclaration>node;
@@ -128,8 +128,8 @@ function getAllTopLevelDeclarations(sourceFile:ts.SourceFile): TSTopLevelDeclare
}
function getTopLevelDeclaration(sourceFile:ts.SourceFile, typeName:string): TSTopLevelDeclare {
let result:TSTopLevelDeclare = null;
function getTopLevelDeclaration(sourceFile: ts.SourceFile, typeName: string): TSTopLevelDeclare {
let result: TSTopLevelDeclare = null;
visitTopLevelDeclarations(sourceFile, (node) => {
if (isDeclaration(node)) {
if (node.name.text === typeName) {
@@ -149,12 +149,12 @@ function getTopLevelDeclaration(sourceFile:ts.SourceFile, typeName:string): TSTo
}
function getNodeText(sourceFile:ts.SourceFile, node:{pos:number; end:number;}): string {
function getNodeText(sourceFile: ts.SourceFile, node: { pos: number; end: number; }): string {
return sourceFile.getFullText().substring(node.pos, node.end);
}
function getMassagedTopLevelDeclarationText(sourceFile:ts.SourceFile, declaration: TSTopLevelDeclare): string {
function getMassagedTopLevelDeclarationText(sourceFile: ts.SourceFile, declaration: TSTopLevelDeclare): string {
let result = getNodeText(sourceFile, declaration);
// if (result.indexOf('MonacoWorker') >= 0) {
// console.log('here!');
@@ -163,7 +163,7 @@ function getMassagedTopLevelDeclarationText(sourceFile:ts.SourceFile, declaratio
if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) {
let interfaceDeclaration = <ts.InterfaceDeclaration | ts.ClassDeclaration>declaration;
let members:ts.NodeArray<ts.Node> = interfaceDeclaration.members;
let members: ts.NodeArray<ts.Node> = interfaceDeclaration.members;
members.forEach((member) => {
try {
let memberText = getNodeText(sourceFile, member);
@@ -182,7 +182,7 @@ function getMassagedTopLevelDeclarationText(sourceFile:ts.SourceFile, declaratio
return result;
}
function format(text:string): string {
function format(text: string): string {
// Parse the source text
let sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true);
@@ -196,9 +196,7 @@ function format(text:string): string {
function getRuleProvider(options: ts.FormatCodeSettings) {
// Share this between multiple formatters using the same options.
// This represents the bulk of the space the formatter uses.
let ruleProvider = new (<any>ts).formatting.RulesProvider();
ruleProvider.ensureUpToDate(options);
return ruleProvider;
return (ts as any).formatting.getFormatContext(options);
}
function applyEdits(text: string, edits: ts.TextChange[]): string {
@@ -214,10 +212,10 @@ function format(text:string): string {
}
}
function createReplacer(data:string): (str:string)=>string {
function createReplacer(data: string): (str: string) => string {
data = data || '';
let rawDirectives = data.split(';');
let directives: [RegExp,string][] = [];
let directives: [RegExp, string][] = [];
rawDirectives.forEach((rawDirective) => {
if (rawDirective.length === 0) {
return;
@@ -231,7 +229,7 @@ function createReplacer(data:string): (str:string)=>string {
directives.push([new RegExp(findStr, 'g'), replaceStr]);
});
return (str:string)=> {
return (str: string) => {
for (let i = 0; i < directives.length; i++) {
str = str.replace(directives[i][0], directives[i][1]);
}
@@ -239,10 +237,11 @@ function createReplacer(data:string): (str:string)=>string {
};
}
function generateDeclarationFile(out: string, inputFiles: { [file: string]: string; }, recipe:string): string {
let lines = recipe.split(/\r\n|\n|\r/);
let result = [];
function generateDeclarationFile(out: string, inputFiles: { [file: string]: string; }, recipe: string): string {
const endl = /\r\n/.test(recipe) ? '\r\n' : '\n';
let lines = recipe.split(endl);
let result = [];
lines.forEach(line => {
@@ -285,7 +284,7 @@ function generateDeclarationFile(out: string, inputFiles: { [file: string]: stri
let replacer = createReplacer(m2[2]);
let typeNames = m2[3].split(/,/);
let typesToExcludeMap: {[typeName:string]:boolean;} = {};
let typesToExcludeMap: { [typeName: string]: boolean; } = {};
let typesToExcludeArr: string[] = [];
typeNames.forEach((typeName) => {
typeName = typeName.trim();
@@ -318,18 +317,17 @@ function generateDeclarationFile(out: string, inputFiles: { [file: string]: stri
result.push(line);
});
let resultTxt = result.join('\n');
let resultTxt = result.join(endl);
resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri');
resultTxt = resultTxt.replace(/\bEvent</g, 'IEvent<');
resultTxt = resultTxt.replace(/\bTPromise</g, 'Promise<');
resultTxt = format(resultTxt);
resultTxt = resultTxt.replace(/\r\n/g, '\n');
return resultTxt;
}
export function getFilesToWatch(out:string): string[] {
export function getFilesToWatch(out: string): string[] {
let recipe = fs.readFileSync(RECIPE_PATH).toString();
let lines = recipe.split(/\r\n|\n|\r/);
let result = [];
@@ -370,10 +368,14 @@ export function run(out: string, inputFiles: { [file: string]: string; }): IMona
let currentContent = fs.readFileSync(DECLARATION_PATH).toString();
log('Finished monaco.d.ts generation');
const one = currentContent.replace(/\r\n/gm, '\n');
const other = result.replace(/\r\n/gm, '\n');
const isTheSame = one === other;
return {
content: result,
filePath: DECLARATION_PATH,
isTheSame: currentContent === result
isTheSame
};
}

View File

@@ -3,9 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module monaco {
declare namespace monaco {
type Thenable<T> = PromiseLike<T>;
export type Thenable<T> = PromiseLike<T>;
export interface IDisposable {
dispose(): void;
@@ -32,6 +32,14 @@ declare module monaco {
Error = 3,
}
export enum MarkerSeverity {
Hint = 1,
Info = 2,
Warning = 4,
Error = 8,
}
#include(vs/base/common/winjs.base.d.ts): TValueCallback, ProgressCallback, Promise
#include(vs/base/common/cancellation): CancellationTokenSource, CancellationToken
#include(vs/base/common/uri): URI, UriComponents
@@ -46,7 +54,7 @@ declare module monaco {
#include(vs/editor/common/core/token): Token
}
declare module monaco.editor {
declare namespace monaco.editor {
#includeAll(vs/editor/standalone/browser/standaloneEditor;modes.=>languages.;editorCommon.=>):
#include(vs/editor/standalone/common/standaloneThemeService): BuiltinTheme, IStandaloneThemeData, IColors
@@ -58,7 +66,7 @@ export interface ICommandHandler {
}
#include(vs/platform/contextkey/common/contextkey): IContextKey
#include(vs/editor/standalone/browser/standaloneServices): IEditorOverrideServices
#include(vs/platform/markers/common/markers): IMarker, IMarkerData
#include(vs/platform/markers/common/markers): IMarker, IMarkerData, IRelatedInformation
#include(vs/editor/standalone/browser/colorizer): IColorizerOptions, IColorizerElementOptions
#include(vs/base/common/scrollable): ScrollbarVisibility
#include(vs/platform/theme/common/themeService): ThemeColor
@@ -75,7 +83,7 @@ export type IReadOnlyModel = ITextModel;
export type IModel = ITextModel;
}
declare module monaco.languages {
declare namespace monaco.languages {
#includeAll(vs/editor/standalone/browser/standaloneLanguages;modes.=>;editorCommon.=>editor.;model.=>editor.;IMarkerData=>editor.IMarkerData):
#includeAll(vs/editor/common/modes/languageConfiguration):
@@ -85,7 +93,7 @@ declare module monaco.languages {
}
declare module monaco.worker {
declare namespace monaco.worker {
#includeAll(vs/editor/common/services/editorSimpleWorker;):

View File

@@ -1,15 +1,17 @@
{
"name": "monaco-editor-core",
"private": true,
"version": "0.9.0",
"version": "0.12.0",
"description": "A browser based code editor",
"author": "Microsoft Corporation",
"license": "MIT",
"typings": "./esm/vs/editor/editor.api.d.ts",
"module": "./esm/vs/editor/editor.main.js",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/vscode"
},
"bugs": {
"bugs": {
"url": "https://github.com/Microsoft/vscode/issues"
}
}

View File

@@ -23,20 +23,15 @@ function yarnInstall(location, opts) {
// {{SQL CARBON EDIT}}
yarnInstall('extensions'); // node modules shared by all extensions
const extensions = [
'vscode-colorize-tests',
'json',
'mssql',
'configuration-editing',
'extension-editing',
'markdown',
'markdown-basics',
'git',
'merge-conflict',
'insights-default',
'account-provider-azure',
'agent'
];
const allExtensionFolders = fs.readdirSync('extensions');
const extensions = allExtensionFolders.filter(e => {
try {
let packageJSON = JSON.parse(fs.readFileSync(path.join('extensions', e, 'package.json')).toString());
return packageJSON && (packageJSON.dependencies || packageJSON.devDependencies);
} catch (e) {
return false;
}
});
extensions.forEach(extension => yarnInstall(`extensions/${extension}`));

View File

@@ -9,6 +9,7 @@
"@types/mime": "0.0.29",
"@types/node": "8.0.33",
"@types/xml2js": "0.0.33",
"@types/request": "^2.47.0",
"azure-storage": "^2.1.0",
"decompress": "^4.2.0",
"documentdb": "1.13.0",
@@ -16,9 +17,11 @@
"fs-extra-promise": "^1.0.1",
"mime": "^1.3.4",
"minimist": "^1.2.0",
"typescript": "2.6.1",
"typescript": "2.8.1",
"vscode": "^1.0.1",
"xml2js": "^0.4.17"
"xml2js": "^0.4.17",
"github-releases": "^0.4.1",
"request": "^2.85.0"
},
"scripts": {
"compile": "tsc -p tsconfig.build.json",

219
build/tfs/common/symbols.ts Normal file
View File

@@ -0,0 +1,219 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as request from 'request';
import { createReadStream, createWriteStream, unlink, mkdir } from 'fs';
import * as github from 'github-releases';
import { join } from 'path';
import { tmpdir } from 'os';
import { promisify } from 'util';
const BASE_URL = 'https://rink.hockeyapp.net/api/2/';
const HOCKEY_APP_TOKEN_HEADER = 'X-HockeyAppToken';
export interface IVersions {
app_versions: IVersion[];
}
export interface IVersion {
id: number;
version: string;
}
export interface IApplicationAccessor {
accessToken: string;
appId: string;
}
export interface IVersionAccessor extends IApplicationAccessor {
id: string;
}
enum Platform {
WIN_32 = 'win32-ia32',
WIN_64 = 'win32-x64',
LINUX_32 = 'linux-ia32',
LINUX_64 = 'linux-x64',
MAC_OS = 'darwin-x64'
}
function symbolsZipName(platform: Platform, electronVersion: string, insiders: boolean): string {
return `${insiders ? 'insiders' : 'stable'}-symbols-v${electronVersion}-${platform}.zip`;
}
const SEED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
async function tmpFile(name: string): Promise<string> {
let res = '';
for (let i = 0; i < 8; i++) {
res += SEED.charAt(Math.floor(Math.random() * SEED.length));
}
const tmpParent = join(tmpdir(), res);
await promisify(mkdir)(tmpParent);
return join(tmpParent, name);
}
function getVersions(accessor: IApplicationAccessor): Promise<IVersions> {
return asyncRequest<IVersions>({
url: `${BASE_URL}/apps/${accessor.appId}/app_versions`,
method: 'GET',
headers: {
[HOCKEY_APP_TOKEN_HEADER]: accessor.accessToken
}
});
}
function createVersion(accessor: IApplicationAccessor, version: string): Promise<IVersion> {
return asyncRequest<IVersion>({
url: `${BASE_URL}/apps/${accessor.appId}/app_versions/new`,
method: 'POST',
headers: {
[HOCKEY_APP_TOKEN_HEADER]: accessor.accessToken
},
formData: {
bundle_version: version
}
});
}
function updateVersion(accessor: IVersionAccessor, symbolsPath: string) {
return asyncRequest<IVersions>({
url: `${BASE_URL}/apps/${accessor.appId}/app_versions/${accessor.id}`,
method: 'PUT',
headers: {
[HOCKEY_APP_TOKEN_HEADER]: accessor.accessToken
},
formData: {
dsym: createReadStream(symbolsPath)
}
});
}
function asyncRequest<T>(options: request.UrlOptions & request.CoreOptions): Promise<T> {
return new Promise<T>((resolve, reject) => {
request(options, (error, response, body) => {
if (error) {
reject(error);
} else {
resolve(JSON.parse(body));
}
});
});
}
function downloadAsset(repository, assetName: string, targetPath: string, electronVersion: string) {
return new Promise((resolve, reject) => {
repository.getReleases({ tag_name: `v${electronVersion}` }, (err, releases) => {
if (err) {
reject(err);
} else {
const asset = releases[0].assets.filter(asset => asset.name === assetName)[0];
if (!asset) {
reject(new Error(`Asset with name ${assetName} not found`));
} else {
repository.downloadAsset(asset, (err, reader) => {
if (err) {
reject(err);
} else {
const writer = createWriteStream(targetPath);
writer.on('error', reject);
writer.on('close', resolve);
reader.on('error', reject);
reader.pipe(writer);
}
});
}
}
});
});
}
interface IOptions {
repository: string;
platform: Platform;
versions: { code: string; insiders: boolean; electron: string; };
access: { hockeyAppToken: string; hockeyAppId: string; githubToken: string };
}
async function ensureVersionAndSymbols(options: IOptions) {
// Check version does not exist
console.log(`HockeyApp: checking for existing version ${options.versions.code} (${options.platform})`);
const versions = await getVersions({ accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId });
if (versions.app_versions.some(v => v.version === options.versions.code)) {
console.log(`HockeyApp: Returning without uploading symbols because version ${options.versions.code} (${options.platform}) was already found`);
return;
}
// Download symbols for platform and electron version
const symbolsName = symbolsZipName(options.platform, options.versions.electron, options.versions.insiders);
const symbolsPath = await tmpFile('symbols.zip');
console.log(`HockeyApp: downloading symbols ${symbolsName} for electron ${options.versions.electron} (${options.platform}) into ${symbolsPath}`);
await downloadAsset(new github({ repo: options.repository, token: options.access.githubToken }), symbolsName, symbolsPath, options.versions.electron);
// Create version
console.log(`HockeyApp: creating new version ${options.versions.code} (${options.platform})`);
const version = await createVersion({ accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId }, options.versions.code);
// Upload symbols
console.log(`HockeyApp: uploading symbols for version ${options.versions.code} (${options.platform})`);
await updateVersion({ id: String(version.id), accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId }, symbolsPath);
// Cleanup
await promisify(unlink)(symbolsPath);
}
// Environment
const pakage = require('../../../package.json');
const product = require('../../../product.json');
const repository = product.electronRepository;
const electronVersion = require('../../lib/electron').getElectronVersion();
const insiders = product.quality !== 'stable';
let codeVersion = pakage.version;
if (insiders) {
codeVersion = `${codeVersion}-insider`;
}
const githubToken = process.argv[2];
const hockeyAppToken = process.argv[3];
const is64 = process.argv[4] === 'x64';
const hockeyAppId = process.argv[5];
let platform: Platform;
if (process.platform === 'darwin') {
platform = Platform.MAC_OS;
} else if (process.platform === 'win32') {
platform = is64 ? Platform.WIN_64 : Platform.WIN_32;
} else {
platform = is64 ? Platform.LINUX_64 : Platform.LINUX_32;
}
// Create version and upload symbols in HockeyApp
if (repository && codeVersion && electronVersion && (product.quality === 'stable' || product.quality === 'insider')) {
ensureVersionAndSymbols({
repository,
platform,
versions: {
code: codeVersion,
insiders,
electron: electronVersion
},
access: {
githubToken,
hockeyAppToken,
hockeyAppId
}
}).then(() => {
console.log('HockeyApp: done');
}).catch(error => {
console.error(`HockeyApp: error (${error})`);
});
} else {
console.log(`HockeyApp: skipping due to unexpected context (repository: ${repository}, codeVersion: ${codeVersion}, electronVersion: ${electronVersion}, quality: ${product.quality})`);
}

View File

@@ -0,0 +1,100 @@
phases:
- phase: Windows
queue: Hosted VS2017
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- powershell: |
$ErrorActionPreference = "Stop"
yarn
.\node_modules\.bin\gulp electron
npm run gulp -- hygiene
.\node_modules\.bin\tsc -p .\src\tsconfig.monaco.json --noEmit
npm run compile
node build/lib/builtInExtensions.js
name: build
- powershell: |
$ErrorActionPreference = "Stop"
.\scripts\test.bat --tfs
.\scripts\test-integration.bat
yarn smoketest --screenshots "$(Build.ArtifactStagingDirectory)\artifacts" --log "$(Build.ArtifactStagingDirectory)\artifacts\smoketest.log"
name: test
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts'
ArtifactName: build-artifacts-win32
publishLocation: Container
condition: succeededOrFailed()
- phase: Linux
queue: Hosted Linux Preview
steps:
- script: |
set -e
apt-get update
apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 libgconf-2-4 dbus xvfb libgtk-3-0
cp build/tfs/linux/x64/xvfb.init /etc/init.d/xvfb
chmod +x /etc/init.d/xvfb
update-rc.d xvfb defaults
ln -sf /bin/dbus-daemon /usr/bin/dbus-daemon
service xvfb start
service dbus start
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- script: |
set -e
yarn
npm run gulp -- electron-x64
- script: |
set -e
npm run gulp -- hygiene
./node_modules/.bin/tsc -p ./src/tsconfig.monaco.json --noEmit
npm run compile
node build/lib/builtInExtensions.js
name: build
- script: |
set -e
DISPLAY=:10 ./scripts/test.sh --tfs
# DISPLAY=:10 ./scripts/test-integration.sh
name: test
- phase: macOS
queue: Hosted macOS Preview
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- script: |
set -e
yarn
npm run gulp -- electron-x64
- script: |
set -e
npm run gulp -- hygiene
./node_modules/.bin/tsc -p ./src/tsconfig.monaco.json --noEmit
npm run compile
node build/lib/builtInExtensions.js
name: build
- script: |
set -e
./scripts/test.sh --tfs
./scripts/test-integration.sh
yarn smoketest --screenshots "$(Build.ArtifactStagingDirectory)/artifacts" --log "$(Build.ArtifactStagingDirectory)/artifacts/smoketest.log"
name: test
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts'
ArtifactName: build-artifacts-darwin
publishLocation: Container
condition: succeededOrFailed()

View File

@@ -0,0 +1,51 @@
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- script: |
echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc
yarn
npm run gulp -- hygiene
npm run monaco-compile-check
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin electron
node build/tfs/common/installDistro.js
- script: |
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-darwin-min
name: build
- script: |
./scripts/test.sh --build --tfs
name: test
- script: |
# archive the unsigned build
pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin-unsigned.zip * && popd
# publish the unsigned build
PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json`
VERSION=`node -p "require(\"$PACKAGEJSON\").version"`
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/tfs/common/publish.js \
"$(VSCODE_QUALITY)" \
darwin \
archive-unsigned \
"VSCode-darwin-$(VSCODE_QUALITY)-unsigned.zip" \
$VERSION \
false \
../VSCode-darwin-unsigned.zip
# enqueue the unsigned build
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
node build/tfs/common/enqueue.js "$(VSCODE_QUALITY)"
npm run gulp -- upload-vscode-configuration

103
build/tfs/linux/build.yml Normal file
View File

@@ -0,0 +1,103 @@
steps:
- script: |
# dependencies
dpkg --add-architecture i386
apt-get update
DEPS=" \
gcc-multilib g++-multilib \
pkg-config \
dbus \
xvfb \
fakeroot \
bc \
bsdmainutils \
rpm \
"
if [[ "$(VSCODE_ARCH)" == "x64" ]]; then
DEPS="$DEPS \
dpkg-dev \
libgconf-2-4 \
libnss3 \
libasound2 \
libxtst6 \
libx11-dev \
libxkbfile-dev \
libxss1 \
libx11-xcb-dev \
libsecret-1-dev \
"
else
DEPS="$DEPS \
dpkg-dev:i386 \
libgconf-2-4:i386 \
libnss3:i386 \
libasound2:i386 \
libxtst6:i386 \
libnotify4:i386 \
libx11-dev:i386 \
libxkbfile-dev:i386 \
libxss1:i386 \
libx11-xcb-dev:i386 \
libgl1-mesa-glx:i386 libgl1-mesa-dri:i386 \
libgirepository-1.0-1:i386 \
gir1.2-glib-2.0:i386 \
gir1.2-secret-1:i386 \
libsecret-1-dev:i386 \
libgtk2.0-0:i386 \
"
fi
apt-get install -y $DEPS
# setup xvfb
cp build/tfs/linux/$(VSCODE_ARCH)/xvfb.init /etc/init.d/xvfb
chmod +x /etc/init.d/xvfb
update-rc.d xvfb defaults
service xvfb start
# setup dbus
ln -sf /bin/dbus-daemon /usr/bin/dbus-daemon
service dbus start
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- script: |
export npm_config_arch="$(VSCODE_ARCH)"
if [[ "$(VSCODE_ARCH)" == "ia32" ]]; then
export PKG_CONFIG_PATH="/usr/lib/i386-linux-gnu/pkgconfig"
fi
echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc
yarn
npm run gulp -- hygiene
npm run monaco-compile-check
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin
node build/tfs/common/installDistro.js
- script: |
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-linux-$(VSCODE_ARCH)-min
name: build
- script: |
npm run gulp -- "electron-$(VSCODE_ARCH)"
DISPLAY=:10 ./scripts/test.sh --build --tfs
name: test
- script: |
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb"
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm"
#npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-snap"
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
./build/tfs/linux/release2.sh "$(VSCODE_ARCH)" "$(LINUX_REPO_PASSWORD)"

67
build/tfs/linux/release2.sh Executable file
View File

@@ -0,0 +1,67 @@
#!/bin/bash
set -e
# Arguments
ARCH="$1"
LINUX_REPO_PASSWORD="$2"
# Variables
PLATFORM_LINUX="linux-$ARCH"
PLATFORM_DEB="linux-deb-$ARCH"
PLATFORM_RPM="linux-rpm-$ARCH"
[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
REPO="`pwd`"
ROOT="$REPO/.."
BUILDNAME="VSCode-$PLATFORM_LINUX"
BUILD="$ROOT/$BUILDNAME"
BUILD_VERSION="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/ | sed -e 's/code-[a-z]*_//g' -e 's/\.deb$//g')"
[ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz"
TARBALL_PATH="$ROOT/$TARBALL_FILENAME"
PACKAGEJSON="$BUILD/resources/app/package.json"
VERSION=$(node -p "require(\"$PACKAGEJSON\").version")
rm -rf $ROOT/code-*.tar.*
(cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME)
node build/tfs/common/publish.js $VSCODE_QUALITY $PLATFORM_LINUX archive-unsigned $TARBALL_FILENAME $VERSION true $TARBALL_PATH
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
node build/tfs/common/publish.js $VSCODE_QUALITY $PLATFORM_DEB package $DEB_FILENAME $VERSION true $DEB_PATH
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
node build/tfs/common/publish.js $VSCODE_QUALITY $PLATFORM_RPM package $RPM_FILENAME $VERSION true $RPM_PATH
# SNAP_FILENAME="$(ls $REPO/.build/linux/snap/$ARCH/ | grep .snap)"
# SNAP_PATH="$REPO/.build/linux/snap/$ARCH/$SNAP_FILENAME"
IS_FROZEN="$(node build/tfs/linux/frozen-check.js $VSCODE_QUALITY)"
if [ -z "$VSCODE_QUALITY" ]; then
echo "VSCODE_QUALITY is not set, skipping repo package publish"
elif [ "$IS_FROZEN" = "true" ]; then
echo "$VSCODE_QUALITY is frozen, skipping repo package publish"
else
if [ "$BUILD_SOURCEBRANCH" = "master" ] || [ "$BUILD_SOURCEBRANCH" = "refs/heads/master" ]; then
if [[ $BUILD_QUEUEDBY = *"Project Collection Service Accounts"* || $BUILD_QUEUEDBY = *"Microsoft.VisualStudio.Services.TFS"* ]]; then
# Write config files needed by API, use eval to force environment variable expansion
pushd build/tfs/linux
# Submit to apt repo
if [ "$DEB_ARCH" = "amd64" ]; then
eval echo '{ \"server\": \"azure-apt-cat.cloudapp.net\", \"protocol\": \"https\", \"port\": \"443\", \"repositoryId\": \"58a4adf642421134a1a48d1a\", \"username\": \"vscode\", \"password\": \"$LINUX_REPO_PASSWORD\" }' > apt-config.json
./repoapi_client.sh -config apt-config.json -addfile $DEB_PATH
fi
# Submit to yum repo (disabled as it's manual until signing is automated)
# eval echo '{ \"server\": \"azure-apt-cat.cloudapp.net\", \"protocol\": \"https\", \"port\": \"443\", \"repositoryId\": \"58a4ae3542421134a1a48d1b\", \"username\": \"vscode\", \"password\": \"$LINUX_REPO_PASSWORD\" }' > yum-config.json
# ./repoapi_client.sh -config yum-config.json -addfile $RPM_PATH
popd
echo "To check repo publish status run ./repoapi_client.sh -config config.json -check <id>"
fi
fi
fi

413
build/tfs/product-build.yml Normal file
View File

@@ -0,0 +1,413 @@
phases:
- phase: Windows
condition: eq(variables['VSCODE_BUILD_WIN32'], 'true')
queue:
name: Hosted VS2017
parallel: 2
matrix:
x64:
VSCODE_ARCH: x64
ia32:
VSCODE_ARCH: ia32
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- powershell: |
$ErrorActionPreference = "Stop"
"machine monacotools.visualstudio.com password $(VSO_PAT)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
$env:npm_config_arch="$(VSCODE_ARCH)"
$env:CHILD_CONCURRENCY="1"
yarn
npm run gulp -- hygiene
npm run monaco-compile-check
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
npm run gulp -- mixin
node build/tfs/common/installDistro.js
node build/lib/builtInExtensions.js
- powershell: |
$ErrorActionPreference = "Stop"
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-min"
npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-copy-inno-updater"
name: build
- powershell: |
$ErrorActionPreference = "Stop"
npm run gulp -- "electron-$(VSCODE_ARCH)"
.\scripts\test.bat --build --tfs
# yarn smoketest -- --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
name: test
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs:
ConnectedServiceName: 'ESRP CodeSign'
FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)'
Pattern: '*.dll,*.exe,*.node'
signConfigType: inlineSignParams
inlineOperation: |
[
{
"keyCode": "CP-229803",
"operationSetCode": "SigntoolSign",
"parameters": [
{
"parameterName": "OpusName",
"parameterValue": "VS Code"
},
{
"parameterName": "OpusInfo",
"parameterValue": "https://code.visualstudio.com/"
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/t \"http://ts4096.gtm.microsoft.com/TSS/AuthenticodeTS\""
}
],
"toolName": "sign",
"toolVersion": "1.0"
},
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolSign",
"parameters": [
{
"parameterName": "OpusName",
"parameterValue": "VS Code"
},
{
"parameterName": "OpusInfo",
"parameterValue": "https://code.visualstudio.com/"
},
{
"parameterName": "Append",
"parameterValue": "/as"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"toolName": "sign",
"toolVersion": "1.0"
},
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolVerify",
"parameters": [
{
"parameterName": "VerifyAll",
"parameterValue": "/all"
}
],
"toolName": "sign",
"toolVersion": "1.0"
}
]
SessionTimeout: 120
- powershell: |
$ErrorActionPreference = "Stop"
npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-archive" "vscode-win32-$(VSCODE_ARCH)-setup"
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs:
ConnectedServiceName: 'ESRP CodeSign'
FolderPath: '$(agent.builddirectory)'
Pattern: VSCodeSetup.exe
signConfigType: inlineSignParams
inlineOperation: |
[
{
"keyCode": "CP-229803",
"operationSetCode": "SigntoolSign",
"parameters": [
{
"parameterName": "OpusName",
"parameterValue": "VS Code"
},
{
"parameterName": "OpusInfo",
"parameterValue": "https://code.visualstudio.com/"
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/t \"http://ts4096.gtm.microsoft.com/TSS/AuthenticodeTS\""
}
],
"toolName": "sign",
"toolVersion": "1.0"
},
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolSign",
"parameters": [
{
"parameterName": "OpusName",
"parameterValue": "VS Code"
},
{
"parameterName": "OpusInfo",
"parameterValue": "https://code.visualstudio.com/"
},
{
"parameterName": "Append",
"parameterValue": "/as"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"toolName": "sign",
"toolVersion": "1.0"
},
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolVerify",
"parameters": [
{
"parameterName": "VerifyAll",
"parameterValue": "/all"
}
],
"toolName": "sign",
"toolVersion": "1.0"
}
]
SessionTimeout: 120
- powershell: |
$ErrorActionPreference = "Stop"
$Repo = "$(pwd)"
$Root = "$Repo\.."
$Exe = "$Repo\.build\win32-$(VSCODE_ARCH)\setup\VSCodeSetup.exe"
$Zip = "$Repo\.build\win32-$(VSCODE_ARCH)\archive\VSCode-win32-$(VSCODE_ARCH).zip"
$Build = "$Root\VSCode-win32-$(VSCODE_ARCH)"
# get version
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
$Version = $PackageJson.version
$Quality = "$env:VSCODE_QUALITY"
$env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)"
$env:MOONCAKE_STORAGE_ACCESS_KEY = "$(MOONCAKE_STORAGE_ACCESS_KEY)"
$env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)"
$assetPlatform = if ("$(VSCODE_ARCH)" -eq "ia32") { "win32" } else { "win32-x64" }
node build/tfs/common/publish.js $Quality "$global:assetPlatform-archive" archive "VSCode-win32-$(VSCODE_ARCH)-$Version.zip" $Version true $Zip
node build/tfs/common/publish.js $Quality "$global:assetPlatform" setup "VSCodeSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $Exe
# publish hockeyapp symbols
$hockeyAppId = if ("$(VSCODE_ARCH)" -eq "ia32") { "$(VSCODE_HOCKEYAPP_ID_WIN32)" } else { "$(VSCODE_HOCKEYAPP_ID_WIN64)" }
node build/tfs/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" $hockeyAppId
- phase: Linux
condition: eq(variables['VSCODE_BUILD_LINUX'], 'true')
queue: linux-x64
variables:
VSCODE_ARCH: x64
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- script: |
set -e
export npm_config_arch="$(VSCODE_ARCH)"
if [[ "$(VSCODE_ARCH)" == "ia32" ]]; then
export PKG_CONFIG_PATH="/usr/lib/i386-linux-gnu/pkgconfig"
fi
echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc
yarn
npm run gulp -- hygiene
npm run monaco-compile-check
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin
node build/tfs/common/installDistro.js
node build/lib/builtInExtensions.js
- script: |
set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-linux-$(VSCODE_ARCH)-min
name: build
- script: |
set -e
npm run gulp -- "electron-$(VSCODE_ARCH)"
DISPLAY=:10 ./scripts/test.sh --build --tfs
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)"
name: test
- script: |
set -e
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb"
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm"
#npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-snap"
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
./build/tfs/linux/release2.sh "$(VSCODE_ARCH)" "$(LINUX_REPO_PASSWORD)"
# publish hockeyapp symbols
node build/tfs/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_LINUX64)"
- phase: Linux32
condition: eq(variables['VSCODE_BUILD_LINUX'], 'true')
queue: linux-ia32
variables:
VSCODE_ARCH: ia32
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- script: |
set -e
export npm_config_arch="$(VSCODE_ARCH)"
if [[ "$(VSCODE_ARCH)" == "ia32" ]]; then
export PKG_CONFIG_PATH="/usr/lib/i386-linux-gnu/pkgconfig"
fi
echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc
yarn
npm run gulp -- hygiene
npm run monaco-compile-check
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin
node build/tfs/common/installDistro.js
node build/lib/builtInExtensions.js
- script: |
set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-linux-$(VSCODE_ARCH)-min
name: build
- script: |
set -e
npm run gulp -- "electron-$(VSCODE_ARCH)"
DISPLAY=:10 ./scripts/test.sh --build --tfs
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)"
name: test
- script: |
set -e
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb"
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm"
#npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-snap"
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
./build/tfs/linux/release2.sh "$(VSCODE_ARCH)" "$(LINUX_REPO_PASSWORD)"
# publish hockeyapp symbols
node build/tfs/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_LINUX32)"
- phase: macOS
condition: eq(variables['VSCODE_BUILD_MACOS'], 'true')
queue: Hosted macOS Preview
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- script: |
set -e
echo "machine monacotools.visualstudio.com password $(VSO_PAT)" > ~/.netrc
yarn
npm run gulp -- hygiene
npm run monaco-compile-check
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin
node build/tfs/common/installDistro.js
node build/lib/builtInExtensions.js
- script: |
set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
npm run gulp -- vscode-darwin-min upload-vscode-sourcemaps
name: build
- script: |
set -e
./scripts/test.sh --build --tfs
APP_NAME="`ls $(agent.builddirectory)/VSCode-darwin | head -n 1`"
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-darwin/$APP_NAME"
name: test
- script: |
set -e
# archive the unsigned build
pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin-unsigned.zip * && popd
# publish the unsigned build
PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json`
VERSION=`node -p "require(\"$PACKAGEJSON\").version"`
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/tfs/common/publish.js \
"$(VSCODE_QUALITY)" \
darwin \
archive-unsigned \
"VSCode-darwin-$(VSCODE_QUALITY)-unsigned.zip" \
$VERSION \
false \
../VSCode-darwin-unsigned.zip
# publish hockeyapp symbols
node build/tfs/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_MACOS)"
# enqueue the unsigned build
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
node build/tfs/common/enqueue.js "$(VSCODE_QUALITY)"
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
npm run gulp -- upload-vscode-configuration

212
build/tfs/win32/build.yml Normal file
View File

@@ -0,0 +1,212 @@
steps:
- task: NodeTool@0
inputs:
versionSpec: "8.9.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.3.2"
- powershell: |
"machine monacotools.visualstudio.com password $(VSO_PAT)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
$env:npm_config_arch="$(VSCODE_ARCH)"
$env:CHILD_CONCURRENCY="1"
yarn
npm run gulp -- hygiene
npm run monaco-compile-check
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
npm run gulp -- mixin
node build/tfs/common/installDistro.js
- powershell: |
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-min"
npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-copy-inno-updater"
name: build
- powershell: |
npm run gulp -- "electron-$(VSCODE_ARCH)"
.\scripts\test.bat --build --tfs
name: test
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs:
ConnectedServiceName: 'ESRP CodeSign'
FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)'
Pattern: '*.dll,*.exe,*.node'
signConfigType: inlineSignParams
inlineOperation: |
[
{
"keyCode": "CP-229803",
"operationSetCode": "SigntoolSign",
"parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/t \"http://ts4096.gtm.microsoft.com/TSS/AuthenticodeTS\""
}
],
"toolName": "sign",
"toolVersion": "1.0"
},
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolSign",
"parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "Append",
"parameterValue": "/as"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"toolName": "sign",
"toolVersion": "1.0"
},
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolVerify",
"parameters": [
{
"parameterName": "VerifyAll",
"parameterValue": "/all"
}
],
"toolName": "sign",
"toolVersion": "1.0"
}
]
SessionTimeout: 120
- powershell: |
npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-archive" "vscode-win32-$(VSCODE_ARCH)-setup"
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs:
ConnectedServiceName: 'ESRP CodeSign'
FolderPath: '$(agent.builddirectory)'
Pattern: VSCodeSetup.exe
signConfigType: inlineSignParams
inlineOperation: |
[
{
"keyCode": "CP-229803",
"operationSetCode": "SigntoolSign",
"parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/t \"http://ts4096.gtm.microsoft.com/TSS/AuthenticodeTS\""
}
],
"toolName": "sign",
"toolVersion": "1.0"
},
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolSign",
"parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "Append",
"parameterValue": "/as"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"toolName": "sign",
"toolVersion": "1.0"
},
{
"keyCode": "CP-230012",
"operationSetCode": "SigntoolVerify",
"parameters": [
{
"parameterName": "VerifyAll",
"parameterValue": "/all"
}
],
"toolName": "sign",
"toolVersion": "1.0"
}
]
SessionTimeout: 120
- powershell: |
$Repo = "$(pwd)"
$Root = "$Repo\.."
$Exe = "$Repo\.build\win32-$(VSCODE_ARCH)\setup\VSCodeSetup.exe"
$Zip = "$Repo\.build\win32-$(VSCODE_ARCH)\archive\VSCode-win32-$(VSCODE_ARCH).zip"
$Build = "$Root\VSCode-win32-$(VSCODE_ARCH)"
# get version
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
$Version = $PackageJson.version
$Quality = "$env:VSCODE_QUALITY"
$env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)"
$env:MOONCAKE_STORAGE_ACCESS_KEY = "$(MOONCAKE_STORAGE_ACCESS_KEY)"
$env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)"
$assetPlatform = if ("$(VSCODE_ARCH)" -eq "ia32") { "win32" } else { "win32-x64" }
node build/tfs/common/publish.js $Quality "$global:assetPlatform-archive" archive "VSCode-win32-$(VSCODE_ARCH)-$Version.zip" $Version true $Zip
node build/tfs/common/publish.js $Quality "$global:assetPlatform" setup "VSCodeSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $Exe

View File

@@ -7,7 +7,6 @@
"preserveConstEnums": true,
"sourceMap": false,
"experimentalDecorators": true,
"newLine": "LF",
// enable JavaScript type checking for the language service
// use the tsconfig.build.json for compiling wich disable JavaScript
// type checking so that JavaScript file are not transpiled

814
build/win32/OSSREADME.json Normal file → Executable file
View File

@@ -1,198 +1,10 @@
[
{
"name": "dtolnay/isatty",
"version": "0.1.6",
"repositoryUrl": "https://github.com/dtolnay/isatty",
"name": "Amanieu/thread_local-rs",
"version": "0.3.5",
"repositoryUrl": "https://github.com/Amanieu/thread_local-rs",
"licenseDetail": [
"Copyright (c) 2016",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-num/num-integer",
"version": "0.1.35",
"repositoryUrl": "https://github.com/rust-num/num-integer",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-lang-nursery/lazy-static.rs",
"version": "1.0.0",
"repositoryUrl": "https://github.com/rust-lang-nursery/lazy-static.rs",
"licenseDetail": [
"Copyright (c) 2010 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-lang/libc",
"version": "0.2.36",
"repositoryUrl": "https://github.com/rust-lang/libc",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "retep998/winapi-rs",
"version": "0.2.2",
"repositoryUrl": "https://github.com/retep998/winapi-rs",
"licenseDetail": [
"Copyright (c) 2015 The winapi-rs Developers",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in all",
"copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
"SOFTWARE."
],
"isProd": true
},
{
"name": "mrhooray/crc-rs",
"version": "1.7.0",
"repositoryUrl": "https://github.com/mrhooray/crc-rs.git",
"licenseDetail": [
"MIT License",
"",
"Copyright (c) 2017 crc-rs Developers",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in all",
"copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
"SOFTWARE."
],
"isProd": true
},
{
"name": "rust-num/num",
"version": "0.1.41",
"repositoryUrl": "https://github.com/rust-num/num",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"Copyright (c) 2016 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
@@ -250,141 +62,13 @@
"isProd": true
},
{
"name": "rust-num/num-traits",
"version": "0.1.42",
"repositoryUrl": "https://github.com/rust-num/num-traits",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "slog-rs/slog",
"version": "2.1.1",
"repositoryUrl": "https://github.com/slog-rs/slog",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-num/num-iter",
"version": "0.1.34",
"repositoryUrl": "https://github.com/rust-num/num-iter",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "vitiral/build_const",
"name": "Sgeo/take_mut",
"version": "0.2.0",
"repositoryUrl": "https://github.com/vitiral/build_const",
"repositoryUrl": "https://github.com/Sgeo/take_mut",
"licenseDetail": [
"The Source EULA",
"",
"Copyright (c) 2017 Garrett Berg, vitiral@gmail.com",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in",
"all copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN",
"THE SOFTWARE."
],
"isProd": true
},
{
"name": "redox-os/termios",
"version": "0.1.1",
"repositoryUrl": "https://github.com/redox-os/termios",
"licenseDetail": [
"MIT License",
"",
"Copyright (c) 2017 Redox OS",
"Copyright (c) 2016 Sgeo",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
@@ -406,36 +90,6 @@
],
"isProd": true
},
{
"name": "redox-os/syscall",
"version": "0.1.37",
"repositoryUrl": "https://github.com/redox-os/syscall",
"licenseDetail": [
"Copyright (c) 2017 Redox OS Developers",
"",
"MIT License",
"",
"Permission is hereby granted, free of charge, to any person obtaining",
"a copy of this software and associated documentation files (the",
"\"Software\"), to deal in the Software without restriction, including",
"without limitation the rights to use, copy, modify, merge, publish,",
"distribute, sublicense, and/or sell copies of the Software, and to",
"permit persons to whom the Software is furnished to do so, subject to",
"the following conditions:",
"",
"The above copyright notice and this permission notice shall be",
"included in all copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,",
"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF",
"MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND",
"NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE",
"LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION",
"WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "Stebalien/term",
"version": "0.4.6",
@@ -717,11 +371,11 @@
"isProd": true
},
{
"name": "Amanieu/thread_local-rs",
"version": "0.3.5",
"repositoryUrl": "https://github.com/Amanieu/thread_local-rs",
"name": "dtolnay/isatty",
"version": "0.1.6",
"repositoryUrl": "https://github.com/dtolnay/isatty",
"licenseDetail": [
"Copyright (c) 2016 The Rust Project Developers",
"Copyright (c) 2016",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
@@ -750,13 +404,13 @@
"isProd": true
},
{
"name": "Sgeo/take_mut",
"version": "0.2.0",
"repositoryUrl": "https://github.com/Sgeo/take_mut",
"name": "mrhooray/crc-rs",
"version": "1.7.0",
"repositoryUrl": "https://github.com/mrhooray/crc-rs.git",
"licenseDetail": [
"The Source EULA",
"MIT License",
"",
"Copyright (c) 2016 Sgeo",
"Copyright (c) 2017 crc-rs Developers",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
@@ -779,11 +433,43 @@
"isProd": true
},
{
"name": "reem/rust-void",
"version": "1.0.2",
"repositoryUrl": "https://github.com/reem/rust-void.git",
"name": "redox-os/syscall",
"version": "0.1.37",
"repositoryUrl": "https://github.com/redox-os/syscall",
"licenseDetail": [
"Copyright (c) 2015 The rust-void Developers",
"Copyright (c) 2017 Redox OS Developers",
"",
"MIT License",
"",
"Permission is hereby granted, free of charge, to any person obtaining",
"a copy of this software and associated documentation files (the",
"\"Software\"), to deal in the Software without restriction, including",
"without limitation the rights to use, copy, modify, merge, publish,",
"distribute, sublicense, and/or sell copies of the Software, and to",
"permit persons to whom the Software is furnished to do so, subject to",
"the following conditions:",
"",
"The above copyright notice and this permission notice shall be",
"included in all copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,",
"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF",
"MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND",
"NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE",
"LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION",
"WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "redox-os/termios",
"version": "0.1.1",
"repositoryUrl": "https://github.com/redox-os/termios",
"licenseDetail": [
"MIT License",
"",
"Copyright (c) 2017 Redox OS",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
@@ -833,46 +519,11 @@
"isProd": true
},
{
"name": "rust-lang/time",
"version": "0.1.39",
"repositoryUrl": "https://github.com/rust-lang/time",
"name": "reem/rust-void",
"version": "1.0.2",
"repositoryUrl": "https://github.com/reem/rust-void.git",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "ticki/termion",
"version": "1.5.1",
"repositoryUrl": "https://github.com/ticki/termion",
"licenseDetail": [
"The Source EULA",
"",
"Copyright (c) 2016 Ticki",
"Copyright (c) 2015 The rust-void Developers",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
@@ -896,7 +547,7 @@
},
{
"name": "retep998/winapi-rs",
"version": "0.2.8",
"version": "0.3.4",
"repositoryUrl": "https://github.com/retep998/winapi-rs",
"licenseDetail": [
"Copyright (c) 2015 The winapi-rs Developers",
@@ -923,7 +574,7 @@
},
{
"name": "retep998/winapi-rs",
"version": "0.3.4",
"version": "0.2.8",
"repositoryUrl": "https://github.com/retep998/winapi-rs",
"licenseDetail": [
"Copyright (c) 2015 The winapi-rs Developers",
@@ -1029,6 +680,264 @@
],
"isProd": true
},
{
"name": "retep998/winapi-rs",
"version": "0.2.2",
"repositoryUrl": "https://github.com/retep998/winapi-rs",
"licenseDetail": [
"Copyright (c) 2015 The winapi-rs Developers",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in all",
"copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
"SOFTWARE."
],
"isProd": true
},
{
"name": "rust-lang-nursery/lazy-static.rs",
"version": "1.0.0",
"repositoryUrl": "https://github.com/rust-lang-nursery/lazy-static.rs",
"licenseDetail": [
"Copyright (c) 2010 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-lang/libc",
"version": "0.2.36",
"repositoryUrl": "https://github.com/rust-lang/libc",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-lang/time",
"version": "0.1.39",
"repositoryUrl": "https://github.com/rust-lang/time",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-num/num",
"version": "0.1.41",
"repositoryUrl": "https://github.com/rust-num/num",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-num/num-integer",
"version": "0.1.35",
"repositoryUrl": "https://github.com/rust-num/num-integer",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-num/num-iter",
"version": "0.1.34",
"repositoryUrl": "https://github.com/rust-num/num-iter",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "rust-num/num-traits",
"version": "0.1.42",
"repositoryUrl": "https://github.com/rust-num/num-traits",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "slog-rs/async",
"version": "2.2.0",
@@ -1410,6 +1319,39 @@
],
"isProd": true
},
{
"name": "slog-rs/slog",
"version": "2.1.1",
"repositoryUrl": "https://github.com/slog-rs/slog",
"licenseDetail": [
"Copyright (c) 2014 The Rust Project Developers",
"",
"Permission is hereby granted, free of charge, to any",
"person obtaining a copy of this software and associated",
"documentation files (the \"Software\"), to deal in the",
"Software without restriction, including without",
"limitation the rights to use, copy, modify, merge,",
"publish, distribute, sublicense, and/or sell copies of",
"the Software, and to permit persons to whom the Software",
"is furnished to do so, subject to the following",
"conditions:",
"",
"The above copyright notice and this permission notice",
"shall be included in all copies or substantial portions",
"of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF",
"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED",
"TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A",
"PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT",
"SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY",
"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR",
"IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER",
"DEALINGS IN THE SOFTWARE."
],
"isProd": true
},
{
"name": "slog-rs/term",
"version": "2.3.0",
@@ -1790,5 +1732,63 @@
" defined by the Mozilla Public License, v. 2.0."
],
"isProd": true
},
{
"name": "ticki/termion",
"version": "1.5.1",
"repositoryUrl": "https://github.com/ticki/termion",
"licenseDetail": [
"The MIT License (MIT)",
"",
"Copyright (c) 2016 Ticki",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in all",
"copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
"SOFTWARE."
],
"isProd": true
},
{
"name": "vitiral/build_const",
"version": "0.2.0",
"repositoryUrl": "https://github.com/vitiral/build_const",
"licenseDetail": [
"The MIT License (MIT)",
"",
"Copyright (c) 2017 Garrett Berg, vitiral@gmail.com",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in",
"all copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN",
"THE SOFTWARE."
],
"isProd": true
}
]

Binary file not shown.

View File

@@ -8,6 +8,10 @@
dependencies:
"@types/node" "*"
"@types/caseless@*":
version "0.12.1"
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.1.tgz#9794c69c8385d0192acc471a540d1f8e0d16218a"
"@types/documentdb@1.10.2":
version "1.10.2"
resolved "https://registry.yarnpkg.com/@types/documentdb/-/documentdb-1.10.2.tgz#6795025cdc51577af5ed531b6f03bd44404f5350"
@@ -22,6 +26,12 @@
version "0.0.33"
resolved "https://registry.yarnpkg.com/@types/es6-promise/-/es6-promise-0.0.33.tgz#280a707e62b1b6bef1a86cc0861ec63cd06c7ff3"
"@types/form-data@*":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e"
dependencies:
"@types/node" "*"
"@types/mime@0.0.29":
version "0.0.29"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-0.0.29.tgz#fbcfd330573b912ef59eeee14602bface630754b"
@@ -34,6 +44,19 @@
version "8.0.33"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd"
"@types/request@^2.47.0":
version "2.47.0"
resolved "https://registry.yarnpkg.com/@types/request/-/request-2.47.0.tgz#76a666cee4cb85dcffea6cd4645227926d9e114e"
dependencies:
"@types/caseless" "*"
"@types/form-data" "*"
"@types/node" "*"
"@types/tough-cookie" "*"
"@types/tough-cookie@*":
version "2.3.3"
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.3.tgz#7f226d67d654ec9070e755f46daebf014628e9d9"
"@types/xml2js@0.0.33":
version "0.0.33"
resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.0.33.tgz#20c5dd6460245284d64a55690015b95e409fb7de"
@@ -331,6 +354,10 @@ color-support@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
colors@^1.1.2:
version "1.3.0"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.0.tgz#5f20c9fef6945cb1134260aab33bfbdc8295e04e"
combined-stream@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818"
@@ -707,6 +734,15 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
github-releases@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/github-releases/-/github-releases-0.4.1.tgz#4a13bdf85c4161344271db3d81db08e7379102ff"
dependencies:
minimatch "3.0.4"
optimist "0.6.1"
prettyjson "1.2.1"
request "2.81.0"
glob-base@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
@@ -1362,7 +1398,7 @@ mime@^1.3.4:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4:
"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
@@ -1376,6 +1412,10 @@ minimist@^1.1.0, minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
minimist@~0.0.1:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
@@ -1453,6 +1493,13 @@ once@^1.3.0, once@^1.4.0:
dependencies:
wrappy "1"
optimist@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
dependencies:
minimist "~0.0.1"
wordwrap "~0.0.2"
ordered-read-streams@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b"
@@ -1531,6 +1578,13 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
prettyjson@1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.1.tgz#fcffab41d19cab4dfae5e575e64246619b12d289"
dependencies:
colors "^1.1.2"
minimist "^1.2.0"
priorityqueuejs@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz#2ee4f23c2560913e08c07ce5ccdd6de3df2c5af8"
@@ -1649,6 +1703,33 @@ replace-ext@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
request@2.81.0, request@~2.81.0:
version "2.81.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.0"
forever-agent "~0.6.1"
form-data "~2.1.1"
har-validator "~4.2.1"
hawk "~3.1.3"
http-signature "~1.1.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
performance-now "^0.2.0"
qs "~6.4.0"
safe-buffer "^5.0.1"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
tunnel-agent "^0.6.0"
uuid "^3.0.0"
request@^2.83.0:
version "2.85.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa"
@@ -1676,6 +1757,31 @@ request@^2.83.0:
tunnel-agent "^0.6.0"
uuid "^3.1.0"
request@^2.85.0:
version "2.87.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e"
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.6.0"
caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.1"
forever-agent "~0.6.1"
form-data "~2.3.1"
har-validator "~5.0.3"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.17"
oauth-sign "~0.8.2"
performance-now "^2.1.0"
qs "~6.5.1"
safe-buffer "^5.1.1"
tough-cookie "~2.3.3"
tunnel-agent "^0.6.0"
uuid "^3.1.0"
request@~2.79.0:
version "2.79.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
@@ -1701,33 +1807,6 @@ request@~2.79.0:
tunnel-agent "~0.4.1"
uuid "^3.0.0"
request@~2.81.0:
version "2.81.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.0"
forever-agent "~0.6.1"
form-data "~2.1.1"
har-validator "~4.2.1"
hawk "~3.1.3"
http-signature "~1.1.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
performance-now "^0.2.0"
qs "~6.4.0"
safe-buffer "^5.0.1"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
tunnel-agent "^0.6.0"
uuid "^3.0.0"
requires-port@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
@@ -1978,9 +2057,9 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
typescript@2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.1.tgz#ef39cdea27abac0b500242d6726ab90e0c846631"
typescript@2.8.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624"
unbzip2-stream@^1.0.9:
version "1.2.5"
@@ -2129,6 +2208,10 @@ vscode@^1.0.1:
url-parse "^1.1.9"
vinyl-source-stream "^1.1.0"
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"

View File

@@ -1,23 +1,20 @@
{
"name": "agent",
"displayName": "SQL Server Agent",
"description": "Manage and troubleshoot SQL Server Agent jobs (early preview)",
"version": "0.29.0",
"description": "Manage and troubleshoot SQL Server Agent jobs",
"version": "0.31.1",
"publisher": "Microsoft",
"preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/LICENSE.txt",
"icon": "images/sqlserver.png",
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
"engines": {
"vscode": "0.10.x"
"vscode": "0.10.x"
},
"activationEvents": [
"*"
],
"main": "./client/out/main",
"scripts": {
"compile": "gulp compile-extension:agent-client"
},
"main": "./out/main",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/sqlopsstudio.git"
@@ -29,22 +26,32 @@
"outputChannels": [
"sqlagent"
],
"commands": [
{
"command": "agent.openNewStepDialog",
"title": "agent.openNewStepDialog"
}
],
"dashboard.tabs": [
{
"id": "data-management-agent",
"description": "Manage and troubleshoot SQL Agent jobs",
"provider": "MSSQL",
"title": "SQL Agent",
"when": "connectionProvider == 'MSSQL' && !mssql:iscloud",
"container": {
"controlhost-container": {
"type": "agent"
}
}
{
"id": "data-management-agent",
"description": "Manage and troubleshoot SQL Agent jobs",
"provider": "MSSQL",
"title": "SQL Agent",
"when": "connectionProvider == 'MSSQL' && !mssql:iscloud",
"container": {
"controlhost-container": {
"type": "agent"
}
}
}
]
},
"dependencies": {
"vscode-nls": "^3.2.1"
},
"devDependencies": {
"vscode": "1.0.1"
}
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7"
}
}

View File

@@ -0,0 +1,38 @@
'use strict';
import * as sqlops from 'sqlops';
export class AgentUtils {
private static _agentService: sqlops.AgentServicesProvider;
private static _connectionService: sqlops.ConnectionProvider;
private static _queryProvider: sqlops.QueryProvider;
public static async getAgentService(): Promise<sqlops.AgentServicesProvider> {
if (!AgentUtils._agentService) {
let currentConnection = await sqlops.connection.getCurrentConnection();
this._agentService = sqlops.dataprotocol.getProvider<sqlops.AgentServicesProvider>(currentConnection.providerName, sqlops.DataProviderType.AgentServicesProvider);
}
return AgentUtils._agentService;
}
public static async getDatabases(ownerUri: string): Promise<string[]> {
if (!AgentUtils._connectionService) {
let currentConnection = await sqlops.connection.getCurrentConnection();
this._connectionService = sqlops.dataprotocol.getProvider<sqlops.ConnectionProvider>(currentConnection.providerName, sqlops.DataProviderType.ConnectionProvider);
}
return AgentUtils._connectionService.listDatabases(ownerUri).then(result => {
if (result && result.databaseNames && result.databaseNames.length > 0) {
return result.databaseNames;
}
});
}
public static async getQueryProvider(): Promise<sqlops.QueryProvider> {
if (!AgentUtils._queryProvider) {
let currentConnection = await sqlops.connection.getCurrentConnection();
this._queryProvider = sqlops.dataprotocol.getProvider<sqlops.QueryProvider>(currentConnection.providerName, sqlops.DataProviderType.QueryProvider);
}
return this._queryProvider;
}
}

View File

@@ -0,0 +1,117 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vscode-nls';
import * as vscode from 'vscode';
import * as sqlops from 'sqlops';
import { AgentUtils } from '../agentUtils';
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
const localize = nls.loadMessageBundle();
export class AlertData implements IAgentDialogData {
ownerUri: string;
dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
id: number;
name: string;
originalName: string;
delayBetweenResponses: number;
eventDescriptionKeyword: string;
eventSource: string;
hasNotification: number;
includeEventDescription: string;
isEnabled: boolean;
jobId: string;
jobName: string;
lastOccurrenceDate: string;
lastResponseDate: string;
messageId: number;
notificationMessage: string;
occurrenceCount: number;
performanceCondition: string;
severity: number;
databaseName: string;
countResetDate: string;
categoryName: string;
alertType: string;
wmiEventNamespace: string;
wmiEventQuery: string;
constructor(ownerUri:string, alertInfo: sqlops.AgentAlertInfo) {
this.ownerUri = ownerUri;
if (alertInfo) {
this.dialogMode = AgentDialogMode.EDIT;
this.id = alertInfo.id;
this.name = alertInfo.name;
this.originalName = alertInfo.name;
this.delayBetweenResponses = alertInfo.delayBetweenResponses;
this.eventDescriptionKeyword = alertInfo.eventDescriptionKeyword;
this.eventSource = alertInfo.eventSource;
this.hasNotification = alertInfo.hasNotification;
this.includeEventDescription = alertInfo.includeEventDescription.toString();
this.isEnabled = alertInfo.isEnabled;
this.jobId = alertInfo.jobId;
this.jobName = alertInfo.jobName;
this.lastOccurrenceDate = alertInfo.lastOccurrenceDate;
this.lastResponseDate = alertInfo.lastResponseDate;
this.messageId = alertInfo.messageId;
this.notificationMessage = alertInfo.notificationMessage;
this.occurrenceCount = alertInfo.occurrenceCount;
this.performanceCondition = alertInfo.performanceCondition;
this.severity = alertInfo.severity;
this.databaseName = alertInfo.databaseName;
this.countResetDate = alertInfo.countResetDate;
this.categoryName = alertInfo.categoryName;
this.alertType = alertInfo.alertType.toString();
this.wmiEventNamespace = alertInfo.wmiEventNamespace;
this.wmiEventQuery = alertInfo.wmiEventQuery;
}
}
public async initialize() {
}
public async save() {
let agentService = await AgentUtils.getAgentService();
let result = this.dialogMode === AgentDialogMode.CREATE
? await agentService.createAlert(this.ownerUri, this.toAgentAlertInfo())
: await agentService.updateAlert(this.ownerUri, this.originalName, this.toAgentAlertInfo());
if (!result || !result.success) {
vscode.window.showErrorMessage(
localize('alertData.saveErrorMessage', "Alert update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
}
}
public toAgentAlertInfo(): sqlops.AgentAlertInfo {
return {
id: this.id,
name: this.name,
delayBetweenResponses: this.delayBetweenResponses,
eventDescriptionKeyword: this.eventDescriptionKeyword,
eventSource: this.eventSource,
hasNotification: this.hasNotification,
includeEventDescription: sqlops.NotifyMethods.none, // this.includeEventDescription,
isEnabled: this.isEnabled,
jobId: this.jobId,
jobName: this.jobName,
lastOccurrenceDate: this.lastOccurrenceDate,
lastResponseDate: this.lastResponseDate,
messageId: this.messageId,
notificationMessage: this.notificationMessage,
occurrenceCount: this.occurrenceCount,
performanceCondition: this.performanceCondition,
severity: this.severity,
databaseName: this.databaseName,
countResetDate: this.countResetDate,
categoryName: this.categoryName,
alertType: sqlops.AlertType.sqlServerEvent, //this.alertType,
wmiEventNamespace: this.wmiEventNamespace,
wmiEventQuery: this.wmiEventQuery
};
}
}

View File

@@ -0,0 +1,151 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import { AgentUtils } from '../agentUtils';
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
export class JobData implements IAgentDialogData {
private readonly JobCompletionActionCondition_Always: string = 'When the job completes';
private readonly JobCompletionActionCondition_OnFailure: string = 'When the job fails';
private readonly JobCompletionActionCondition_OnSuccess: string = 'When the job succeeds';
// Error Messages
private readonly CreateJobErrorMessage_NameIsEmpty = 'Job name must be provided';
private _ownerUri: string;
private _jobCategories: string[];
private _operators: string[];
private _defaultOwner: string;
private _jobCompletionActionConditions: sqlops.CategoryValue[];
public dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
public name: string;
public enabled: boolean = true;
public description: string;
public category: string;
public categoryId: number;
public owner: string;
public emailLevel: sqlops.JobCompletionActionCondition = sqlops.JobCompletionActionCondition.OnFailure;
public pageLevel: sqlops.JobCompletionActionCondition = sqlops.JobCompletionActionCondition.OnFailure;
public eventLogLevel: sqlops.JobCompletionActionCondition = sqlops.JobCompletionActionCondition.OnFailure;
public deleteLevel: sqlops.JobCompletionActionCondition = sqlops.JobCompletionActionCondition.OnSuccess;
public operatorToEmail: string;
public operatorToPage: string;
public jobSteps: sqlops.AgentJobStepInfo[];
public jobSchedules: sqlops.AgentJobScheduleInfo[];
public alerts: sqlops.AgentAlertInfo[];
constructor(ownerUri: string, private _agentService: sqlops.AgentServicesProvider = null) {
this._ownerUri = ownerUri;
}
public get jobCategories(): string[] {
return this._jobCategories;
}
public get operators(): string[] {
return this._operators;
}
public get ownerUri(): string {
return this._ownerUri;
}
public get defaultOwner(): string {
return this._defaultOwner;
}
public get JobCompletionActionConditions(): sqlops.CategoryValue[] {
return this._jobCompletionActionConditions;
}
public async initialize() {
this._agentService = await AgentUtils.getAgentService();
let jobDefaults = await this._agentService.getJobDefaults(this.ownerUri);
if (jobDefaults && jobDefaults.success) {
this._jobCategories = jobDefaults.categories.map((cat) => {
return cat.name;
});
this._defaultOwner = jobDefaults.owner;
this._operators = ['', this._defaultOwner];
}
this._jobCompletionActionConditions = [{
displayName: this.JobCompletionActionCondition_OnSuccess,
name: sqlops.JobCompletionActionCondition.OnSuccess.toString()
}, {
displayName: this.JobCompletionActionCondition_OnFailure,
name: sqlops.JobCompletionActionCondition.OnFailure.toString()
}, {
displayName: this.JobCompletionActionCondition_Always,
name: sqlops.JobCompletionActionCondition.Always.toString()
}];
this.jobSchedules = [];
}
public async save() {
await this._agentService.createJob(this.ownerUri, {
name: this.name,
owner: this.owner,
description: this.description,
EmailLevel: this.emailLevel,
PageLevel: this.pageLevel,
EventLogLevel: this.eventLogLevel,
DeleteLevel: this.deleteLevel,
OperatorToEmail: this.operatorToEmail,
OperatorToPage: this.operatorToPage,
enabled: this.enabled,
category: this.category,
Alerts: this.alerts,
JobSchedules: this.jobSchedules,
JobSteps: this.jobSteps,
// The properties below are not collected from UI
// We could consider using a seperate class for create job request
//
currentExecutionStatus: 0,
lastRunOutcome: 0,
currentExecutionStep: '',
hasTarget: true,
hasSchedule: false,
hasStep: false,
runnable: true,
categoryId: 0,
categoryType: 1, // LocalJob, hard-coding the value, corresponds to the target tab in SSMS
lastRun: '',
nextRun: '',
jobId: ''
}).then(result => {
if (!result.success) {
console.info(result.errorMessage);
}
});
}
public validate(): { valid: boolean, errorMessages: string[] } {
let validationErrors: string[] = [];
if (!(this.name && this.name.trim())) {
validationErrors.push(this.CreateJobErrorMessage_NameIsEmpty);
}
return {
valid: validationErrors.length === 0,
errorMessages: validationErrors
};
}
public addJobSchedule(schedule: sqlops.AgentJobScheduleInfo) {
let existingSchedule = this.jobSchedules.find(item => item.name === schedule.name);
if (!existingSchedule) {
this.jobSchedules.push(schedule);
}
}
}

View File

@@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { AgentUtils } from '../agentUtils';
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
export class JobStepData implements IAgentDialogData {
public dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
public ownerUri: string;
public jobId: string; //
public jobName: string;
public script: string; //
public scriptName: string;
public stepName: string; //
public subSystem: string; //
public id: number;
public failureAction: string; //
public successAction: string; //
public failStepId: number;
public successStepId: number;
public command: string;
public commandExecutionSuccessCode: number;
public databaseName: string; //
public databaseUserName: string;
public server: string;
public outputFileName: string; //
public appendToLogFile: boolean;
public appendToStepHist: boolean;
public writeLogToTable: boolean;
public appendLogToTable: boolean;
public retryAttempts: number; //
public retryInterval: number; //
public proxyName: string;
constructor(ownerUri:string) {
this.ownerUri = ownerUri;
}
public async initialize() {
}
public async save() {
let agentService = await AgentUtils.getAgentService();
agentService.createJobStep(this.ownerUri, {
jobId: this.jobId,
jobName: this.jobName,
script: this.script,
scriptName: this.scriptName,
stepName: this.stepName,
subSystem: this.subSystem,
id: 1,
failureAction: this.failureAction,
successAction: this.successAction,
failStepId: this.failStepId,
successStepId: this.successStepId,
command: this.command,
commandExecutionSuccessCode: this.commandExecutionSuccessCode,
databaseName: this.databaseName,
databaseUserName: this.databaseUserName,
server: this.server,
outputFileName: this.outputFileName,
appendToLogFile: this.appendToLogFile,
appendToStepHist: this.appendToStepHist,
writeLogToTable: this.writeLogToTable,
appendLogToTable: this.appendLogToTable,
retryAttempts: this.retryAttempts,
retryInterval: this.retryInterval,
proxyName: this.proxyName
}).then(result => {
console.info(result);
});
}
}

View File

@@ -0,0 +1,68 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import { AgentUtils } from '../agentUtils';
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
export class OperatorData implements IAgentDialogData {
public dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
ownerUri: string;
name: string;
id: number;
emailAddress: string;
enabled: boolean;
lastEmailDate: string;
lastNetSendDate: string;
lastPagerDate: string;
pagerAddress: string;
categoryName: string;
pagerDays: string;
saturdayPagerEndTime: string;
saturdayPagerStartTime: string;
sundayPagerEndTime: string;
sundayPagerStartTime: string;
netSendAddress: string;
weekdayPagerStartTime: string;
weekdayPagerEndTime: string;
constructor(ownerUri:string) {
this.ownerUri = ownerUri;
}
public async initialize() {
}
public async save() {
let agentService = await AgentUtils.getAgentService();
let result = await agentService.createOperator(this.ownerUri, this.toAgentOperatorInfo());
if (!result || !result.success) {
// TODO handle error here
}
}
public toAgentOperatorInfo(): sqlops.AgentOperatorInfo {
return {
name: this.name,
id: this.id,
emailAddress: this.emailAddress,
enabled: this.enabled,
lastEmailDate: this.lastEmailDate,
lastNetSendDate: this.lastNetSendDate,
lastPagerDate: this.lastPagerDate,
pagerAddress: this.pagerAddress,
categoryName: this.categoryName,
pagerDays: sqlops.WeekDays.weekDays, //this.pagerDays,
saturdayPagerEndTime: this.saturdayPagerEndTime,
saturdayPagerStartTime: this.saturdayPagerStartTime,
sundayPagerEndTime: this.sundayPagerEndTime,
sundayPagerStartTime: this.sundayPagerStartTime,
netSendAddress: this.netSendAddress,
weekdayPagerStartTime: this.weekdayPagerStartTime,
weekdayPagerEndTime: this.weekdayPagerEndTime
};
}
}

View File

@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import { AgentUtils } from '../agentUtils';
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
export class PickScheduleData implements IAgentDialogData {
public dialogMode: AgentDialogMode = AgentDialogMode.VIEW;
public ownerUri: string;
public schedules: sqlops.AgentJobScheduleInfo[];
public selectedSchedule: sqlops.AgentJobScheduleInfo;
constructor(ownerUri:string) {
this.ownerUri = ownerUri;
}
public async initialize() {
let agentService = await AgentUtils.getAgentService();
let result = await agentService.getJobSchedules(this.ownerUri);
if (result && result.success) {
this.schedules = result.schedules;
}
}
public async save() {
}
}

View File

@@ -0,0 +1,48 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import { AgentUtils } from '../agentUtils';
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
export class ProxyData implements IAgentDialogData {
public dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
ownerUri: string;
id: number;
accountName: string;
description: string;
credentialName: string;
credentialIdentity: string;
credentialId: number;
isEnabled: boolean;
constructor(ownerUri:string) {
this.ownerUri = ownerUri;
}
public async initialize() {
}
public async save() {
let agentService = await AgentUtils.getAgentService();
let result = await agentService.createProxy(this.ownerUri, this.toAgentProxyInfo());
if (!result || !result.success) {
// TODO handle error here
}
}
public toAgentProxyInfo(): sqlops.AgentProxyInfo {
return {
id: this.id,
accountName: this.accountName,
description: this.description,
credentialName: this.credentialName,
credentialIdentity: this.credentialIdentity,
credentialId: this.credentialId,
isEnabled: this.isEnabled
};
}
}

View File

@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import { AgentUtils } from '../agentUtils';
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
export class ScheduleData implements IAgentDialogData {
public dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
public ownerUri: string;
public schedules: sqlops.AgentJobScheduleInfo[];
public selectedSchedule: sqlops.AgentJobScheduleInfo;
constructor(ownerUri:string) {
this.ownerUri = ownerUri;
}
public async initialize() {
let agentService = await AgentUtils.getAgentService();
let result = await agentService.getJobSchedules(this.ownerUri);
if (result && result.success) {
this.schedules = result.schedules;
}
}
public async save() {
}
}

View File

@@ -0,0 +1,78 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vscode-nls';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
const localize = nls.loadMessageBundle();
export abstract class AgentDialog<T extends IAgentDialogData> {
private static readonly OkButtonText: string = localize('agentDialog.OK', 'OK');
private static readonly CancelButtonText: string = localize('agentDialog.Cancel', 'Cancel');
protected _onSuccess: vscode.EventEmitter<T> = new vscode.EventEmitter<T>();
public readonly onSuccess: vscode.Event<T> = this._onSuccess.event;
public dialog: sqlops.window.modelviewdialog.Dialog;
constructor(public ownerUri: string, public model: T, public title: string) {
}
public get dialogMode(): AgentDialogMode {
return this.model.dialogMode;
}
protected abstract async updateModel();
protected abstract async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog);
public async openDialog() {
this.dialog = sqlops.window.modelviewdialog.createDialog(this.title);
await this.model.initialize();
await this.initializeDialog(this.dialog);
this.dialog.okButton.label = AgentDialog.OkButtonText;
this.dialog.okButton.onClick(async () => await this.execute());
this.dialog.cancelButton.label = AgentDialog.CancelButtonText;
this.dialog.cancelButton.onClick(async () => await this.cancel());
sqlops.window.modelviewdialog.openDialog(this.dialog);
}
protected async execute() {
this.updateModel();
let success = await this.model.save();
if (success) {
this._onSuccess.fire(this.model);
}
}
protected async cancel() {
}
protected getActualConditionValue(checkbox: sqlops.CheckBoxComponent, dropdown: sqlops.DropDownComponent): sqlops.JobCompletionActionCondition {
return checkbox.checked ? Number(this.getDropdownValue(dropdown)) : sqlops.JobCompletionActionCondition.Never;
}
protected getDropdownValue(dropdown: sqlops.DropDownComponent): string {
return (typeof dropdown.value === 'string') ? dropdown.value : dropdown.value.name;
}
protected setConditionDropdownSelectedValue(dropdown: sqlops.DropDownComponent, selectedValue: number) {
let idx: number = 0;
for (idx = 0; idx < dropdown.values.length; idx++) {
if (Number((<sqlops.CategoryValue>dropdown.values[idx]).name) === selectedValue) {
dropdown.value = dropdown.values[idx];
break;
}
}
}
}

View File

@@ -0,0 +1,355 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vscode-nls';
import * as sqlops from 'sqlops';
import { AgentDialog } from './agentDialog';
import { AgentUtils } from '../agentUtils';
import { AlertData } from '../data/alertData';
const localize = nls.loadMessageBundle();
export class AlertDialog extends AgentDialog<AlertData> {
// Top level
private static readonly CreateDialogTitle: string = localize('alertDialog.createAlert', 'Create Alert');
private static readonly EditDialogTitle: string = localize('alertDialog.editAlert', 'Edit Alert');
private static readonly GeneralTabText: string = localize('alertDialog.General', 'General');
private static readonly ResponseTabText: string = localize('alertDialog.Response', 'Response');
private static readonly OptionsTabText: string = localize('alertDialog.Options', 'Options');
// General tab strings
private static readonly NameLabel: string = localize('alertDialog.Name', 'Name');
private static readonly TypeLabel: string = localize('alertDialog.Type', 'Type');
private static readonly EnabledCheckboxLabel: string = localize('alertDialog.Enabled', 'Enabled');
private static readonly DatabaseLabel: string = localize('alertDialog.DatabaseName', 'Database name');
private static readonly ErrorNumberLabel: string = localize('alertDialog.ErrorNumber', 'Error number');
private static readonly SeverityLabel: string = localize('alertDialog.Severity', 'Severity');
private static readonly RaiseIfMessageContainsLabel: string = localize('alertDialog.RaiseAlertContains', 'Raise alert when message contains');
private static readonly MessageTextLabel: string = localize('alertDialog.MessageText', 'Message text');
private static readonly AlertTypeSqlServerEventString: string = localize('alertDialog.SqlServerEventAlert', 'SQL Server event alert');
private static readonly AlertTypePerformanceConditionString: string = localize('alertDialog.PerformanceCondition', 'SQL Server performance condition alert');
private static readonly AlertTypeWmiEventString: string = localize('alertDialog.WmiEvent', 'WMI event alert');
private static readonly AlertSeverity001Label: string = localize('alertDialog.Severity001', '001 - Miscellaneous System Information');
private static readonly AlertSeverity002Label: string = localize('alertDialog.Severity002', '002 - Reserved');
private static readonly AlertSeverity003Label: string = localize('alertDialog.Severity003', '003 - Reserved');
private static readonly AlertSeverity004Label: string = localize('alertDialog.Severity004', '004 - Reserved');
private static readonly AlertSeverity005Label: string = localize('alertDialog.Severity005', '005 - Reserved');
private static readonly AlertSeverity006Label: string = localize('alertDialog.Severity006', '006 - Reserved');
private static readonly AlertSeverity007Label: string = localize('alertDialog.Severity007', '007 - Notification: Status Information');
private static readonly AlertSeverity008Label: string = localize('alertDialog.Severity008', '008 - Notification: User Intervention Required');
private static readonly AlertSeverity009Label: string = localize('alertDialog.Severity009', '009 - User Defined');
private static readonly AlertSeverity010Label: string = localize('alertDialog.Severity010', '010 - Information');
private static readonly AlertSeverity011Label: string = localize('alertDialog.Severity011', '011 - Specified Database Object Not Found');
private static readonly AlertSeverity012Label: string = localize('alertDialog.Severity012', '012 - Unused');
private static readonly AlertSeverity013Label: string = localize('alertDialog.Severity013', '013 - User Transaction Syntax Error');
private static readonly AlertSeverity014Label: string = localize('alertDialog.Severity014', '014 - Insufficient Permission');
private static readonly AlertSeverity015Label: string = localize('alertDialog.Severity015', '015 - Syntax Error in SQL Statements');
private static readonly AlertSeverity016Label: string = localize('alertDialog.Severity016', '016 - Miscellaneous User Error');
private static readonly AlertSeverity017Label: string = localize('alertDialog.Severity017', '017 - Insufficient Resources');
private static readonly AlertSeverity018Label: string = localize('alertDialog.Severity018', '018 - Nonfatal Internal Error');
private static readonly AlertSeverity019Label: string = localize('alertDialog.Severity019', '019 - Fatal Error in Resource');
private static readonly AlertSeverity020Label: string = localize('alertDialog.Severity020', '020 - Fatal Error in Current Process');
private static readonly AlertSeverity021Label: string = localize('alertDialog.Severity021', '021 - Fatal Error in Database Processes');
private static readonly AlertSeverity022Label: string = localize('alertDialog.Severity022', '022 - Fatal Error: Table Integrity Suspect');
private static readonly AlertSeverity023Label: string = localize('alertDialog.Severity023', '023 - Fatal Error: Database Integrity Suspect');
private static readonly AlertSeverity024Label: string = localize('alertDialog.Severity024', '024 - Fatal Error: Hardware Error');
private static readonly AlertSeverity025Label: string = localize('alertDialog.Severity025', '025 - Fatal Error');
private static readonly AlertTypes: string[] = [
AlertDialog.AlertTypeSqlServerEventString,
AlertDialog.AlertTypePerformanceConditionString,
AlertDialog.AlertTypeWmiEventString
];
private static readonly AlertSeverities: string[] = [
AlertDialog.AlertSeverity001Label,
AlertDialog.AlertSeverity002Label,
AlertDialog.AlertSeverity003Label,
AlertDialog.AlertSeverity004Label,
AlertDialog.AlertSeverity005Label,
AlertDialog.AlertSeverity006Label,
AlertDialog.AlertSeverity007Label,
AlertDialog.AlertSeverity008Label,
AlertDialog.AlertSeverity009Label,
AlertDialog.AlertSeverity010Label,
AlertDialog.AlertSeverity011Label,
AlertDialog.AlertSeverity012Label,
AlertDialog.AlertSeverity013Label,
AlertDialog.AlertSeverity014Label,
AlertDialog.AlertSeverity015Label,
AlertDialog.AlertSeverity016Label,
AlertDialog.AlertSeverity017Label,
AlertDialog.AlertSeverity018Label,
AlertDialog.AlertSeverity019Label,
AlertDialog.AlertSeverity020Label,
AlertDialog.AlertSeverity021Label,
AlertDialog.AlertSeverity022Label,
AlertDialog.AlertSeverity023Label,
AlertDialog.AlertSeverity024Label,
AlertDialog.AlertSeverity025Label
];
// Response tab strings
private static readonly ExecuteJobCheckBoxLabel: string = localize('alertDialog.ExecuteJob', 'Execute Job');
private static readonly ExecuteJobTextBoxLabel: string = localize('alertDialog.ExecuteJobName', 'Job Name');
private static readonly NotifyOperatorsTextBoxLabel: string = localize('alertDialog.NotifyOperators', 'Notify Operators');
private static readonly NewJobButtonLabel: string = localize('alertDialog.NewJob', 'New Job');
private static readonly OperatorListLabel: string = localize('alertDialog.OperatorList', 'Operator List');
private static readonly OperatorNameColumnLabel: string = localize('alertDialog.OperatorName', 'Operator');
private static readonly OperatorEmailColumnLabel: string = localize('alertDialog.OperatorEmail', 'E-mail');
private static readonly OperatorPagerColumnLabel: string = localize('alertDialog.OperatorPager', 'Pager');
private static readonly NewOperatorButtonLabel: string = localize('alertDialog.NewOperator', 'New Operator');
// Options tab strings
private static readonly IncludeErrorInEmailCheckBoxLabel: string = localize('alertDialog.IncludeErrorInEmail', 'Include alert error text in e-mail');
private static readonly IncludeErrorInPagerCheckBoxLabel: string = localize('alertDialog.IncludeErrorInPager', 'Include alert error text in pager');
private static readonly AdditionalMessageTextBoxLabel: string = localize('alertDialog.AdditionalNotification', 'Additional notification message to send');
private static readonly DelayBetweenResponsesTextBoxLabel: string = localize('alertDialog.DelayBetweenResponse', 'Delay between responses');
private static readonly DelayMinutesTextBoxLabel: string = localize('alertDialog.DelayMinutes', 'Delay Minutes');
private static readonly DelaySecondsTextBoxLabel: string = localize('alertDialog.DelaySeconds', 'Delay Seconds');
// UI Components
private generalTab: sqlops.window.modelviewdialog.DialogTab;
private responseTab: sqlops.window.modelviewdialog.DialogTab;
private optionsTab: sqlops.window.modelviewdialog.DialogTab;
// General tab controls
private nameTextBox: sqlops.InputBoxComponent;
private typeDropDown: sqlops.DropDownComponent;
private severityDropDown: sqlops.DropDownComponent;
private databaseDropDown: sqlops.DropDownComponent;
private enabledCheckBox: sqlops.CheckBoxComponent;
private raiseAlertMessageCheckBox: sqlops.CheckBoxComponent;
private raiseAlertMessageTextBox: sqlops.InputBoxComponent;
// Response tab controls
private executeJobTextBox: sqlops.InputBoxComponent;
private executeJobCheckBox: sqlops.CheckBoxComponent;
private newJobButton: sqlops.ButtonComponent;
private notifyOperatorsCheckBox: sqlops.CheckBoxComponent;
private operatorsTable: sqlops.TableComponent;
private newOperatorButton: sqlops.ButtonComponent;
// Options tab controls
private additionalMessageTextBox: sqlops.InputBoxComponent;
private includeErrorInEmailTextBox: sqlops.CheckBoxComponent;
private includeErrorInPagerTextBox: sqlops.CheckBoxComponent;
private delayMinutesTextBox: sqlops.InputBoxComponent;
private delaySecondsTextBox: sqlops.InputBoxComponent;
constructor(ownerUri: string, alertInfo: sqlops.AgentAlertInfo = null) {
super(ownerUri,
new AlertData(ownerUri, alertInfo),
alertInfo ? AlertDialog.EditDialogTitle : AlertDialog.CreateDialogTitle);
}
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
let databases = await AgentUtils.getDatabases(this.ownerUri);
this.generalTab = sqlops.window.modelviewdialog.createTab(AlertDialog.GeneralTabText);
this.responseTab = sqlops.window.modelviewdialog.createTab(AlertDialog.ResponseTabText);
this.optionsTab = sqlops.window.modelviewdialog.createTab(AlertDialog.OptionsTabText);
this.initializeGeneralTab(databases);
this.initializeResponseTab();
this.initializeOptionsTab();
dialog.content = [this.generalTab, this.responseTab, this.optionsTab];
}
private initializeGeneralTab(databases: string[]) {
this.generalTab.registerContent(async view => {
this.nameTextBox = view.modelBuilder.inputBox().component();
this.enabledCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: AlertDialog.EnabledCheckboxLabel
}).component();
this.databaseDropDown = view.modelBuilder.dropDown()
.withProperties({
value: databases[0],
values: databases
}).component();
this.typeDropDown = view.modelBuilder.dropDown()
.withProperties({
value: AlertDialog.AlertTypes[0],
values: AlertDialog.AlertTypes
}).component();
this.severityDropDown = view.modelBuilder.dropDown()
.withProperties({
value: AlertDialog.AlertSeverities[0],
values: AlertDialog.AlertSeverities
}).component();
this.raiseAlertMessageCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: AlertDialog.RaiseIfMessageContainsLabel
}).component();
this.raiseAlertMessageTextBox = view.modelBuilder.inputBox().component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.nameTextBox,
title: AlertDialog.NameLabel
}, {
component: this.enabledCheckBox,
title: ''
}, {
component: this.typeDropDown,
title: AlertDialog.TypeLabel
}, {
component: this.databaseDropDown,
title: AlertDialog.DatabaseLabel
}, {
component: this.severityDropDown,
title: AlertDialog.SeverityLabel
}, {
component: this.raiseAlertMessageCheckBox,
title: ''
}, {
component: this.raiseAlertMessageTextBox,
title: AlertDialog.MessageTextLabel
}
]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.nameTextBox.value = this.model.name;
this.enabledCheckBox.checked = this.model.isEnabled;
});
}
private initializeResponseTab() {
this.responseTab.registerContent(async view => {
this.executeJobCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: AlertDialog.ExecuteJobCheckBoxLabel
}).component();
this.executeJobTextBox = view.modelBuilder.inputBox().component();
this.newJobButton = view.modelBuilder.button().withProperties({
label: AlertDialog.NewJobButtonLabel,
width: 80
}).component();
this.notifyOperatorsCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: AlertDialog.NotifyOperatorsTextBoxLabel
}).component();
this.operatorsTable = view.modelBuilder.table()
.withProperties({
columns: [
AlertDialog.OperatorNameColumnLabel,
AlertDialog.OperatorEmailColumnLabel,
AlertDialog.OperatorPagerColumnLabel
],
data: [],
height: 500
}).component();
this.newOperatorButton = view.modelBuilder.button().withProperties({
label: this.newOperatorButton,
width: 80
}).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.executeJobCheckBox,
title: ''
}, {
component: this.executeJobTextBox,
title: AlertDialog.ExecuteJobTextBoxLabel
}, {
component: this.newJobButton,
title: AlertDialog.NewJobButtonLabel
}, {
component: this.notifyOperatorsCheckBox,
title: ''
}, {
component: this.operatorsTable,
title: AlertDialog.OperatorListLabel,
actions: [this.newOperatorButton]
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
});
}
private initializeOptionsTab() {
this.optionsTab.registerContent(async view => {
this.includeErrorInEmailTextBox = view.modelBuilder.checkBox()
.withProperties({
label: AlertDialog.IncludeErrorInEmailCheckBoxLabel
}).component();
this.includeErrorInPagerTextBox = view.modelBuilder.checkBox()
.withProperties({
label: AlertDialog.IncludeErrorInPagerCheckBoxLabel
}).component();
this.additionalMessageTextBox = view.modelBuilder.inputBox().component();
this.delayMinutesTextBox = view.modelBuilder.inputBox().component();
this.delaySecondsTextBox = view.modelBuilder.inputBox().component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.includeErrorInEmailTextBox,
title: ''
}, {
component: this.includeErrorInPagerTextBox,
title: ''
}, {
component: this.additionalMessageTextBox,
title: AlertDialog.AdditionalMessageTextBoxLabel
}, {
component: this.delayMinutesTextBox,
title: AlertDialog.DelayMinutesTextBoxLabel
}, {
component: this.delaySecondsTextBox,
title: AlertDialog.DelaySecondsTextBoxLabel
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
});
}
private getSeverityNumber(): number {
let selected = this.getDropdownValue(this.severityDropDown);
let severityNumber: number = 0;
if (selected) {
let index = AlertDialog.AlertSeverities.indexOf(selected);
if (index >= 0) {
severityNumber = index + 1;
}
}
return severityNumber;
}
protected updateModel() {
this.model.name = this.nameTextBox.value;
this.model.isEnabled = this.enabledCheckBox.checked;
this.model.alertType = this.getDropdownValue(this.typeDropDown);
this.model.databaseName = this.getDropdownValue(this.databaseDropDown);
this.model.severity = this.getSeverityNumber();
this.model.messageId = undefined;
let raiseIfError = this.raiseAlertMessageCheckBox.checked;
if (raiseIfError) {
let messageText = this.raiseAlertMessageTextBox.value;
}
}
}

View File

@@ -0,0 +1,425 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import { JobData } from '../data/jobData';
import { JobStepDialog } from './jobStepDialog';
import { PickScheduleDialog } from './pickScheduleDialog';
import { AlertDialog } from './alertDialog';
import { AgentDialog } from './agentDialog';
export class JobDialog extends AgentDialog<JobData> {
// TODO: localize
// Top level
private static readonly DialogTitle: string = 'New Job';
private readonly GeneralTabText: string = 'General';
private readonly StepsTabText: string = 'Steps';
private readonly SchedulesTabText: string = 'Schedules';
private readonly AlertsTabText: string = 'Alerts';
private readonly NotificationsTabText: string = 'Notifications';
// General tab strings
private readonly NameTextBoxLabel: string = 'Name';
private readonly OwnerTextBoxLabel: string = 'Owner';
private readonly CategoryDropdownLabel: string = 'Category';
private readonly DescriptionTextBoxLabel: string = 'Description';
private readonly EnabledCheckboxLabel: string = 'Enabled';
// Steps tab strings
private readonly JobStepsTopLabelString: string = 'Job step list';
private readonly StepsTable_StepColumnString: string = 'Step';
private readonly StepsTable_NameColumnString: string = 'Name';
private readonly StepsTable_TypeColumnString: string = 'Type';
private readonly StepsTable_SuccessColumnString: string = 'On Success';
private readonly StepsTable_FailureColumnString: string = 'On Failure';
private readonly NewStepButtonString: string = 'New...';
private readonly InsertStepButtonString: string = 'Insert...';
private readonly EditStepButtonString: string = 'Edit';
private readonly DeleteStepButtonString: string = 'Delete';
// Notifications tab strings
private readonly NotificationsTabTopLabelString: string = 'Actions to perform when the job completes';
private readonly EmailCheckBoxString: string = 'Email';
private readonly PagerCheckBoxString: string = 'Page';
private readonly EventLogCheckBoxString: string = 'Write to the Windows Application event log';
private readonly DeleteJobCheckBoxString: string = 'Automatically delete job';
// Schedules tab strings
private readonly SchedulesTopLabelString: string = 'Schedules list';
private readonly PickScheduleButtonString: string = 'Pick Schedule';
// Alerts tab strings
private readonly AlertsTopLabelString: string = 'Alerts list';
private readonly NewAlertButtonString: string = 'New Alert';
// UI Components
private generalTab: sqlops.window.modelviewdialog.DialogTab;
private stepsTab: sqlops.window.modelviewdialog.DialogTab;
private alertsTab: sqlops.window.modelviewdialog.DialogTab;
private schedulesTab: sqlops.window.modelviewdialog.DialogTab;
private notificationsTab: sqlops.window.modelviewdialog.DialogTab;
// General tab controls
private nameTextBox: sqlops.InputBoxComponent;
private ownerTextBox: sqlops.InputBoxComponent;
private categoryDropdown: sqlops.DropDownComponent;
private descriptionTextBox: sqlops.InputBoxComponent;
private enabledCheckBox: sqlops.CheckBoxComponent;
// Steps tab controls
private stepsTable: sqlops.TableComponent;
private newStepButton: sqlops.ButtonComponent;
private insertStepButton: sqlops.ButtonComponent;
private editStepButton: sqlops.ButtonComponent;
private deleteStepButton: sqlops.ButtonComponent;
// Notifications tab controls
private notificationsTabTopLabel: sqlops.TextComponent;
private emailCheckBox: sqlops.CheckBoxComponent;
private emailOperatorDropdown: sqlops.DropDownComponent;
private emailConditionDropdown: sqlops.DropDownComponent;
private pagerCheckBox: sqlops.CheckBoxComponent;
private pagerOperatorDropdown: sqlops.DropDownComponent;
private pagerConditionDropdown: sqlops.DropDownComponent;
private eventLogCheckBox: sqlops.CheckBoxComponent;
private eventLogConditionDropdown: sqlops.DropDownComponent;
private deleteJobCheckBox: sqlops.CheckBoxComponent;
private deleteJobConditionDropdown: sqlops.DropDownComponent;
// Schedule tab controls
private schedulesTable: sqlops.TableComponent;
private pickScheduleButton: sqlops.ButtonComponent;
// Alert tab controls
private alertsTable: sqlops.TableComponent;
private newAlertButton: sqlops.ButtonComponent;
constructor(ownerUri: string) {
super(ownerUri, new JobData(ownerUri), JobDialog.DialogTitle);
}
protected async initializeDialog() {
this.generalTab = sqlops.window.modelviewdialog.createTab(this.GeneralTabText);
this.stepsTab = sqlops.window.modelviewdialog.createTab(this.StepsTabText);
this.alertsTab = sqlops.window.modelviewdialog.createTab(this.AlertsTabText);
this.schedulesTab = sqlops.window.modelviewdialog.createTab(this.SchedulesTabText);
this.notificationsTab = sqlops.window.modelviewdialog.createTab(this.NotificationsTabText);
this.initializeGeneralTab();
this.initializeStepsTab();
this.initializeAlertsTab();
this.initializeSchedulesTab();
this.initializeNotificationsTab();
this.dialog.content = [this.generalTab, this.stepsTab, this.schedulesTab, this.alertsTab, this.notificationsTab];
this.dialog.registerCloseValidator(() => {
this.updateModel();
let validationResult = this.model.validate();
if (!validationResult.valid) {
// TODO: Show Error Messages
console.error(validationResult.errorMessages.join(','));
}
return validationResult.valid;
});
}
private initializeGeneralTab() {
this.generalTab.registerContent(async view => {
this.nameTextBox = view.modelBuilder.inputBox().component();
this.ownerTextBox = view.modelBuilder.inputBox().component();
this.categoryDropdown = view.modelBuilder.dropDown().component();
this.descriptionTextBox = view.modelBuilder.inputBox().withProperties({
multiline: true,
height: 200
}).component();
this.enabledCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: this.EnabledCheckboxLabel
}).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.nameTextBox,
title: this.NameTextBoxLabel
}, {
component: this.ownerTextBox,
title: this.OwnerTextBoxLabel
}, {
component: this.categoryDropdown,
title: this.CategoryDropdownLabel
}, {
component: this.descriptionTextBox,
title: this.DescriptionTextBoxLabel
}, {
component: this.enabledCheckBox,
title: ''
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.ownerTextBox.value = this.model.defaultOwner;
this.categoryDropdown.values = this.model.jobCategories;
this.categoryDropdown.value = this.model.jobCategories[0];
this.enabledCheckBox.checked = this.model.enabled;
this.descriptionTextBox.value = '';
});
}
private initializeStepsTab() {
this.stepsTab.registerContent(async view => {
this.stepsTable = view.modelBuilder.table()
.withProperties({
columns: [
this.StepsTable_StepColumnString,
this.StepsTable_NameColumnString,
this.StepsTable_TypeColumnString,
this.StepsTable_SuccessColumnString,
this.StepsTable_FailureColumnString
],
data: [],
height: 800
}).component();
this.newStepButton = view.modelBuilder.button().withProperties({
label: this.NewStepButtonString,
width: 80
}).component();
this.newStepButton.onDidClick((e)=>{
let stepDialog = new JobStepDialog(this.model.ownerUri, '', '', 1, this.model);
stepDialog.openNewStepDialog();
});
this.insertStepButton = view.modelBuilder.button().withProperties({
label: this.InsertStepButtonString,
width: 80
}).component();
this.editStepButton = view.modelBuilder.button().withProperties({
label: this.EditStepButtonString,
width: 80
}).component();
this.deleteStepButton = view.modelBuilder.button().withProperties({
label: this.DeleteStepButtonString,
width: 80
}).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.stepsTable,
title: this.JobStepsTopLabelString,
actions: [this.newStepButton, this.insertStepButton, this.editStepButton, this.deleteStepButton]
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
});
}
private initializeAlertsTab() {
this.alertsTab.registerContent(async view => {
this.alertsTable = view.modelBuilder.table()
.withProperties({
columns: [
'Alert Name'
],
data: [],
height: 600,
width: 400
}).component();
this.newAlertButton = view.modelBuilder.button().withProperties({
label: this.NewAlertButtonString,
width: 80
}).component();
this.newAlertButton.onDidClick((e)=>{
let alertDialog = new AlertDialog(this.model.ownerUri);
alertDialog.onSuccess((dialogModel) => {
});
alertDialog.openDialog();
});
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.alertsTable,
title: this.AlertsTopLabelString,
actions: [this.newAlertButton]
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
});
}
private initializeSchedulesTab() {
this.schedulesTab.registerContent(async view => {
this.schedulesTable = view.modelBuilder.table()
.withProperties({
columns: [
'Schedule Name'
],
data: [],
height: 600,
width: 400
}).component();
this.pickScheduleButton = view.modelBuilder.button().withProperties({
label: this.PickScheduleButtonString,
width: 80
}).component();
this.pickScheduleButton.onDidClick((e)=>{
let pickScheduleDialog = new PickScheduleDialog(this.model.ownerUri);
pickScheduleDialog.onSuccess((dialogModel) => {
let selectedSchedule = dialogModel.selectedSchedule;
if (selectedSchedule) {
this.model.addJobSchedule(selectedSchedule);
this.populateScheduleTable();
}
});
pickScheduleDialog.showDialog();
});
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.schedulesTable,
title: this.SchedulesTopLabelString,
actions: [this.pickScheduleButton]
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.populateScheduleTable();
});
}
private populateScheduleTable() {
if (this.model.jobSchedules) {
let data: any[][] = [];
for (let i = 0; i < this.model.jobSchedules.length; ++i) {
let schedule = this.model.jobSchedules[i];
data[i] = [ schedule.name ];
}
this.schedulesTable.data = data;
}
}
private initializeNotificationsTab() {
this.notificationsTab.registerContent(async view => {
this.notificationsTabTopLabel = view.modelBuilder.text().withProperties({ value: this.NotificationsTabTopLabelString }).component();
this.emailCheckBox = view.modelBuilder.checkBox().withProperties({
label: this.EmailCheckBoxString,
width: 80
}).component();
this.pagerCheckBox = view.modelBuilder.checkBox().withProperties({
label: this.PagerCheckBoxString,
width: 80
}).component();
this.eventLogCheckBox = view.modelBuilder.checkBox().withProperties({
label: this.EventLogCheckBoxString,
width: 250
}).component();
this.deleteJobCheckBox = view.modelBuilder.checkBox().withProperties({
label: this.DeleteJobCheckBoxString,
width: 250
}).component();
this.emailCheckBox.onChanged(() => {
this.emailConditionDropdown.enabled = this.emailCheckBox.checked;
this.emailOperatorDropdown.enabled = this.emailCheckBox.checked;
});
this.pagerCheckBox.onChanged(() => {
this.pagerConditionDropdown.enabled = this.pagerCheckBox.checked;
this.pagerOperatorDropdown.enabled = this.pagerCheckBox.checked;
});
this.eventLogCheckBox.onChanged(() => {
this.eventLogConditionDropdown.enabled = this.eventLogCheckBox.checked;
});
this.deleteJobCheckBox.onChanged(() => {
this.deleteJobConditionDropdown.enabled = this.deleteJobCheckBox.checked;
});
this.emailOperatorDropdown = view.modelBuilder.dropDown().withProperties({ width: 150 }).component();
this.pagerOperatorDropdown = view.modelBuilder.dropDown().withProperties({ width: 150 }).component();
this.emailConditionDropdown = view.modelBuilder.dropDown().withProperties({ width: 150 }).component();
this.pagerConditionDropdown = view.modelBuilder.dropDown().withProperties({ width: 150 }).component();
this.eventLogConditionDropdown = view.modelBuilder.dropDown().withProperties({ width: 150 }).component();
this.deleteJobConditionDropdown = view.modelBuilder.dropDown().withProperties({ width: 150 }).component();
let emailContainer = this.createRowContainer(view).withItems([this.emailCheckBox, this.emailOperatorDropdown, this.emailConditionDropdown]).component();
let pagerContainer = this.createRowContainer(view).withItems([this.pagerCheckBox, this.pagerOperatorDropdown, this.pagerConditionDropdown]).component();
let eventLogContainer = this.createRowContainer(view).withItems([this.eventLogCheckBox, this.eventLogConditionDropdown]).component();
let deleteJobContainer = this.createRowContainer(view).withItems([this.deleteJobCheckBox, this.deleteJobConditionDropdown]).component();
let formModel = view.modelBuilder.formContainer().withFormItems([
{
component: this.notificationsTabTopLabel,
title: ''
}, {
component: emailContainer,
title: ''
}, {
component: pagerContainer,
title: ''
}, {
component: eventLogContainer,
title: ''
}, {
component: deleteJobContainer,
title: ''
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.emailConditionDropdown.values = this.model.JobCompletionActionConditions;
this.pagerConditionDropdown.values = this.model.JobCompletionActionConditions;
this.eventLogConditionDropdown.values = this.model.JobCompletionActionConditions;
this.deleteJobConditionDropdown.values = this.model.JobCompletionActionConditions;
this.setConditionDropdownSelectedValue(this.emailConditionDropdown, this.model.emailLevel);
this.setConditionDropdownSelectedValue(this.pagerConditionDropdown, this.model.pageLevel);
this.setConditionDropdownSelectedValue(this.eventLogConditionDropdown, this.model.eventLogLevel);
this.setConditionDropdownSelectedValue(this.deleteJobConditionDropdown, this.model.deleteLevel);
this.emailOperatorDropdown.values = this.model.operators;
this.pagerOperatorDropdown.values = this.model.operators;
this.emailCheckBox.checked = false;
this.pagerCheckBox.checked = false;
this.eventLogCheckBox.checked = false;
this.deleteJobCheckBox.checked = false;
this.emailOperatorDropdown.enabled = false;
this.pagerOperatorDropdown.enabled = false;
this.emailConditionDropdown.enabled = false;
this.pagerConditionDropdown.enabled = false;
this.eventLogConditionDropdown.enabled = false;
this.deleteJobConditionDropdown.enabled = false;
});
}
private createRowContainer(view: sqlops.ModelView): sqlops.FlexBuilder {
return view.modelBuilder.flexContainer().withLayout({
flexFlow: 'row',
alignItems: 'left',
justifyContent: 'space-between'
});
}
protected updateModel() {
this.model.name = this.nameTextBox.value;
this.model.owner = this.ownerTextBox.value;
this.model.enabled = this.enabledCheckBox.checked;
this.model.description = this.descriptionTextBox.value;
this.model.category = this.getDropdownValue(this.categoryDropdown);
this.model.emailLevel = this.getActualConditionValue(this.emailCheckBox, this.emailConditionDropdown);
this.model.operatorToEmail = this.getDropdownValue(this.emailOperatorDropdown);
this.model.operatorToPage = this.getDropdownValue(this.pagerOperatorDropdown);
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
}
}

View File

@@ -0,0 +1,490 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import { JobStepData } from '../data/jobStepData';
import { AgentUtils } from '../agentUtils';
import { JobData } from '../data/jobData';
const path = require('path');
export class JobStepDialog {
// TODO: localize
// Top level
//
private static readonly DialogTitle: string = 'New Job Step';
private static readonly FileBrowserDialogTitle: string = 'Locate Database Files - ';
private static readonly OkButtonText: string = 'OK';
private static readonly CancelButtonText: string = 'Cancel';
private static readonly GeneralTabText: string = 'General';
private static readonly AdvancedTabText: string = 'Advanced';
private static readonly OpenCommandText: string = 'Open...';
private static readonly ParseCommandText: string = 'Parse';
private static readonly NextButtonText: string = 'Next';
private static readonly PreviousButtonText: string = 'Previous';
private static readonly SuccessAction: string = 'On success action';
private static readonly FailureAction: string = 'On failure action';
// Dropdown options
private static readonly TSQLScript: string = 'Transact-SQL script (T-SQL)';
private static readonly AgentServiceAccount: string = 'SQL Server Agent Service Account';
private static readonly NextStep: string = 'Go to the next step';
private static readonly QuitJobReportingSuccess: string = 'Quit the job reporting success';
private static readonly QuitJobReportingFailure: string = 'Quit the job reporting failure';
// UI Components
// Dialogs
private dialog: sqlops.window.modelviewdialog.Dialog;
private fileBrowserDialog: sqlops.window.modelviewdialog.Dialog;
// Dialog tabs
private generalTab: sqlops.window.modelviewdialog.DialogTab;
private advancedTab: sqlops.window.modelviewdialog.DialogTab;
//Input boxes
private nameTextBox: sqlops.InputBoxComponent;
private commandTextBox: sqlops.InputBoxComponent;
private selectedPathTextBox: sqlops.InputBoxComponent;
private retryAttemptsBox: sqlops.InputBoxComponent;
private retryIntervalBox: sqlops.InputBoxComponent;
private outputFileNameBox: sqlops.InputBoxComponent;
private fileBrowserNameBox: sqlops.InputBoxComponent;
// Dropdowns
private typeDropdown: sqlops.DropDownComponent;
private runAsDropdown: sqlops.DropDownComponent;
private databaseDropdown: sqlops.DropDownComponent;
private successActionDropdown: sqlops.DropDownComponent;
private failureActionDropdown: sqlops.DropDownComponent;
private fileTypeDropdown: sqlops.DropDownComponent;
// Buttons
private openButton: sqlops.ButtonComponent;
private parseButton: sqlops.ButtonComponent;
private nextButton: sqlops.ButtonComponent;
private previousButton: sqlops.ButtonComponent;
private outputFileBrowserButton: sqlops.ButtonComponent;
// Checkbox
private appendToExistingFileCheckbox: sqlops.CheckBoxComponent;
private logToTableCheckbox: sqlops.CheckBoxComponent;
private fileBrowserTree: sqlops.FileBrowserTreeComponent;
private jobModel: JobData;
private model: JobStepData;
private ownerUri: string;
private jobName: string;
private server: string;
private stepId: number;
constructor(
ownerUri: string,
jobName: string,
server: string,
stepId: number,
jobModel?: JobData
) {
this.model = new JobStepData(ownerUri);
this.stepId = stepId;
this.ownerUri = ownerUri;
this.jobName = jobName;
this.server = server;
this.jobModel = jobModel;
}
private initializeUIComponents() {
this.dialog = sqlops.window.modelviewdialog.createDialog(JobStepDialog.DialogTitle);
this.generalTab = sqlops.window.modelviewdialog.createTab(JobStepDialog.GeneralTabText);
this.advancedTab = sqlops.window.modelviewdialog.createTab(JobStepDialog.AdvancedTabText);
this.dialog.content = [this.generalTab, this.advancedTab];
this.dialog.okButton.onClick(async () => await this.execute());
this.dialog.okButton.label = JobStepDialog.OkButtonText;
this.dialog.cancelButton.label = JobStepDialog.CancelButtonText;
}
private createCommands(view, queryProvider: sqlops.QueryProvider) {
this.openButton = view.modelBuilder.button()
.withProperties({
label: JobStepDialog.OpenCommandText,
width: '80px'
}).component();
this.parseButton = view.modelBuilder.button()
.withProperties({
label: JobStepDialog.ParseCommandText,
width: '80px'
}).component();
this.parseButton.onDidClick(e => {
if (this.commandTextBox.value) {
queryProvider.parseSyntax(this.ownerUri, this.commandTextBox.value).then(result => {
if (result && result.parseable) {
this.dialog.message = { text: 'The command was successfully parsed.', level: 2};
} else if (result && !result.parseable) {
this.dialog.message = { text: 'The command failed' };
}
});
}
});
this.commandTextBox = view.modelBuilder.inputBox()
.withProperties({
height: 300,
width: 400,
multiline: true,
inputType: 'text'
})
.component();
this.nextButton = view.modelBuilder.button()
.withProperties({
label: JobStepDialog.NextButtonText,
enabled: false,
width: '80px'
}).component();
this.previousButton = view.modelBuilder.button()
.withProperties({
label: JobStepDialog.PreviousButtonText,
enabled: false,
width: '80px'
}).component();
}
private createGeneralTab(databases: string[], queryProvider: sqlops.QueryProvider) {
this.generalTab.registerContent(async (view) => {
this.nameTextBox = view.modelBuilder.inputBox()
.withProperties({
}).component();
this.nameTextBox.required = true;
this.typeDropdown = view.modelBuilder.dropDown()
.withProperties({
value: JobStepDialog.TSQLScript,
values: [JobStepDialog.TSQLScript]
})
.component();
this.runAsDropdown = view.modelBuilder.dropDown()
.withProperties({
value: '',
values: ['']
})
.component();
this.runAsDropdown.enabled = false;
this.typeDropdown.onValueChanged((type) => {
if (type.selected !== JobStepDialog.TSQLScript) {
this.runAsDropdown.value = JobStepDialog.AgentServiceAccount;
this.runAsDropdown.values = [this.runAsDropdown.value];
} else {
this.runAsDropdown.value = '';
this.runAsDropdown.values = [''];
}
});
this.databaseDropdown = view.modelBuilder.dropDown()
.withProperties({
value: databases[0],
values: databases
}).component();
// create the commands section
this.createCommands(view, queryProvider);
let buttonContainer = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row',
justifyContent: 'space-between',
width: 420
}).withItems([this.openButton, this.parseButton, this.previousButton, this.nextButton], {
flex: '1 1 50%'
}).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.nameTextBox,
title: 'Step name'
}, {
component: this.typeDropdown,
title: 'Type'
}, {
component: this.runAsDropdown,
title: 'Run as'
}, {
component: this.databaseDropdown,
title: 'Database'
}, {
component: this.commandTextBox,
title: 'Command',
actions: [buttonContainer]
}], {
horizontal: false,
componentWidth: 420
}).component();
let formWrapper = view.modelBuilder.loadingComponent().withItem(formModel).component();
formWrapper.loading = false;
await view.initializeModel(formWrapper);
});
}
private createRunAsUserOptions(view) {
let userInputBox = view.modelBuilder.inputBox()
.withProperties({ inputType: 'text', width: '100px' }).component();
let viewButton = view.modelBuilder.button()
.withProperties({ label: '...', width: '20px' }).component();
let viewButtonContainer = view.modelBuilder.flexContainer()
.withLayout({ width: 100, textAlign: 'right' })
.withItems([viewButton], { flex: '1 1 50%' }).component();
let userInputBoxContainer = view.modelBuilder.flexContainer()
.withLayout({ width: 200, textAlign: 'left' })
.withItems([userInputBox], { flex: '1 1 50%' }).component();
let runAsUserContainer = view.modelBuilder.flexContainer()
.withLayout({ width: 200 })
.withItems([userInputBoxContainer, viewButtonContainer], { flex: '1 1 50%' })
.component();
let runAsUserForm = view.modelBuilder.formContainer()
.withFormItems([{
component: runAsUserContainer,
title: 'Run as user'
}], { horizontal: true, componentWidth: 200 }).component();
return runAsUserForm;
}
private createAdvancedTab() {
this.advancedTab.registerContent(async (view) => {
this.successActionDropdown = view.modelBuilder.dropDown()
.withProperties({
value: JobStepDialog.NextStep,
values: [JobStepDialog.NextStep, JobStepDialog.QuitJobReportingSuccess, JobStepDialog.QuitJobReportingFailure]
})
.component();
let retryFlexContainer = this.createRetryCounters(view);
this.failureActionDropdown = view.modelBuilder.dropDown()
.withProperties({
value: JobStepDialog.QuitJobReportingFailure,
values: [JobStepDialog.QuitJobReportingFailure, JobStepDialog.NextStep, JobStepDialog.QuitJobReportingSuccess]
})
.component();
let optionsGroup = this.createTSQLOptions(view);
let viewButton = view.modelBuilder.button()
.withProperties({ label: 'View', width: '50px' }).component();
viewButton.enabled = false;
this.logToTableCheckbox = view.modelBuilder.checkBox()
.withProperties({
label: 'Log to table'
}).component();
let appendToExistingEntryInTableCheckbox = view.modelBuilder.checkBox()
.withProperties({ label: 'Append output to existing entry in table' }).component();
appendToExistingEntryInTableCheckbox.enabled = false;
this.logToTableCheckbox.onChanged(e => {
viewButton.enabled = e;
appendToExistingEntryInTableCheckbox.enabled = e;
});
let appendCheckboxContainer = view.modelBuilder.groupContainer()
.withItems([appendToExistingEntryInTableCheckbox]).component();
let logToTableContainer = view.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'row', justifyContent: 'space-between', width: 300 })
.withItems([this.logToTableCheckbox, viewButton]).component();
let logStepOutputHistoryCheckbox = view.modelBuilder.checkBox()
.withProperties({ label: 'Include step output in history' }).component();
let runAsUserOptions = this.createRunAsUserOptions(view);
let formModel = view.modelBuilder.formContainer()
.withFormItems(
[{
component: this.successActionDropdown,
title: JobStepDialog.SuccessAction
}, {
component: retryFlexContainer,
title: ''
}, {
component: this.failureActionDropdown,
title: JobStepDialog.FailureAction
}, {
component: optionsGroup,
title: 'Transact-SQL script (T-SQL)'
}, {
component: logToTableContainer,
title: ''
}, {
component: appendCheckboxContainer,
title: ' '
}, {
component: logStepOutputHistoryCheckbox,
title: ''
}, {
component: runAsUserOptions,
title: ''
}], {
componentWidth: 400
}).component();
let formWrapper = view.modelBuilder.loadingComponent().withItem(formModel).component();
formWrapper.loading = false;
view.initializeModel(formWrapper);
});
}
private createRetryCounters(view) {
this.retryAttemptsBox = view.modelBuilder.inputBox()
.withValidation(component => component.value >= 0)
.withProperties({
inputType: 'number'
})
.component();
this.retryIntervalBox = view.modelBuilder.inputBox()
.withValidation(component => component.value >= 0)
.withProperties({
inputType: 'number'
}).component();
let retryAttemptsContainer = view.modelBuilder.formContainer()
.withFormItems(
[{
component: this.retryAttemptsBox,
title: 'Retry Attempts'
}], {
horizontal: false
})
.component();
let retryIntervalContainer = view.modelBuilder.formContainer()
.withFormItems(
[{
component: this.retryIntervalBox,
title: 'Retry Interval (minutes)'
}], {
horizontal: false
})
.component();
let retryFlexContainer = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row',
}).withItems([retryAttemptsContainer, retryIntervalContainer]).component();
return retryFlexContainer;
}
private openFileBrowserDialog() {
let fileBrowserTitle = JobStepDialog.FileBrowserDialogTitle + `${this.server}`;
this.fileBrowserDialog = sqlops.window.modelviewdialog.createDialog(fileBrowserTitle);
let fileBrowserTab = sqlops.window.modelviewdialog.createTab('File Browser');
this.fileBrowserDialog.content = [fileBrowserTab];
fileBrowserTab.registerContent(async (view) => {
this.fileBrowserTree = view.modelBuilder.fileBrowserTree()
.withProperties({ ownerUri: this.ownerUri, width: 420, height: 700 })
.component();
this.selectedPathTextBox = view.modelBuilder.inputBox()
.withProperties({ inputType: 'text'})
.component();
this.fileBrowserTree.onDidChange((args) => {
this.selectedPathTextBox.value = args.fullPath;
this.fileBrowserNameBox.value = args.isFile ? path.win32.basename(args.fullPath) : '';
});
this.fileTypeDropdown = view.modelBuilder.dropDown()
.withProperties({
value: 'All Files (*)',
values: ['All Files (*)']
})
.component();
this.fileBrowserNameBox = view.modelBuilder.inputBox()
.withProperties({})
.component();
let fileBrowserContainer = view.modelBuilder.formContainer()
.withFormItems([{
component: this.fileBrowserTree,
title: ''
}, {
component: this.selectedPathTextBox,
title: 'Selected path:'
}, {
component: this.fileTypeDropdown,
title: 'Files of type:'
}, {
component: this.fileBrowserNameBox,
title: 'File name:'
}
]).component();
view.initializeModel(fileBrowserContainer);
});
this.fileBrowserDialog.okButton.onClick(() => {
this.outputFileNameBox.value = path.join(path.dirname(this.selectedPathTextBox.value), this.fileBrowserNameBox.value);
});
this.fileBrowserDialog.okButton.label = JobStepDialog.OkButtonText;
this.fileBrowserDialog.cancelButton.label = JobStepDialog.CancelButtonText;
sqlops.window.modelviewdialog.openDialog(this.fileBrowserDialog);
}
private createTSQLOptions(view) {
this.outputFileBrowserButton = view.modelBuilder.button()
.withProperties({ width: '20px', label: '...' }).component();
this.outputFileBrowserButton.onDidClick(() => this.openFileBrowserDialog());
this.outputFileNameBox = view.modelBuilder.inputBox()
.withProperties({
width: '150px',
inputType: 'text'
}).component();
let outputViewButton = view.modelBuilder.button()
.withProperties({
width: '50px',
label: 'View'
}).component();
outputViewButton.enabled = false;
let outputButtonContainer = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row',
textAlign: 'right',
width: 120
}).withItems([this.outputFileBrowserButton, outputViewButton], { flex: '1 1 50%' }).component();
let outputFlexBox = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row',
width: 350
}).withItems([this.outputFileNameBox, outputButtonContainer], {
flex: '1 1 50%'
}).component();
this.appendToExistingFileCheckbox = view.modelBuilder.checkBox()
.withProperties({
label: 'Append output to existing file'
}).component();
this.appendToExistingFileCheckbox.enabled = false;
this.outputFileNameBox.onTextChanged((input) => {
if (input !== '') {
this.appendToExistingFileCheckbox.enabled = true;
} else {
this.appendToExistingFileCheckbox.enabled = false;
}
});
let outputFileForm = view.modelBuilder.formContainer()
.withFormItems([{
component: outputFlexBox,
title: 'Output file'
}, {
component: this.appendToExistingFileCheckbox,
title: ''
}], { horizontal: true, componentWidth: 200 }).component();
return outputFileForm;
}
private async execute() {
this.model.jobName = this.jobName;
this.model.id = this.stepId;
this.model.server = this.server;
this.model.stepName = this.nameTextBox.value;
this.model.subSystem = this.typeDropdown.value as string;
this.model.databaseName = this.databaseDropdown.value as string;
this.model.script = this.commandTextBox.value;
this.model.successAction = this.successActionDropdown.value as string;
this.model.retryAttempts = +this.retryAttemptsBox.value;
this.model.retryInterval = +this.retryIntervalBox.value;
this.model.failureAction = this.failureActionDropdown.value as string;
this.model.outputFileName = this.outputFileNameBox.value;
this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked;
await this.model.save();
}
public async openNewStepDialog() {
let databases = await AgentUtils.getDatabases(this.ownerUri);
let queryProvider = await AgentUtils.getQueryProvider();
this.initializeUIComponents();
this.createGeneralTab(databases, queryProvider);
this.createAdvancedTab();
sqlops.window.modelviewdialog.openDialog(this.dialog);
}
}

View File

@@ -0,0 +1,405 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import { OperatorData } from '../data/operatorData';
import * as nls from 'vscode-nls';
import { AgentDialog } from './agentDialog';
const localize = nls.loadMessageBundle();
export class OperatorDialog extends AgentDialog<OperatorData> {
// Top level
private static readonly DialogTitle: string = localize('createOperator.createOperator', 'Create Operator');
private static readonly GeneralTabText: string = localize('createOperator.General', 'General');
private static readonly NotificationsTabText: string = localize('createOperator.Notifications', 'Notifications');
// General tab strings
private static readonly NameLabel: string = localize('createOperator.Name', 'Name');
private static readonly EnabledCheckboxLabel: string = localize('createOperator.Enabled', 'Enabled');
private static readonly EmailNameTextLabel: string = localize('createOperator.EmailName', 'E-mail Name');
private static readonly PagerEmailNameTextLabel: string = localize('createOperator.PagerEmailName', 'Pager E-mail Name');
private static readonly PagerMondayCheckBoxLabel: string = localize('createOperator.PagerMondayCheckBox', 'Monday');
private static readonly PagerTuesdayCheckBoxLabel: string = localize('createOperator.PagerTuesdayCheckBox', 'Tuesday');
private static readonly PagerWednesdayCheckBoxLabel: string = localize('createOperator.PagerWednesdayCheckBox', 'Wednesday');
private static readonly PagerThursdayCheckBoxLabel: string = localize('createOperator.PagerThursdayCheckBox', 'Thursday');
private static readonly PagerFridayCheckBoxLabel: string = localize('createOperator.PagerFridayCheckBox', 'Friday ');
private static readonly PagerSaturdayCheckBoxLabel: string = localize('createOperator.PagerSaturdayCheckBox', 'Saturday');
private static readonly PagerSundayCheckBoxLabel: string = localize('createOperator.PagerSundayCheckBox', 'Sunday');
// Notifications tab strings
private static readonly AlertsTableLabel: string = localize('createOperator.AlertListHeading', 'Alert list');
private static readonly AlertNameColumnLabel: string = localize('createOperator.AlertNameColumnLabel', 'Alert name');
private static readonly AlertEmailColumnLabel: string = localize('createOperator.AlertEmailColumnLabel', 'E-mail');
private static readonly AlertPagerColumnLabel: string = localize('createOperator.AlertPagerColumnLabel', 'Pager');
// UI Components
private generalTab: sqlops.window.modelviewdialog.DialogTab;
private notificationsTab: sqlops.window.modelviewdialog.DialogTab;
// General tab controls
private nameTextBox: sqlops.InputBoxComponent;
private enabledCheckBox: sqlops.CheckBoxComponent;
private emailNameTextBox: sqlops.InputBoxComponent;
private pagerEmailNameTextBox: sqlops.InputBoxComponent;
private pagerMondayCheckBox: sqlops.CheckBoxComponent;
private pagerTuesdayCheckBox: sqlops.CheckBoxComponent;
private pagerWednesdayCheckBox: sqlops.CheckBoxComponent;
private pagerThursdayCheckBox: sqlops.CheckBoxComponent;
private pagerFridayCheckBox: sqlops.CheckBoxComponent;
private pagerSaturdayCheckBox: sqlops.CheckBoxComponent;
private pagerSundayCheckBox: sqlops.CheckBoxComponent;
private weekdayPagerStartTimeInput: sqlops.InputBoxComponent;
private weekdayPagerEndTimeInput: sqlops.InputBoxComponent;
private saturdayPagerStartTimeInput: sqlops.InputBoxComponent;
private saturdayPagerEndTimeInput: sqlops.InputBoxComponent;
private sundayPagerStartTimeInput: sqlops.InputBoxComponent;
private sundayPagerEndTimeInput: sqlops.InputBoxComponent;
// Notification tab controls
private alertsTable: sqlops.TableComponent;
constructor(ownerUri: string) {
super(ownerUri, new OperatorData(ownerUri), OperatorDialog.DialogTitle);
}
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
this.generalTab = sqlops.window.modelviewdialog.createTab(OperatorDialog.GeneralTabText);
this.notificationsTab = sqlops.window.modelviewdialog.createTab(OperatorDialog.NotificationsTabText);
this.initializeGeneralTab();
this.initializeNotificationTab();
this.dialog.content = [this.generalTab, this.notificationsTab];
}
private initializeGeneralTab() {
this.generalTab.registerContent(async view => {
this.nameTextBox = view.modelBuilder.inputBox().component();
this.enabledCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: OperatorDialog.EnabledCheckboxLabel
}).component();
this.enabledCheckBox.checked = true;
this.emailNameTextBox = view.modelBuilder.inputBox().component();
this.pagerEmailNameTextBox = view.modelBuilder.inputBox().component();
this.enabledCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: OperatorDialog.EnabledCheckboxLabel
}).component();
this.pagerMondayCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: OperatorDialog.PagerMondayCheckBoxLabel
}).component();
this.pagerMondayCheckBox.onChanged(() => {
if (this.pagerMondayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = true;
this.weekdayPagerEndTimeInput.enabled = true;
} else {
if (!this.pagerTuesdayCheckBox.checked && !this.pagerWednesdayCheckBox.checked &&
!this.pagerThursdayCheckBox.checked && !this.pagerFridayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = false;
this.weekdayPagerEndTimeInput.enabled = false;
}
}
});
this.pagerTuesdayCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: OperatorDialog.PagerTuesdayCheckBoxLabel
}).component();
this.pagerTuesdayCheckBox.onChanged(() => {
if (this.pagerTuesdayCheckBox .checked) {
this.weekdayPagerStartTimeInput.enabled = true;
this.weekdayPagerEndTimeInput.enabled = true;
} else {
if (!this.pagerMondayCheckBox.checked && !this.pagerWednesdayCheckBox.checked &&
!this.pagerThursdayCheckBox.checked && !this.pagerFridayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = false;
this.weekdayPagerEndTimeInput.enabled = false;
}
}
});
this.pagerWednesdayCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: OperatorDialog.PagerWednesdayCheckBoxLabel
}).component();
this.pagerWednesdayCheckBox.onChanged(() => {
if (this.pagerWednesdayCheckBox .checked) {
this.weekdayPagerStartTimeInput.enabled = true;
this.weekdayPagerEndTimeInput.enabled = true;
} else {
if (!this.pagerMondayCheckBox.checked && !this.pagerTuesdayCheckBox.checked &&
!this.pagerThursdayCheckBox.checked && !this.pagerFridayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = false;
this.weekdayPagerEndTimeInput.enabled = false;
}
}
});
this.pagerThursdayCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: OperatorDialog.PagerThursdayCheckBoxLabel
}).component();
this.pagerThursdayCheckBox.onChanged(() => {
if (this.pagerThursdayCheckBox .checked) {
this.weekdayPagerStartTimeInput.enabled = true;
this.weekdayPagerEndTimeInput.enabled = true;
} else {
if (!this.pagerMondayCheckBox.checked && !this.pagerWednesdayCheckBox.checked &&
!this.pagerTuesdayCheckBox.checked && !this.pagerFridayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = false;
this.weekdayPagerEndTimeInput.enabled = false;
}
}
});
this.weekdayPagerStartTimeInput = view.modelBuilder.inputBox()
.withProperties({
inputType: 'time',
placeHolder: '08:00:00'
}).component();
this.weekdayPagerStartTimeInput.enabled = false;
let weekdayStartInputContainer = view.modelBuilder.formContainer()
.withFormItems([{
component: this.weekdayPagerStartTimeInput,
title: 'Workday begin'
}]).component();
this.weekdayPagerEndTimeInput = view.modelBuilder.inputBox()
.withProperties({
inputType: 'time',
placeHolder: '06:00:00'
}).component();
this.weekdayPagerEndTimeInput.enabled = false;
let weekdayEndInputContainer = view.modelBuilder.formContainer()
.withFormItems([{
component: this.weekdayPagerEndTimeInput,
title: 'Workday end'
}]).component();
this.pagerFridayCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: OperatorDialog.PagerFridayCheckBoxLabel,
width: 80
}).component();
this.pagerFridayCheckBox.onChanged(() => {
if (this.pagerFridayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = true;
this.weekdayPagerEndTimeInput.enabled = true;
} else {
if (!this.pagerMondayCheckBox.checked && !this.pagerWednesdayCheckBox.checked &&
!this.pagerThursdayCheckBox.checked && !this.pagerTuesdayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = false;
this.weekdayPagerEndTimeInput.enabled = false;
}
}
});
let pagerFridayCheckboxContainer = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row',
alignItems: 'baseline'
}).withItems([this.pagerFridayCheckBox, weekdayStartInputContainer, weekdayEndInputContainer])
.component();
this.pagerSaturdayCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: OperatorDialog.PagerSaturdayCheckBoxLabel,
width: 80
}).component();
this.pagerSaturdayCheckBox.onChanged(() => {
if (this.pagerSaturdayCheckBox.checked) {
this.saturdayPagerStartTimeInput.enabled = true;
this.saturdayPagerEndTimeInput.enabled = true;
} else {
this.saturdayPagerStartTimeInput.enabled = false;
this.saturdayPagerEndTimeInput.enabled = false;
}
});
this.saturdayPagerStartTimeInput = view.modelBuilder.inputBox()
.withProperties({
inputType: 'time',
placeHolder: '08:00:00'
}).component();
this.saturdayPagerStartTimeInput.enabled = false;
let saturdayStartInputContainer = view.modelBuilder.formContainer()
.withFormItems([{
component: this.saturdayPagerStartTimeInput,
title: 'Workday begin'
}]).component();
this.saturdayPagerEndTimeInput = view.modelBuilder.inputBox()
.withProperties({
inputType: 'time',
placeHolder: '06:00:00'
}).component();
this.saturdayPagerEndTimeInput.enabled = false;
let saturdayEndInputContainer = view.modelBuilder.formContainer()
.withFormItems([{
component: this.saturdayPagerEndTimeInput,
title: 'Workday end'
}]).component();
let pagerSaturdayCheckboxContainer = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row',
alignItems: 'baseline'
}).withItems([this.pagerSaturdayCheckBox, saturdayStartInputContainer, saturdayEndInputContainer])
.component();
this.pagerSundayCheckBox = view.modelBuilder.checkBox()
.withProperties({
label: OperatorDialog.PagerSundayCheckBoxLabel,
width: 80
}).component();
this.pagerSundayCheckBox.onChanged(() => {
if (this.pagerSundayCheckBox.checked) {
this.sundayPagerStartTimeInput.enabled = true;
this.sundayPagerEndTimeInput.enabled = true;
} else {
this.sundayPagerStartTimeInput.enabled = false;
this.sundayPagerEndTimeInput.enabled = false;
}
});
this.sundayPagerStartTimeInput = view.modelBuilder.inputBox()
.withProperties({
inputType: 'time',
placeHolder: '08:00:00'
}).component();
this.sundayPagerStartTimeInput.enabled = false;
let sundayStartInputContainer = view.modelBuilder.formContainer()
.withFormItems([{
component: this.sundayPagerStartTimeInput,
title: 'Workday begin'
}]).component();
this.sundayPagerEndTimeInput = view.modelBuilder.inputBox()
.withProperties({
inputType: 'time',
placeHolder: '06:00:00'
}).component();
this.sundayPagerEndTimeInput.enabled = false;
let sundayEndInputContainer = view.modelBuilder.formContainer()
.withFormItems([{
component: this.sundayPagerEndTimeInput,
title: 'Workday end'
}]).component();
let pagerSundayCheckboxContainer = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row',
alignItems: 'baseline'
}).withItems([this.pagerSundayCheckBox, sundayStartInputContainer, sundayEndInputContainer])
.component();
let checkBoxContainer = view.modelBuilder.formContainer()
.withFormItems([{
component: this.pagerMondayCheckBox,
title: ''
}, {
component: this.pagerTuesdayCheckBox,
title: ''
}, {
component: this.pagerWednesdayCheckBox,
title: ''
}, {
component: this.pagerThursdayCheckBox,
title: ''
}, {
component: pagerFridayCheckboxContainer,
title: ''
}, {
component: pagerSaturdayCheckboxContainer,
title: ''
}, {
component: pagerSundayCheckboxContainer,
title: ''
}]).component();
let pagerContainer = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row'
}).withItems([checkBoxContainer])
.component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.nameTextBox,
title: OperatorDialog.NameLabel
}, {
component: this.enabledCheckBox,
title: ''
}, {
component: this.emailNameTextBox,
title: OperatorDialog.EmailNameTextLabel
}, {
component: this.pagerEmailNameTextBox,
title: OperatorDialog.PagerEmailNameTextLabel
}, {
component: pagerContainer,
title: ''
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
});
}
private initializeNotificationTab() {
this.notificationsTab.registerContent(async view => {
this.alertsTable = view.modelBuilder.table()
.withProperties({
columns: [
OperatorDialog.AlertNameColumnLabel,
OperatorDialog.AlertEmailColumnLabel,
OperatorDialog.AlertPagerColumnLabel
],
data: [],
height: 500
}).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.alertsTable,
title: OperatorDialog.AlertsTableLabel
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
});
}
protected updateModel() {
this.model.name = this.nameTextBox.value;
this.model.enabled = this.enabledCheckBox.checked;
this.model.emailAddress = this.emailNameTextBox.value;
this.model.pagerAddress = this.pagerEmailNameTextBox.value;
this.model.weekdayPagerStartTime = this.weekdayPagerStartTimeInput.value;
this.model.weekdayPagerEndTime = this.weekdayPagerEndTimeInput.value;
this.model.saturdayPagerStartTime = this.saturdayPagerStartTimeInput.value;
this.model.saturdayPagerEndTime = this.saturdayPagerEndTimeInput.value;
this.model.sundayPagerStartTime = this.sundayPagerStartTimeInput.value;
this.model.sundayPagerEndTime = this.sundayPagerEndTimeInput.value;
}
}

View File

@@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import { PickScheduleData } from '../data/pickScheduleData';
export class PickScheduleDialog {
// TODO: localize
// Top level
private readonly DialogTitle: string = 'Job Schedules';
private readonly OkButtonText: string = 'OK';
private readonly CancelButtonText: string = 'Cancel';
private readonly SchedulesTabText: string = 'Schedules';
// UI Components
private dialog: sqlops.window.modelviewdialog.Dialog;
private schedulesTable: sqlops.TableComponent;
private model: PickScheduleData;
private _onSuccess: vscode.EventEmitter<PickScheduleData> = new vscode.EventEmitter<PickScheduleData>();
public readonly onSuccess: vscode.Event<PickScheduleData> = this._onSuccess.event;
constructor(ownerUri: string) {
this.model = new PickScheduleData(ownerUri);
}
public async showDialog() {
await this.model.initialize();
this.dialog = sqlops.window.modelviewdialog.createDialog(this.DialogTitle);
this.initializeContent();
this.dialog.okButton.onClick(async () => await this.execute());
this.dialog.cancelButton.onClick(async () => await this.cancel());
this.dialog.okButton.label = this.OkButtonText;
this.dialog.cancelButton.label = this.CancelButtonText;
sqlops.window.modelviewdialog.openDialog(this.dialog);
}
private initializeContent() {
this.dialog.registerContent(async view => {
this.schedulesTable = view.modelBuilder.table()
.withProperties({
columns: [
'Schedule Name'
],
data: [],
height: 600,
width: 400
}).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.schedulesTable,
title: 'Schedules'
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
if (this.model.schedules) {
let data: any[][] = [];
for (let i = 0; i < this.model.schedules.length; ++i) {
let schedule = this.model.schedules[i];
data[i] = [ schedule.name ];
}
this.schedulesTable.data = data;
}
});
}
private async execute() {
this.updateModel();
await this.model.save();
this._onSuccess.fire(this.model);
}
private async cancel() {
}
private updateModel() {
let selectedRows = this.schedulesTable.selectedRows;
if (selectedRows && selectedRows.length > 0) {
let selectedRow = selectedRows[0];
this.model.selectedSchedule = this.model.schedules[selectedRow];
}
}
}

View File

@@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vscode-nls';
import * as sqlops from 'sqlops';
import { AgentDialog } from './agentDialog';
import { ProxyData } from '../data/proxyData';
const localize = nls.loadMessageBundle();
export class ProxyDialog extends AgentDialog<ProxyData> {
// Top level
private static readonly DialogTitle: string = localize('createProxy.createAlert', 'Create Alert');
private static readonly GeneralTabText: string = localize('createProxy.General', 'General');
// General tab strings
private static readonly ProxyNameTextBoxLabel: string = localize('createProxy.ProxyName', 'Proxy name');
private static readonly CredentialNameTextBoxLabel: string = localize('createProxy.CredentialName', 'Credential name');
private static readonly DescriptionTextBoxLabel: string = localize('createProxy.Description', 'Description');
private static readonly SubsystemsTableLabel: string = localize('createProxy.Subsystems', 'Subsystems');
private static readonly SubsystemNameColumnLabel: string = localize('createProxy.SubsystemName', 'Subsystem');
// UI Components
private generalTab: sqlops.window.modelviewdialog.DialogTab;
// General tab controls
private proxyNameTextBox: sqlops.InputBoxComponent;
private credentialNameTextBox: sqlops.InputBoxComponent;
private descriptionTextBox: sqlops.InputBoxComponent;
private subsystemsTable: sqlops.TableComponent;
constructor(ownerUri: string) {
super(ownerUri, new ProxyData(ownerUri), ProxyDialog.DialogTitle);
}
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
this.generalTab = sqlops.window.modelviewdialog.createTab(ProxyDialog.GeneralTabText);
this.initializeGeneralTab();
this.dialog.content = [this.generalTab];
}
private initializeGeneralTab() {
this.generalTab.registerContent(async view => {
this.proxyNameTextBox = view.modelBuilder.inputBox().component();
this.credentialNameTextBox = view.modelBuilder.inputBox().component();
this.descriptionTextBox = view.modelBuilder.inputBox().component();
this.subsystemsTable = view.modelBuilder.table()
.withProperties({
columns: [
ProxyDialog.SubsystemNameColumnLabel
],
data: [],
height: 500
}).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.proxyNameTextBox,
title: ProxyDialog.ProxyNameTextBoxLabel
}, {
component: this.credentialNameTextBox,
title: ProxyDialog.CredentialNameTextBoxLabel
}, {
component: this.descriptionTextBox,
title: ProxyDialog.DescriptionTextBoxLabel
}, {
component: this.subsystemsTable,
title: ProxyDialog.SubsystemsTableLabel
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
});
}
protected updateModel() {
this.model.accountName = this.proxyNameTextBox.value;
this.model.credentialName = this.credentialNameTextBox.value;
this.model.description = this.descriptionTextBox.value;
}
}

View File

@@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import { ScheduleData } from '../data/scheduleData';
export class ScheduleDialog {
// Top level
private readonly DialogTitle: string = 'New Schedule';
private readonly OkButtonText: string = 'OK';
private readonly CancelButtonText: string = 'Cancel';
// UI Components
private dialog: sqlops.window.modelviewdialog.Dialog;
private schedulesTable: sqlops.TableComponent;
private model: ScheduleData;
private _onSuccess: vscode.EventEmitter<ScheduleData> = new vscode.EventEmitter<ScheduleData>();
public readonly onSuccess: vscode.Event<ScheduleData> = this._onSuccess.event;
constructor(ownerUri: string) {
this.model = new ScheduleData(ownerUri);
}
public async showDialog() {
await this.model.initialize();
this.dialog = sqlops.window.modelviewdialog.createDialog(this.DialogTitle);
this.initializeContent();
this.dialog.okButton.onClick(async () => await this.execute());
this.dialog.cancelButton.onClick(async () => await this.cancel());
this.dialog.okButton.label = this.OkButtonText;
this.dialog.cancelButton.label = this.CancelButtonText;
sqlops.window.modelviewdialog.openDialog(this.dialog);
}
private initializeContent() {
this.dialog.registerContent(async view => {
this.schedulesTable = view.modelBuilder.table()
.withProperties({
columns: [
'Schedule Name'
],
data: [],
height: 600,
width: 400
}).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: this.schedulesTable,
title: 'Schedules'
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
if (this.model.schedules) {
let data: any[][] = [];
for (let i = 0; i < this.model.schedules.length; ++i) {
let schedule = this.model.schedules[i];
data[i] = [ schedule.name ];
}
this.schedulesTable.data = data;
}
});
}
private async execute() {
this.updateModel();
await this.model.save();
this._onSuccess.fire(this.model);
}
private async cancel() {
}
private updateModel() {
let selectedRows = this.schedulesTable.selectedRows;
if (selectedRows && selectedRows.length > 0) {
let selectedRow = selectedRows[0];
this.model.selectedSchedule = this.model.schedules[selectedRow];
}
}
}

View File

@@ -0,0 +1,17 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export enum AgentDialogMode {
CREATE = 1,
EDIT = 2,
VIEW = 3
}
export interface IAgentDialogData {
dialogMode: AgentDialogMode;
initialize(): void;
save(): void;
}

View File

@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import vscode = require('vscode');
import { MainController } from './mainController';
export let controller: MainController;
export function activate(context: vscode.ExtensionContext) {
controller = new MainController(context);
controller.activate();
}
// this method is called when your extension is deactivated
export function deactivate(): void {
if (controller) {
controller.deactivate();
}
}

View File

@@ -0,0 +1,61 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import { AlertDialog } from './dialogs/alertDialog';
import { JobDialog } from './dialogs/jobDialog';
import { OperatorDialog } from './dialogs/operatorDialog';
import { ProxyDialog } from './dialogs/proxyDialog';
import { JobStepDialog } from './dialogs/jobStepDialog';
import { PickScheduleDialog } from './dialogs/pickScheduleDialog';
/**
* The main controller class that initializes the extension
*/
export class MainController {
protected _context: vscode.ExtensionContext;
// PUBLIC METHODS //////////////////////////////////////////////////////
public constructor(context: vscode.ExtensionContext) {
this._context = context;
}
/**
* Activates the extension
*/
public activate(): void {
vscode.commands.registerCommand('agent.openCreateJobDialog', (ownerUri: string) => {
let dialog = new JobDialog(ownerUri);
dialog.openDialog();
});
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, jobId: string, server: string, stepId: number) => {
let dialog = new JobStepDialog(ownerUri, jobId, server, stepId);
dialog.openNewStepDialog();
});
vscode.commands.registerCommand('agent.openPickScheduleDialog', (ownerUri: string) => {
let dialog = new PickScheduleDialog(ownerUri);
dialog.showDialog();
});
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, alertInfo: sqlops.AgentAlertInfo) => {
let dialog = new AlertDialog(ownerUri, alertInfo);
dialog.openDialog();
});
vscode.commands.registerCommand('agent.openCreateOperatorDialog', (ownerUri: string) => {
let dialog = new OperatorDialog(ownerUri);
dialog.openDialog();
});
vscode.commands.registerCommand('agent.openCreateProxyDialog', (ownerUri: string) => {
let dialog = new ProxyDialog(ownerUri);
dialog.openDialog();
});
}
/**
* Deactivates the extension
*/
public deactivate(): void {
}
}

View File

@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import 'mocha';
import * as vscode from 'vscode';
import * as sqlops from 'sqlops';
import { JobData } from '../data/jobData';
import { TestAgentService } from './testAgentService';
const testOwnerUri = 'agent://testuri';
suite('Agent extension', () => {
test('Create Job Data', async () => {
let testAgentService = new TestAgentService();
let data = new JobData(testOwnerUri, testAgentService);
data.save();
});
});

View File

@@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as sqlops from 'sqlops';
export class TestAgentService implements sqlops.AgentServicesProvider {
handle?: number;
readonly providerId: string = 'Test Provider';
// Job management methods
getJobs(ownerUri: string): Thenable<sqlops.AgentJobsResult> {
return undefined;
}
getJobHistory(ownerUri: string, jobId: string): Thenable<sqlops.AgentJobHistoryResult> {
return undefined;
}
jobAction(ownerUri: string, jobName: string, action: string): Thenable<sqlops.ResultStatus> {
return undefined;
}
createJob(ownerUri: string, jobInfo: sqlops.AgentJobInfo): Thenable<sqlops.CreateAgentJobResult> {
return undefined;
}
updateJob(ownerUri: string, originalJobName: string, jobInfo: sqlops.AgentJobInfo): Thenable<sqlops.UpdateAgentJobResult> {
return undefined;
}
deleteJob(ownerUri: string, jobInfo: sqlops.AgentJobInfo): Thenable<sqlops.ResultStatus> {
return undefined;
}
getJobDefaults(ownerUri: string): Thenable<sqlops.AgentJobDefaultsResult> {
return undefined;
}
// Job Step management methods
createJobStep(ownerUri: string, jobInfo: sqlops.AgentJobStepInfo): Thenable<sqlops.CreateAgentJobStepResult> {
return undefined;
}
updateJobStep(ownerUri: string, originalJobStepName: string, jobInfo: sqlops.AgentJobStepInfo): Thenable<sqlops.UpdateAgentJobStepResult> {
return undefined;
}
deleteJobStep(ownerUri: string, jobInfo: sqlops.AgentJobStepInfo): Thenable<sqlops.ResultStatus> {
return undefined;
}
// Alert management methods
getAlerts(ownerUri: string): Thenable<sqlops.AgentAlertsResult> {
return undefined;
}
createAlert(ownerUri: string, alertInfo: sqlops.AgentAlertInfo): Thenable<sqlops.CreateAgentAlertResult> {
return undefined;
}
updateAlert(ownerUri: string, originalAlertName: string, alertInfo: sqlops.AgentAlertInfo): Thenable<sqlops.UpdateAgentAlertResult> {
return undefined;
}
deleteAlert(ownerUri: string, alertInfo: sqlops.AgentAlertInfo): Thenable<sqlops.ResultStatus> {
return undefined;
}
// Operator management methods
getOperators(ownerUri: string): Thenable<sqlops.AgentOperatorsResult> {
return undefined;
}
createOperator(ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo): Thenable<sqlops.CreateAgentOperatorResult> {
return undefined;
}
updateOperator(ownerUri: string, originalOperatorName: string, operatorInfo: sqlops.AgentOperatorInfo): Thenable<sqlops.UpdateAgentOperatorResult> {
return undefined;
}
deleteOperator(ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo): Thenable<sqlops.ResultStatus> {
return undefined;
}
// Proxy management methods
getProxies(ownerUri: string): Thenable<sqlops.AgentProxiesResult> {
return undefined;
}
createProxy(ownerUri: string, proxyInfo: sqlops.AgentProxyInfo): Thenable<sqlops.CreateAgentOperatorResult> {
return undefined;
}
updateProxy(ownerUri: string, originalProxyName: string, proxyInfo: sqlops.AgentProxyInfo): Thenable<sqlops.UpdateAgentOperatorResult> {
return undefined;
}
deleteProxy(ownerUri: string, proxyInfo: sqlops.AgentProxyInfo): Thenable<sqlops.ResultStatus> {
return undefined;
}
// Job Schedule management methods
getJobSchedules(ownerUri: string): Thenable<sqlops.AgentJobSchedulesResult> {
return undefined;
}
createJobSchedule(ownerUri: string, scheduleInfo: sqlops.AgentJobScheduleInfo): Thenable<sqlops.CreateAgentJobScheduleResult> {
return undefined;
}
updateJobSchedule(ownerUri: string, originalScheduleName: string, scheduleInfo: sqlops.AgentJobScheduleInfo): Thenable<sqlops.UpdateAgentJobScheduleResult> {
return undefined;
}
deleteJobSchedule(ownerUri: string, scheduleInfo: sqlops.AgentJobScheduleInfo): Thenable<sqlops.ResultStatus> {
return undefined;
}
registerOnUpdated(handler: () => any): void {
}
}

View File

@@ -4,5 +4,6 @@
*--------------------------------------------------------------------------------------------*/
/// <reference path='../../../../src/vs/vscode.d.ts'/>
/// <reference path='../../../../src/vs/vscode.proposed.d.ts'/>
/// <reference types='@types/node'/>
/// <reference path='../../../../src/sql/sqlops.d.ts'/>
/// <reference path='../../../../src/sql/sqlops.proposed.d.ts'/>
/// <reference types='@types/node'/>

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/mmims/language-batchfile/commit/3dd105c31484e5975144478dac1aa91d8f51e528",
"version": "https://github.com/mmims/language-batchfile/commit/6235c491be4dff49cd3966b50142874d7f79580a",
"name": "Batch File",
"scopeName": "source.batchfile",
"patterns": [
@@ -46,14 +46,17 @@
"commands": {
"patterns": [
{
"match": "(?<=^|[\\s@])(?i:adprep|append|arp|assoc|at|atmadm|attrib|auditpol|autochk|autoconv|autofmt|bcdboot|bcdedit|bdehdcfg|bitsadmin|bootcfg|brea|cacls|cd|certreq|certutil|change|chcp|chdir|chglogon|chgport|chgusr|chkdsk|chkntfs|choice|cipher|clip|clscluadmin|cluster|cmd|cmdkey|cmstp|color|comp|compact|convert|copy|cprofile|cscript|csvde|date|dcdiag|dcgpofix|dcpromo|defra|del|dfscmd|dfsdiag|dfsrmig|diantz|dir|dirquota|diskcomp|diskcopy|diskpart|diskperf|diskraid|diskshadow|dispdiag|doin|dnscmd|doskey|driverquery|dsacls|dsadd|dsamain|dsdbutil|dsget|dsmgmt|dsmod|dsmove|dsquery|dsrm|edit|endlocal|eraseesentutl|eventcreate|eventquery|eventtriggers|evntcmd|expand|extract|fc|filescrn|find|findstr|finger|flattemp|fonde|forfiles|format|freedisk|fsutil|ftp|ftype|fveupdate|getmac|gettype|gpfixup|gpresult|gpupdate|graftabl|hashgen|hep|helpctr|hostname|icacls|iisreset|inuse|ipconfig|ipxroute|irftp|ismserv|jetpack|klist|ksetup|ktmutil|ktpass|label|ldifd|ldp|lodctr|logman|logoff|lpq|lpr|macfile|makecab|manage-bde|mapadmin|md|mkdir|mklink|mmc|mode|more|mount|mountvol|move|mqbup|mqsvc|mqtgsvc|msdt|msg|msiexec|msinfo32|mstsc|nbtstat|net computer|net group|net localgroup|net print|net session|net share|net start|net stop|net use|net user|net view|net|netcfg|netdiag|netdom|netsh|netstat|nfsadmin|nfsshare|nfsstat|nlb|nlbmgr|nltest|nslookup|ntackup|ntcmdprompt|ntdsutil|ntfrsutl|openfiles|pagefileconfig|path|pathping|pause|pbadmin|pentnt|perfmon|ping|pnpunatten|pnputil|popd|powercfg|powershell|powershell_ise|print|prncnfg|prndrvr|prnjobs|prnmngr|prnport|prnqctl|prompt|pubprn|pushd|pushprinterconnections|pwlauncher|qappsrv|qprocess|query|quser|qwinsta|rasdial|rcp|rd|rdpsign|regentc|recover|redircmp|redirusr|reg|regini|regsvr32|relog|ren|rename|rendom|repadmin|repair-bde|replace|reset session|rxec|risetup|rmdir|robocopy|route|rpcinfo|rpcping|rsh|runas|rundll32|rwinsta|sc|schtasks|scwcmd|secedit|serverceipoptin|servrmanagercmd|serverweroptin|setlocal|setspn|setx|sfc|shadow|shift|showmount|shutdown|sort|start|storrept|subst|sxstrace|ysocmgr|systeminfo|takeown|tapicfg|taskkill|tasklist|tcmsetup|telnet|tftp|time|timeout|title|tlntadmn|tpmvscmgr|tpmvscmgr|tacerpt|tracert|tree|tscon|tsdiscon|tsecimp|tskill|tsprof|type|typeperf|tzutil|uddiconfig|umount|unlodctr|ver|verifier|verif|vol|vssadmin|w32tm|waitfor|wbadmin|wdsutil|wecutil|wevtutil|where|whoami|winnt|winnt32|winpop|winrm|winrs|winsat|wlbs|mic|wscript|xcopy)(?=$|\\s)",
"match": "(?<=^|[\\s@])(?i:adprep|append|arp|assoc|at|atmadm|attrib|auditpol|autochk|autoconv|autofmt|bcdboot|bcdedit|bdehdcfg|bitsadmin|bootcfg|brea|cacls|cd|certreq|certutil|change|chcp|chdir|chglogon|chgport|chgusr|chkdsk|chkntfs|choice|cipher|clip|cls|clscluadmin|cluster|cmd|cmdkey|cmstp|color|comp|compact|convert|copy|cprofile|cscript|csvde|date|dcdiag|dcgpofix|dcpromo|defra|del|dfscmd|dfsdiag|dfsrmig|diantz|dir|dirquota|diskcomp|diskcopy|diskpart|diskperf|diskraid|diskshadow|dispdiag|doin|dnscmd|doskey|driverquery|dsacls|dsadd|dsamain|dsdbutil|dsget|dsmgmt|dsmod|dsmove|dsquery|dsrm|edit|endlocal|eraseesentutl|eventcreate|eventquery|eventtriggers|evntcmd|expand|extract|fc|filescrn|find|findstr|finger|flattemp|fonde|forfiles|format|freedisk|fsutil|ftp|ftype|fveupdate|getmac|gettype|gpfixup|gpresult|gpupdate|graftabl|hashgen|hep|helpctr|hostname|icacls|iisreset|inuse|ipconfig|ipxroute|irftp|ismserv|jetpack|klist|ksetup|ktmutil|ktpass|label|ldifd|ldp|lodctr|logman|logoff|lpq|lpr|macfile|makecab|manage-bde|mapadmin|md|mkdir|mklink|mmc|mode|more|mount|mountvol|move|mqbup|mqsvc|mqtgsvc|msdt|msg|msiexec|msinfo32|mstsc|nbtstat|net computer|net group|net localgroup|net print|net session|net share|net start|net stop|net use|net user|net view|net|netcfg|netdiag|netdom|netsh|netstat|nfsadmin|nfsshare|nfsstat|nlb|nlbmgr|nltest|nslookup|ntackup|ntcmdprompt|ntdsutil|ntfrsutl|openfiles|pagefileconfig|path|pathping|pause|pbadmin|pentnt|perfmon|ping|pnpunatten|pnputil|popd|powercfg|powershell|powershell_ise|print|prncnfg|prndrvr|prnjobs|prnmngr|prnport|prnqctl|prompt|pubprn|pushd|pushprinterconnections|pwlauncher|qappsrv|qprocess|query|quser|qwinsta|rasdial|rcp|rd|rdpsign|regentc|recover|redircmp|redirusr|reg|regini|regsvr32|relog|ren|rename|rendom|repadmin|repair-bde|replace|reset session|rxec|risetup|rmdir|robocopy|route|rpcinfo|rpcping|rsh|runas|rundll32|rwinsta|sc|schtasks|scwcmd|secedit|serverceipoptin|servrmanagercmd|serverweroptin|setspn|setx|sfc|shadow|shift|showmount|shutdown|sort|start|storrept|subst|sxstrace|ysocmgr|systeminfo|takeown|tapicfg|taskkill|tasklist|tcmsetup|telnet|tftp|time|timeout|title|tlntadmn|tpmvscmgr|tpmvscmgr|tacerpt|tracert|tree|tscon|tsdiscon|tsecimp|tskill|tsprof|type|typeperf|tzutil|uddiconfig|umount|unlodctr|ver|verifier|verif|vol|vssadmin|w32tm|waitfor|wbadmin|wdsutil|wecutil|wevtutil|where|whoami|winnt|winnt32|winpop|winrm|winrs|winsat|wlbs|mic|wscript|xcopy)(?=$|\\s)",
"name": "keyword.command.batchfile"
},
{
"begin": "(?<=^|[\\s@])(?i:echo)(?=$|\\s|\\.)",
"begin": "(?i)(?<=^|[\\s@])(echo)(?:(?=$|\\.|:)|\\s+(?:(on|off)(?=\\s*$))?)",
"beginCaptures": {
"0": {
"1": {
"name": "keyword.command.batchfile"
},
"2": {
"name": "keyword.other.special-method.batchfile"
}
},
"end": "(?=$\\n|[&|><)])",
@@ -72,6 +75,17 @@
}
]
},
{
"match": "(?i)(?<=^|[\\s@])(setlocal)(?:\\s*$|\\s+(EnableExtensions|DisableExtensions|EnableDelayedExpansion|DisableDelayedExpansion)(?=\\s*$))",
"captures": {
"1": {
"name": "keyword.command.batchfile"
},
"2": {
"name": "keyword.other.special-method.batchfile"
}
}
},
{
"include": "#command_set"
}
@@ -110,35 +124,7 @@
"include": "#parens"
},
{
"begin": "(\")\\s*([^ ][^=]*)(=)\"?",
"beginCaptures": {
"1": {
"name": "punctuation.definition.string.begin.batchfile"
},
"2": {
"name": "variable.other.readwrite.batchfile"
},
"3": {
"name": "keyword.operator.assignment.batchfile"
}
},
"end": "\"",
"endCaptures": {
"0": {
"name": "string.quoted.double.batchfile"
}
},
"patterns": [
{
"include": "#variables"
},
{
"include": "#numbers"
},
{
"include": "#parens"
}
]
"include": "#command_set_strings"
},
{
"include": "#strings"
@@ -215,6 +201,9 @@
"begin": "\\s+/[pP]\\s+",
"end": "(?=$\\n|[&|><)])",
"patterns": [
{
"include": "#command_set_strings"
},
{
"begin": "([^ ][^=]*)(=)",
"beginCaptures": {
@@ -294,6 +283,42 @@
}
]
},
"command_set_strings": {
"patterns": [
{
"begin": "(\")\\s*([^ ][^=]*)(=)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.string.begin.batchfile"
},
"2": {
"name": "variable.other.readwrite.batchfile"
},
"3": {
"name": "keyword.operator.assignment.batchfile"
}
},
"end": "\"",
"endCaptures": {
"0": {
"name": "punctuation.definition.string.end.batchfile"
}
},
"name": "string.quoted.double.batchfile",
"patterns": [
{
"include": "#variables"
},
{
"include": "#numbers"
},
{
"include": "#escaped_characters"
}
]
}
]
},
"comments": {
"patterns": [
{
@@ -359,7 +384,7 @@
"controls": {
"patterns": [
{
"match": "(?<=^|\\s)(?i)(?:goto|call|exit)(?=$|\\s)",
"match": "(?i)(?<=^|\\s)(?:call|exit(?=$|\\s)|goto(?=$|\\s|:))",
"name": "keyword.control.statement.batchfile"
},
{
@@ -389,7 +414,7 @@
"escaped_characters": {
"patterns": [
{
"match": "%%|\\^\\^!|\\^.|\\^\\n",
"match": "%%|\\^\\^!|\\^(?=.)|\\^\\n",
"name": "constant.character.escape.batchfile"
}
]
@@ -397,7 +422,7 @@
"labels": {
"patterns": [
{
"match": "^\\s*(:)([^+=,;:\\s].*)$",
"match": "(?i)(?:^\\s*|(?<=goto)\\s*)(:)([^+=,;:\\s].*)$",
"captures": {
"1": {
"name": "punctuation.separator.batchfile"
@@ -432,11 +457,11 @@
"name": "keyword.operator.logical.batchfile"
},
{
"match": "&&?|\\|\\|",
"match": "(?<!\\^)&&?|\\|\\|",
"name": "keyword.operator.conditional.batchfile"
},
{
"match": "\\|",
"match": "(?<!\\^)\\|",
"name": "keyword.operator.pipe.batchfile"
},
{
@@ -493,6 +518,10 @@
},
"name": "string.quoted.double.batchfile",
"patterns": [
{
"match": "%%",
"name": "constant.character.escape.batchfile"
},
{
"include": "#variables"
}
@@ -507,9 +536,11 @@
"captures": {
"1": {
"name": "punctuation.definition.variable.batchfile"
},
"2": {
"name": "variable.parameter.batchfile"
}
},
"name": "variable.parameter.batchfile"
}
},
{
"include": "#variable"

View File

@@ -22,7 +22,7 @@
}
},
{
"c": " off",
"c": " ",
"t": "source.batchfile",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -32,6 +32,17 @@
"hc_black": "default: #FFFFFF"
}
},
{
"c": "off",
"t": "source.batchfile keyword.other.special-method.batchfile",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
}
},
{
"c": "setlocal",
"t": "source.batchfile keyword.command.batchfile",
@@ -89,13 +100,13 @@
},
{
"c": "%",
"t": "source.batchfile variable.parameter.batchfile punctuation.definition.variable.batchfile",
"t": "source.batchfile punctuation.definition.variable.batchfile",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
"hc_black": "default: #FFFFFF"
}
},
{

View File

@@ -7,10 +7,6 @@
"engines": {
"vscode": "^1.0.0"
},
"categories": [
"Languages",
"Other"
],
"activationEvents": [
"onLanguage:json",
"onLanguage:jsonc"

View File

@@ -70,7 +70,12 @@ function autoFixSettingsJSON(willSaveEvent: vscode.TextDocumentWillSaveEvent): v
onError(error: ParseErrorCode, offset: number, length: number): void {
if (error === ParseErrorCode.CommaExpected && lastEndOfSomething > -1) {
const fixPosition = document.positionAt(lastEndOfSomething);
edit.insert(document.uri, fixPosition, ',');
// Don't insert a comma immediately before a : or ' :'
const colonRange = document.getWordRangeAtPosition(fixPosition, / *:/);
if (!colonRange) {
edit.insert(document.uri, fixPosition, ',');
}
}
}
});

View File

@@ -4,5 +4,5 @@
"version": "0.0.0",
"license": "Apache2",
"repositoryURL": "https://github.com/moby/moby",
"description": "The file syntaxes/Dockerfile.tmLanguage was included from https://github.com/moby/moby/blob/master/contrib/syntax/textmate/Docker.tmbundle/Syntaxes/Dockerfile.tmLanguage."
"description": "The file syntaxes/docker.tmLanguage was included from https://github.com/moby/moby/blob/master/contrib/syntax/textmate/Docker.tmbundle/Syntaxes/Dockerfile.tmLanguage."
}]

View File

@@ -7,10 +7,6 @@
"engines": {
"vscode": "^1.4.0"
},
"categories": [
"Languages",
"Other"
],
"activationEvents": [
"onLanguage:json",
"onLanguage:markdown",

View File

@@ -834,6 +834,23 @@
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
}
],
"editor/context": [
{
"command": "git.stageSelectedRanges",
"group": "2_git@1",
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.unstageSelectedRanges",
"group": "2_git@2",
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.revertSelectedRanges",
"group": "2_git@3",
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
}
],
"scm/change/title": [
{
"command": "git.stageChange",
@@ -861,7 +878,7 @@
],
"description": "%config.path%",
"default": null,
"isExecutable": true
"scope": "application"
},
"git.autoRepositoryDetection": {
"type": "boolean",
@@ -964,6 +981,12 @@
"scope": "resource",
"default": true,
"description": "%config.detectSubmodules%"
},
"git.detectSubmodulesLimit": {
"type": "number",
"scope": "resource",
"default": 10,
"description": "%config.detectSubmodulesLimit%"
}
}
},
@@ -1090,7 +1113,8 @@
"byline": "^5.0.0",
"file-type": "^7.2.0",
"iconv-lite": "0.4.19",
"vscode-extension-telemetry": "0.0.15",
"jschardet": "^1.6.0",
"vscode-extension-telemetry": "0.0.17",
"vscode-nls": "^3.2.1",
"which": "^1.3.0"
},
@@ -1102,4 +1126,4 @@
"@types/which": "^1.0.28",
"mocha": "^3.2.0"
}
}
}

View File

@@ -70,6 +70,7 @@
"config.showInlineOpenFileAction": "Controls whether to show an inline Open File action in the Git changes view.",
"config.inputValidation": "Controls when to show commit message input validation.",
"config.detectSubmodules": "Controls whether to automatically detect git submodules.",
"config.detectSubmodulesLimit": "Controls the limit of git submodules detected.",
"colors.modified": "Color for modified resources.",
"colors.deleted": "Color for deleted resources.",
"colors.untracked": "Color for untracked resources.",

View File

@@ -6,37 +6,55 @@
'use strict';
import { Model } from './model';
import { Uri } from 'vscode';
import { Repository as ModelRepository } from './repository';
import { Uri, SourceControlInputBox } from 'vscode';
export interface InputBox {
value: string;
}
export class InputBoxImpl implements InputBox {
set value(value: string) { this.inputBox.value = value; }
get value(): string { return this.inputBox.value; }
constructor(private inputBox: SourceControlInputBox) { }
}
export interface Repository {
readonly rootUri: Uri;
readonly inputBox: InputBox;
}
export interface API {
getRepositories(): Promise<Repository[]>;
export class RepositoryImpl implements Repository {
readonly rootUri: Uri;
readonly inputBox: InputBox;
constructor(repository: ModelRepository) {
this.rootUri = Uri.file(repository.root);
this.inputBox = new InputBoxImpl(repository.inputBox);
}
}
export function createApi(modelPromise: Promise<Model>) {
return {
async getRepositories(): Promise<Repository[]> {
const model = await modelPromise;
export interface API {
getRepositories(): Promise<Repository[]>;
getGitPath(): Promise<string>;
}
return model.repositories.map(repository => ({
rootUri: Uri.file(repository.root),
inputBox: {
set value(value: string) {
repository.inputBox.value = value;
},
get value(): string {
return repository.inputBox.value;
}
}
}));
}
};
export class APIImpl implements API {
constructor(private modelPromise: Promise<Model>) { }
async getGitPath(): Promise<string> {
const model = await this.modelPromise;
return model.git.path;
}
async getRepositories(): Promise<Repository[]> {
const model = await this.modelPromise;
return model.repositories.map(repository => new RepositoryImpl(repository));
}
}
export function createApi(modelPromise: Promise<Model>): API {
return new APIImpl(modelPromise);
}

View File

@@ -5,7 +5,7 @@
'use strict';
import { Uri, commands, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn, ProgressLocation, TextEditor, CancellationTokenSource, StatusBarAlignment } from 'vscode';
import { Uri, commands, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn, ProgressLocation, TextEditor, MessageOptions } from 'vscode';
import { Ref, RefType, Git, GitErrorCodes, Branch } from './git';
import { Repository, Resource, Status, CommitOptions, ResourceGroupType } from './repository';
import { Model } from './model';
@@ -328,8 +328,6 @@ export class CommandCenter {
return '';
}
private static cloneId = 0;
@command('git.clone')
async clone(url?: string): Promise<void> {
if (!url) {
@@ -350,15 +348,18 @@ export class CommandCenter {
}
const config = workspace.getConfiguration('git');
let value = config.get<string>('defaultCloneDirectory') || os.homedir();
let defaultCloneDirectory = config.get<string>('defaultCloneDirectory') || os.homedir();
defaultCloneDirectory = defaultCloneDirectory.replace(/^~/, os.homedir());
const parentPath = await window.showInputBox({
prompt: localize('parent', "Parent Directory"),
value,
ignoreFocusOut: true
const uris = await window.showOpenDialog({
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false,
defaultUri: Uri.file(defaultCloneDirectory),
openLabel: localize('selectFolder', "Select Repository Location")
});
if (!parentPath) {
if (!uris || uris.length === 0) {
/* __GDPR__
"clone" : {
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
@@ -368,25 +369,33 @@ export class CommandCenter {
return;
}
const tokenSource = new CancellationTokenSource();
const cancelCommandId = `cancelClone${CommandCenter.cloneId++}`;
const commandDisposable = commands.registerCommand(cancelCommandId, () => tokenSource.cancel());
const statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
statusBarItem.text = localize('cancel', "$(sync~spin) Cloning repository... Click to cancel");
statusBarItem.tooltip = localize('cancel tooltip', "Cancel clone");
statusBarItem.command = cancelCommandId;
statusBarItem.show();
const clonePromise = this.git.clone(url, parentPath.replace(/^~/, os.homedir()), tokenSource.token);
const uri = uris[0];
const parentPath = uri.fsPath;
try {
window.withProgress({ location: ProgressLocation.SourceControl, title: localize('cloning', "Cloning git repository...") }, () => clonePromise);
const opts = {
location: ProgressLocation.Notification,
title: localize('cloning', "Cloning git repository '{0}'...", url),
cancellable: true
};
const repositoryPath = await clonePromise;
const repositoryPath = await window.withProgress(
opts,
(_, token) => this.git.clone(url!, parentPath, token)
);
const choices = [];
let message = localize('proposeopen', "Would you like to open the cloned repository?");
const open = localize('openrepo', "Open Repository");
const result = await window.showInformationMessage(localize('proposeopen', "Would you like to open the cloned repository?"), open);
choices.push(open);
const addToWorkspace = localize('add', "Add to Workspace");
if (workspace.workspaceFolders) {
message = localize('proposeopen2', "Would you like to open the cloned repository, or add it to the current workspace?");
choices.push(addToWorkspace);
}
const result = await window.showInformationMessage(message, ...choices);
const openFolder = result === open;
/* __GDPR__
@@ -396,8 +405,13 @@ export class CommandCenter {
}
*/
this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'success' }, { openFolder: openFolder ? 1 : 0 });
const uri = Uri.file(repositoryPath);
if (openFolder) {
commands.executeCommand('vscode.openFolder', Uri.file(repositoryPath));
commands.executeCommand('vscode.openFolder', uri);
} else if (result === addToWorkspace) {
workspace.updateWorkspaceFolders(workspace.workspaceFolders!.length, 0, { uri });
}
} catch (err) {
if (/already exists and is not an empty directory/.test(err && err.stderr || '')) {
@@ -419,9 +433,6 @@ export class CommandCenter {
}
throw err;
} finally {
commandDisposable.dispose();
statusBarItem.dispose();
}
}
@@ -1205,7 +1216,7 @@ export class CommandCenter {
const message = localize('confirm force delete branch', "The branch '{0}' is not fully merged. Delete anyway?", name);
const yes = localize('delete branch', "Delete Branch");
const pick = await window.showWarningMessage(message, yes);
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick === yes) {
await run(true);
@@ -1333,7 +1344,7 @@ export class CommandCenter {
const remoteCharCnt = remotePick.label.length;
repository.pull(false, remotePick.label, branchPick.label.slice(remoteCharCnt + 1));
repository.pullFrom(false, remotePick.label, branchPick.label.slice(remoteCharCnt + 1));
}
@command('git.pull', { repository: true })
@@ -1345,7 +1356,7 @@ export class CommandCenter {
return;
}
await repository.pull();
await repository.pull(repository.HEAD);
}
@command('git.pullRebase', { repository: true })
@@ -1357,7 +1368,7 @@ export class CommandCenter {
return;
}
await repository.pullWithRebase();
await repository.pullWithRebase(repository.HEAD);
}
@command('git.push', { repository: true })
@@ -1375,7 +1386,7 @@ export class CommandCenter {
}
try {
await repository.push();
await repository.push(repository.HEAD);
} catch (err) {
if (err.gitErrorCode !== GitErrorCodes.NoUpstreamBranch) {
throw err;
@@ -1443,7 +1454,7 @@ export class CommandCenter {
const shouldPrompt = config.get<boolean>('confirmSync') === true;
if (shouldPrompt) {
const message = localize('sync is unpredictable', "This action will push and pull commits to and from '{0}'.", HEAD.upstream);
const message = localize('sync is unpredictable', "This action will push and pull commits to and from '{0}/{1}'.", HEAD.upstream.remote, HEAD.upstream.name);
const yes = localize('ok', "OK");
const neverAgain = localize('never again', "OK, Don't Show Again");
const pick = await window.showWarningMessage(message, { modal: true }, yes, neverAgain);
@@ -1456,9 +1467,9 @@ export class CommandCenter {
}
if (rebase) {
await repository.syncRebase();
await repository.syncRebase(HEAD);
} else {
await repository.sync();
await repository.sync(HEAD);
}
}
@@ -1476,7 +1487,7 @@ export class CommandCenter {
return;
}
await repository.sync();
await repository.sync(HEAD);
}));
}
@@ -1635,6 +1646,10 @@ export class CommandCenter {
this.telemetryReporter.sendTelemetryEvent('git.command', { command: id });
return result.catch(async err => {
const options: MessageOptions = {
modal: err.gitErrorCode === GitErrorCodes.DirtyWorkTree
};
let message: string;
switch (err.gitErrorCode) {
@@ -1664,9 +1679,11 @@ export class CommandCenter {
return;
}
options.modal = true;
const outputChannel = this.outputChannel as OutputChannel;
const openOutputChannelChoice = localize('open git log', "Open Git Log");
const choice = await window.showErrorMessage(message, openOutputChannelChoice);
const choice = await window.showErrorMessage(message, options, openOutputChannelChoice);
if (choice === openOutputChannelChoice) {
outputChannel.show();

View File

@@ -0,0 +1,81 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as jschardet from 'jschardet';
jschardet.Constants.MINIMUM_THRESHOLD = 0.2;
function detectEncodingByBOM(buffer: NodeBuffer): string | null {
if (!buffer || buffer.length < 2) {
return null;
}
const b0 = buffer.readUInt8(0);
const b1 = buffer.readUInt8(1);
// UTF-16 BE
if (b0 === 0xFE && b1 === 0xFF) {
return 'utf16be';
}
// UTF-16 LE
if (b0 === 0xFF && b1 === 0xFE) {
return 'utf16le';
}
if (buffer.length < 3) {
return null;
}
const b2 = buffer.readUInt8(2);
// UTF-8
if (b0 === 0xEF && b1 === 0xBB && b2 === 0xBF) {
return 'utf8';
}
return null;
}
const IGNORE_ENCODINGS = [
'ascii',
'utf-8',
'utf-16',
'utf-32'
];
const JSCHARDET_TO_ICONV_ENCODINGS: { [name: string]: string } = {
'ibm866': 'cp866',
'big5': 'cp950'
};
export function detectEncoding(buffer: Buffer): string | null {
let result = detectEncodingByBOM(buffer);
if (result) {
return result;
}
const detected = jschardet.detect(buffer);
if (!detected || !detected.encoding) {
return null;
}
const encoding = detected.encoding;
// Ignore encodings that cannot guess correctly
// (http://chardet.readthedocs.io/en/latest/supported-encodings.html)
if (0 <= IGNORE_ENCODINGS.indexOf(encoding.toLowerCase())) {
return null;
}
const normalizedEncodingName = encoding.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
const mapped = JSCHARDET_TO_ICONV_ENCODINGS[normalizedEncodingName];
return mapped || normalizedEncodingName;
}

View File

@@ -15,6 +15,7 @@ import iconv = require('iconv-lite');
import * as filetype from 'file-type';
import { assign, uniqBy, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent } from './util';
import { CancellationToken } from 'vscode';
import { detectEncoding } from './encoding';
const readfile = denodeify<string, string | null, string>(fs.readFile);
@@ -53,8 +54,13 @@ export interface Ref {
remote?: string;
}
export interface UpstreamRef {
remote: string;
name: string;
}
export interface Branch extends Ref {
upstream?: string;
upstream?: UpstreamRef;
ahead?: number;
behind?: number;
}
@@ -361,14 +367,14 @@ function getGitErrorCode(stderr: string): string | undefined {
export class Git {
private gitPath: string;
readonly path: string;
private env: any;
private _onOutput = new EventEmitter();
get onOutput(): EventEmitter { return this._onOutput; }
constructor(options: IGitOptions) {
this.gitPath = options.gitPath;
this.path = options.gitPath;
this.env = options.env || {};
}
@@ -382,11 +388,29 @@ export class Git {
}
async clone(url: string, parentPath: string, cancellationToken?: CancellationToken): Promise<string> {
const folderName = decodeURI(url).replace(/^.*\//, '').replace(/\.git$/, '') || 'repository';
const folderPath = path.join(parentPath, folderName);
let baseFolderName = decodeURI(url).replace(/^.*\//, '').replace(/\.git$/, '') || 'repository';
let folderName = baseFolderName;
let folderPath = path.join(parentPath, folderName);
let count = 1;
while (count < 20 && await new Promise(c => fs.exists(folderPath, c))) {
folderName = `${baseFolderName}-${count++}`;
folderPath = path.join(parentPath, folderName);
}
await mkdirp(parentPath);
await this.exec(parentPath, ['clone', url, folderPath], { cancellationToken });
try {
await this.exec(parentPath, ['clone', url, folderPath], { cancellationToken });
} catch (err) {
if (err.stderr) {
err.stderr = err.stderr.replace(/^Cloning.+$/m, '').trim();
err.stderr = err.stderr.replace(/^ERROR:\s+/, '').trim();
}
throw err;
}
return folderPath;
}
@@ -442,7 +466,7 @@ export class Git {
}
spawn(args: string[], options: SpawnOptions = {}): cp.ChildProcess {
if (!this.gitPath) {
if (!this.path) {
throw new Error('git could not be found in the system.');
}
@@ -464,7 +488,7 @@ export class Git {
this.log(`> git ${args.join(' ')}\n`);
}
return cp.spawn(this.gitPath, args, options);
return cp.spawn(this.path, args, options);
}
private log(output: string): void {
@@ -654,9 +678,16 @@ export class Repository {
return result.stdout;
}
async bufferString(object: string, encoding: string = 'utf8'): Promise<string> {
async bufferString(object: string, encoding: string = 'utf8', autoGuessEncoding = false): Promise<string> {
const stdout = await this.buffer(object);
return iconv.decode(stdout, iconv.encodingExists(encoding) ? encoding : 'utf8');
if (autoGuessEncoding) {
encoding = detectEncoding(stdout) || encoding;
}
encoding = iconv.encodingExists(encoding) ? encoding : 'utf8';
return iconv.decode(stdout, encoding);
}
async buffer(object: string): Promise<Buffer> {
@@ -988,7 +1019,7 @@ export class Repository {
}
async pull(rebase?: boolean, remote?: string, branch?: string): Promise<void> {
const args = ['pull'];
const args = ['pull', '--tags'];
if (rebase) {
args.push('-r');
@@ -1008,7 +1039,8 @@ export class Repository {
err.gitErrorCode = GitErrorCodes.NoUserNameConfigured;
} else if (/Could not read from remote repository/.test(err.stderr || '')) {
err.gitErrorCode = GitErrorCodes.RemoteConnectionError;
} else if (/Pull is not possible because you have unmerged files|Cannot pull with rebase: You have unstaged changes|Your local changes to the following files would be overwritten|Please, commit your changes before you can merge/.test(err.stderr)) {
} else if (/Pull is not possible because you have unmerged files|Cannot pull with rebase: You have unstaged changes|Your local changes to the following files would be overwritten|Please, commit your changes before you can merge/i.test(err.stderr)) {
err.stderr = err.stderr.replace(/Cannot pull with rebase: You have unstaged changes/i, 'Cannot pull with rebase, you have unstaged changes');
err.gitErrorCode = GitErrorCodes.DirtyWorkTree;
}
@@ -1218,10 +1250,16 @@ export class Repository {
const commit = result.stdout.trim();
try {
const res2 = await this.run(['rev-parse', '--symbolic-full-name', '--abbrev-ref', name + '@{u}']);
const upstream = res2.stdout.trim();
const res2 = await this.run(['rev-parse', '--symbolic-full-name', name + '@{u}']);
const fullUpstream = res2.stdout.trim();
const match = /^refs\/remotes\/([^/]+)\/(.+)$/.exec(fullUpstream);
const res3 = await this.run(['rev-list', '--left-right', name + '...' + upstream]);
if (!match) {
throw new Error(`Could not parse upstream branch: ${fullUpstream}`);
}
const upstream = { remote: match[1], name: match[2] };
const res3 = await this.run(['rev-list', '--left-right', name + '...' + fullUpstream]);
let ahead = 0, behind = 0;
let i = 0;

View File

@@ -17,6 +17,7 @@ import { Askpass } from './askpass';
import { toDisposable, filterEvent, eventToPromise } from './util';
import TelemetryReporter from 'vscode-extension-telemetry';
import { API, createApi } from './api';
import { GitProtocolHandler } from './protocolHandler';
let telemetryReporter: TelemetryReporter;
@@ -51,7 +52,8 @@ async function init(context: ExtensionContext, outputChannel: OutputChannel, dis
disposables.push(
new CommandCenter(git, model, outputChannel, telemetryReporter),
new GitContentProvider(model),
new GitDecorations(model)
new GitDecorations(model),
new GitProtocolHandler()
);
await checkGitVersion(info);

View File

@@ -66,7 +66,7 @@ export class Model {
private disposables: Disposable[] = [];
constructor(private git: Git, private globalState: Memento, private outputChannel: OutputChannel) {
constructor(readonly git: Git, private globalState: Memento, private outputChannel: OutputChannel) {
workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables);
this.onDidChangeWorkspaceFolders({ added: workspace.workspaceFolders || [], removed: [] });
@@ -227,14 +227,17 @@ export class Model {
const changeListener = repository.onDidChangeRepository(uri => this._onDidChangeRepository.fire({ repository, uri }));
const originalResourceChangeListener = repository.onDidChangeOriginalResource(uri => this._onDidChangeOriginalResource.fire({ repository, uri }));
const submodulesLimit = workspace
.getConfiguration('git', Uri.file(repository.root))
.get<number>('detectSubmodulesLimit') as number;
const checkForSubmodules = () => {
if (repository.submodules.length > 10) {
if (repository.submodules.length > submodulesLimit) {
window.showWarningMessage(localize('too many submodules', "The '{0}' repository has {1} submodules which won't be opened automatically. You can still open each one individually by opening a file within.", path.basename(repository.root), repository.submodules.length));
statusListener.dispose();
return;
}
this.scanSubmodules(repository);
this.scanSubmodules(repository, submodulesLimit);
};
const statusListener = repository.onDidRunGitStatus(checkForSubmodules);
@@ -256,7 +259,7 @@ export class Model {
this._onDidOpenRepository.fire(repository);
}
private scanSubmodules(repository: Repository): void {
private scanSubmodules(repository: Repository, limit: number): void {
const shouldScanSubmodules = workspace
.getConfiguration('git', Uri.file(repository.root))
.get<boolean>('detectSubmodules') === true;
@@ -266,6 +269,7 @@ export class Model {
}
repository.submodules
.slice(0, limit)
.map(r => path.join(repository.root, r.path))
.forEach(p => this.eventuallyScanPossibleGitRepository(p));
}

View File

@@ -0,0 +1,39 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ProtocolHandler, Uri, window, Disposable, commands } from 'vscode';
import { dispose } from './util';
import * as querystring from 'querystring';
export class GitProtocolHandler implements ProtocolHandler {
private disposables: Disposable[] = [];
constructor() {
this.disposables.push(window.registerProtocolHandler(this));
}
handleUri(uri: Uri): void {
switch (uri.path) {
case '/clone': this.clone(uri);
}
}
private clone(uri: Uri): void {
const data = querystring.parse(uri.query);
if (!data.url) {
console.warn('Failed to open URI:', uri);
}
commands.executeCommand('git.clone', data.url);
}
dispose(): void {
this.disposables = dispose(this.disposables);
}
}

View File

@@ -728,24 +728,48 @@ export class Repository implements Disposable {
}
@throttle
async pullWithRebase(): Promise<void> {
await this.run(Operation.Pull, () => this.repository.pull(true));
async pullWithRebase(head: Branch | undefined): Promise<void> {
let remote: string | undefined;
let branch: string | undefined;
if (head && head.name && head.upstream) {
remote = head.upstream.remote;
branch = `${head.upstream.name}`;
}
await this.run(Operation.Pull, () => this.repository.pull(true, remote, branch));
}
@throttle
async pull(rebase?: boolean, remote?: string, name?: string): Promise<void> {
await this.run(Operation.Pull, () => this.repository.pull(rebase, remote, name));
}
async pull(head: Branch | undefined): Promise<void> {
let remote: string | undefined;
let branch: string | undefined;
@throttle
async push(): Promise<void> {
await this.run(Operation.Push, () => this.repository.push());
if (head && head.name && head.upstream) {
remote = head.upstream.remote;
branch = `${head.upstream.name}`;
}
await this.run(Operation.Pull, () => this.repository.pull(false, remote, branch));
}
async pullFrom(rebase?: boolean, remote?: string, branch?: string): Promise<void> {
await this.run(Operation.Pull, () => this.repository.pull(rebase, remote, branch));
}
@throttle
async push(head: Branch): Promise<void> {
let remote: string | undefined;
let branch: string | undefined;
if (head && head.name && head.upstream) {
remote = head.upstream.remote;
branch = `${head.name}:${head.upstream.name}`;
}
await this.run(Operation.Push, () => this.repository.push(remote, branch));
}
async pushTo(remote?: string, name?: string, setUpstream: boolean = false): Promise<void> {
await this.run(Operation.Push, () => this.repository.push(remote, name, setUpstream));
}
@@ -754,47 +778,53 @@ export class Repository implements Disposable {
await this.run(Operation.Push, () => this.repository.push(remote, undefined, false, true));
}
private async _sync(rebase: boolean): Promise<void> {
@throttle
sync(head: Branch): Promise<void> {
return this._sync(head, false);
}
@throttle
async syncRebase(head: Branch): Promise<void> {
return this._sync(head, true);
}
private async _sync(head: Branch, rebase: boolean): Promise<void> {
let remote: string | undefined;
let pullBranch: string | undefined;
let pushBranch: string | undefined;
if (head.name && head.upstream) {
remote = head.upstream.remote;
pullBranch = `${head.upstream.name}`;
pushBranch = `${head.name}:${head.upstream.name}`;
}
await this.run(Operation.Sync, async () => {
await this.repository.pull(rebase);
await this.repository.pull(rebase, remote, pullBranch);
const shouldPush = this.HEAD && typeof this.HEAD.ahead === 'number' ? this.HEAD.ahead > 0 : true;
if (shouldPush) {
await this.repository.push();
await this.repository.push(remote, pushBranch);
}
});
}
@throttle
sync(): Promise<void> {
return this._sync(false);
}
@throttle
async syncRebase(): Promise<void> {
return this._sync(true);
}
async show(ref: string, filePath: string): Promise<string> {
return await this.run(Operation.Show, async () => {
return this.run(Operation.Show, () => {
const relativePath = path.relative(this.repository.root, filePath).replace(/\\/g, '/');
const configFiles = workspace.getConfiguration('files', Uri.file(filePath));
const encoding = configFiles.get<string>('encoding');
const defaultEncoding = configFiles.get<string>('encoding');
const autoGuessEncoding = configFiles.get<boolean>('autoGuessEncoding');
// TODO@joao: Resource config api
return await this.repository.bufferString(`${ref}:${relativePath}`, encoding);
return this.repository.bufferString(`${ref}:${relativePath}`, defaultEncoding, autoGuessEncoding);
});
}
async buffer(ref: string, filePath: string): Promise<Buffer> {
return await this.run(Operation.Show, async () => {
return this.run(Operation.Show, () => {
const relativePath = path.relative(this.repository.root, filePath).replace(/\\/g, '/');
// const configFiles = workspace.getConfiguration('files', Uri.file(filePath));
// const encoding = configFiles.get<string>('encoding');
// TODO@joao: REsource config api
return await this.repository.buffer(`${ref}:${relativePath}`);
return this.repository.buffer(`${ref}:${relativePath}`);
});
}

View File

@@ -0,0 +1,11 @@
declare module 'jschardet' {
export interface IDetectedMap {
encoding: string,
confidence: number
}
export function detect(buffer: NodeBuffer): IDetectedMap;
export const Constants: {
MINIMUM_THRESHOLD: number,
}
}

View File

@@ -303,6 +303,10 @@ export function detectUnicodeEncoding(buffer: Buffer): Encoding | null {
return null;
}
function isWindowsPath(path: string): boolean {
return /^[a-zA-Z]:\\/.test(path);
}
export function isDescendant(parent: string, descendant: string): boolean {
if (parent === descendant) {
return true;
@@ -312,5 +316,11 @@ export function isDescendant(parent: string, descendant: string): boolean {
parent += sep;
}
// Windows is case insensitive
if (isWindowsPath(parent)) {
parent = parent.toLowerCase();
descendant = descendant.toLowerCase();
}
return descendant.startsWith(parent);
}

View File

@@ -145,6 +145,10 @@ isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
jschardet@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.6.0.tgz#c7d1a71edcff2839db2f9ec30fc5d5ebd3c1a678"
json3@3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
@@ -253,9 +257,9 @@ supports-color@3.1.2:
dependencies:
has-flag "^1.0.0"
vscode-extension-telemetry@0.0.15:
version "0.0.15"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz#685c32f3b67e8fb85ba689c1d7f88ff90ff87856"
vscode-extension-telemetry@0.0.17:
version "0.0.17"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.17.tgz#15123e7edb34e7b9724b6056f54a869bbb922cb7"
dependencies:
applicationinsights "1.0.1"

View File

@@ -0,0 +1,7 @@
test/**
client/tsconfig.json
client/src/**
server/bin
server/tsconfig.json
server/src/**
server/node_modules/@types/**

View File

@@ -8,11 +8,11 @@ import * as path from 'path';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { workspace, languages, ExtensionContext, extensions, Uri, LanguageConfiguration, TextDocument, FoldingRangeList, FoldingRange, Disposable } from 'vscode';
import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification } from 'vscode-languageclient';
import { workspace, languages, ExtensionContext, extensions, Uri, LanguageConfiguration, TextDocument, FoldingRangeKind, FoldingRange, Disposable, FoldingContext } from 'vscode';
import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification, CancellationToken } from 'vscode-languageclient';
import TelemetryReporter from 'vscode-extension-telemetry';
import { FoldingRangesRequest } from './protocol/foldingProvider.proposed';
import { FoldingRangeRequest, FoldingRangeRequestParam, FoldingRangeClientCapabilities, FoldingRangeKind as LSFoldingRangeKind } from 'vscode-languageserver-protocol-foldingprovider';
import { hash } from './utils/hash';
@@ -57,9 +57,6 @@ interface JSONSchemaSettings {
let telemetryReporter: TelemetryReporter | undefined;
let foldingProviderRegistration: Disposable | undefined = void 0;
const foldingSetting = 'json.experimental.syntaxFolding';
export function activate(context: ExtensionContext) {
let toDispose = context.subscriptions;
@@ -70,7 +67,7 @@ export function activate(context: ExtensionContext) {
// The server is implemented in node
let serverModule = context.asAbsolutePath(path.join('server', 'out', 'jsonServerMain.js'));
// The debug options for the server
let debugOptions = { execArgv: ['--nolazy', '--inspect=6046'] };
let debugOptions = { execArgv: ['--nolazy', '--inspect=' + (9000 + Math.round(Math.random() * 10000))] };
// If the extension is launch in debug mode the debug server options are use
// Otherwise the run options are used
@@ -100,6 +97,21 @@ export function activate(context: ExtensionContext) {
// Create the language client and start the client.
let client = new LanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), serverOptions, clientOptions);
client.registerProposedFeatures();
client.registerFeature({
fillClientCapabilities(capabilities: FoldingRangeClientCapabilities): void {
let textDocumentCap = capabilities.textDocument;
if (!textDocumentCap) {
textDocumentCap = capabilities.textDocument = {};
}
textDocumentCap.foldingRange = {
dynamicRegistration: false,
rangeLimit: 5000,
lineFoldingOnly: true
};
},
initialize(capabilities, documentSelector): void {
}
});
let disposable = client.start();
toDispose.push(disposable);
@@ -130,13 +142,7 @@ export function activate(context: ExtensionContext) {
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context));
initFoldingProvider();
toDispose.push(workspace.onDidChangeConfiguration(c => {
if (c.affectsConfiguration(foldingSetting)) {
initFoldingProvider();
}
}));
toDispose.push({ dispose: () => foldingProviderRegistration && foldingProviderRegistration.dispose() });
toDispose.push(initFoldingProvider());
});
let languageConfiguration: LanguageConfiguration = {
@@ -149,27 +155,36 @@ export function activate(context: ExtensionContext) {
languages.setLanguageConfiguration('json', languageConfiguration);
languages.setLanguageConfiguration('jsonc', languageConfiguration);
function initFoldingProvider() {
let enable = workspace.getConfiguration().get(foldingSetting);
if (enable) {
if (!foldingProviderRegistration) {
foldingProviderRegistration = languages.registerFoldingProvider(documentSelector, {
provideFoldingRanges(document: TextDocument) {
return client.sendRequest(FoldingRangesRequest.type, { textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document) }).then(res => {
if (res && Array.isArray(res.ranges)) {
return new FoldingRangeList(res.ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.type)));
}
return null;
});
function initFoldingProvider(): Disposable {
function getKind(kind: string | undefined): FoldingRangeKind | undefined {
if (kind) {
switch (kind) {
case LSFoldingRangeKind.Comment:
return FoldingRangeKind.Comment;
case LSFoldingRangeKind.Imports:
return FoldingRangeKind.Imports;
case LSFoldingRangeKind.Region:
return FoldingRangeKind.Region;
}
}
return void 0;
}
return languages.registerFoldingRangeProvider(documentSelector, {
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) {
const param: FoldingRangeRequestParam = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document)
};
return client.sendRequest(FoldingRangeRequest.type, param, token).then(ranges => {
if (Array.isArray(ranges)) {
return ranges.map(r => new FoldingRange(r.startLine, r.endLine, getKind(r.kind)));
}
return null;
}, error => {
client.logFailedRequest(FoldingRangeRequest.type, error);
return null;
});
}
} else {
if (foldingProviderRegistration) {
foldingProviderRegistration.dispose();
foldingProviderRegistration = void 0;
}
}
});
}
}

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