2015-02-10 19:41:24 +00:00
define ( function ( require , exports , module ) {
2015-04-27 17:07:49 +00:00
main . consumes = [ "Plugin" , "cli_commands" , "proc" , "api" , "auth" ] ;
2015-02-10 19:41:24 +00:00
main . provides = [ "cli.publish" ] ;
return main ;
function main ( options , imports , register ) {
var Plugin = imports . Plugin ;
var cmd = imports . cli _commands ;
var proc = imports . proc ;
var auth = imports . auth ;
var api = imports . api ;
2015-02-19 16:03:55 +00:00
var TEST _MODE = ! ! process . env . C9 _TEST _MODE ;
2015-04-29 20:41:54 +00:00
var SHELLSCRIPT = TEST _MODE ? "" : require ( "text!./publish.git.sh" ) ;
2015-02-10 19:41:24 +00:00
var TAR = "tar" ;
var APIHOST = options . apiHost ;
var BASICAUTH = process . env . C9 _TEST _AUTH ;
var SCM = {
"git" : {
binary : "git" ,
clone : "clone"
} ,
"mercurial" : {
binary : "hg" ,
clone : "clone"
} ,
"hg" : {
binary : "hg" ,
clone : "clone"
}
} ;
var fs = require ( "fs" ) ;
var join = require ( "path" ) . join ;
var os = require ( "os" ) ;
var FormData = require ( "form-data" ) ;
var http = require ( APIHOST . indexOf ( "localhost" ) > - 1 ? "http" : "https" ) ;
2015-04-04 01:07:31 +00:00
var Path = require ( "path" ) ;
2015-02-10 19:41:24 +00:00
var basename = require ( "path" ) . basename ;
2015-03-29 23:15:52 +00:00
var dirname = require ( "path" ) . dirname ;
2015-04-04 01:07:31 +00:00
var async = require ( "async" ) ;
2015-02-10 19:41:24 +00:00
var verbose = false ;
var force = false ;
2015-04-04 01:07:31 +00:00
var dryRun = false ;
2015-04-24 23:24:10 +00:00
var createTag = false ;
2015-02-10 19:41:24 +00:00
// Set up basic auth for api if needed
if ( BASICAUTH ) api . basicAuth = BASICAUTH ;
/***** Initialization *****/
var plugin = new Plugin ( "Ajax.org" , main . consumes ) ;
// var emit = plugin.getEmitter();
var loaded ;
function load ( ) {
if ( loaded ) return ;
loaded = true ;
cmd . addCommand ( {
name : "publish" ,
info : " Publishes a cloud9 package." ,
usage : "[--verbose] [--force] [<newversion> | major | minor | patch | build]" ,
options : {
"verbose" : {
"description" : "Output more information" ,
"alias" : "v" ,
"default" : false ,
"boolean" : true
} ,
"force" : {
"description" : "Ignore warnings" ,
"alias" : "f" ,
"default" : false ,
"boolean" : true
2015-04-04 01:07:31 +00:00
} ,
"dry-run" : {
"description" : "Only build a test version" ,
"default" : false ,
"boolean" : true
2015-04-24 23:24:10 +00:00
} ,
"tag" : {
"description" : "Create git tag for published version" ,
"alias" : "t" ,
"default" : false ,
"boolean" : true
2015-02-10 19:41:24 +00:00
}
} ,
check : function ( argv ) {
2015-05-02 23:35:04 +00:00
2015-02-10 19:41:24 +00:00
} ,
exec : function ( argv ) {
verbose = argv [ "verbose" ] ;
force = argv [ "force" ] ;
2015-04-04 01:07:31 +00:00
dryRun = argv [ "dry-run" ] ;
2015-04-24 23:24:10 +00:00
createTag = argv [ "tag" ] ;
2015-02-10 19:41:24 +00:00
publish (
argv . _ [ 1 ] ,
function ( err , data ) {
if ( err ) {
if ( err . message || typeof err == "string" )
console . error ( err . message || err ) ;
if ( ! verbose )
console . error ( "\nTry running with --verbose flag for more information" ) ;
process . exit ( 1 ) ;
}
2015-04-21 23:25:29 +00:00
else if ( ! dryRun ) {
2015-02-10 19:41:24 +00:00
console . log ( "Succesfully published version" , data . version ) ;
process . exit ( 0 ) ;
}
} ) ;
}
} ) ;
2015-04-24 23:24:10 +00:00
cmd . addCommand ( {
2015-04-21 23:25:29 +00:00
name : "build" ,
2015-04-27 00:29:26 +00:00
info : " Builds development version of package to load in non-debug mode." ,
2015-04-21 23:25:29 +00:00
usage : "[--devel]" ,
options : {
"devel" : {
"description" : "" ,
"alias" : "d" ,
"default" : false ,
"boolean" : true
}
} ,
exec : function ( argv ) {
if ( argv [ "devel" ] ) {
var code = function ( argument ) {
/* TODO explain */
define ( "plugins/PACKAGE_NAME/__installed__" , [ ] , [
"plugins/PACKAGE_NAME/__debug__"
] ) ;
define ( "plugins/PACKAGE_NAME/__debug__" , [ ] , function ( require , exports , module ) {
main . consumes = [ "plugin.debug" ] ;
main . provides = [ ] ;
return main ;
function main ( options , imports , register ) {
var debug = imports [ "plugin.debug" ] ;
debug . loadPackage ( "PACKAGE_NAME" ) ;
}
} ) ;
} . toString ( ) ;
var cwd = process . cwd ( ) ;
var packageName = basename ( cwd ) ;
var indent = code . match ( /\n\r?(\s*)/ ) [ 1 ] . length ;
code = code
. replace ( /\r/g , "" )
. replace ( new RegExp ( "^ {" + indent + "}" , "gm" ) , "" )
. replace ( /^.*?{|}$/g , "" )
. trim ( )
. replace ( /PACKAGE_NAME/g , packageName ) ;
2015-04-27 17:07:49 +00:00
fs . writeFileSync ( cwd + "/__installed__.js" , code , "utf8" ) ;
}
else {
dryRun = true ;
2015-05-29 15:01:06 +00:00
publish ( { local : true } , function ( err ) {
if ( err ) {
console . error ( err ) ;
if ( ! verbose )
console . error ( "\nTry running with --verbose flag for more information" ) ;
process . exit ( 1 ) ;
}
} ) ;
2015-04-21 23:25:29 +00:00
}
}
} ) ;
2015-02-10 19:41:24 +00:00
cmd . addCommand ( {
name : "unpublish" ,
info : "Disables a cloud9 package." ,
usage : "[--verbose]" ,
options : {
"verbose" : {
"description" : "Output more information" ,
"alias" : "v" ,
"default" : false ,
"boolean" : true
}
} ,
check : function ( argv ) { } ,
exec : function ( argv ) {
verbose = argv [ "verbose" ] ;
unpublish (
function ( err , data ) {
if ( err ) {
console . error ( err . message || err || "Terminated." ) ;
process . exit ( 1 ) ;
}
else {
console . log ( "Succesfully disabled package" ) ;
process . exit ( 0 ) ;
}
} ) ;
}
} ) ;
}
/***** Methods *****/
2015-05-14 13:18:43 +00:00
function spawn ( command , options , callback ) {
if ( options . stdio == null ) {
// if verbose, echo stdout
// always echo stderr
options . stdio = [
"pipe" ,
verbose ? process . stdout : "ignore" ,
process . stderr
] ;
}
proc . spawn ( command , options , function ( err , child ) {
if ( err ) return callback ( err ) ;
child . on ( "exit" , function ( code ) {
if ( code !== 0 ) {
var error = new Error ( "Command failed: " + command ) ;
error . code = code ;
return callback ( error ) ;
}
callback ( ) ;
} ) ;
} ) ;
}
2015-02-10 19:41:24 +00:00
function stringifyError ( err ) {
return ( verbose ? JSON . stringify ( err , 4 , " " ) : ( typeof err == "string" ? err : err . message ) ) ;
}
2015-04-21 23:25:29 +00:00
function publish ( options , callback ) {
if ( typeof options != "object" )
options = { version : options } ;
var version = options . version ;
2015-02-10 19:41:24 +00:00
var cwd = process . cwd ( ) ;
var packagePath = cwd + "/package.json" ;
2015-04-24 23:24:10 +00:00
fs . readFile ( packagePath , "utf8" , function ( err , data ) {
2015-02-10 19:41:24 +00:00
if ( err ) return callback ( new Error ( "ERROR: Could not find package.json in " + cwd ) ) ;
var json ;
try { json = JSON . parse ( data ) ; }
catch ( e ) {
return callback ( new Error ( "ERROR: Could not parse package.json: " , e . message ) ) ;
}
// Basic Validation
2015-04-27 19:07:00 +00:00
if ( json . private )
return callback ( new Error ( "ERROR: Private flag in package.json prevents from publishing" ) ) ;
2015-02-10 19:41:24 +00:00
if ( ! json . name )
return callback ( new Error ( "ERROR: Missing name property in package.json" ) ) ;
if ( basename ( cwd ) != json . name ) {
console . warn ( "WARNING: The name property in package.json is not equal to the directory name, which is " + basename ( cwd ) ) ;
if ( ! force )
return callback ( new Error ( "Use --force to ignore this warning." ) ) ;
}
if ( ! json . repository )
return callback ( new Error ( "ERROR: Missing repository property in package.json" ) ) ;
2015-04-27 19:59:45 +00:00
if ( ! json . repository . url )
return callback ( new Error ( "ERROR: Missing repository.url property in package.json" ) ) ;
2015-02-10 19:41:24 +00:00
if ( ! json . categories || json . categories . length == 0 )
return callback ( new Error ( "ERROR: At least one category is required in package.json" ) ) ;
// Validate README.md
if ( ! fs . existsSync ( join ( cwd , "README.md" ) ) ) {
console . warn ( "WARNING: README.md is missing." ) ;
if ( ! force )
return callback ( new Error ( "Use --force to ignore these warnings." ) ) ;
}
2015-04-27 19:12:12 +00:00
if ( json . description )
2015-04-27 19:43:38 +00:00
console . warn ( "WARNING: Description property in package.json will be ignored. README.md will be used." ) ;
2015-04-27 19:12:12 +00:00
2015-04-28 22:27:11 +00:00
var description = fs . readFileSync ( join ( cwd , "README.md" ) , "utf8" )
2015-04-28 22:16:55 +00:00
. replace ( /^\#.*\n*/ , "" ) ;
2015-04-27 17:07:49 +00:00
2015-02-10 19:41:24 +00:00
// Validate plugins
var plugins = { } ;
2015-03-06 20:11:52 +00:00
fs . readdirSync ( cwd ) . forEach ( function ( filename ) {
2015-04-15 23:30:14 +00:00
if ( /(__\w*__|_test)\.js$/ . test ( filename ) || ! /\.js$/ . test ( filename ) ) return ;
2015-03-06 20:11:52 +00:00
try {
var val = fs . readFileSync ( cwd + "/" + filename ) ;
} catch ( e ) {
if ( e . code == "EISDIR" ) return ;
throw e ;
}
2015-02-10 19:41:24 +00:00
if ( ! /\(options,\s*imports,\s*register\)/ . test ( val ) ) return ;
if ( ! /consumes\s*=/ . test ( val ) ) return ;
if ( ! /provides\s*=/ . test ( val ) ) return ;
plugins [ filename ] = { } ;
} ) ;
var warned , failed ;
Object . keys ( plugins ) . forEach ( function ( name ) {
if ( ! json . plugins [ name . replace ( /\.js$/ , "" ) ] ) {
console . warn ( "WARNING: Plugin '" + name + "' is not listed in package.json." ) ;
warned = true ;
}
2015-04-21 01:48:05 +00:00
else if ( ! fs . existsSync ( join ( cwd , name . replace ( /\.js$/ , "_test.js" ) ) ) ) {
2015-05-29 15:01:06 +00:00
console . warn ( "ERROR: Plugin '" + name + "' has no test associated with it. There must be a file called '" + name . replace ( /\.js$/ , "" ) + "_test.js' containing tests." ) ;
warned = true ;
2015-04-21 01:48:05 +00:00
}
2015-02-10 19:41:24 +00:00
} ) ;
if ( failed )
return callback ( new Error ( ) ) ;
2015-04-21 23:25:29 +00:00
if ( warned && ! force && ! dryRun )
2015-02-10 19:41:24 +00:00
return callback ( new Error ( "Use --force to ignore these warnings." ) ) ;
2015-04-24 23:24:10 +00:00
if ( version ) {
2015-04-21 23:25:29 +00:00
var v = ( json . version || "0.0.1" ) . split ( "." ) ;
// Update the version field in the package.json file
if ( version == "major" ) {
v [ 0 ] ++ ;
v [ 1 ] = 0 ;
v [ 2 ] = 0 ;
}
else if ( version == "minor" ) {
v [ 1 ] ++ ;
v [ 2 ] = 0 ;
}
else if ( version == "patch" || version == "build" ) v [ 2 ] ++ ;
else if ( version . match ( /^\d+\.\d+\.\d+$/ ) )
v = version . split ( "." ) ;
else
return callback ( new Error ( "Invalid version. Semver required: " + version ) ) ;
json . version = v . join ( "." ) ;
2015-02-10 19:41:24 +00:00
}
2015-04-26 18:18:40 +00:00
return build ( ) ;
2015-02-10 19:41:24 +00:00
2015-04-26 18:18:40 +00:00
function updatePackageJSON ( next ) {
if ( ! version )
return next ( ) ;
// Write the package.json file
var indent = data . match ( /{\n\r?^ {4}"/ ) ? 4 : 2 ;
2015-04-28 22:27:11 +00:00
var newData = JSON . stringify ( json , null , indent ) ;
2015-04-29 18:48:58 +00:00
fs . writeFile ( cwd + "/.c9/.build/package.json" , newData , function ( ) {
2015-04-26 18:18:40 +00:00
if ( dryRun )
return next ( ) ; // if dry-run is passed only update path in .build
fs . writeFile ( packagePath , newData , function ( err ) {
if ( err ) return callback ( err ) ;
return next ( ) ;
} ) ;
} ) ;
}
2015-04-24 22:15:25 +00:00
2015-02-10 19:41:24 +00:00
// Build the package
// @TODO add a .c9exclude file that excludes files
var zipFilePath ;
function build ( ) {
2015-03-29 23:15:52 +00:00
var base = dirname ( cwd ) ;
var packageName = json . name ;
var config = Object . keys ( plugins ) . map ( function ( p ) {
2015-04-14 00:44:47 +00:00
return "plugins/" + packageName + "/" + p . replace ( /\.js$/ , "" ) ;
2015-03-29 23:15:52 +00:00
} ) ;
2015-04-14 00:44:47 +00:00
var result , packedFiles = [ ] , staticPlugin ;
2015-04-13 21:08:51 +00:00
async . series ( [
function ( next ) {
fs . readdir ( cwd , function ( err , files ) {
if ( err )
return next ( ) ;
var extraCode = [ ] ;
function forEachFile ( dir , f ) {
try {
fs . readdirSync ( dir ) . forEach ( function ( filename ) {
var data = fs . readFileSync ( dir + "/" + filename , "utf8" ) ;
f ( filename , data ) ;
2015-04-13 19:44:42 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
} catch ( e ) {
console . error ( e ) ;
2015-04-13 19:44:42 +00:00
}
2015-04-13 21:08:51 +00:00
}
if ( files . indexOf ( "builders" ) != - 1 ) {
forEachFile ( cwd + "/builders" , function ( filename , data ) {
2015-04-14 00:44:47 +00:00
packedFiles . push ( cwd + "/builders/" + filename ) ;
2015-04-13 21:08:51 +00:00
extraCode . push ( {
type : "builders" ,
filename : filename ,
data : data
2015-04-13 19:44:42 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
} ) ;
}
if ( files . indexOf ( "keymaps" ) != - 1 ) {
forEachFile ( cwd + "/keymaps" , function ( filename , data ) {
2015-04-14 00:44:47 +00:00
packedFiles . push ( cwd + "/keymaps/" + filename ) ;
2015-04-13 21:08:51 +00:00
extraCode . push ( {
type : "keymaps" ,
filename : filename ,
data : data
2015-04-13 19:44:42 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
} ) ;
}
if ( files . indexOf ( "modes" ) != - 1 ) {
forEachFile ( cwd + "/modes" , function ( filename , data ) {
2015-05-06 15:14:31 +00:00
if ( /(?:_highlight_rules|_test|_worker|_fold|_behaviou?r)\.js$/ . test ( filename ) )
2015-04-13 21:08:51 +00:00
return ;
2015-05-06 15:14:31 +00:00
if ( ! /\.js$/ . test ( filename ) )
return ;
var firstLine = data . split ( "\n" , 1 ) [ 0 ] . replace ( /\/\*|\*\//g , "" ) . trim ( ) ;
if ( ! /caption\s*:[^;]+/i . test ( firstLine ) ) {
packedFiles . push ( cwd + "/modes/" + filename ) ;
console . error ( "Ignoring mode with invalid header: " , firstLine ) ;
console . error ( " at " + cwd + "/modes/" + filename ) ;
return ;
}
2015-04-13 21:08:51 +00:00
extraCode . push ( {
type : "modes" ,
filename : filename ,
data : firstLine
2015-04-13 19:44:42 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
} ) ;
}
if ( files . indexOf ( "outline" ) != - 1 ) {
forEachFile ( cwd + "/outline" , function ( filename , data ) {
2015-04-14 00:44:47 +00:00
packedFiles . push ( cwd + "/outline/" + filename ) ;
2015-04-13 21:08:51 +00:00
extraCode . push ( {
type : "outline" ,
filename : filename ,
data : data
2015-04-13 19:44:42 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
} ) ;
}
if ( files . indexOf ( "runners" ) != - 1 ) {
forEachFile ( cwd + "/runners" , function ( filename , data ) {
2015-04-14 00:44:47 +00:00
packedFiles . push ( cwd + "/runners/" + filename ) ;
2015-04-13 21:08:51 +00:00
extraCode . push ( {
type : "runners" ,
filename : filename ,
data : data
2015-04-13 19:44:42 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
} ) ;
}
if ( files . indexOf ( "snippets" ) != - 1 ) {
forEachFile ( cwd + "/snippets" , function ( filename , data ) {
2015-04-14 00:44:47 +00:00
packedFiles . push ( cwd + "/snippets/" + filename ) ;
2015-04-13 21:08:51 +00:00
extraCode . push ( {
type : "snippets" ,
filename : filename ,
data : data
2015-04-13 19:44:42 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
} ) ;
}
if ( files . indexOf ( "themes" ) != - 1 ) {
forEachFile ( cwd + "/themes" , function ( filename , data ) {
2015-04-14 00:44:47 +00:00
packedFiles . push ( cwd + "/themes/" + filename ) ;
2015-04-13 21:08:51 +00:00
extraCode . push ( {
type : "themes" ,
filename : filename ,
data : data
2015-04-13 19:44:42 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
} ) ;
}
2015-04-14 00:44:47 +00:00
if ( files . indexOf ( "templates" ) != - 1 ) {
forEachFile ( cwd + "/templates" , function ( filename , data ) {
packedFiles . push ( cwd + "/templates/" + filename ) ;
2015-04-13 21:08:51 +00:00
extraCode . push ( {
2015-04-14 00:44:47 +00:00
type : "templates" ,
2015-04-13 21:08:51 +00:00
filename : filename ,
data : data
} ) ;
} ) ;
}
2015-04-21 23:25:29 +00:00
packedFiles . push ( cwd + "/__installed__.js" ) ;
2015-04-15 22:18:02 +00:00
if ( json . installer ) {
2015-04-16 22:20:53 +00:00
var path = join ( cwd , json . installer ) ;
var installerCode = fs . readFileSync ( path , "utf8" ) ;
2015-05-01 16:00:22 +00:00
var m = installerCode . match ( /\.version\s*=\s*(\d+)/ ) ;
2015-04-16 22:20:53 +00:00
2015-05-01 16:00:22 +00:00
var installerVersion = m && m [ 1 ] ;
2015-04-16 22:20:53 +00:00
if ( ! installerVersion )
return callback ( new Error ( "ERROR: missing installer version in " + json . installer ) ) ;
2015-04-15 22:18:02 +00:00
extraCode . push ( {
type : "installer" ,
2015-04-16 22:20:53 +00:00
filename : json . installer ,
2015-04-29 18:48:58 +00:00
data : installerVersion
2015-04-15 22:18:02 +00:00
} ) ;
}
2015-04-13 21:08:51 +00:00
if ( ! extraCode . length )
return next ( ) ;
2015-04-13 19:44:42 +00:00
2015-04-13 21:08:51 +00:00
var code = ( function ( ) {
2015-04-14 00:44:47 +00:00
define ( function ( require , exports , module ) {
2015-04-13 21:08:51 +00:00
main . consumes = [
"Plugin" , "plugin.debug"
] ;
main . provides = [ ] ;
return main ;
function main ( options , imports , register ) {
var debug = imports [ "plugin.debug" ] ;
2015-04-14 00:44:47 +00:00
var Plugin = imports . Plugin ;
2015-04-13 21:08:51 +00:00
var plugin = new Plugin ( ) ;
2015-04-16 22:20:53 +00:00
plugin . version = "VERSION" ;
plugin . on ( "load" , function load ( ) {
extraCode . forEach ( function ( x ) {
2015-04-16 23:57:57 +00:00
debug . addStaticPlugin ( x . type , "PACKAGE_NAME" , x . filename , x . data , plugin ) ;
2015-04-16 22:20:53 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
} ) ;
2015-04-17 00:29:27 +00:00
plugin . load ( "PACKAGE_NAME.bundle" ) ;
2015-04-16 22:20:53 +00:00
2015-04-13 21:08:51 +00:00
register ( null , { } ) ;
}
} ) ;
} ) . toString ( ) ;
var indent = code . match ( /\n\r?(\s*)/ ) [ 1 ] . length ;
code = code
. replace ( /\r/g , "" )
. replace ( new RegExp ( "^ {" + indent + "}" , "gm" ) , "" )
. replace ( /^.*?{|}$/g , "" )
2015-04-16 23:57:57 +00:00
. replace ( /PACKAGE_NAME/g , packageName )
2015-04-16 22:20:53 +00:00
. replace ( /VERSION/g , json . version )
2015-04-13 21:08:51 +00:00
. replace ( /^(\s*)extraCode/gm , function ( _ , indent ) {
return JSON . stringify ( extraCode , null , 4 )
. replace ( /^/gm , indent ) ;
} ) ;
staticPlugin = {
source : code ,
2015-04-14 00:44:47 +00:00
id : "plugins/" + packageName + "/__static__" ,
2015-04-13 21:08:51 +00:00
path : ""
} ;
next ( ) ;
} ) ;
} ,
function ( next ) {
var build = require ( "architect-build/build" ) ;
2015-04-14 00:44:47 +00:00
var paths = { } ;
paths [ "plugins/" + packageName ] = cwd ;
2015-04-14 19:03:54 +00:00
var additional = [ ] ;
2015-04-14 20:02:27 +00:00
var packedConfig = config . slice ( ) ;
2015-04-14 19:03:54 +00:00
if ( staticPlugin ) {
additional . push ( staticPlugin ) ;
packedConfig . push ( staticPlugin . id ) ;
}
2015-04-15 23:30:14 +00:00
var path = "plugins/" + packageName + "/__installed__" ;
2015-04-14 19:03:54 +00:00
additional . push ( {
id : path ,
source : 'define("' + path + '", [],' +
2015-06-04 23:17:07 +00:00
JSON . stringify ( packedConfig . map ( function ( p ) {
var name = p . slice ( p . lastIndexOf ( "/" ) + 1 )
var options = json . plugins [ name ] || { } ;
options . packagePath = p ;
return options ;
} ) , null , 4 ) + ');' ,
2015-04-14 19:03:54 +00:00
literal : true ,
order : - 1
} ) ;
2015-04-13 21:08:51 +00:00
build ( config , {
2015-04-14 19:03:54 +00:00
additional : additional ,
2015-04-13 21:08:51 +00:00
paths : paths ,
enableBrowser : true ,
includeConfig : false ,
noArchitect : true ,
compress : ! dryRun ,
obfuscate : true ,
oneLine : true ,
filter : [ ] ,
ignore : [ ] ,
withRequire : false ,
stripLess : false ,
basepath : base ,
} , function ( e , r ) {
result = r ;
2015-04-14 00:44:47 +00:00
result . sources . forEach ( function ( m ) {
2015-04-14 19:03:54 +00:00
m . file && packedFiles . push ( m . file ) ;
2015-04-04 01:07:31 +00:00
} ) ;
2015-04-13 21:08:51 +00:00
next ( ) ;
} ) ;
} ,
function ( next ) {
2015-04-24 21:59:55 +00:00
if ( options . local )
2015-05-14 13:18:43 +00:00
return fs . writeFile ( cwd + "/__installed__.js" , result . code , "utf8" , callback ) ;
2015-04-24 21:59:55 +00:00
next ( ) ;
2015-04-13 21:08:51 +00:00
} ,
function ( next ) {
2015-04-24 21:59:55 +00:00
proc . execFile ( "rm" , {
2015-04-26 18:18:40 +00:00
args : [ "-rf" , ".c9/.build" ] ,
2015-04-24 21:59:55 +00:00
cwd : cwd
} , function ( ) {
2015-04-24 22:15:25 +00:00
mkdirP ( cwd + "/.c9/.build" ) ;
fs . writeFile ( cwd + "/.c9/.build/__installed__.js" , result . code , "utf8" , next ) ;
2015-04-24 21:59:55 +00:00
} ) ;
} ,
function ( next ) {
var copy = require ( "architect-build/copy" ) ;
2015-04-26 18:18:40 +00:00
var excludeRe = /^\.(gitignore|hgignore|git|c9|hg)$/ ;
2015-04-24 21:59:55 +00:00
var excludeMap = Object . create ( null ) ;
packedFiles . push ( cwd + "/__installed__.js" ) ;
packedFiles . forEach ( function ( p ) {
p = "/" + normalizePath ( Path . relative ( cwd , p ) ) ;
excludeMap [ p ] = 1 ;
} ) ;
2015-04-24 22:15:25 +00:00
copy ( cwd , cwd + "/.c9/.build" , {
2015-04-24 21:59:55 +00:00
exclude : function ( name , parent ) {
if ( excludeRe . test ( name ) )
return true ;
var fullPath = parent . substr ( cwd . length ) + "/" + name ;
if ( excludeMap [ fullPath ] )
return true ;
return false ;
}
2015-04-26 18:18:40 +00:00
} ) ;
next ( ) ;
} ,
updatePackageJSON ,
function ( next ) {
2015-04-24 21:59:55 +00:00
zip ( ) ;
2015-04-13 21:08:51 +00:00
}
] ) ;
2015-03-29 23:15:52 +00:00
}
2015-04-24 21:59:55 +00:00
function zip ( ) {
2015-04-04 01:07:31 +00:00
zipFilePath = join ( os . tmpDir ( ) , json . name + "@" + json . version ) + ".tar.gz" ;
2015-04-24 21:59:55 +00:00
var tarArgs = [ "-zcvf" , normalizePath ( zipFilePath ) ] ;
2015-04-14 00:44:47 +00:00
var c9ignore = normalizePath ( process . env . HOME + "/.c9/.c9ignore" ) ;
2015-02-10 19:41:24 +00:00
fs . exists ( c9ignore , function ( exists ) {
if ( exists ) {
tarArgs . push ( "--exclude-from=" + c9ignore ) ;
}
2015-04-24 21:59:55 +00:00
tarArgs . push ( "." ) ;
2015-05-14 13:18:43 +00:00
spawn ( TAR , {
2015-04-04 01:07:31 +00:00
args : tarArgs ,
2015-04-24 22:15:25 +00:00
cwd : cwd + "/.c9/.build"
2015-05-14 13:18:43 +00:00
} , function ( err ) {
if ( err )
return callback ( new Error ( "ERROR: Could not package directory" ) ) ;
console . log ( "Built package" , json . name + "@" + json . version +
( dryRun ? " at " + zipFilePath : "" ) ) ;
2015-02-10 19:41:24 +00:00
2015-05-14 13:18:43 +00:00
if ( dryRun ) return callback ( ) ;
2015-02-10 19:41:24 +00:00
2015-05-14 13:18:43 +00:00
upload ( ) ;
2015-02-10 19:41:24 +00:00
} ) ;
} ) ;
}
// Update c9.io with the new version being published.
function upload ( ) {
// Check if the plugin is already registered
if ( verbose )
console . log ( "Uploading package " + json . name ) ;
api . packages . get ( json . name , function ( err , pkg ) {
if ( err ) { } // Ignore error, if we don't get a response it means this package hasn't been published yet
if ( ! pkg || pkg . error ) {
if ( verbose )
console . log ( "Package not registered, creating new." ) ;
// Registers the package name on c9.io if it is being published for the first time.
api . user . get ( "" , function ( err , user ) {
if ( err ) return callback ( new Error ( "ERROR: Failed to get user details from API - " + stringifyError ( err ) ) ) ;
api . packages . post ( "" , {
contentType : "application/json" ,
body : {
name : json . name ,
2015-04-28 22:27:11 +00:00
description : description ,
2015-02-10 19:41:24 +00:00
owner _type : "user" , // @TODO implement this when adding orgs
owner _id : parseInt ( user . id ) ,
permissions : json . permissions || "world" ,
categories : json . categories ,
repository : json . repository ,
longname : json . longname ,
website : json . website ,
screenshots : json . screenshots || [ ] ,
pricing : json . pricing || { }
}
} , function ( err , pkg ) {
if ( err )
return callback ( new Error ( "ERROR: Failed to upload new package to API - "
+ stringifyError ( err ) ) ) ;
next ( pkg ) ;
} ) ;
} ) ;
}
else {
if ( verbose )
console . log ( "Plugin already registered, updating." ) ;
api . packages . put ( json . name , {
contentType : "application/json" ,
body : {
permissions : json . permissions ,
categories : json . categories ,
repository : json . repository ,
longname : json . longname ,
website : json . website ,
2015-04-28 22:27:11 +00:00
description : description ,
2015-02-10 19:41:24 +00:00
screenshots : json . screenshots ,
pricing : json . pricing ,
enabled : true
}
} , function ( err , pkg ) {
if ( err )
return callback ( new Error ( "ERROR: Failed to update existing package - "
+ stringifyError ( err ) ) ) ;
if ( verbose )
2015-04-24 23:24:10 +00:00
console . log ( "Successfully updated metadata of existing package" ) ;
2015-02-10 19:41:24 +00:00
next ( pkg ) ;
} ) ;
}
function next ( pkg ) {
// Create Version
if ( verbose )
console . log ( "Sending new version " , json . version ) ;
var form = new FormData ( ) ;
form . append ( 'version' , json . version ) ;
form . append ( 'options' , JSON . stringify ( json . plugins ) ) ;
form . append ( 'package' , fs . createReadStream ( zipFilePath ) ) ;
var path = "/packages/" + json . name
+ "/versions?access_token="
+ encodeURIComponent ( auth . accessToken ) ;
var host = APIHOST . split ( ":" ) [ 0 ]
var port = parseInt ( APIHOST . split ( ":" ) [ 1 ] ) || null ;
var request = http . request ( {
agent : false ,
method : "post" ,
host : host ,
port : port ,
path : path ,
auth : BASICAUTH ,
headers : form . getHeaders ( )
} ) ;
form . pipe ( request ) ;
request . on ( 'response' , function ( res ) {
2015-04-24 23:24:10 +00:00
// TODO better handle version exists error
2015-05-03 15:27:16 +00:00
if ( res . statusCode == 412 )
2015-04-24 23:24:10 +00:00
console . error ( "ERROR: most likely version " + json . version + " already exisits, try increasing version" ) ;
2015-02-10 19:41:24 +00:00
if ( res . statusCode != 200 )
return callback ( new Error ( "ERROR: Unknown Error:" + res . statusCode ) ) ;
2015-04-24 23:24:10 +00:00
commitAndPush ( ) ;
} ) ;
}
} ) ;
}
function commitAndPush ( ) {
// Create Version Complete
if ( ! createTag )
callback ( null , json ) ;
2015-05-14 13:18:43 +00:00
spawn ( "bash" , {
2015-04-24 23:24:10 +00:00
args : [ "-c" , SHELLSCRIPT , "--" , json . version , normalizePath ( packagePath ) ]
} , function ( err , p ) {
2015-05-14 13:18:43 +00:00
if ( err ) return callback ( err ) ;
console . log ( "Created tag and updated package.json to version" , json . version ) ;
callback ( null , json ) ;
2015-02-10 19:41:24 +00:00
} ) ;
}
} ) ;
}
function unpublish ( callback ) {
var packagePath = process . cwd ( ) + "/package.json" ;
fs . readFile ( packagePath , function ( err , data ) {
if ( err ) return callback ( err ) ; // @TODO package.json not found
var json ;
try { json = JSON . parse ( data ) ; }
catch ( e ) {
return callback ( new Error ( "ERROR: Could not parse package.json: " , e . message ) ) ;
}
if ( ! json . name )
return callback ( new Error ( "ERROR: Missing name property in package.json" ) ) ;
api . packages . put ( json . name + "/disable" , { } , callback ) ;
} ) ;
}
function mkdirP ( path ) {
var dirs = path . split ( '/' ) ;
var prevDir = dirs . splice ( 0 , 1 ) + "/" ;
while ( dirs . length > 0 ) {
var curDir = prevDir + dirs . splice ( 0 , 1 ) ;
if ( ! fs . existsSync ( curDir ) ) {
fs . mkdirSync ( curDir ) ;
}
prevDir = curDir + '/' ;
}
}
2015-04-21 23:25:29 +00:00
function normalizePath ( p ) {
if ( process . platform == "win32" )
p = p . replace ( /\\/g , "/" ) . replace ( /^(\w):/ , "/$1" ) ;
return p ;
}
2015-02-10 19:41:24 +00:00
/***** Lifecycle *****/
plugin . on ( "load" , function ( ) {
load ( ) ;
} ) ;
plugin . on ( "enable" , function ( ) {
} ) ;
plugin . on ( "disable" , function ( ) {
} ) ;
plugin . on ( "unload" , function ( ) {
loaded = false ;
verbose = false ;
force = false ;
} ) ;
2015-04-29 18:48:58 +00:00
/***** Register and define API *****/
2015-02-10 19:41:24 +00:00
/ * *
*
* * /
plugin . freezePublicAPI ( {
/ * *
*
* /
publish : publish ,
/ * *
*
* /
2015-04-27 17:07:49 +00:00
unpublish : unpublish
2015-02-10 19:41:24 +00:00
} ) ;
register ( null , {
"cli.publish" : plugin
} ) ;
}
} ) ;