inpect backups for extensions
authorSteve Hackbarth <stephenhackbarth@gmail.com>
Tue, 22 Jul 2014 21:59:09 +0000 (17:59 -0400)
committerSteve Hackbarth <stephenhackbarth@gmail.com>
Tue, 22 Jul 2014 21:59:09 +0000 (17:59 -0400)
scripts/lib/build_all.js
scripts/lib/build_database.js
scripts/lib/build_database_util.js

index 24b40e3..af0416e 100644 (file)
@@ -36,75 +36,19 @@ var _ = require('underscore'),
     var buildSpecs = {},
       databases = [],
       extension,
-      //
-      // Looks in a database to see which extensions are registered, and
-      // tacks onto that list the core directories.
-      //
       getRegisteredExtensions = function (database, callback) {
-        var result,
-          credsClone = JSON.parse(JSON.stringify(creds)),
-          existsSql = "select relname from pg_class where relname = 'ext'",
-          preInstallSql = "select xt.js_init();update xt.ext set ext_location = '/core-extensions' " +
-            "where ext_name = 'oauth2' and ext_location = '/xtuple-extensions';",
-          extSql = preInstallSql + "SELECT * FROM xt.ext ORDER BY ext_load_order",
-          defaultExtensions = [
-            { ext_location: '/core-extensions', ext_name: 'crm' },
-            { ext_location: '/core-extensions', ext_name: 'project' },
-            { ext_location: '/core-extensions', ext_name: 'sales' },
-            { ext_location: '/core-extensions', ext_name: 'billing' },
-            { ext_location: '/core-extensions', ext_name: 'purchasing' },
-            { ext_location: '/core-extensions', ext_name: 'oauth2' }
-          ],
-          adaptExtensions = function (err, res) {
-            if (err) {
-              callback(err);
-              return;
-            }
-
-            var paths = _.map(_.compact(res.rows), function (row) {
-              var location = row.ext_location,
-                name = row.ext_name,
-                extPath;
-
-              if (location === '/core-extensions') {
-                extPath = path.join(__dirname, "/../../enyo-client/extensions/source/", name);
-              } else if (location === '/xtuple-extensions') {
-                extPath = path.join(__dirname, "../../../xtuple-extensions/source", name);
-              } else if (location === '/private-extensions') {
-                extPath = path.join(__dirname, "../../../private-extensions/source", name);
-              } else if (location === 'npm') {
-                extPath = path.join(__dirname, "../../node_modules", name);
-              }
-              return extPath;
-            });
-
-            paths.unshift(path.join(__dirname, "../../enyo-client")); // core path
-            paths.unshift(path.join(__dirname, "../../lib/orm")); // lib path
-            paths.unshift(path.join(__dirname, "../../foundation-database")); // foundation path
-            callback(null, {
-              extensions: _.compact(paths),
-              database: database,
-              keepSql: options.keepSql,
-              populateData: options.populateData,
-              wipeViews: options.wipeViews,
-              clientOnly: options.clientOnly,
-              databaseOnly: options.databaseOnly
-            });
-          };
-
+        var credsClone = JSON.parse(JSON.stringify(creds));
         credsClone.database = database;
-        dataSource.query(existsSql, credsClone, function (err, res) {
-          if (err) {
-            callback(err);
-            return;
-          }
-          if (res.rowCount === 0) {
-            // xt.ext doesn't exist, because this is probably a brand-new DB.
-            // No problem! Give them the core extensions.
-            adaptExtensions(null, { rows: defaultExtensions });
-          } else {
-            dataSource.query(extSql, credsClone, adaptExtensions);
-          }
+        buildDatabaseUtil.inspectDatabaseExtensions(credsClone, function (err, paths) {
+          callback(null, {
+            extensions: paths,
+            database: database,
+            keepSql: options.keepSql,
+            populateData: options.populateData,
+            wipeViews: options.wipeViews,
+            clientOnly: options.clientOnly,
+            databaseOnly: options.databaseOnly
+          });
         });
       },
       buildAll = function (specs, creds, buildAllCallback) {
@@ -118,7 +62,7 @@ var _ = require('underscore'),
               return _.flatten(memo);
             }, []);
             var npmExtensions = _.filter(allExtensions, function (extName) {
-              return extName.indexOf("node_modules") >= 0;
+              return extName && extName.indexOf("node_modules") >= 0;
             });
             if (npmExtensions.length === 0) {
               done();
@@ -165,13 +109,10 @@ var _ = require('underscore'),
       },
       config;
 
-    // the config path is not relative if it starts with a slash
-    if (options.config && options.config.substring(0, 1) === '/') {
-      config = require(options.config);
-    } else if (options.config) {
-      config = require(path.join(process.cwd(), options.config));
+    if (options.config) {
+      config = require(path.resolve(process.cwd(), options.config));
     } else {
-      config = require(path.join(__dirname, "../../node-datasource/config.js"));
+      config = require(path.resolve(__dirname, "../../node-datasource/config.js"));
     }
     creds = config.databaseServer;
     creds.encryptionKeyFile = config.datasource.encryptionKeyFile;
@@ -193,6 +134,9 @@ var _ = require('underscore'),
     } else if (options.backup && options.source) {
       callback("You can build from backup or from source but not both.");
 
+    } else if (options.backup && options.extension) {
+      callback("When you're building from a backup you get whatever extensions the backup merits.");
+
     } else if (options.initialize &&
         (options.backup || options.source) &&
         options.database &&
@@ -203,16 +147,18 @@ var _ = require('underscore'),
 
       buildSpecs.database = options.database;
       if (options.backup) {
-        // the backup path is not relative if it starts with a slash
-        buildSpecs.backup = options.backup.substring(0, 1) === '/' ?
-          options.backup :
-          path.join(process.cwd(), options.backup);
+        buildSpecs.backup = path.resolve(process.cwd(), options.backup);
+        buildSpecs.extensions = false;
+        // we'll determine the extensions by looking at the db after restore
       }
       if (options.source) {
-        // the source path is not relative if it starts with a slash
-        buildSpecs.source = options.source.substring(0, 1) === '/' ?
-          options.source :
-          path.join(process.cwd(), options.source);
+        buildSpecs.source = path.resolve(process.cwd(), options.source);
+        // if we initialize with the foundation, that means we want
+        // an unmobilized build
+        buildSpecs.extensions = options.extension ?
+          [options.extension] :
+          buildDatabaseUtil.defaultExtensions;
+        console.log("extensions are ", buildSpecs);
       }
       buildSpecs.initialize = true;
       buildSpecs.keepSql = options.keepSql;
@@ -220,19 +166,6 @@ var _ = require('underscore'),
       buildSpecs.wipeViews = options.wipeViews;
       buildSpecs.clientOnly = options.clientOnly;
       buildSpecs.databaseOnly = options.databaseOnly;
-      // if we initialize with the foundation, that means we want
-      // an unmobilized build
-      buildSpecs.extensions = options.extension ? [options.extension] : [
-        path.join(__dirname, '../../foundation-database'),
-        path.join(__dirname, '../../lib/orm'),
-        path.join(__dirname, '../../enyo-client'),
-        path.join(__dirname, '../../enyo-client/extensions/source/crm'),
-        path.join(__dirname, '../../enyo-client/extensions/source/project'),
-        path.join(__dirname, '../../enyo-client/extensions/source/sales'),
-        path.join(__dirname, '../../enyo-client/extensions/source/billing'),
-        path.join(__dirname, '../../enyo-client/extensions/source/purchasing'),
-        path.join(__dirname, '../../enyo-client/extensions/source/oauth2')
-      ];
       buildAll([buildSpecs], creds, callback);
 
     } else if (options.initialize || options.backup || options.source) {
@@ -244,10 +177,7 @@ var _ = require('underscore'),
       // the user has specified an extension to build or unregister
       // extensions are assumed to be specified relative to the cwd
       buildSpecs = _.map(databases, function (database) {
-        // the extension is not relative if it starts with a slash
-        var extension = options.extension.substring(0, 1) === '/' ?
-          options.extension :
-          path.join(process.cwd(), options.extension);
+        var extension = path.resolve(process.cwd(), options.extension);
         return {
           database: database,
           frozen: options.frozen,
index d86e089..462996c 100644 (file)
@@ -62,6 +62,7 @@ var  async = require('async'),
         specs[0].wasInitialized = true;
         specs[0].backup = undefined;
         specs[0].source = undefined;
+        console.log("specs are", specs);
         buildDatabase(specs, creds, masterCallback);
       });
       return;
index e2da5e7..67df0c1 100644 (file)
@@ -15,7 +15,17 @@ regexp:true, undef:true, strict:true, trailing:true, white:true */
     winston = require('winston');
 
 
-
+  var defaultExtensions = [
+    path.join(__dirname, '../../foundation-database'),
+    path.join(__dirname, '../../lib/orm'),
+    path.join(__dirname, '../../enyo-client'),
+    path.join(__dirname, '../../enyo-client/extensions/source/crm'),
+    path.join(__dirname, '../../enyo-client/extensions/source/project'),
+    path.join(__dirname, '../../enyo-client/extensions/source/sales'),
+    path.join(__dirname, '../../enyo-client/extensions/source/billing'),
+    path.join(__dirname, '../../enyo-client/extensions/source/purchasing'),
+    path.join(__dirname, '../../enyo-client/extensions/source/oauth2')
+  ];
 
   var convertFromMetasql = function (content, filename, defaultSchema) {
     var lines = content.split("\n"),
@@ -376,6 +386,74 @@ regexp:true, undef:true, strict:true, trailing:true, white:true */
     });
   };
 
+  var pathFromExtension = function (name, location) {
+    if (location === '/core-extensions') {
+      return path.join(__dirname, "/../../enyo-client/extensions/source/", name);
+    } else if (location === '/xtuple-extensions') {
+      return path.join(__dirname, "../../../xtuple-extensions/source", name);
+    } else if (location === '/private-extensions') {
+      return path.join(__dirname, "../../../private-extensions/source", name);
+    } else if (location === 'npm') {
+      return path.join(__dirname, "../../node_modules", name);
+    }
+  };
+
+  //
+  // Looks in a database to see which extensions are registered, and
+  // tacks onto that list the core directories.
+  //
+  var inspectMobilizedDatabase = function (creds, done) {
+    var extSql = "SELECT * FROM xt.ext ORDER BY ext_load_order";
+    dataSource.query(extSql, creds, function (err, res) {
+      console.log("extSql", err, res);
+      if (err) {
+        return done(err);
+      }
+
+      var paths = _.map(_.compact(res.rows), function (row) {
+        return pathFromExtension(row.ext_name, row.ext_location);
+      });
+
+      paths.unshift(path.join(__dirname, "../../enyo-client")); // core path
+      paths.unshift(path.join(__dirname, "../../lib/orm")); // lib path
+      paths.unshift(path.join(__dirname, "../../foundation-database")); // foundation path
+      done(null, _.compact(paths));
+    });
+  };
+
+  // xtmfg -> inventory + manufacturing
+  // xwd -> inventory + distribution
+  var inspectUnmobilizedDatabase = function (creds, done) {
+    var extSql = "select * from public.pkghead where pkghead_name in ('xtmfg', 'xwd');",
+      editionMap = {
+        xtmfg: ["inventory", "manufacturing"],
+        xwd: ["inventory", "distribution"]
+      };
+    dataSource.query(extSql, creds, function (err, res) {
+      if (err) {
+        return done(err);
+      }
+      var extensions = _.unique(_.flatten(_.map(res.rows, function (row) {
+        return _.map(editionMap[row.pkghead_name], function (ext) {
+          return path.join(__dirname, "../../../private-extensions/source", ext);
+        });
+      })));
+      done(err, defaultExtensions.concat(extensions));
+    });
+  };
+
+  var inspectDatabaseExtensions = function (creds, done) {
+    var isMobilizedSql = "select * from information_schema.tables where table_schema = 'xt' and table_name = 'ext';";
+
+    dataSource.query(isMobilizedSql, creds, function (err, res) {
+      if (res.rowCount === 0) {
+        inspectUnmobilizedDatabase(creds, done);
+      } else {
+        inspectMobilizedDatabase(creds, done);
+      }
+    });
+  };
+
   //
   // Step 0 (optional, triggered by flags), wipe out the database
   // and load it from scratch using pg_restore something.backup unless
@@ -416,10 +494,12 @@ regexp:true, undef:true, strict:true, trailing:true, white:true */
           if (err) {
             console.log("ignoring restore db error", err);
           }
-          callback(null, res);
+          done(null, res);
         });
       },
       finish = function (err, results) {
+        console.log(arguments);
+        console.log("new spec", spec);
         if (err) {
           winston.error("init database error", err.message, err.stack, err);
         }
@@ -437,7 +517,15 @@ regexp:true, undef:true, strict:true, trailing:true, white:true */
       async.series([
         dropDatabase,
         createDatabase,
-        restoreBackup
+        restoreBackup,
+        function (done) {
+          credsClone.database = databaseName;
+          inspectDatabaseExtensions(credsClone, function (err, paths) {
+            // in the case of a build-from-backup, we ignore any user desires and dictate the extensions
+            spec.extensions = paths;
+            done();
+          });
+        }
       ], finish);
     }
   };
@@ -524,6 +612,7 @@ regexp:true, undef:true, strict:true, trailing:true, white:true */
     async.each(specs, unregisterEach, masterCallback);
   };
 
+  exports.defaultExtensions = defaultExtensions;
   exports.explodeManifest = explodeManifest;
   exports.initDatabase = initDatabase;
   exports.sendToDatabase = sendToDatabase;