177 lines
5.8 KiB
JavaScript
177 lines
5.8 KiB
JavaScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
'use strict';
|
|
|
|
var path = require('path');
|
|
var fs = require('fs');
|
|
var plist = require('fast-plist');
|
|
var cson = require('cson-parser');
|
|
var https = require('https');
|
|
var url = require('url');
|
|
|
|
let commitDate = '0000-00-00';
|
|
|
|
/**
|
|
* @param {string} urlString
|
|
*/
|
|
function getOptions(urlString) {
|
|
var _url = url.parse(urlString);
|
|
var headers = {
|
|
'User-Agent': 'VSCode'
|
|
};
|
|
var token = process.env['GITHUB_TOKEN'];
|
|
if (token) {
|
|
headers['Authorization'] = 'token ' + token;
|
|
}
|
|
return {
|
|
protocol: _url.protocol,
|
|
host: _url.host,
|
|
port: _url.port,
|
|
path: _url.path,
|
|
headers: headers
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {string} url
|
|
* @param {number} redirectCount
|
|
*/
|
|
function download(url, redirectCount) {
|
|
return new Promise((c, e) => {
|
|
var content = '';
|
|
https.get(getOptions(url), function (response) {
|
|
response.on('data', function (data) {
|
|
content += data.toString();
|
|
}).on('end', function () {
|
|
if (response.statusCode === 403 && response.headers['x-ratelimit-remaining'] === '0') {
|
|
e('GitHub API rate exceeded. Set GITHUB_TOKEN environment variable to increase rate limit.');
|
|
return;
|
|
}
|
|
let count = redirectCount || 0;
|
|
if (count < 5 && response.statusCode >= 300 && response.statusCode <= 303 || response.statusCode === 307) {
|
|
let location = response.headers['location'];
|
|
if (location) {
|
|
console.log("Redirected " + url + " to " + location);
|
|
download(location, count + 1).then(c, e);
|
|
return;
|
|
}
|
|
}
|
|
c(content);
|
|
});
|
|
}).on('error', function (err) {
|
|
e(err.message);
|
|
});
|
|
});
|
|
}
|
|
|
|
function getCommitSha(repoId, repoPath) {
|
|
var commitInfo = 'https://api.github.com/repos/' + repoId + '/commits?path=' + repoPath;
|
|
return download(commitInfo).then(function (content) {
|
|
try {
|
|
let lastCommit = JSON.parse(content)[0];
|
|
return Promise.resolve({
|
|
commitSha: lastCommit.sha,
|
|
commitDate: lastCommit.commit.author.date
|
|
});
|
|
} catch (e) {
|
|
return Promise.reject(new Error("Failed extracting the SHA: " + content));
|
|
}
|
|
});
|
|
}
|
|
|
|
exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'master', packageJsonPathOverride = '') {
|
|
var contentPath = 'https://raw.githubusercontent.com/' + repoId + `/${version}/` + repoPath;
|
|
console.log('Reading from ' + contentPath);
|
|
return download(contentPath).then(function (content) {
|
|
var ext = path.extname(repoPath);
|
|
var grammar;
|
|
if (ext === '.tmLanguage' || ext === '.plist') {
|
|
grammar = plist.parse(content);
|
|
} else if (ext === '.cson') {
|
|
grammar = cson.parse(content);
|
|
} else if (ext === '.json' || ext === '.JSON-tmLanguage') {
|
|
grammar = JSON.parse(content);
|
|
} else {
|
|
return Promise.reject(new Error('Unknown file extension: ' + ext));
|
|
}
|
|
if (modifyGrammar) {
|
|
modifyGrammar(grammar);
|
|
}
|
|
return getCommitSha(repoId, repoPath).then(function (info) {
|
|
let result = {
|
|
information_for_contributors: [
|
|
'This file has been converted from https://github.com/' + repoId + '/blob/master/' + repoPath,
|
|
'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.'
|
|
]
|
|
};
|
|
|
|
if (info) {
|
|
result.version = 'https://github.com/' + repoId + '/commit/' + info.commitSha;
|
|
}
|
|
|
|
let keys = ['name', 'scopeName', 'comment', 'injections', 'patterns', 'repository'];
|
|
for (let key of keys) {
|
|
if (grammar.hasOwnProperty(key)) {
|
|
result[key] = grammar[key];
|
|
}
|
|
}
|
|
|
|
try {
|
|
fs.writeFileSync(dest, JSON.stringify(result, null, '\t').replace(/\n/g, '\r\n'));
|
|
let cgmanifestRead = JSON.parse(fs.readFileSync('./cgmanifest.json').toString());
|
|
let promises = new Array();
|
|
const currentCommitDate = info.commitDate.substr(0, 10);
|
|
|
|
// Add commit sha to cgmanifest.
|
|
if (currentCommitDate > commitDate) {
|
|
let packageJsonPath = 'https://raw.githubusercontent.com/' + repoId + `/${info.commitSha}/`;
|
|
if (packageJsonPathOverride) {
|
|
packageJsonPath += packageJsonPathOverride;
|
|
}
|
|
packageJsonPath += 'package.json';
|
|
for (let i = 0; i < cgmanifestRead.registrations.length; i++) {
|
|
if (cgmanifestRead.registrations[i].component.git.repositoryUrl.substr(cgmanifestRead.registrations[i].component.git.repositoryUrl.length - repoId.length, repoId.length) === repoId) {
|
|
cgmanifestRead.registrations[i].component.git.commitHash = info.commitSha;
|
|
commitDate = currentCommitDate;
|
|
promises.push(download(packageJsonPath).then(function (packageJson) {
|
|
if (packageJson) {
|
|
try {
|
|
cgmanifestRead.registrations[i].version = JSON.parse(packageJson).version;
|
|
} catch (e) {
|
|
console.log('Cannot get version. File does not exist at ' + packageJsonPath);
|
|
}
|
|
}
|
|
}));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Promise.all(promises).then(function (allResult) {
|
|
fs.writeFileSync('./cgmanifest.json', JSON.stringify(cgmanifestRead, null, '\t').replace(/\n/g, '\r\n'));
|
|
});
|
|
if (info) {
|
|
console.log('Updated ' + path.basename(dest) + ' to ' + repoId + '@' + info.commitSha.substr(0, 7) + ' (' + currentCommitDate + ')');
|
|
} else {
|
|
console.log('Updated ' + path.basename(dest));
|
|
}
|
|
} catch (e) {
|
|
return Promise.reject(e);
|
|
}
|
|
});
|
|
|
|
}, console.error).catch(e => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
});
|
|
};
|
|
|
|
if (path.basename(process.argv[1]) === 'update-grammar.js') {
|
|
for (var i = 3; i < process.argv.length; i += 2) {
|
|
exports.update(process.argv[2], process.argv[i], process.argv[i + 1]);
|
|
}
|
|
}
|