浏览代码

Added grunt dev:init task.

Szymon Kupś 10 年之前
父节点
当前提交
7c80cf1c96
共有 6 个文件被更改,包括 300 次插入2 次删除
  1. 37 0
      dev/tasks/dev.js
  2. 64 0
      dev/tasks/test/dev.js
  3. 113 0
      dev/tasks/test/tools.js
  4. 75 0
      dev/tasks/utils/tools.js
  5. 3 1
      gruntfile.js
  6. 8 1
      package.json

+ 37 - 0
dev/tasks/dev.js

@@ -0,0 +1,37 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+var tools = require( './utils/tools' );
+var path = require( 'path' );
+var ckeditor5Path = process.cwd();
+var json = require( path.join( ckeditor5Path, 'package.json' ) );
+var dependencies = json.dependencies;
+
+module.exports = function( grunt ) {
+	grunt.registerTask( 'dev', function( target ) {
+		var pluginPath;
+
+		switch ( target ) {
+			case 'init':
+				var ckeDependencies = tools.getCKEditorDependencies( dependencies );
+				var location = path.join( ckeditor5Path, '..' );
+
+				if ( ckeDependencies ) {
+					Object.keys( ckeDependencies ).forEach( function( name ) {
+						grunt.log.writeln( 'Clonning repository ' + ckeDependencies[ name ] + '...' );
+						tools.cloneRepository( name, ckeDependencies[ name ], location );
+
+						pluginPath = path.join( location, name );
+						grunt.log.writeln( 'Linking ' + pluginPath + ' into ' + ckeditor5Path + '...' );
+						tools.npmLink( pluginPath, ckeditor5Path, name );
+					} );
+				}
+				break;
+		}
+	} );
+};
+

+ 64 - 0
dev/tasks/test/dev.js

@@ -0,0 +1,64 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+/* global describe, it */
+
+var chai = require( 'chai' );
+var tools = require( '../utils/tools' );
+var sinon = require( 'sinon' );
+var path = require( 'path' );
+var expect = chai.expect;
+var dev = require( './../dev' );
+var grunt = {
+	tasks: {},
+	registerTask: function( taskName, fn ) {
+		this.tasks[ taskName ] = fn;
+	},
+	log: {
+		writeln: function() {}
+	}
+};
+
+dev( grunt );
+
+describe( 'tasks', function() {
+	describe( 'dev:init', function() {
+		it( 'should get ckeditor5- dependencies, clone repositories and link them', function() {
+			var getDepsSpy = sinon.spy( tools, 'getCKEditorDependencies' );
+			var cloneRepositoryStub = sinon.stub( tools, 'cloneRepository' );
+			var npmLinkStub = sinon.stub( tools, 'npmLink' );
+			var ckeditor5Path = process.cwd();
+			var location = path.join( ckeditor5Path, '..' );
+			var dependencies, keys;
+
+			grunt.tasks.dev( 'init' );
+
+			getDepsSpy.restore();
+			cloneRepositoryStub.restore();
+			npmLinkStub.restore();
+
+			expect( getDepsSpy.calledOnce ).to.equal( true );
+			dependencies = getDepsSpy.firstCall.returnValue;
+
+			if ( dependencies ) {
+				keys = Object.keys( dependencies );
+
+				expect( cloneRepositoryStub.callCount ).to.equal( keys.length );
+				expect( npmLinkStub.callCount ).to.equal( keys.length );
+
+				keys.forEach( function( key, i ) {
+					expect( cloneRepositoryStub.getCall( i ).args[0] ).equal( key );
+					expect( cloneRepositoryStub.getCall( i ).args[1] ).equal( dependencies[ key ] );
+					expect( cloneRepositoryStub.getCall( i ).args[2] ).equal( location );
+
+					expect( npmLinkStub.getCall( i ).args[0] ).equal( path.join( location, key ) );
+					expect( npmLinkStub.getCall( i ).args[1] ).equal( ckeditor5Path );
+					expect( npmLinkStub.getCall( i ).args[2] ).equal( key );
+				} );
+			}
+		} );
+	} );
+} );

+ 113 - 0
dev/tasks/test/tools.js

