lib/qx/tool/cli/commands/MConfig.js
async function() {
      var parsedArgs = await this.__parseImpl();
      var config = {};
      var contribConfig = {
        version: qx.tool.cli.ConfigSchemas.lockfile.version
      };

      if (parsedArgs.config) {
        config = await this.__loadJson(parsedArgs.config);
        let lockfile = qx.tool.cli.ConfigSchemas.lockfile.filename;
        try {
          var name = path.join(path.dirname(parsedArgs.config), lockfile);
          contribConfig = await this.__loadJson(name);
        } catch (ex) {
          // Nothing
        }
        // check semver-type compatibility (i.e. compatible as long as major version stays the same)
        let schemaVersion = semver.coerce(qx.tool.cli.ConfigSchemas.lockfile.version, true).raw;
        let fileVersion = contribConfig.version ? semver.coerce(contribConfig.version, true).raw : "1.0.0";
        if (semver.major(schemaVersion) > semver.major(fileVersion)) {
          if (this.argv.force) {
            let config = {
              verbose: this.argv.verbose,
              quite: this.argv.quiet,
              save: false
            };
            const installer = new qx.tool.cli.commands.contrib.Install(config);
            let filepath = installer.getContribFileName();
            let backup = filepath + ".old";
            await fs.copyFileAsync(filepath, backup);
            if (!this.argv.quiet) {
              console.info(`A backup of ${lockfile} has been saved to ${backup}, in case you need to revert to it.`);
            }
            await installer.deleteContribData();
            for (let lib of contribConfig.libraries) {
              if (!await installer.isInstalled(lib.uri, lib.repo_tag)) {
                if (lib.repo_tag) {
                  await installer.install(lib.uri, lib.repo_tag);
                } else if (lib.path && fs.existsSync(lib.path)) {
                  await installer.installFromLocaPath(lib.path, lib.uri);
                }
              } else if (this.argv.verbose) {
                console.info(`>>> ${lib.uri}@${lib.repo_tag} is already installed.`);
              }
            }
            contribConfig = await installer.getContribData();
          } else {
            throw new qx.tool.cli.Utils.UserError(
              `*** Warning ***\n` +
              `The schema of '${lockfile}' has changed. Execute 'qx clean && qx compile --force' to delete and regenerate it.\n` +
              `You might have to re-apply manual modifications to '${lockfile}'.`
            );
          }
        }
      }
      this._mergeArguments(parsedArgs, config, contribConfig);
      if (config.libraries) {
        for (const aPath of config.libraries) {
          if (typeof aPath === "object" && typeof aPath.path === "string") {
            throw new Error("Configuration for libraries has changed - it is now an array of strings, each of which is a path to the directory containing Manifest.json.  Please run 'qx upgrade'");
          }
          await this.__loadJs(path.join(aPath, "compile.js"), config);
        }
      }
      return config;
    }
async function() {
      var parsedArgs = await this.__parseImpl();
      var config = {};
      var contribConfig = {
        version: qx.tool.cli.ConfigSchemas.lockfile.version
      };

      if (parsedArgs.config) {
        config = await this.__loadJson(parsedArgs.config);
        let lockfile = qx.tool.cli.ConfigSchemas.lockfile.filename;
        try {
          var name = path.join(path.dirname(parsedArgs.config), lockfile);
          contribConfig = await this.__loadJson(name);
        } catch (ex) {
          // Nothing
        }
        // check semver-type compatibility (i.e. compatible as long as major version stays the same)
        let schemaVersion = semver.coerce(qx.tool.cli.ConfigSchemas.lockfile.version, true).raw;
        let fileVersion = contribConfig.version ? semver.coerce(contribConfig.version, true).raw : "1.0.0";
        if (semver.major(schemaVersion) > semver.major(fileVersion)) {
          if (this.argv.force) {
            let config = {
              verbose: this.argv.verbose,
              quite: this.argv.quiet,
              save: false
            };
            const installer = new qx.tool.cli.commands.contrib.Install(config);
            let filepath = installer.getContribFileName();
            let backup = filepath + ".old";
            await fs.copyFileAsync(filepath, backup);
            if (!this.argv.quiet) {
              console.info(`A backup of ${lockfile} has been saved to ${backup}, in case you need to revert to it.`);
            }
            await installer.deleteContribData();
            for (let lib of contribConfig.libraries) {
              if (!await installer.isInstalled(lib.uri, lib.repo_tag)) {
                if (lib.repo_tag) {
                  await installer.install(lib.uri, lib.repo_tag);
                } else if (lib.path && fs.existsSync(lib.path)) {
                  await installer.installFromLocaPath(lib.path, lib.uri);
                }
              } else if (this.argv.verbose) {
                console.info(`>>> ${lib.uri}@${lib.repo_tag} is already installed.`);
              }
            }
            contribConfig = await installer.getContribData();
          } else {
            throw new qx.tool.cli.Utils.UserError(
              `*** Warning ***\n` +
              `The schema of '${lockfile}' has changed. Execute 'qx clean && qx compile --force' to delete and regenerate it.\n` +
              `You might have to re-apply manual modifications to '${lockfile}'.`
            );
          }
        }
      }
      this._mergeArguments(parsedArgs, config, contribConfig);
      if (config.libraries) {
        for (const aPath of config.libraries) {
          if (typeof aPath === "object" && typeof aPath.path === "string") {
            throw new Error("Configuration for libraries has changed - it is now an array of strings, each of which is a path to the directory containing Manifest.json.  Please run 'qx upgrade'");
          }
          await this.__loadJs(path.join(aPath, "compile.js"), config);
        }
      }
      return config;
    }
