Browse Source

Merge pull request #2314 from ian-r-rose/add_sibling_script

Add script for temporarily adding sibling packages to lerna build so they may be built against master.
Steven Silvester 8 years ago
parent
commit
34f69a1f1a
4 changed files with 147 additions and 2 deletions
  1. 22 1
      docs/extensions_dev.md
  2. 3 1
      package.json
  3. 64 0
      scripts/add-sibling.js
  4. 58 0
      scripts/remove-sibling.js

+ 22 - 1
docs/extensions_dev.md

@@ -98,7 +98,28 @@ only copy the current contents of the source folder.
 Note that the application is built against **released** versions of the
 core JupyterLab extensions.  If your extension depends on JupyterLab
 extensions, it should be compatible with the versions used in the
-`jupyterlab/package.template.json` entry point file.
+`jupyterlab/package.template.json` entry point file.  If you must
+install a extension into a development branch of JupyterLab, you
+have to graft it into the source tree of JupyterLab itself.
+This may be done using the command
+
+```
+npm run addsibling <path-or-url>
+```
+
+in the JupyterLab root directory, where `<path-or-url>` refers either to an 
+extension npm package on the local filesystem, or a URL to a git 
+repository for an extension npm package. This operation may be subsequently
+reversed by running
+
+```
+npm run addsibling <extension-name>
+```
+
+This will remove the package metadata from the source tree, but wil **not**
+remove any files added by the `addsibling` script, which should be removed
+manually.
+
 
 The package should export EMCAScript 5 compatible JavaScript.  It can 
 import CSS using the syntax `require('foo.css')`.  The CSS files

+ 3 - 1
package.json

@@ -22,7 +22,9 @@
     "publish": "npm update && npm install && npm run clean && npm run build && lerna publish -m \"Publish\"",
     "update:dependency": "node scripts/update-dependency.js",
     "watch": "watch \"npm run build\" ./packages/** --wait 10 --filter=scripts/watch-filter.js --ignoreDotFiles",
