2014-05-16 07:50:08 +10:00
var path = require ( 'path' ) ;
2014-06-24 10:40:24 +10:00
var fs = require ( 'fs' ) ;
2014-03-18 16:30:44 -06:00
2014-05-16 07:50:08 +10:00
var Q = require ( 'q' ) ;
2016-04-24 12:46:25 -06:00
var rimraf = require ( 'rimraf' ) ;
2016-02-24 08:35:06 -07:00
var globby = require ( 'globby' ) ;
2014-03-18 16:30:44 -06:00
2014-05-16 07:50:08 +10:00
var git = require ( './git' ) ;
var copy = require ( './util' ) . copy ;
function getCacheDir ( ) {
2014-06-24 08:28:52 +10:00
return path . relative ( process . cwd ( ) , path . resolve ( _ _dirname , '../.cache' ) ) ;
2014-05-16 07:50:08 +10: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 15:10:54 +00: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-16 07:50:08 +10:00
} ) ;
}
function getRepo ( options ) {
if ( options . repo ) {
return Q . resolve ( options . repo ) ;
} else {
2015-10-14 03:03:59 +02:00
return getRemoteUrl ( process . cwd ( ) , options . remote ) ;
2014-05-16 07:50:08 +10:00
}
}
2014-05-30 06:15:13 -06:00
/ * *
* Push a git branch to a remote ( pushes gh - pages by default ) .
2015-12-02 07:13:55 -08:00
* @ param { string } basePath The base path .
* @ param { Object } config Publish options .
2015-12-07 13:38:16 +01:00
* @ param { Function } callback Callback .
2014-05-30 06:15:13 -06:00
* /
2015-12-07 13:38:16 +01:00
exports . publish = function publish ( basePath , config , callback ) {
2014-06-26 07:27:52 +10:00
if ( typeof config === 'function' ) {
2015-12-07 13:38:16 +01:00
callback = config ;
2014-06-26 07:27:52 +10:00
config = { } ;
}
2014-05-16 07:50:08 +10:00
var defaults = {
2017-04-04 15:53:54 +02:00
dest : '.' ,
2014-05-16 07:50:08 +10:00
add : false ,
git : 'git' ,
clone : getCacheDir ( ) ,
dotfiles : false ,
branch : 'gh-pages' ,
remote : 'origin' ,
src : '**/*' ,
only : '.' ,
push : true ,
message : 'Updates' ,
silent : false ,
2014-05-30 06:15:13 -06:00
logger : function ( ) { }
2014-05-16 07:50:08 +10:00
} ;
// override defaults with any task options
2015-12-02 07:51:09 -08: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-16 07:50:08 +10:00
2015-12-08 09:20:08 -07: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-24 10:40:24 +10:00
try {
2014-06-26 07:25:47 +10:00
if ( ! fs . statSync ( basePath ) . isDirectory ( ) ) {
2014-06-24 10:40:24 +10:00
done ( new Error ( 'The "base" option must be an existing directory' ) ) ;
return ;
}
} catch ( err ) {
done ( err ) ;
2014-05-30 06:15:13 -06:00
return ;
2014-05-16 07:50:08 +10:00
}
2016-02-24 08:35:06 -07:00
var files = globby . sync ( options . src , {
2014-06-26 07:25:47 +10:00
cwd : basePath ,
2014-05-16 07:50:08 +10:00
dot : options . dotfiles
2014-06-24 10:40:24 +10:00
} ) . filter ( function ( file ) {
2014-06-26 07:25:47 +10:00
return ! fs . statSync ( path . join ( basePath , file ) ) . isDirectory ( ) ;
2014-06-24 10:40:24 +10:00
} ) ;
2014-05-16 07:50:08 +10:00
if ( ! Array . isArray ( files ) || files . length === 0 ) {
2014-05-30 06:15:13 -06:00
done ( new Error ( 'Files must be provided in the "src" property.' ) ) ;
return ;
2014-05-16 07:50:08 +10:00
}
2016-02-24 08:35:06 -07:00
var only = globby . sync ( options . only , { cwd : basePath } ) ;
2014-05-16 07:50:08 +10: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 06:20:07 -06:00
'running the "clean" task first.' ;
2014-05-16 07:50:08 +10: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' ) ;
2017-04-04 15:53:54 +02:00
var outputFiles = only . map ( function ( file ) {
return path . join ( options . dest , file ) ;
} ) ;
return git . rm ( outputFiles . join ( ' ' ) , options . clone ) ;
2014-05-16 07:50:08 +10:00
} else {
return Q . resolve ( ) ;
}
} )
. then ( function ( ) {
log ( 'Copying files' ) ;
2017-04-04 15:53:54 +02:00
return copy ( files , basePath , path . join ( options . clone , options . dest ) ) ;
2014-05-16 07:50:08 +10: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 07:13:55 -08:00
return deferred . resolve ( ) ;
} )
2014-05-16 07:50:08 +10:00
. fail ( function ( error ) {
2015-12-02 07:13:55 -08:00
// tagging failed probably because this tag alredy exists
log ( 'Tagging failed, continuing' ) ;
options . logger ( error ) ;
return deferred . resolve ( ) ;
} ) ;
2014-05-16 07:50:08 +10: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 06:15:13 -06:00
/ * *
* Clean the cache directory .
* /
2014-05-16 07:50:08 +10:00
exports . clean = function clean ( ) {
2016-04-24 12:46:25 -06:00
rimraf . sync ( getCacheDir ( ) ) ;
2014-05-16 07:50:08 +10:00
} ;