Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit83be111

Browse files
authored
Add updateChannel setting (microsoft#2465)
* Read json from harded-coded file location* Expose settings tracker* Get linux download url* Remove unused imports* Correctly get changed setting* Add update timer* Minimum end to end* Refactoring; Commenting; Renaming* Commenting* Add optional param to download fn; Refactoring; Renaming* Commenting; Then parse fn* Mark vars const; Add todos; Refactoring* Commenting; Refactoring* url from any to string; Index into parsed json as separate step* Use temp files to prevent clutter* Correct windows platform name check; Replace quotes* Resolve vsixName for mac + win* Factor version comparisons into ParsedVersion class while correcting version comparison* Use which utility to find code script* Update timer to once per hour* Move downloadFileToDestination to common; Replace downloadCpptoolsJsonAsync* Return changed settings on onDidChangeSettings* Get changed settings without stealing them* Remove tracker from client interface* Add basic isReleaseJson fn; Add telemetry; Add catch functions* Write type predicates for release json* Refactoring; Rewrite version check; Rewrite build selection* Factor target build search into helper fn* Reorder fn defs* Uninstall version before installing if downgrading* Add undefined checks; Update version comparison* Reorder fn* Telemetry rename; Parse versions more safely* Turn ParsedVersion into interface; Rename release to build* Fix fn return types* Commenting* Remove unneeded validity check* Rename telemetry event; Correct fn return type* Update setting description* Remove promise rejection* Remove unwanted changes* Rename var* Remove imports; Move call to updateSettingsAsync to .then in abTesting* Remove import; Remove unneeded uses of await* Remove comment* Reformat else ifs* Remove '| undefined' instances* Use find fn more idiomatically* Add type specification for predicates + rename them* Add url var to shorten call to downloadFileToDestination* Move parsedVersion to separate file* Move parsedVersion into PackageVersion class* Move helper fn's to separate file* Get script name for both insiders and release VSCode (untested)* Move packageVersion + ghAPI from LanguageServe to src* Update imports to reflect mv; Check isValid on PackageVersion* Add todo's* Correctly get download URL; Correctly verify releaseJson by only checking recent 5 builds* Check version numbers against undefined instead of 0* Await install command before removing install file; Change var name* Re-merge package.json* Rename ghAPI.ts to githubAPI.ts* Rename vars; Remove TODO* Modify version comparison (untested)* Remove todo* Create file async* Download and install file async* Rework promises* Make functions async where possible* Commenting* Grandfather in insiders users* Change syntax via await keyword* Re-enable interval timer* Add updateChannel settings get* Immediately check for update on extension activation if on insiders* Surround windows code script path in quotes* Rename versionStr to version* Change telemetry event* Update telemetry/exception handling* Update telemetry strings; Reformat is functions* Another pass at promises + telemetry* Commenting* Remove undefined from fn return* Fix headers not being forwarded to recursive call* Another pass at promises* Correctly return promise in checkAndApplyUpdate* Remove debug vars* Rename fns* Fix version parsing* Tidy version comparison* Remove commented out code* Variable rename; Add newline at EOF* Add newline at EOF* Commenting; Unbind functions and use function syntax for .thens* Error message; add rejection* Correct exceptions being handled one promise too late* PR feedback* Rewrite promise chain to await to allow premature cancellation of promise chain* Mark vars const; Comment; Rename var
1 parent2f931d9 commit83be111

File tree

9 files changed

+422
-47
lines changed

9 files changed

+422
-47
lines changed

‎Extension/package.json‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,16 @@
456456
"default":null,
457457
"description":"The value to use for the system include path. If set, it overrides the system include path acquired via\"compilerPath\" and\"compileCommands\" settings.",
458458
"scope":"resource"
459+
},
460+
"C_Cpp.updateChannel": {
461+
"type":"string",
462+
"enum": [
463+
"Default",
464+
"Insiders"
465+
],
466+
"default":"Default",
467+
"description":"Set to “Insiders” to receive the latest Insiders builds, which include upcoming features and bug fixes.",
468+
"scope":"resource"
459469
}
460470
}
461471
},