-    "watch:main": "watch \"npm run build:main\" ./packages/** --wait 10 --filter=scripts/watch-filter.js --ignoreDotFiles"
+    "watch:main": "watch \"npm run build:main\" ./packages/** --wait 10 --filter=scripts/watch-filter.js --ignoreDotFiles",
+    "addsibling": "node scripts/add-sibling.js",
+    "removesibling": "node scripts/remove-sibling.js"
   },
   "dependencies": {},
   "devDependencies": {

+ 64 - 0
scripts/add-sibling.js

@@ -0,0 +1,64 @@
+#!/usr/bin/env node
+var fs = require('fs-extra');
+var path = require('path');
+var childProcess = require('child_process');
+
+/**
+ * Add an extension to the source tree of JupyterLab.
+ * It takes as an argument either a path to a directory
+ * on the local filesystem or a URL to a git repository.
+ * In the former case, it copies the directory into the
+ * source tree, in the latter it adds the repository as
+ * a git submodule.
+ *
+ * It also adds the relevant metadata to the build files.
+ */
+
+// Make sure we have required command line arguments.
+if (process.argv.length < 3) {
+    var msg = '** Must supply a target extension';
+    process.stderr.write(msg);
+    process.exit(1);
+}
+
+// Extract the desired git repository and repository name.
+var target = process.argv[2];
+var basePath = path.resolve('.');
+
+var packagePath = '';
+if (target[0] === '.' || target[0] === '/') {
+  // If the target starts with a '.' or a '/', treat it as a local path.
+  packagePath = path.resolve(target);
+  packageDirName = target.split('/').pop();
+  // Copy the package directory contents to the sibling package.
+  var newPackagePath = path.join(basePath, 'packages', packageDirName);
+  fs.copySync(packagePath, newPackagePath);
+} else { 
+  // Otherwise treat it as a git reposotory and try to add it.
+  var packageDirName = target.split('/').pop().split('.')[0];
+  var packagePath = path.join(basePath, 'packages', packageDirName);
+  // Add the repository as a submodule.
+  childProcess.execSync('git submodule add --force '+ target + ' ' + packagePath);
+}
+
+// Get the package.json of the extension.
+var package = require(path.join(packagePath, 'package.json'));
+
+// Add the extension to packages/all-packages/package.json
+var allPackagesPath = path.join(basePath, 'packages', 'all-packages', 'package.json');
+var allPackages = require(allPackagesPath);
+allPackages.dependencies[package.name] = '~'+String(package.version);
+fs.writeFileSync(allPackagesPath, JSON.stringify(allPackages, null, 2) + '\n');
+
+// Add the extension to packages/all-packages/src/index.ts
+var indexPath = path.join(basePath, 'packages', 'all-packages', 'src', 'index.ts');
+var index = fs.readFileSync(indexPath, 'utf8');
+index = index + 'import "' + package.name + '";\n';
+fs.writeFileSync(indexPath, index);
+
+// Add the extension to jupyterlab/package.json
+var jupyterlabPackagePath = path.join(basePath, 'jupyterlab', 'package.json');
+var jupyterlabPackage = require(jupyterlabPackagePath);
+jupyterlabPackage.dependencies[package.name] = '~'+String(package.version);
+jupyterlabPackage.jupyterlab.extensions.push(package.name);
+fs.writeFileSync(jupyterlabPackagePath, JSON.stringify(jupyterlabPackage, null, 2) + '\n');

+ 58 - 0
scripts/remove-sibling.js

@@ -0,0 +1,58 @@
+#!/usr/bin/env node
+
+/**
+ * Remove an extension from the relevant metadata
+ * files of the JupyterLab source tree so that it
+ * is not included in the build. Intended for testing
+ * adding/removing extensions against development
+ * branches of JupyterLab.
+ *
+ * Note: this does not remove any files or submodules
+ * that may have been copied by the add-sibling.js
+ * script, and as such they are not true inverses of
+ * each other.
+ */
+
+var fs = require('fs');
+var path = require('path');
+var childProcess = require('child_process');
+
+// Make sure we have required command line arguments.
+if (process.argv.length < 3) {
+    var msg = '** Must supply a target extension name';
+    process.stderr.write(msg);
+    process.exit(1);
+}
+
+// Get the repository name.
+var target = process.argv[2];
+var basePath = path.resolve('.');
+
+// Get the package.json of the extension.
+var packagePath = path.join(basePath, 'packages', target);
+var package = require(path.join(packagePath, 'package.json'));
+
+// Remove the extension from packages/all-packages/package.json
+var allPackagesPath = path.join(basePath, 'packages', 'all-packages', 'package.json');
+var allPackages = require(allPackagesPath);
+allPackages.dependencies[package.name] = undefined;
+fs.writeFileSync(allPackagesPath, JSON.stringify(allPackages, null, 2) + '\n');
+
+// Remove the extension from packages/all-packages/src/index.ts
+var indexPath = path.join(basePath, 'packages', 'all-packages', 'src', 'index.ts');
+var index = fs.readFileSync(indexPath, 'utf8');
+var indexEntries = index.split('\n');
+var indexEntries = indexEntries.filter(function(e) {
+  return e.indexOf(package.name) === -1;
+});
+fs.writeFileSync(indexPath, indexEntries.join('\n'));
+
+// Remove the extension from jupyterlab/package.json
+var jupyterlabPackagePath = path.join(basePath, 'jupyterlab', 'package.json');
+var jupyterlabPackage = require(jupyterlabPackagePath);
+jupyterlabPackage.dependencies[package.name] = undefined;
+let extensions = jupyterlabPackage.jupyterlab.extensions.filter(function(e) {
+  return e.indexOf(package.name) === -1;
+});
+jupyterlabPackage.jupyterlab.extensions = extensions;
+fs.writeFileSync(jupyterlabPackagePath, JSON.stringify(jupyterlabPackage, null, 2) + '\n');