@@ -0,0 +1,113 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+/* global describe, it */
+
+var chai = require( 'chai' );
+var sinon = require( 'sinon' );
+var expect = chai.expect;
+var tools = require( '../utils/tools' );
+
+describe( 'utils', function() {
+	describe( 'tools', function() {
+		describe( 'cloneRepository', function() {
+			it( 'should be defined', function() {
+				expect( tools.cloneRepository ).to.be.a( 'function' );
+			} );
+
+			it( 'should run clone repository commands', function( ) {
+				var shExecStub = sinon.stub( tools, 'shExec' );
+				var name = 'test';
+				var gitHubUrl = 'ckeditor/test';
+				var destination = '/destination/dir';
+
+				tools.cloneRepository( name, gitHubUrl, destination );
+				shExecStub.restore();
+
+				expect( shExecStub.calledOnce ).to.equal( true );
+				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( 'cd ' + destination + ' && git clone git@github.com:' + gitHubUrl );
+			} );
+
+			it( 'should checkout proper commit/branch if provided', function() {
+				var shExecStub = sinon.stub( tools, 'shExec' );
+				var name = 'test';
+				var url = 'ckeditor/test';
+				var branch = 'branch';
+				var gitHubUrl = url + '#' + branch;
+				var destination = '/destination/dir';
+
+				tools.cloneRepository( name, gitHubUrl, destination );
+				shExecStub.restore();
+
+				expect( shExecStub.calledOnce ).to.equal( true );
+				expect( shExecStub.firstCall.args[ 0 ] ).to.equal(
+					'cd ' + destination + ' && ' +
+					'git clone git@github.com:' + url + ' && ' +
+					'cd ' + name + ' && ' +
+					'git checkout ' + branch
+				);
+			} );
+		} );
+
+		describe( 'npmLink', function() {
+			it( 'should be defined', function() {
+				expect( tools.cloneRepository ).to.be.a( 'function' );
+			} );
+
+			it( 'should run npm link commands', function( ) {
+				var shExecStub = sinon.stub( tools, 'shExec' );
+				var source = '/source/dir';
+				var destination = '/destination/dir';
+				var pluginName = 'ckeditor5-plugin-name';
+				var isWin = process.platform == 'win32';
+				var linkCommands = [
+					'cd ' + source,
+					( !isWin ? 'sudo ' : '' ) + 'npm link',
+					'cd ' + destination,
+					'npm link ' + pluginName
+				];
+
+				tools.npmLink( source, destination, pluginName );
+				shExecStub.restore();
+
+				expect( shExecStub.calledOnce ).to.equal( true );
+				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( linkCommands.join( ' && ' ) );
+			} );
+		} );
+
+		describe( 'getCKEditorDependencies', function() {
+			it( 'should be defined', function() {
+				expect( tools.getCKEditorDependencies ).to.be.a( 'function' );
+			} );
+
+			it( 'should return null if no CKEditor5 repository is found', function() {
+				var dependencies = {
+					'plugin1': '',
+					'plugin2': '',
+					'plugin3': ''
+				};
+				expect( tools.getCKEditorDependencies( dependencies ) ).to.equal( null );
+			} );
+
+			it( 'should return only ckeditor5- dependencies', function() {
+				var dependencies = {
+					'plugin1': '',
+					'ckeditor5-plugin-image': 'ckeditor/ckeditor5-plugin-image',
+					'plugin2': '',
+					'ckeditor5-core': 'ckeditor/ckeditor5-core'
+				};
+
+				var ckeditorDependencies = tools.getCKEditorDependencies( dependencies );
+
+				expect( ckeditorDependencies ).to.be.an( 'object' );
+				expect( ckeditorDependencies.plugin1 ).to.be.a( 'undefined' );
+				expect( ckeditorDependencies.plugin2 ).to.be.a( 'undefined' );
+				expect( ckeditorDependencies[ 'ckeditor5-plugin-image' ] ).to.be.a( 'string' );
+				expect( ckeditorDependencies[ 'ckeditor5-core' ] ).to.be.a( 'string' );
+			} );
+		} );
+	} );
+} );

+ 75 - 0
dev/tasks/utils/tools.js

@@ -3,6 +3,8 @@
 var dirtyFiles,
 var dirtyFiles,
 	ignoreList;
 	ignoreList;
 
 
