Spaces:
Sleeping
Sleeping
| const path = require('path'); | |
| const util = require('util'); | |
| const filenamify = require('filenamify'); | |
| const findCacheDir = require('find-cache-dir'); | |
| const fs = require('fs-extra'); | |
| const globby = require('globby'); | |
| const Git = require('./git.js'); | |
| const copy = require('./util.js').copy; | |
| const getUser = require('./util.js').getUser; | |
| const log = util.debuglog('gh-pages'); | |
| /** | |
| * Get the cache directory. | |
| * @param {string} [optPath] Optional path. | |
| * @return {string} The full path to the cache directory. | |
| */ | |
| function getCacheDir(optPath) { | |
| const dir = findCacheDir({name: 'gh-pages'}); | |
| if (!optPath) { | |
| return dir; | |
| } | |
| return path.join(dir, filenamify(optPath)); | |
| } | |
| /** | |
| * Clean the cache directory. | |
| */ | |
| exports.clean = function clean() { | |
| fs.removeSync(getCacheDir()); | |
| }; | |
| exports.defaults = { | |
| dest: '.', | |
| add: false, | |
| git: 'git', | |
| depth: 1, | |
| dotfiles: false, | |
| branch: 'gh-pages', | |
| remote: 'origin', | |
| src: '**/*', | |
| remove: '.', | |
| push: true, | |
| history: true, | |
| message: 'Updates', | |
| silent: false, | |
| }; | |
| exports.getCacheDir = getCacheDir; | |
| function getRepo(options) { | |
| if (options.repo) { | |
| return Promise.resolve(options.repo); | |
| } else { | |
| const git = new Git(process.cwd(), options.git); | |
| return git.getRemoteUrl(options.remote); | |
| } | |
| } | |
| /** | |
| * Push a git branch to a remote (pushes gh-pages by default). | |
| * @param {string} basePath The base path. | |
| * @param {Object} config Publish options. | |
| * @param {Function} callback Callback. | |
| * @return {Promise} A promise. | |
| */ | |
| exports.publish = function publish(basePath, config, callback) { | |
| if (typeof config === 'function') { | |
| callback = config; | |
| config = {}; | |
| } | |
| const options = Object.assign({}, exports.defaults, config); | |
| // For backward compatibility before fixing #334 | |
| if (options.only) { | |
| options.remove = options.only; | |
| } | |
| if (!callback) { | |
| callback = function (err) { | |
| if (err) { | |
| log(err.message); | |
| } | |
| }; | |
| } | |
| function done(err) { | |
| try { | |
| callback(err); | |
| } catch (err2) { | |
| log('Publish callback threw: %s', err2.message); | |
| } | |
| } | |
| try { | |
| if (!fs.statSync(basePath).isDirectory()) { | |
| const err = new Error('The "base" option must be an existing directory'); | |
| done(err); | |
| return Promise.reject(err); | |
| } | |
| } catch (err) { | |
| done(err); | |
| return Promise.reject(err); | |
| } | |
| const files = globby | |
| .sync(options.src, { | |
| cwd: basePath, | |
| dot: options.dotfiles, | |
| }) | |
| .filter((file) => { | |
| return !fs.statSync(path.join(basePath, file)).isDirectory(); | |
| }); | |
| if (!Array.isArray(files) || files.length === 0) { | |
| done( | |
| new Error('The pattern in the "src" property didn\'t match any files.'), | |
| ); | |
| return; | |
| } | |
| let repoUrl; | |
| let userPromise; | |
| if (options.user) { | |
| userPromise = Promise.resolve(options.user); | |
| } else { | |
| userPromise = getUser(); | |
| } | |
| return userPromise.then((user) => | |
| getRepo(options) | |
| .then((repo) => { | |
| repoUrl = repo; | |
| const clone = getCacheDir(repo); | |
| log('Cloning %s into %s', repo, clone); | |
| return Git.clone(repo, clone, options.branch, options); | |
| }) | |
| .then((git) => { | |
| return git.getRemoteUrl(options.remote).then((url) => { | |
| if (url !== repoUrl) { | |
| const message = | |
| 'Remote url mismatch. Got "' + | |
| url + | |
| '" ' + | |
| 'but expected "' + | |
| repoUrl + | |
| '" in ' + | |
| git.cwd + | |
| '. Try running the `gh-pages-clean` script first.'; | |
| throw new Error(message); | |
| } | |
| return git; | |
| }); | |
| }) | |
| .then((git) => { | |
| // only required if someone mucks with the checkout between builds | |
| log('Cleaning'); | |
| return git.clean(); | |
| }) | |
| .then((git) => { | |
| log('Fetching %s', options.remote); | |
| return git.fetch(options.remote); | |
| }) | |
| .then((git) => { | |
| log('Checking out %s/%s ', options.remote, options.branch); | |
| return git.checkout(options.remote, options.branch); | |
| }) | |
| .then((git) => { | |
| if (!options.history) { | |
| return git.deleteRef(options.branch); | |
| } else { | |
| return git; | |
| } | |
| }) | |
| .then((git) => { | |
| if (options.add) { | |
| return git; | |
| } | |
| log('Removing files'); | |
| const files = globby | |
| .sync(options.remove, { | |
| cwd: path.join(git.cwd, options.dest), | |
| }) | |
| .map((file) => path.join(options.dest, file)); | |
| if (files.length > 0) { | |
| return git.rm(files); | |
| } else { | |
| return git; | |
| } | |
| }) | |
| .then((git) => { | |
| if (options.nojekyll) { | |
| log('Creating .nojekyll'); | |
| fs.createFileSync(path.join(git.cwd, '.nojekyll')); | |
| } | |
| if (options.cname) { | |
| log('Creating CNAME for %s', options.cname); | |
| fs.writeFileSync(path.join(git.cwd, 'CNAME'), options.cname); | |
| } | |
| log('Copying files'); | |
| return copy(files, basePath, path.join(git.cwd, options.dest)).then( | |
| function () { | |
| return git; | |
| }, | |
| ); | |
| }) | |
| .then((git) => { | |
| return Promise.resolve( | |
| options.beforeAdd && options.beforeAdd(git), | |
| ).then(() => git); | |
| }) | |
| .then((git) => { | |
| log('Adding all'); | |
| return git.add('.'); | |
| }) | |
| .then((git) => { | |
| if (!user) { | |
| return git; | |
| } | |
| return git.exec('config', 'user.email', user.email).then(() => { | |
| if (!user.name) { | |
| return git; | |
| } | |
| return git.exec('config', 'user.name', user.name); | |
| }); | |
| }) | |
| .then((git) => { | |
| log('Committing'); | |
| return git.commit(options.message); | |
| }) | |
| .then((git) => { | |
| if (options.tag) { | |
| log('Tagging'); | |
| return git.tag(options.tag).catch((error) => { | |
| // tagging failed probably because this tag alredy exists | |
| log(error); | |
| log('Tagging failed, continuing'); | |
| return git; | |
| }); | |
| } else { | |
| return git; | |
| } | |
| }) | |
| .then((git) => { | |
| if (options.push) { | |
| log('Pushing'); | |
| return git.push(options.remote, options.branch, !options.history); | |
| } else { | |
| return git; | |
| } | |
| }) | |
| .then( | |
| () => done(), | |
| (error) => { | |
| if (options.silent) { | |
| error = new Error( | |
| 'Unspecified error (run without silent option for detail)', | |
| ); | |
| } | |
| done(error); | |
| }, | |
| ), | |
| ); | |
| }; | |