Skip to content
This repository has been archived by the owner on Jun 1, 2020. It is now read-only.

Add GitHub auto-updater #33

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
"glob": "^7",
"is-there": "^4.4.3",
"lodash": "^4.17.4",
"minimatch": "^3.0.4",
"nodegit": "^0.20",
"request": "^2.85.0",
"request-promise": "^4.2.2",
"semver-stable": "^2.0.4"
},
"engines": {
Expand Down
189 changes: 189 additions & 0 deletions updaters/github.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
var async = require('async');
var _ = require('lodash');
var path = require('path');
var cdnjs = require('./cdnjs');
var fs = require('fs-extra');
var stable = require('semver-stable');
var compareVersions = require('compare-versions');
var colors = require('colors');
var rp = require('request-promise');
var minimatch = require('minimatch');

var update = function (library, callback) {
var userAgent = 'CDNJS GitHub auto-updater';

async.series([
function (next) {
rp({
uri: 'https://api.github.com/repos/'
+ githubRepo(library.autoupdate.target) + '/tags',
headers: {
'User-Agent': userAgent
}
})
.then(function (string) {
var response = JSON.parse(string);
var versions = _.map(response, function (tag) {
return { version: tag.name, tree: tag.commit.sha };
});

var needed = _.filter(versions, function (version) {
var tagName = versions[0].version;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

version.version[0] should be the one to retrieve a tag name :)

if ((tagName === 'v' || tagName === 'V' || tagName === 'r') &&
version.length > 1 && !isNaN(version[1])) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we want to check version length and numberic version, so it would be version.version.length > 1 && !isNaN(version.version[1])according to your version object.

version.version = version.version.substr(1);
}

return (!cdnjs.checkVersion(library, version.version) && /\d+/.test(version.version));
});

if (needed.length > 0) {
console.log(library.name, 'needs versions:', needed.join(', ').blue);
}

async.eachSeries(needed, function (tag, callback) {
var fullData = tag;
tag = tag.version;
if ((tag[0] === 'v' || tag[0] === 'V' || tag[0] === 'r') &&
tag.length > 1 && !isNaN(tag[1])) {
tag = tag.substr(1);
}

var basePath = library.autoupdate.basePath || '';
var allFiles = [];

rp({
uri: 'https://api.github.com/repos/'
+ githubRepo(library.autoupdate.target) + '/git/trees/'
+ fullData.tree + '?recursive=1',
headers: {
'User-Agent': userAgent
}
})
.then(function (jsonString) {
var filesJson = JSON.parse(jsonString);
_.each(library.autoupdate.fileMap, function (mapGroup) {
var cBasePath = mapGroup.basePath || '';
var files = [];
_.each(mapGroup.files, function (cRule) {
var newFiles = [];
for (var file of filesJson.tree) {
if (file.path.indexOf(cBasePath) === 0) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add && file.type !== "tree" here in order to prevent directory match like what option nodir: true can do in glob library.

if (minimatch(file.path, cRule, {
nodir: true,
realpath: true
})) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove nodir and realpath option, they are only for glob lib and there has no effect in minimatch lib.
Then the code block here can be simpler:

if (minimatch(file.path, cRule)) {
  newFiles.push({ path: file.path, tree: fullData.tree });
}

newFiles.push({ path: file.path, tree: fullData.tree });
}
}
}

files = files.concat(newFiles);
if (newFiles.length === 0) {
console.log('Not found'.red, cRule.cyan, tag);
fs.mkdirsSync(path.normalize(
path.join(__dirname, '../../cdnjs', 'ajax', 'libs', library.name, tag)));
}
});

allFiles = allFiles.concat(files.map(function (c) {
return {
_: c.path,
basePath: cBasePath,
tree: c.tree
};
}));
});

console.log('All files for ' + library.name + ' v' + tag, '-', allFiles.length);
library.version = library.version || '0.0.0';
var greaterVer;
try {
greaterVer = compareVersions(tag, library.version) > 0;
} catch (e) {
greaterVer = false;
}

if ((allFiles.length !== 0) &&
((!library.version) ||
((greaterVer) &&
((stable.is(tag)) ||
(!stable.is(tag) && !stable.is(library.version))))))
{
console.log('Updated package.json to version'.green, tag);
var libraryPath = path.normalize(
path.join(__dirname, '../../cdnjs', 'ajax',
'libs', library.name, 'package.json')
);
var libraryJSON = JSON.parse(fs.readFileSync(libraryPath, 'utf8'));
libraryJSON.version = tag;
fs.writeFileSync(libraryPath, JSON.stringify(libraryJSON, undefined, 2) + '\n');
}

async.each(allFiles, function (file, callback) {
var fileName = file._;
var fileTarget = path.normalize(
path.join(__dirname, '../../cdnjs', 'ajax',
'libs', library.name, tag, fileName)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fileName here should be path.relative(file.basePath, fileName);,
I suppose a better way is to replace it with a local and meaningful variable
(instead of using path.relative(file.basePath, fileName); directly)
e.g. Add

var localFileName = path.relative(file.basePath, file._);

under fileName declaration. And use it to replace fileName.

);
fs.ensureFile(fileTarget, function (err) {
if (err) {
console.log('Some strange error occured here'.red);
console.dir(err);
callback();
} else {
rp({
uri: 'https://raw.githubusercontent.com/'
+ githubRepo(library.autoupdate.target) + '/'
+ path.normalize(path.join(file.tree, file.basePath, fileName)),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path.normalize(path.join(file.tree, fileName) is enough, fileName has included basePath.

headers: {
'User-Agent': userAgent
}
})
.then(function (fileData) {
fs.writeFile(fileTarget, fileData, function (err) {
if (err) {
console.dir(err);
console.log('Some strange error occured here'.red);
callback();
} else {
fs.chmodSync(fileTarget, '0644');
callback();
}
});
})
.catch(function (err) {
console.log('error in file retrieval from GitHub');
callback();
});
}
});
},

function () {
callback();
});
});
},

function () {
console.log(library.name.green, 'updated from GitHub'.green);
callback(null, 1);
});
})
.catch(function (err) {
console.log(library.name, 'git tag handle failed');
console.dir(err);
next();
});
}
]);
};

var githubRepo = function (url) {
return url.slice(url.indexOf('/', 10) + 1, url.indexOf('.git'));
};

module.exports = {
update: update
};