Skip to content

Commit

Permalink
more modularization and testing
Browse files Browse the repository at this point in the history
  • Loading branch information
dylang committed Sep 22, 2013
1 parent cd8a8be commit 3fa5b36
Show file tree
Hide file tree
Showing 12 changed files with 4,878 additions and 127 deletions.
17 changes: 3 additions & 14 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,13 @@ module.exports = function (grunt) {
}
},
watch: {
example: {
files: [
'Gruntfile.js',
'tasks/**/*.js',
'test/**/*.js'
],
tasks: ['notify:custom_options'],
options: {
nospawn: false
}
},
test: {
files: [
'Gruntfile.js',
'tasks/**/*.js',
'test/**/*.js'
'lib/**/*',
'test/**/*'
],
tasks: ['cafemocha'],
tasks: ['test'],
options: {
nospawn: true
}
Expand Down
80 changes: 19 additions & 61 deletions lib/changelog.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,93 +2,49 @@

var npm = require('./datasrc/npm');
var github = require('./datasrc/github');
var semver = require('semver');
var versionFilter = require('./util/versionFilter');
var log = require('./log');
var Q = require('q');

function processNpmAndGithubData(data) {
function processNpmAndGithubData(data, versionRequested) {

var i;
var project;
var upcoming;
var Versions = data.versions;
var releaseRequested = data.releaseRequested;
var versions = data.filteredVersions || data.versions;

if (data) {
project = data.project;
}

log.debug('release requested: ' + releaseRequested);

if (data && data.changes) {
if (data.changes[0].date > Versions[0].date) {
Versions.unshift({ version: 'Upcoming', date: data.changes[0].date, upcoming: true });
if (data.changes[0].date > versions[0].date) {
versions.unshift({ version: 'Upcoming', date: data.changes[0].date, upcoming: true });
}

data.changes.forEach(function(change){
var i;
//log('change', change);
if (change) {
for (i = Versions.length - 1; i > 0; i--) {
if (change.date < Versions[i].date) {
for (i = versions.length - 1; i > 0; i--) {
if (change.date < versions[i].date) {
break;
}
}
Versions[i].changes = Versions[i].changes || [];
Versions[i].changes.push(change);
versions[i].changes = versions[i].changes || [];
versions[i].changes.push(change);
}
});
}

// Removing Upcoming.
if (Versions[0].upcoming) {
upcoming = Versions.shift();
}

if (releaseRequested) {
var tmpVersions = [];

// All == all versions
if (releaseRequested.toString().toLowerCase() === 'all') {
tmpVersions = Versions;
}
// Latest == Latest single version
else if (releaseRequested.toString().toLowerCase() === 'latest') {
tmpVersions.push(Versions[0]);
}
// Upcoming == Show what's in the pipeline for the next release
else if (releaseRequested.toString().toLowerCase() === 'upcoming') {
if (upcoming) {
tmpVersions.push(upcoming);
}

// Integer == that many versions. 1 = one version.
} else if (parseInt(releaseRequested, 10) == releaseRequested) {
for (i = 0; i < Math.min(releaseRequested, Versions.length - 1); i++) {
tmpVersions.push(Versions[i]);
}
var filteredVersions = versionFilter(versions, versionRequested);

// Require valid version
} else if (!semver.valid(releaseRequested)) {
throw new Error('Invalid version syntax. Versions can be latest, an integer, or n.n.n where n are integers.');

// x.x.x then look for that specific version
} else {
Versions.forEach(function(Version) {
if (semver.satisfies(Version.version, releaseRequested)) {
tmpVersions.push(Version);
}
});
}
Versions = tmpVersions;
}

return {
project: project,
versions: Versions
versions: filteredVersions
};
}

function generate(project, releaseRequested) {
function generate(project, versionRequested) {

if (!project) {
return new Error('Need help? --help or more help at https://github.com/dylang/changelog');
Expand All @@ -99,21 +55,23 @@ function generate(project, releaseRequested) {
if (repo && repo[1]) {
repo = repo[1].replace(/\.git$/, '');
log.debug('using github repo ' + repo);
return github.changelog(repo, releaseRequested);
return github.changelog(repo, versionRequested);
}

return new Error('Bad repo url: ' + project);
}

if (project.split('/').length === 2) {
log.debug('using github repo ' + project);
return github.changelog(project, releaseRequested);
return github.changelog(project, versionRequested);
}

log.debug('using npm module ' + project);
return npm.packageHistory(project, releaseRequested)
return npm.packageHistory(project)
.then(github.commitMessages)
.then(processNpmAndGithubData);
.then(function(data) {
return processNpmAndGithubData(data, versionRequested);
});
}

module.exports = {
Expand Down
22 changes: 7 additions & 15 deletions lib/datasrc/github.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use strict";

var URL = require('url');
var Request = require('request');
var request = require('request');
var log = require('../log');
var Q = require('q');
var moment = require('moment');
Expand All @@ -22,23 +22,15 @@ function commitMessages(options) {

var url = 'https://api.github.com/repos/' + project + '/commits?per_page=100';
log.debug('requesting: ' + url);
Request({uri: url}, function (error, response, body) {
request({uri: url, json: true}, function (err, res, data) {
log.debug('complete: ' + url);

if (error) {
return deferred.reject(error);
}

var data;

try {
data = JSON.parse(body);
} catch (e) {
return deferred.reject('Invalid response from Github: ' + body);
if (err) {
return deferred.reject(err);
}

if (!data.map) {
return deferred.reject('Unknown Github Repo: ' + options.repo + '. ' + (data.message || body));
return deferred.reject('Unknown Github Repo: ' + options.repo + '. ' + (data.message || JSON.stringify(data)));
}

var changes = data.map(function(change){
Expand All @@ -56,8 +48,7 @@ function commitMessages(options) {
repository: 'https://github.com/' + project
},
changes: changes,
versions: options.versions,
releaseRequested: options.releaseRequested
versions: options.versions
});
});
return deferred.promise;
Expand Down Expand Up @@ -86,6 +77,7 @@ function changelog(repo, releaseRequested) {
versionsArray.push(versionsCache[simpleDate]);
});

// THIS SHOULD GO AWAY
if (releaseRequested) {
var tmpVersions = [];
var i;
Expand Down
48 changes: 25 additions & 23 deletions lib/datasrc/npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ var request = require('request');
var semver = require('semver');
var log = require('../log');
var Q = require('q');
var versionFilter = require('../util/versionFilter');


function sortVersions (a, b) {
if (semver.gt(a, b)) { return -1; }
Expand All @@ -28,51 +30,39 @@ var repo = '';
return repo;
}

function packageHistory(moduleName, releaseRequested) {
function packageHistory(moduleName) {
var deferred = Q.defer();
var v = [];
var url = 'http://registry.npmjs.org/' + moduleName;
log.debug('requesting: ' + url);

request({ uri: url }, function (err, res, raw) {
request({ uri: url, json: true }, function (err, res, data) {
log.debug('complete: ' + url);

if (err) {
return deferred.reject(new Error(err));
}

var data = JSON.parse(raw);
if (!data) {
return deferred.reject('No data for ' + url);
}

if (data.error === 'not_found') {
return deferred.reject('Npm module ' + moduleName + ' was not found.');
}

var repo = findRepoUrl(data);

if (!repo && data && data.versions) {
if (!repo && data.versions) {
Object.keys(data.versions).forEach(function(version) {
if (!repo) {
repo = findRepoUrl(data.versions[version]);
}
});
}

if (data && data.time) {
var time = data.time;
delete time.created;
delete time.modified;
var keys = Object.keys(time).sort(sortVersions);
keys.forEach(function(version){
v.push({
version: version,
date: new Date(time[version])
});
});
}

if (!repo) {
var author;
if (data && data.author) {
if (data.author) {
author = data.author.name || 'Creator of Module';

if (data.author.email || data.author.url) {
Expand All @@ -83,14 +73,26 @@ function packageHistory(moduleName, releaseRequested) {
return deferred.reject((author ? author : 'Owner of module ') + ' did not specify the repository url in the package.json for ' + moduleName + '. You should let the author know.');
}

if ((!err && !repo) || (data && !v.length)) {
return deferred.reject(new Error('Unknown package: ' + moduleName));
if (!data.time) {
return deferred.reject('No published versions for ' + moduleName);
}

var time = data.time;
delete time.created;
delete time.modified;

var versions = Object.keys(time)
.sort(sortVersions)
.map(function(version){
return {
version: version,
date: new Date(time[version])
};
});

deferred.resolve({
repo: repo,
versions: v,
releaseRequested: releaseRequested
versions: versions
});
});

Expand Down
47 changes: 47 additions & 0 deletions lib/util/versionFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict';
var semver = require('semver');

function versionFilter(versions, filter) {

if (!versions || !versions.length) {
throw new Error('No versions found');
}

var filterWord = (filter || '').toString().toLowerCase();

// Upcoming == Show what's in the pipeline for the next release
if (filterWord === 'upcoming') {
return versions.filter(function(version){
return version.upcoming;
});
}

var filterCount = filterWord === 'latest' ? 1
: filterWord === 'all' ? versions.length
: filterWord === '' ? versions.length
: !isNaN(filter) && Math.round(filter) === parseInt(filter, 10) ? parseInt(filter, 10)
: false;

var releasedVersions = versions.filter(function(version){
return !version.upcoming;
});

// Integer == that many versions. 1 = one version.
if (filterCount) {
return releasedVersions.filter(function(version, i) {
return i < filterCount;
});
}

if (semver.validRange(filter)) {
return releasedVersions.filter(function(Version) {
return semver.satisfies(Version.version, filter);
});
}

// Require valid version
throw new Error('Invalid version syntax. Versions can be latest, an integer, or n.n.n where n are integers.');
}

module.exports = versionFilter;

16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,21 @@
"q": "~0.9.7",
"chai": "~1.7.2",
"chalk": "~0.2.1",
"moment": "~2.2.1",
"grunt": "~0.4.1",
"grunt-contrib-jshint": "~0.6.4",
"grunt-cafe-mocha": "~0.1.8",
"grunt-notify": "~0.2.13",
"grunt-contrib-watch": "~0.5.3"
"moment": "~2.2.1"
},
"engines": {
"node": "*"
},
"devDependencies": {
"chai": "~1.7.2",
"mocha": "~1.13.0"
"mocha": "~1.13.0",
"proxyquire": "~0.5.1",
"grunt": "~0.4.1",
"grunt-contrib-jshint": "~0.6.4",
"grunt-cafe-mocha": "~0.1.8",
"grunt-notify": "~0.2.13",
"grunt-contrib-watch": "~0.5.3"

},
"scripts": {
"test": "grunt test"
Expand Down
Loading

0 comments on commit 3fa5b36

Please sign in to comment.