Files
bower/test/packages.js
Sindre Sorhus 4ae1b5e04d Replace colors with chalk
colors.js has serious deficiencies like extending String.prototype which can cause all kinds of problems. Two modules using colors.js can conflict with each others, and it infects imported child modules. It's also better to explicit.

[chalk](https://github.com/sindresorhus/chalk)
2013-08-07 22:06:47 +02:00

205 lines
6.2 KiB
JavaScript

var fs = require('graceful-fs');
var path = require('path');
var Q = require('q');
var semver = require('semver');
var mout = require('mout');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var chalk = require('chalk');
var cmd = require('../lib/util/cmd');
var packages = require('./packages.json');
var nopt = require('nopt');
var options = nopt({
'force': Boolean
}, {
'f': '--force'
});
var env = {
'GIT_AUTHOR_DATE': 'Sun Apr 7 22:13:13 2013 +0000',
'GIT_AUTHOR_NAME': 'André Cruz',
'GIT_AUTHOR_EMAIL': 'amdfcruz@gmail.com',
'GIT_COMMITTER_DATE': 'Sun Apr 7 22:13:13 2013 +0000',
'GIT_COMMITTER_NAME': 'André Cruz',
'GIT_COMMITTER_EMAIL': 'amdfcruz@gmail.com'
};
// Preserve the original environment
mout.object.mixIn(env, process.env);
function ensurePackage(dir) {
var promise;
// If force is specified, delete folder
if (options.force) {
promise = Q.nfcall(rimraf, dir)
.then(function () {
throw new Error();
});
// Otherwise check if .git is already created
} else {
promise = Q.nfcall(fs.stat, path.join(dir, '.git'));
}
// Only create if stat failed
return promise.fail(function () {
// Create dir
return Q.nfcall(mkdirp, dir)
// Init git repo
.then(cmd.bind(null, 'git', ['init'], { cwd: dir }))
// Create dummy file
.then(function () {
return Q.nfcall(fs.writeFile, path.join(dir, '.master'), 'based on master');
})
// Stage files
.then(cmd.bind(null, 'git', ['add', '-A'], { cwd: dir }))
// Commit
// Note that we force a specific date and author so that the same
// commit-sha's are always equal
// These commit-sha's are used internally in tests!
.then(function () {
return cmd('git', ['commit', '-m"Initial commit."'], {
cwd: dir,
env: env
});
})
.then(function () {
return dir;
});
});
}
function checkRelease(dir, release) {
if (semver.valid(release)) {
return cmd('git', ['tag', '-l'], { cwd: dir })
.spread(function (stdout) {
return stdout.split(/\s*\r*\n\s*/).some(function (tag) {
return semver.clean(tag) === release;
});
});
}
return cmd('git', ['branch', '--list'], { cwd: dir })
.spread(function (stdout) {
return stdout.split(/\s*\r*\n\s*/).some(function (branch) {
branch = branch.trim().replace(/^\*?\s*/, '');
return branch === release;
});
});
}
function createRelease(dir, release, files) {
var branch = semver.valid(release) ? 'branch-' + release : release;
// Checkout master
return cmd('git', ['checkout', 'master', '-f'], { cwd: dir })
// Attempt to delete branch, ignoring the error
.then(function () {
return cmd('git', ['branch', '-D', branch], { cwd: dir })
.fail(function () {});
})
// Checkout based on master
.then(cmd.bind(null, 'git', ['checkout', '-b', branch, 'master'], { cwd: dir }))
// Create files
.then(function () {
var promise;
var promises = [];
mout.object.forOwn(files, function (contents, name) {
name = path.join(dir, name);
// Convert contents to JSON if they are not a string
if (typeof contents !== 'string') {
contents = JSON.stringify(contents, null, ' ');
}
promise = Q.nfcall(mkdirp, path.dirname(name))
.then(function () {
return Q.nfcall(fs.writeFile, name, contents);
});
promises.push(promise);
});
// Delete dummy .master file that is present on the master branch
promise = Q.nfcall(fs.unlink, path.join(dir, '.master'));
promises.push(promise);
return Q.all(promises);
})
// Stage files
.then(cmd.bind(null, 'git', ['add', '-A'], { cwd: dir }))
// Commit
// Note that we force a specific date and author so that the same
// commit-sha's are always equal
// These commit-sha's are used internally in tests!
.then(function () {
return cmd('git', ['commit', '-m"Commit for ' + branch + '."'], {
cwd: dir,
env: env
});
})
// Tag
.then(function () {
if (!semver.valid(release)) {
return;
}
return cmd('git', ['tag', '-f', release], { cwd: dir })
// Delete branch (not necessary anymore)
.then(cmd.bind(null, 'git', ['checkout', 'master', '-f'], { cwd: dir }))
.then(cmd.bind(null, 'git', ['branch', '-D', branch], { cwd: dir }));
});
}
var promises = [];
// Process packages.json
mout.object.forOwn(packages, function (pkg, name) {
var promise;
var dir = path.join(__dirname, 'assets', name);
// Ensure package is created
promise = ensurePackage(dir);
promise = promise.fail(function (err) {
console.log('Failed to create ' + name);
console.log(err.message);
});
mout.object.forOwn(pkg, function (files, release) {
// Check if the release already exists
promise = promise.then(checkRelease.bind(null, dir, release))
.then(function (exists) {
// Skip it if already created
if (exists) {
return console.log(chalk.cyan('> ') + 'Package ' + name + '#' + release + ' already created');
}
// Create it based on the metadata
return createRelease(dir, release, files)
.then(function () {
console.log(chalk.green('> ') + 'Package ' + name + '#' + release + ' successfully created');
});
})
.fail(function (err) {
console.log(chalk.red('> ') + 'Failed to create ' + name + '#' + release);
console.log(err.message.trim());
if (err.details) {
console.log(err.details.trim());
}
console.log(err.stack);
});
});
promises.push(promise);
});
Q.allSettled(promises, function (results) {
results.forEach(function (result) {
if (result.state !== 'fulfilled') {
process.exit(1);
}
});
});