2014-05-15 17:50:08 -04:00
|
|
|
var path = require('path');
|
2014-06-23 20:40:24 -04:00
|
|
|
var fs = require('fs');
|
2014-03-18 18:30:44 -04:00
|
|
|
|
2014-05-15 17:50:08 -04:00
|
|
|
var Q = require('q');
|
2016-04-24 14:46:25 -04:00
|
|
|
var rimraf = require('rimraf');
|
2016-02-24 10:35:06 -05:00
|
|
|
var globby = require('globby');
|
2014-03-18 18:30:44 -04:00
|
|
|
|
2014-05-15 17:50:08 -04:00
|
|
|
var git = require('./git');
|
|
|
|
|
|
|
|
var copy = require('./util').copy;
|
|
|
|
|
|
|
|
function getCacheDir() {
|
2014-06-23 18:28:52 -04:00
|
|
|
return path.relative(process.cwd(), path.resolve(__dirname, '../.cache'));
|
2014-05-15 17:50:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
function getRemoteUrl(dir, remote) {
|
|
|
|
var repo;
|
|
|
|
return git(['config', '--get', 'remote.' + remote + '.url'], dir)
|
|
|
|
.progress(function(chunk) {
|
|
|
|
repo = String(chunk).split(/[\n\r]/).shift();
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
if (repo) {
|
|
|
|
return Q.resolve(repo);
|
|
|
|
} else {
|
|
|
|
return Q.reject(new Error(
|
|
|
|
'Failed to get repo URL from options or current directory.'));
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.fail(function(err) {
|
|
|
|
return Q.reject(new Error(
|
2015-11-09 10:10:54 -05:00
|
|
|
'Failed to get remote.' + remote + '.url (task must either be ' +
|
|
|
|
'run in a git repository with a configured ' + remote + ' remote ' +
|
|
|
|
'or must be configured with the "repo" option).'));
|
2014-05-15 17:50:08 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function getRepo(options) {
|
|
|
|
if (options.repo) {
|
|
|
|
return Q.resolve(options.repo);
|
|
|
|
} else {
|
2015-10-13 21:03:59 -04:00
|
|
|
return getRemoteUrl(process.cwd(), options.remote);
|
2014-05-15 17:50:08 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-30 08:15:13 -04:00
|
|
|
/**
|
|
|
|
* Push a git branch to a remote (pushes gh-pages by default).
|
2015-12-02 10:13:55 -05:00
|
|
|
* @param {string} basePath The base path.
|
|
|
|
* @param {Object} config Publish options.
|
2015-12-07 07:38:16 -05:00
|
|
|
* @param {Function} callback Callback.
|
2014-05-30 08:15:13 -04:00
|
|
|
*/
|
2015-12-07 07:38:16 -05:00
|
|
|
exports.publish = function publish(basePath, config, callback) {
|
2014-06-25 17:27:52 -04:00
|
|
|
if (typeof config === 'function') {
|
2015-12-07 07:38:16 -05:00
|
|
|
callback = config;
|
2014-06-25 17:27:52 -04:00
|
|
|
config = {};
|
|
|
|
}
|
|
|
|
|
2014-05-15 17:50:08 -04:00
|
|
|
var defaults = {
|
|
|
|
add: false,
|
|
|
|
git: 'git',
|
|
|
|
clone: getCacheDir(),
|
|
|
|
dotfiles: false,
|
|
|
|
branch: 'gh-pages',
|
|
|
|
remote: 'origin',
|
|
|
|
src: '**/*',
|
|
|
|
only: '.',
|
|
|
|
push: true,
|
|
|
|
message: 'Updates',
|
|
|
|
silent: false,
|
2014-05-30 08:15:13 -04:00
|
|
|
logger: function() {}
|
2014-05-15 17:50:08 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
// override defaults with any task options
|
2015-12-02 10:51:09 -05:00
|
|
|
// TODO: Require Node >= 4 and use Object.assign
|
|
|
|
var options = {};
|
|
|
|
for (var d in defaults) {
|
|
|
|
options[d] = defaults[d];
|
|
|
|
}
|
|
|
|
for (var c in config) {
|
|
|
|
options[c] = config[c];
|
|
|
|
}
|
2014-05-15 17:50:08 -04:00
|
|
|
|
2015-12-08 11:20:08 -05:00
|
|
|
function log(message) {
|
|
|
|
if (!options.silent) {
|
|
|
|
options.logger(message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!callback) {
|
|
|
|
callback = function(err) {
|
|
|
|
if (err) {
|
|
|
|
log(err.message);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function done(err) {
|
|
|
|
try {
|
|
|
|
callback(err);
|
|
|
|
} catch (err2) {
|
|
|
|
log('Publish callback threw: ', err2.message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-23 20:40:24 -04:00
|
|
|
try {
|
2014-06-25 17:25:47 -04:00
|
|
|
if (!fs.statSync(basePath).isDirectory()) {
|
2014-06-23 20:40:24 -04:00
|
|
|
done(new Error('The "base" option must be an existing directory'));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
done(err);
|
2014-05-30 08:15:13 -04:00
|
|
|
return;
|
2014-05-15 17:50:08 -04:00
|
|
|
}
|
|
|
|
|
2016-02-24 10:35:06 -05:00
|
|
|
var files = globby.sync(options.src, {
|
2014-06-25 17:25:47 -04:00
|
|
|
cwd: basePath,
|
2014-05-15 17:50:08 -04:00
|
|
|
dot: options.dotfiles
|
2014-06-23 20:40:24 -04:00
|
|
|
}).filter(function(file) {
|
2014-06-25 17:25:47 -04:00
|
|
|
return !fs.statSync(path.join(basePath, file)).isDirectory();
|
2014-06-23 20:40:24 -04:00
|
|
|
});
|
2014-05-15 17:50:08 -04:00
|
|
|
|
|
|
|
if (!Array.isArray(files) || files.length === 0) {
|
2014-05-30 08:15:13 -04:00
|
|
|
done(new Error('Files must be provided in the "src" property.'));
|
|
|
|
return;
|
2014-05-15 17:50:08 -04:00
|
|
|
}
|
|
|
|
|
2016-02-24 10:35:06 -05:00
|
|
|
var only = globby.sync(options.only, {cwd: basePath});
|
2014-05-15 17:50:08 -04:00
|
|
|
|
|
|
|
git.exe(options.git);
|
|
|
|
|
|
|
|
var repoUrl;
|
|
|
|
getRepo(options)
|
|
|
|
.then(function(repo) {
|
|
|
|
repoUrl = repo;
|
|
|
|
log('Cloning ' + repo + ' into ' + options.clone);
|
|
|
|
return git.clone(repo, options.clone, options.branch, options);
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
return getRemoteUrl(options.clone, options.remote)
|
|
|
|
.then(function(url) {
|
|
|
|
if (url !== repoUrl) {
|
|
|
|
var message = 'Remote url mismatch. Got "' + url + '" ' +
|
|
|
|
'but expected "' + repoUrl + '" in ' + options.clone +
|
|
|
|
'. If you have changed your "repo" option, try ' +
|
2014-05-30 08:20:07 -04:00
|
|
|
'running the "clean" task first.';
|
2014-05-15 17:50:08 -04:00
|
|
|
return Q.reject(new Error(message));
|
|
|
|
} else {
|
|
|
|
return Q.resolve();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
// only required if someone mucks with the checkout between builds
|
|
|
|
log('Cleaning');
|
|
|
|
return git.clean(options.clone);
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
log('Fetching ' + options.remote);
|
|
|
|
return git.fetch(options.remote, options.clone);
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
log('Checking out ' + options.remote + '/' +
|
|
|
|
options.branch);
|
|
|
|
return git.checkout(options.remote, options.branch,
|
|
|
|
options.clone);
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
if (!options.add) {
|
|
|
|
log('Removing files');
|
|
|
|
return git.rm(only.join(' '), options.clone);
|
|
|
|
} else {
|
|
|
|
return Q.resolve();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
log('Copying files');
|
2014-06-25 17:25:47 -04:00
|
|
|
return copy(files, basePath, options.clone);
|
2014-05-15 17:50:08 -04:00
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
log('Adding all');
|
|
|
|
return git.add('.', options.clone);
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
if (options.user) {
|
|
|
|
return git(['config', 'user.email', options.user.email],
|
|
|
|
options.clone)
|
|
|
|
.then(function() {
|
|
|
|
return git(['config', 'user.name', options.user.name],
|
|
|
|
options.clone);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return Q.resolve();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
log('Committing');
|
|
|
|
return git.commit(options.message, options.clone);
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
if (options.tag) {
|
|
|
|
log('Tagging');
|
|
|
|
var deferred = Q.defer();
|
|
|
|
git.tag(options.tag, options.clone)
|
|
|
|
.then(function() {
|
2015-12-02 10:13:55 -05:00
|
|
|
return deferred.resolve();
|
|
|
|
})
|
2014-05-15 17:50:08 -04:00
|
|
|
.fail(function(error) {
|
2015-12-02 10:13:55 -05:00
|
|
|
// tagging failed probably because this tag alredy exists
|
|
|
|
log('Tagging failed, continuing');
|
|
|
|
options.logger(error);
|
|
|
|
return deferred.resolve();
|
|
|
|
});
|
2014-05-15 17:50:08 -04:00
|
|
|
return deferred.promise;
|
|
|
|
} else {
|
|
|
|
return Q.resolve();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
if (options.push) {
|
|
|
|
log('Pushing');
|
|
|
|
return git.push(options.remote, options.branch,
|
|
|
|
options.clone);
|
|
|
|
} else {
|
|
|
|
return Q.resolve();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then(function() {
|
|
|
|
done();
|
|
|
|
}, function(error) {
|
|
|
|
if (options.silent) {
|
|
|
|
error = new Error(
|
|
|
|
'Unspecified error (run without silent option for detail)');
|
|
|
|
}
|
|
|
|
done(error);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-05-30 08:15:13 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Clean the cache directory.
|
|
|
|
*/
|
2014-05-15 17:50:08 -04:00
|
|
|
exports.clean = function clean() {
|
2016-04-24 14:46:25 -04:00
|
|
|
rimraf.sync(getCacheDir());
|
2014-05-15 17:50:08 -04:00
|
|
|
};
|