+var repositoryRegExp = /^(ckeditor\/[^#]+)(?:#)?(.*)/;
+
 module.exports = {
 module.exports = {
 	/**
 	/**
 	 * Check if a task (including its optional target) is in the queue of tasks to be executed by Grunt.
 	 * Check if a task (including its optional target) is in the queue of tasks to be executed by Grunt.
@@ -136,5 +138,78 @@ module.exports = {
 		}
 		}
 
 
 		return ret.output;
 		return ret.output;
+	},
+
+	/**
+	 * Links repository located in source path to repository located in destination path. Uses npm link.
+	 *
+	 * @param {String} sourcePath
+	 * @param {String} destinationPath
+	 * @param {String} pluginName
+	 */
+	npmLink: function( sourcePath, destinationPath, pluginName ) {
+		// Don't use sudo on windows when executing npm link.
+		var isWin = process.platform == 'win32';
+		var linkCommands = [
+			'cd ' + sourcePath,
+			( !isWin ? 'sudo ' : '' ) + 'npm link',
+			'cd ' + destinationPath,
+			'npm link ' + pluginName
+		];
+
+		module.exports.shExec( linkCommands.join( ' && ' ) );
+	},
+
+	/**
+	 * Clones repository from provided GitHub URL. Only short GitHub urls are supported that starts with 'ckeditor/'.
+	 * https://docs.npmjs.com/files/package.json#github-urls
+	 *
+	 * @param {String} name Repository name.
+	 * @param {String} gitHubUrl GitHub url to repository.
+	 * @param {String} location Destination path.
+	 */
+	cloneRepository: function( name, gitHubUrl, location ) {
+		var match = gitHubUrl.match( repositoryRegExp );
+
+		if ( match && match[ 1 ] )  {
+			var cloneCommands = [
+				'cd ' + location,
+				'git clone git@github.com:' + match[ 1 ]
+			];
+
+			// If commit-ish suffix is included - run git checkout.
+			if ( match[ 2 ] ) {
+				cloneCommands.push( 'cd ' + name );
+				cloneCommands.push( 'git checkout ' + match[ 2 ] );
+			}
+
+			module.exports.shExec( cloneCommands.join( ' && ' ) );
+		}
+	},
+
+	/**
+	 * Returns dependencies that starts with ckeditor5-, and have valid, short GitHub url. Returns null if no
+	 * dependencies are found.
+	 *
+	 * @param {Object} dependencies Dependencies object loaded from package.json file.
+	 * @returns {Object|null}
+	 */
+	getCKEditorDependencies: function( dependencies ) {
+		var result = null;
+		var regexp = /^ckeditor5-/;
+
+		if ( dependencies ) {
+			Object.keys( dependencies ).forEach( function( key ) {
+				if ( regexp.test( key ) && repositoryRegExp.test( dependencies[ key ] ) ) {
+					if ( result === null ) {
+						result = {};
+					}
+
+					result[ key ] = dependencies[ key ];
+				}
+			} );
+		}
+
+		return result;
 	}
 	}
 };
 };

+ 3 - 1
gruntfile.js

@@ -26,7 +26,9 @@ module.exports = function( grunt ) {
 			options: {
 			options: {
 				excludeFiles: ignoreFiles
 				excludeFiles: ignoreFiles
 			}
 			}
-		}
+		},
+
+		dev: {}
 	} );
 	} );
 
 
 	// Finally load the tasks.
 	// Finally load the tasks.

+ 8 - 1
package.json

@@ -20,14 +20,18 @@
     "benderjs-mocha": "^0.3.0",
     "benderjs-mocha": "^0.3.0",
     "benderjs-promise": "^0.1.0",
     "benderjs-promise": "^0.1.0",
     "benderjs-sinon": "^0.3.0",
     "benderjs-sinon": "^0.3.0",
+    "chai": "~1.10.0",
     "del": "^2.0.2",
     "del": "^2.0.2",
     "grunt": "^0",
     "grunt": "^0",
     "grunt-jscs": "^2.0.0",
     "grunt-jscs": "^2.0.0",
     "grunt-contrib-jshint": "^0",
     "grunt-contrib-jshint": "^0",
     "grunt-githooks": "^0",
     "grunt-githooks": "^0",
+    "inquirer": "^0.11.0",
+    "mocha": "^2.2.5",
     "ncp": "^2.0.0",
     "ncp": "^2.0.0",
     "replace": "^0.3.0",
     "replace": "^0.3.0",
-    "shelljs": "^0"
+    "shelljs": "^0",
+    "sinon": "^1.17.0"
   },
   },
   "author": "CKSource (http://cksource.com/)",
   "author": "CKSource (http://cksource.com/)",
   "license": "See LICENSE.md",
   "license": "See LICENSE.md",
@@ -36,5 +40,8 @@
   "repository": {
   "repository": {
     "type": "git",
     "type": "git",
     "url": "https://github.com/ckeditor/ckeditor5.git"
     "url": "https://github.com/ckeditor/ckeditor5.git"
+  },
+  "scripts": {
+    "test": "mocha dev/tasks/test"
   }
   }
 }
 }