async function ( ) { var parsedArgs = await this . __parseImpl ( ) ; var config = { } ; var contribConfig = { version : qx . tool . cli . ConfigSchemas . lockfile . version } ; if ( parsedArgs . config ) { config = await this . __loadJson ( parsedArgs . config ) ; let lockfile = qx . tool . cli . ConfigSchemas . lockfile . filename ; try { var name = path . join ( path . dirname ( parsedArgs . config ) , lockfile ) ; contribConfig = await this . __loadJson ( name ) ; } catch ( ex ) { // Nothing } // check semver-type compatibility (i.e. compatible as long as major version stays the same) let schemaVersion = semver . coerce ( qx . tool . cli . ConfigSchemas . lockfile . version , true ) . raw ; let fileVersion = contribConfig . version ? semver . coerce ( contribConfig . version , true ) . raw : "1.0.0" ; if ( semver . major ( schemaVersion ) > semver . major ( fileVersion ) ) { if ( this . argv . force ) { let config = { verbose : this . argv . verbose , quite : this . argv . quiet , save : false } ; const installer = new qx . tool . cli . commands . contrib . Install ( config ) ; let filepath = installer . getContribFileName ( ) ; let backup = filepath + ".old" ; await fs . copyFileAsync ( filepath , backup ) ; if ( ! this . argv . quiet ) { console . info ( ` ${ lockfile } ${ backup } ` ) ; } await installer . deleteContribData ( ) ; for ( let lib of contribConfig . libraries ) { if ( ! await installer . isInstalled ( lib . uri , lib . repo_tag ) ) { if ( lib . repo_tag ) { await installer . install ( lib . uri , lib . repo_tag ) ; } else if ( lib . path && fs . existsSync ( lib . path ) ) { await installer . installFromLocaPath ( lib . path , lib . uri ) ; } } else if ( this . argv . verbose ) { console . info ( ` ${ lib . uri } ${ lib . repo_tag } ` ) ; } } contribConfig = await installer . getContribData ( ) ; } else { throw new qx . tool . cli . Utils . UserError ( ` \n ` + ` ${ lockfile } \n ` + ` ${ lockfile } ` ) ; } } } this . _mergeArguments ( parsedArgs , config , contribConfig ) ; if ( config . libraries ) { for ( const aPath of config . libraries ) { if ( typeof aPath === "object" && typeof aPath . path === "string" ) { throw new Error ( "Configuration for libraries has changed - it is now an array of strings, each of which is a path to the directory containing Manifest.json.  Please run 'qx upgrade'" ) ; } await this . __loadJs ( path . join ( aPath , "compile.js" ) , config ) ; } } return config ; }
Parses the command line and produces configuration data

Loads a configuration file from a .js or .json file; if you provide a .js
file the file MUST return a function.
If there is also a .json, then it is loaded and parsed first.

The Function returned from a .js file MUST accept two arguments, one for the
data (which will be null if there is no .json) and the second is the callback
to call when complete; the callback takes an error object and the output
configuration data.

Configuration files do not support processes, job executions, or even
macros - if you want to add basic processing (eg for macros), use a .js file to
manipulate the data.  If you want to customise the Maker that is produced, you
need to use the API directly.
Parses the command line and produces configuration data