‎Extension/src/LanguageServer/client.ts‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export interface Client {
165165
RootUri:vscode.Uri;
166166
Name:string;
167167
TrackedDocuments:Set<vscode.TextDocument>;
168-
onDidChangeSettings():void;
168+
onDidChangeSettings():{[key:string] :string};
169169
onDidChangeVisibleTextEditors(editors:vscode.TextEditor[]):void;
170170
onRegisterCustomConfigurationProvider(provider:CustomConfigurationProvider1):Thenable<void>;
171171
updateCustomConfigurations(requestingProvider?:CustomConfigurationProvider1):Thenable<void>;
@@ -413,8 +413,8 @@ class DefaultClient implements Client {
413413
returnnewLanguageClient(`cpptools:${serverName}`,serverOptions,clientOptions);
414414
}
415415

416-
publiconDidChangeSettings():void{
417-
letchangedSettings:{[key:string] :string}=this.settingsTracker.getChangedSettings();
416+
publiconDidChangeSettings():{[key:string] :string}{
417+
letchangedSettings:{[key:string] :string}=this.settingsTracker.getChangedSettings();
418418

419419
if(Object.keys(changedSettings).length>0){
420420
if(changedSettings["commentContinuationPatterns"]){
@@ -427,6 +427,8 @@ class DefaultClient implements Client {
427427
this.configuration.onDidChangeSettings();
428428
telemetry.logLanguageServerEvent("CppSettingsChange",changedSettings,null);
429429
}
430+
431+
returnchangedSettings;
430432
}
431433

432434
publiconDidChangeVisibleTextEditors(editors:vscode.TextEditor[]):void{
@@ -1266,7 +1268,7 @@ class NullClient implements Client {
12661268
RootUri:vscode.Uri=vscode.Uri.file("/");
12671269
Name:string="(empty)";
12681270
TrackedDocuments=newSet<vscode.TextDocument>();
1269-
onDidChangeSettings():void{}
1271+
onDidChangeSettings():{[key:string] :string}{return{};}
12701272
onDidChangeVisibleTextEditors(editors:vscode.TextEditor[]):void{}
12711273
onRegisterCustomConfigurationProvider(provider:CustomConfigurationProvider1):Thenable<void>{returnPromise.resolve();}
12721274
updateCustomConfigurations(requestingProvider?:CustomConfigurationProvider1):Thenable<void>{returnPromise.resolve();}

‎Extension/src/LanguageServer/extension.ts‎

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ import { CppSettings } from './settings';
1717
import{PersistentWorkspaceState}from'./persistentState';
1818
import{getLanguageConfig}from'./languageConfig';
1919
import{getCustomConfigProviders}from'./customProviders';
20+
import{PlatformInformation}from'../platform';
2021
import{Range}from'vscode-languageclient';
22+
import{execSync}from'child_process';
23+
import*astmpfrom'tmp';
24+
import{getTargetBuildUrl}from'../githubAPI';
2125

2226
letprevCrashFile:string;
2327
letclients:ClientCollection;
@@ -26,9 +30,11 @@ let ui: UI;
2630
letdisposables:vscode.Disposable[]=[];
2731
letlanguageConfigurations:vscode.Disposable[]=[];
2832
letintervalTimer:NodeJS.Timer;
33+
letinsiderUpdateTimer:NodeJS.Timer;
2934
letrealActivationOccurred:boolean=false;
3035
lettempCommands:vscode.Disposable[]=[];
3136
letactivatedPreviously:PersistentWorkspaceState<boolean>;
37+
constinsiderUpdateTimerInterval:number=1000*60*60;
3238

3339
/**
3440
* activate: set up the extension for language services
@@ -126,6 +132,12 @@ function realActivation(): void {
126132

127133
reportMacCrashes();
128134

135+
constsettings:CppSettings=newCppSettings(clients.ActiveClient.RootUri);
136+
if(settings.updateChannel==='Insiders'){
137+
insiderUpdateTimer=setInterval(checkAndApplyUpdate,insiderUpdateTimerInterval,settings.updateChannel);
138+
checkAndApplyUpdate(settings.updateChannel);
139+
}
140+
129141
intervalTimer=setInterval(onInterval,2500);
130142
}
131143

@@ -142,7 +154,19 @@ export function updateLanguageConfigurations(): void {
142154
*********************************************/
143155

144156
functiononDidChangeSettings():void{
157+
constchangedActiveClientSettings:{[key:string] :string}=clients.ActiveClient.onDidChangeSettings();
145158
clients.forEach(client=>client.onDidChangeSettings());
159+
160+
constnewUpdateChannel:string=changedActiveClientSettings['updateChannel'];
161+
if(newUpdateChannel){
162+
if(newUpdateChannel==='Default'){
163+
clearInterval(insiderUpdateTimer);
164+
}elseif(newUpdateChannel==='Insiders'){
165+
insiderUpdateTimer=setInterval(checkAndApplyUpdate,insiderUpdateTimerInterval);
166+
}
167+
168+
checkAndApplyUpdate(newUpdateChannel);
169+
}
146170
}
147171

148172
letsaveMessageShown:boolean=false;
@@ -200,6 +224,78 @@ function onInterval(): void {
200224
clients.ActiveClient.onInterval();
201225
}
202226

227+
/**
228+
* Install a VSIX package. This helper function will exist until VSCode offers a command to do so.
229+
*@param updateChannel The user's updateChannel setting.
230+
*/
231+
asyncfunctioninstallVsix(vsixLocation:string,updateChannel:string):Promise<void>{
232+
// Get the path to the VSCode command -- replace logic later when VSCode allows calling of
233+
// workbench.extensions.action.installVSIX from TypeScript w/o instead popping up a file dialog
234+
returnPlatformInformation.GetPlatformInformation().then((platformInfo)=>{
235+
constvsCodeScriptPath:string=function(platformInfo):string{
236+
if(platformInfo.platform==='win32'){
237+
constvsCodeProcessPath:string=path.dirname(process.execPath);
238+
return'"'+path.join(vsCodeProcessPath,'bin','code.cmd')+'"';
239+
}else{
240+
constvsCodeProcessPath:string=path.basename(process.execPath);
241+
conststdout:Buffer=execSync('which '+vsCodeProcessPath);
242+
returnstdout.toString().trim();
243+
}
244+
}(platformInfo);
245+
if(!vsCodeScriptPath){
246+
returnPromise.reject(newError('Failed to find VS Code script'));
247+
}
248+
249+
// Install the VSIX
250+
constinstallCommand:string=vsCodeScriptPath+' --install-extension '+vsixLocation;
251+
try{
252+
if(updateChannel==='Default'){
253+
// Uninstall the current version, as the version to install is a previous version
254+
constuninstallCommand:string=vsCodeScriptPath+' --uninstall-extension ms-vscode.cpptools';
255+
execSync(uninstallCommand);
256+
}
257+
execSync(installCommand);
258+
clearInterval(insiderUpdateTimer);
259+
returnPromise.resolve();
260+
}catch(error){
261+
returnPromise.reject(newError('Failed to install VSIX'));
262+
}
263+
});
264+
}
265+
266+
/**
267+
* Query package.json and the GitHub API to determine whether the user should update, if so then install the update.
268+
* The update can be an upgrade or downgrade depending on the the updateChannel setting.
269+
*@param updateChannel The user's updateChannel setting.
270+
*/
271+
asyncfunctioncheckAndApplyUpdate(updateChannel:string):Promise<void>{
272+
constp:Promise<void>=newPromise<void>((resolve,reject)=>{
273+
getTargetBuildUrl(updateChannel).then(downloadUrl=>{
274+
if(!downloadUrl){
275+
resolve();
276+
return;
277+
}
278+
279+
// Create a temporary file, download the vsix to it, then install the vsix
280+
tmp.file({postfix:'.vsix'},(err,vsixPath,fd,cleanupCallback)=>{
281+
if(err){
282+
reject(newError('Failed to create vsix file'));
283+
return;
284+
}
285+
286+
util.downloadFileToDestination(downloadUrl,vsixPath)
287+
.then(()=>installVsix(vsixPath,updateChannel))
288+
.then(()=>telemetry.logLanguageServerEvent('installVsix',{'success':'true'}))
289+
.then(()=>resolve(),()=>reject());
290+
});
291+
},error=>reject(error));
292+
});
293+
returnp.catch((error:Error)=>{
294+
telemetry.logLanguageServerEvent('installVsix',{'error':error.message,'success':'false'});
295+
returnPromise.reject(error);
296+
});
297+
}
298+
203299
/*********************************************
204300
* registered commands
205301
*********************************************/
@@ -516,6 +612,7 @@ export function deactivate(): Thenable<void> {
516612
console.log("deactivating extension");
517613
telemetry.logLanguageServerEvent("LanguageServerShutdown");
518614
clearInterval(intervalTimer);
615+
clearInterval(insiderUpdateTimer);
519616
disposables.forEach(d=>d.dispose());
520617
languageConfigurations.forEach(d=>d.dispose());
521618
ui.dispose();

‎Extension/src/LanguageServer/settings.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export class CppSettings extends Settings {
5353
publicgetcommentContinuationPatterns():(string|CommentPattern)[]{returnsuper.Section.get<(string|CommentPattern)[]>("commentContinuationPatterns");}
5454
publicgetconfigurationWarnings():string{returnsuper.Section.get<string>("configurationWarnings");}
5555
publicgetpreferredPathSeparator():string{returnsuper.Section.get<string>("preferredPathSeparator");}
56+
publicgetupdateChannel():string{returnsuper.Section.get<string>("updateChannel");}
5657
publicgetdefaultIncludePath():string[]{returnsuper.Section.get<string[]>("default.includePath");}
5758
publicgetdefaultDefines():string[]{returnsuper.Section.get<string[]>("default.defines");}
5859
publicgetdefaultMacFrameworkPath():string[]{returnsuper.Section.get<string[]>("default.macFrameworkPath");}

‎Extension/src/abTesting.ts‎

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@
44
* ------------------------------------------------------------------------------------------ */
55
'use strict';
66

7-
import*asurlfrom'url';
8-
import*ashttpsfrom'https';
9-
import{ClientRequest}from'http';
10-
import*asvscodefrom'vscode';
11-
import*asfsfrom'fs';
12-
137
import*asutilfrom'./common';
148
import*asTelemetryfrom'./telemetry';
159
import{PersistentState}from'./LanguageServer/persistentState';
@@ -61,7 +55,7 @@ export class ABTestSettings {
6155

6256
privateasyncupdateSettingsAsync():Promise<void>{
6357
constcpptoolsJsonFile:string=util.getExtensionFilePath(localConfigFile);
64-
58+
6559
try{
6660
constexists:boolean=awaitutil.checkFileExists(cpptoolsJsonFile);
6761
if(exists){
@@ -83,50 +77,17 @@ export class ABTestSettings {
8377
}
8478
}
8579

86-
// NOTE: Code is copied from DownloadPackage in packageManager.ts, but with ~75% fewer lines.
87-
privatedownloadCpptoolsJsonAsync(urlString):Promise<void>{
88-
returnnewPromise<void>((resolve,reject)=>{
89-
letparsedUrl:url.Url=url.parse(urlString);
90-
letrequest:ClientRequest=https.request({
91-
host:parsedUrl.host,
92-
path:parsedUrl.path,
93-
agent:util.getHttpsProxyAgent(),
94-
rejectUnauthorized:vscode.workspace.getConfiguration().get("http.proxyStrictSSL",true)
95-
},(response)=>{
96-
if(response.statusCode===301||response.statusCode===302){
97-
letredirectUrl:string|string[];
98-
if(typeofresponse.headers.location==="string"){
99-
redirectUrl=response.headers.location;
100-
}else{
101-
redirectUrl=response.headers.location[0];
102-
}
103-
returnresolve(this.downloadCpptoolsJsonAsync(redirectUrl));// Redirect - download from new location
104-
}
105-
if(response.statusCode!==200){
106-
returnreject();
107-
}
108-
letdownloadedBytes=0;// tslint:disable-line
109-
letcppToolsJsonFile:fs.WriteStream=fs.createWriteStream(util.getExtensionFilePath(localConfigFile));
110-
response.on('data',(data)=>{downloadedBytes+=data.length;});
111-
response.on('end',()=>{cppToolsJsonFile.close();});
112-
cppToolsJsonFile.on('close',()=>{resolve();this.updateSettingsAsync();});
113-
response.on('error',(error)=>{reject();});
114-
response.pipe(cppToolsJsonFile,{end:false});
115-
});
116-
request.on('error',(error)=>{reject();});
117-
request.end();
118-
});
119-
}
120-
12180
privatedownloadCpptoolsJsonPkgAsync():Promise<void>{
12281
lethasError:boolean=false;
12382
lettelemetryProperties:{[key:string]:string}={};
124-
returnthis.downloadCpptoolsJsonAsync("https://go.microsoft.com/fwlink/?linkid=852750")
83+
constlocalConfigPath:string=util.getExtensionFilePath(localConfigFile);
84+
returnutil.downloadFileToDestination("https://go.microsoft.com/fwlink/?linkid=852750",localConfigPath)
12585
.catch((error)=>{
12686
// More specific error info is not likely to be helpful, and we get detailed download data from the initial install.
12787
hasError=true;
12888
})
12989
.then(()=>{
90+
this.updateSettingsAsync();
13091
telemetryProperties['success']=(!hasError).toString();
13192
Telemetry.logDebuggerEvent("cpptoolsJsonDownload",telemetryProperties);
13293
});

‎Extension/src/common.ts‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import * as url from 'url';
1414
import{PlatformInformation}from'./platform';
1515
import{getOutputChannelLogger,showOutputChannel}from'./logger';
1616
import*asassertfrom'assert';
17+
import*ashttpsfrom'https';
18+
import{ClientRequest,OutgoingHttpHeaders}from'http';
1719

1820
exportletextensionContext:vscode.ExtensionContext;
1921
exportfunctionsetExtensionContext(context:vscode.ExtensionContext):void{
@@ -577,3 +579,40 @@ export function promptForReloadWindowDueToSettingsChange(): void {
577579
}
578580
});
579581
}
582+
583+
exportfunctiondownloadFileToDestination(urlStr:string,destinationPath:string,headers?:OutgoingHttpHeaders):Promise<void>{
584+
returnnewPromise<void>((resolve,reject)=>{
585+
letparsedUrl:url.Url=url.parse(urlStr);
586+
letrequest:ClientRequest=https.request({
587+
host:parsedUrl.host,
588+
path:parsedUrl.path,
589+
agent:getHttpsProxyAgent(),
590+
rejectUnauthorized:vscode.workspace.getConfiguration().get('http.proxyStrictSSL',true),
591+
headers:headers
592+
},(response)=>{
593+
if(response.statusCode===301||response.statusCode===302){// If redirected
594+
// Download from new location
595+
letredirectUrl:string;
596+
if(typeofresponse.headers.location==='string'){
597+
redirectUrl=response.headers.location;
598+
}else{
599+
redirectUrl=response.headers.location[0];
600+
}
601+
returnresolve(downloadFileToDestination(redirectUrl,destinationPath,headers));
602+
}
603+
if(response.statusCode!==200){// If request is not successful
604+
returnreject();
605+
}
606+
// Write file using downloaded data
607+
letdownloadedBytes=0;// tslint:disable-line
608+
letcreatedFile:fs.WriteStream=fs.createWriteStream(destinationPath);
609+
response.on('data',(data)=>{downloadedBytes+=data.length;});
610+
response.on('end',()=>{createdFile.close();});
611+
createdFile.on('close',()=>{resolve();});
612+
response.on('error',(error)=>{reject();});
613+
response.pipe(createdFile,{end:false});
614+
});
615+
request.on('error',(error)=>{reject();});
616+
request.end();
617+
});
618+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp