Skip to content

Commit 975e607

Browse files
Merge pull request #2766 from gregg-miskelly/UpdatePackageDependancies
Fix 'npm run gulp updatePackageDependencies'
2 parents 6657f99 + 630c34c commit 975e607

File tree

5 files changed

+125
-39
lines changed

5 files changed

+125
-39
lines changed

.vscode/launch.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"version": "0.2.0",
3-
"configurations": [
3+
"configurations": [
44
{
55
"name": "Launch Extension",
66
"type": "extensionHost",
@@ -100,6 +100,21 @@
100100
"outFiles": [
101101
"${workspaceRoot}/out/test/**/*.js"
102102
]
103+
},
104+
{
105+
"type": "node",
106+
"request": "launch",
107+
"name": "Launch gulp task",
108+
"preLaunchTask": "build",
109+
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
110+
"args": [
111+
"updatePackageDependencies"
112+
],
113+
"env": {
114+
"NEW_DEPS_URLS": "https://download.visualstudio.microsoft.com/download/pr/9c36608c-cb04-451f-8df7-547eeb9b5d55/8626f25cb9fb40cd6fa2508009fccd1d/coreclr-debug-linux-x64.zip,https://download.visualstudio.microsoft.com/download/pr/9c36608c-cb04-451f-8df7-547eeb9b5d55/b5b307980f5da0bc161018acfad043c9/coreclr-debug-osx-x64.zip,https://download.visualstudio.microsoft.com/download/pr/9c36608c-cb04-451f-8df7-547eeb9b5d55/4b9c72a90d4558d8e72e653c1ea79936/coreclr-debug-win7-x64.zip",
115+
"NEW_DEPS_VERSION": "1.18.0"
116+
},
117+
"cwd": "${workspaceFolder}"
103118
}
104119
]
105120
}

gulpfile.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ require('./tasks/offlinePackagingTasks');
1616
require('./tasks/backcompatTasks');
1717
require('./tasks/coverageTasks');
1818

19-
gulp.task('generateOptionsSchema', () => {
19+
gulp.task('generateOptionsSchema', () : void => {
2020
optionsSchemaGenerator.GenerateOptionsSchema();
2121
});
2222

23-
gulp.task('updatePackageDependencies', () => {
24-
packageDependencyUpdater.updatePackageDependencies();
23+
// Disable warning about wanting an async function
24+
// tslint:disable-next-line
25+
gulp.task('updatePackageDependencies', () : Promise<void> => {
26+
return packageDependencyUpdater.updatePackageDependencies();
2527
});
2628

2729
gulp.task('tslint', () => {

package-lock.json

Lines changed: 1 addition & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/packageManager/isValidDownload.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@ export interface DownloadValidator {
1212
}
1313

1414
export function isValidDownload(buffer: Buffer, integrity: string, eventStream: EventStream): boolean {
15-
let hash = crypto.createHash('sha256');
1615
if (integrity && integrity.length > 0) {
1716
eventStream.post(new DownloadValidation());
18-
hash.update(buffer);
19-
let value = hash.digest('hex');
20-
if (value.toUpperCase() == integrity.toUpperCase()) {
17+
let value = getBufferIntegrityHash(buffer);
18+
if (value == integrity.toUpperCase()) {
2119
eventStream.post(new IntegrityCheckSuccess());
2220
return true;
2321
}
@@ -28,4 +26,11 @@ export function isValidDownload(buffer: Buffer, integrity: string, eventStream:
2826

2927
// no integrity has been specified
3028
return true;
29+
}
30+
31+
export function getBufferIntegrityHash(buffer: Buffer) : string {
32+
let hash = crypto.createHash('sha256');
33+
hash.update(buffer);
34+
let value = hash.digest('hex').toUpperCase();
35+
return value;
3136
}

src/tools/UpdatePackageDependencies.ts

Lines changed: 94 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,47 @@
66
import * as fs from 'fs';
77
import * as os from 'os';
88
import { Package } from '../packageManager/Package';
9-
9+
import { DownloadFile } from '../packageManager/FileDownloader';
10+
import { EventStream } from '../EventStream';
11+
import * as Event from "../omnisharp/loggingEvents";
12+
import NetworkSettings, { NetworkSettingsProvider } from '../NetworkSettings';
13+
import { getBufferIntegrityHash } from '../packageManager/isValidDownload';
1014

1115
interface PackageJSONFile
1216
{
1317
runtimeDependencies : Package[];
1418
}
1519

16-
export function updatePackageDependencies() {
20+
export async function updatePackageDependencies() : Promise<void> {
1721

18-
const urlsIndex = process.argv.indexOf("--urls");
19-
const newPrimaryUrls = urlsIndex >= 0 ? process.argv[urlsIndex+1] : undefined;
20-
21-
const fallbackUrlsIndex = process.argv.indexOf("--fallbackUrls");
22-
const newFallbackUrls = fallbackUrlsIndex >= 0 ? process.argv[fallbackUrlsIndex+1] : undefined;
22+
const newPrimaryUrls = process.env["NEW_DEPS_URLS"];
23+
const newVersion = process.env["NEW_DEPS_VERSION"];
2324

24-
if (newPrimaryUrls === undefined || newPrimaryUrls === "-?" || newPrimaryUrls === "-h") {
25-
console.log("This command will update the URLs for package dependencies in package.json");
25+
if (!newPrimaryUrls || !newVersion) {
26+
console.log();
27+
console.log("'npm run gulp updatePackageDependencies' will update package.json with new URLs of dependencies.");
2628
console.log();
27-
console.log("Syntax: updatePackageDependencies --urls \"<url1>,<url2>,...\" [--fallbackUrls \"<fallback-url-1>,<fallback-url-2>...\"]");
29+
console.log("To use:");
30+
const setEnvVarPrefix = os.platform() === 'win32' ? "set " : "export ";
31+
const setEnvVarQuote = os.platform() === 'win32' ? "" : "\'";
32+
console.log(` ${setEnvVarPrefix}NEW_DEPS_URLS=${setEnvVarQuote}https://example1/foo-osx.zip,https://example1/foo-win.zip,https://example1/foo-linux.zip${setEnvVarQuote}`);
33+
console.log(` ${setEnvVarPrefix}NEW_DEPS_VERSION=${setEnvVarQuote}1.2.3${setEnvVarQuote}`);
34+
console.log(" npm run gulp updatePackageDependencies");
2835
console.log();
2936
return;
3037
}
3138

32-
if (newPrimaryUrls.length === 0) {
33-
throw new Error("Invalid first argument to updatePackageDependencies. URL string argument expected.");
39+
const newPrimaryUrlArray = newPrimaryUrls.split(',');
40+
for (let urlToUpdate of newPrimaryUrlArray) {
41+
if (!urlToUpdate.startsWith("https://")) {
42+
throw new Error("Unexpected 'NEW_DEPS_URLS' value. All URLs should start with 'https://'.");
43+
}
3444
}
3545

46+
if (! /^[0-9]+\.[0-9]+\.[0-9]+$/.test(newVersion)) {
47+
throw new Error("Unexpected 'NEW_DEPS_VERSION' value. Expected format similar to: 1.2.3.");
48+
}
49+
3650
let packageJSON: PackageJSONFile = JSON.parse(fs.readFileSync('package.json').toString());
3751

3852
// map from lowercase filename to Package
@@ -54,23 +68,79 @@ export function updatePackageDependencies() {
5468
if (dependency === undefined) {
5569
throw new Error(`Unable to update item for url '${url}'. No 'runtimeDependency' found with filename '${fileName}'.`);
5670
}
57-
58-
console.log(`Updating ${url}`);
5971
return dependency;
6072
};
6173

62-
newPrimaryUrls.split(',').forEach(urlToUpdate =>{
63-
console.log(`Trying to update ${urlToUpdate}`);
64-
let dependency = findDependencyToUpdate(urlToUpdate);
65-
dependency.url = urlToUpdate;
74+
const dottedVersionRegExp = /[0-9]+\.[0-9]+\.[0-9]+/g;
75+
const dashedVersionRegExp = /[0-9]+-[0-9]+-[0-9]+/g;
76+
77+
const getMatchCount = (regexp: RegExp, searchString: string) : number => {
78+
regexp.lastIndex = 0;
79+
let retVal = 0;
80+
while (regexp.test(searchString)) {
81+
retVal++;
82+
}
83+
regexp.lastIndex = 0;
84+
return retVal;
85+
};
86+
87+
// First quickly make sure we could match up the URL to an existing item.
88+
for (let urlToUpdate of newPrimaryUrlArray) {
89+
const dependency = findDependencyToUpdate(urlToUpdate);
90+
if (dependency.fallbackUrl) {
91+
const dottedMatches : number = getMatchCount(dottedVersionRegExp, dependency.fallbackUrl);
92+
const dashedMatches : number = getMatchCount(dashedVersionRegExp, dependency.fallbackUrl);
93+
const matchCount : number = dottedMatches + dashedMatches;
94+
95+
if (matchCount == 0) {
96+
throw new Error(`Version number not found in fallback URL '${dependency.fallbackUrl}'.`);
97+
}
98+
if (matchCount > 1) {
99+
throw new Error(`Ambiguous version pattern found in fallback URL '${dependency.fallbackUrl}'. Multiple version strings found.`);
100+
}
101+
}
102+
}
103+
104+
// Next take another pass to try and update to the URL
105+
const eventStream = new EventStream();
106+
eventStream.subscribe((event: Event.BaseEvent) => {
107+
switch (event.constructor.name) {
108+
case Event.DownloadFailure.name:
109+
console.log("Failed to download: " + (<Event.DownloadFailure>event).message);
110+
break;
111+
}
66112
});
113+
const networkSettingsProvider : NetworkSettingsProvider = () => new NetworkSettings(/*proxy:*/ null, /*stringSSL:*/ true);
67114

68-
if (newFallbackUrls !== undefined) {
69-
newFallbackUrls.split(',').forEach(urlToUpdate =>{
70-
console.log(`Trying to update ${urlToUpdate}`);
71-
let dependency = findDependencyToUpdate(urlToUpdate);
72-
dependency.fallbackUrl = urlToUpdate;
73-
});
115+
const downloadAndGetHash = async (url:string) : Promise<string> => {
116+
console.log(`Downlodaing from '${url}'`);
117+
const buffer : Buffer = await DownloadFile(url, eventStream, networkSettingsProvider, url, null);
118+
return getBufferIntegrityHash(buffer);
119+
};
120+
121+
for (let urlToUpdate of newPrimaryUrlArray) {
122+
let dependency = findDependencyToUpdate(urlToUpdate);
123+
dependency.url = urlToUpdate;
124+
dependency.integrity = await downloadAndGetHash(dependency.url);
125+
126+
if (dependency.fallbackUrl) {
127+
128+
// NOTE: We already verified in the first loop that one of these patterns will work, grab the one that does
129+
let regex: RegExp = dottedVersionRegExp;
130+
let newValue: string = newVersion;
131+
if (!dottedVersionRegExp.test(dependency.fallbackUrl)) {
132+
regex = dashedVersionRegExp;
133+
newValue = newVersion.replace(/\./g, "-");
134+
}
135+
dottedVersionRegExp.lastIndex = 0;
136+
137+
dependency.fallbackUrl = dependency.fallbackUrl.replace(regex, newValue);
138+
const fallbackUrlIntegrity = await downloadAndGetHash(dependency.fallbackUrl);
139+
140+
if (dependency.integrity !== fallbackUrlIntegrity) {
141+
throw new Error(`File downloaded from primary URL '${dependency.url}' doesn't match '${dependency.fallbackUrl}'.`);
142+
}
143+
}
74144
}
75145

76146
let content = JSON.stringify(packageJSON, null, 2);

0 commit comments

Comments
 (0)