<commit_before>import _ from 'underscore';
import util from 'util';
import { Console } from '../console/console.js';
import buildmessage from '../utils/buildmessage.js';
import files from '../fs/files.js';
import bundler from '../isobuild/bundler.js';
import archinfo from '../utils/archinfo.js';
import release from '../packaging/release.js';
import isopackets from '../tool-env/isopackets.js';
import utils from '../utils/utils.js';

import { CORDOVA_ARCH } from './index.js';

// Hard-coded size constants

const iconsIosSizes = {
  'iphone': '60x60',
  'iphone_2x': '120x120',
  'iphone_3x': '180x180',
  'ipad': '76x76',
  'ipad_2x': '152x152'
};

const iconsAndroidSizes = {
  'android_ldpi': '36x36',
  'android_mdpi': '42x42',
  'android_hdpi': '72x72',
  'android_xhdpi': '96x96'
};

const launchIosSizes = {
  'iphone': '320x480',
  'iphone_2x': '640x960',
  'iphone5': '640x1136',
  'iphone6': '750x1334',
  'iphone6p_portrait': '1242x2208',
  'iphone6p_landscape': '2208x1242',
  'ipad_portrait': '768x1004',
  'ipad_portrait_2x': '1536x2008',
  'ipad_landscape': '1024x748',
  'ipad_landscape_2x': '2048x1496'
};

const launchAndroidSizes = {
  'android_ldpi_portrait': '320x426',
  'android_ldpi_landscape': '426x320',
  'android_mdpi_portrait': '320x470',
  'android_mdpi_landscape': '470x320',
  'android_hdpi_portrait': '480x640',
  'android_hdpi_landscape': '640x480',
  'android_xhdpi_portrait': '720x960',
  'android_xhdpi_landscape': '960x720'
};

export class CordovaBuilder {
  constructor(cordovaProject, bundlePath, plugins, options) {
    this.cordovaProject = cordovaProject;

    this.bundlePath = bundlePath;
    this.plugins = plugins;
    this.options = options;

    this.resourcesPath = files.pathJoin(
      this.cordovaProject.projectRoot,
      'resources');
  }

  get projectContext() {
    return this.cordovaProject.projectContext;
  }

  start() {
    buildmessage.assertInCapture();

    buildmessage.enterJob({ title: `preparing Cordova project` }, () => {
      this.initalizeDefaults();

      this.processControlFile();

      this.writeConfigXmlAndCopyResources();
      this.copyWWW();
      this.copyBuildOverride();

      this.cordovaProject.ensurePlatformsAreSynchronized();
      this.cordovaProject.ensurePluginsAreSynchronized(this.plugins,
        this.pluginsConfiguration);
    });
  }

  initalizeDefaults() {
    this.metadata = {
      id: 'com.id' + this.projectContext.appIdentifier,
      version: '0.0.1',
      buildNumber: undefined,
      name: this.cordovaProject.appName,
      description: 'New Meteor Mobile App',
      author: 'A Meteor Developer',
      email: 'n/a',
      website: 'n/a'
    };

    // set some defaults different from the Phonegap/Cordova defaults
    this.additionalConfiguration = {
      'webviewbounce': false,
      'DisallowOverscroll': true,
      'deployment-target': '7.0'
    };

    if (this.projectContext.packageMap.getInfo('launch-screen')) {
      this.additionalConfiguration.AutoHideSplashScreen = false;
      this.additionalConfiguration.SplashScreen = 'screen';
      this.additionalConfiguration.SplashScreenDelay = 10000;
    }

    // Default access rules for plain Meteor-Cordova apps.
    // Rules can be extended with mobile-config API.
    // The value is `true` if the protocol or domain should be allowed,
    // 'external' if should handled externally.
    this.accessRules = {
      // Allow external calls to things like email client or maps app or a
      // phonebook app.
      'tel:*': 'external',
      'geo:*': 'external',
      'mailto:*': 'external',
      'sms:*': 'external',
      'market:*': 'external',

      // phonegap/cordova related protocols
      // "file:" protocol is used to access first files from disk
      'file:*': true,
      'cdv:*': true,
      'gap:*': true,

      // allow Meteor's local emulated server url - this is the url from which the
      // application loads its assets
      'http://meteor.local/*': true
    };

    const mobileServerUrl = this.options.mobileServerUrl;
    const serverDomain = mobileServerUrl ?
      utils.parseUrl(mobileServerUrl).host : null;

    // If the remote server domain is known, allow access to it for xhr and DDP
    // connections.
    if (serverDomain) {
      this.accessRules['*://' + serverDomain + '/*'] = true;
      // Android talks to localhost over 10.0.2.2. This config file is used for
      // multiple platforms, so any time that we say the server is on localhost we
      // should also say it is on 10.0.2.2.
      if (serverDomain === 'localhost') {
        this.accessRules['*://10.0.2.2/*'] = true;
      }
    }

    this.imagePaths = {
      icon: {},
      splash: {}
    };

    // Defaults are Meteor meatball images located in tools/cordova/assets directory
    const assetsPath = files.pathJoin(__dirname, 'assets');
    const iconsPath = files.pathJoin(assetsPath, 'icons');
    const launchScreensPath = files.pathJoin(assetsPath, 'launchscreens');

    const setIcon = (size, name) => {
      this.imagePaths.icon[name] = files.pathJoin(iconsPath, size + '.png');
    };

    const setLaunchscreen = (size, name) => {
      this.imagePaths.splash[name] = files.pathJoin(launchScreensPath, size + '.png');
    };

    _.each(iconsIosSizes, setIcon);
    _.each(iconsAndroidSizes, setIcon);
    _.each(launchIosSizes, setLaunchscreen);
    _.each(launchAndroidSizes, setLaunchscreen);

    this.pluginsConfiguration = {};
  }

  processControlFile() {
    const controlFilePath =
      files.pathJoin(this.projectContext.projectDir, 'mobile-config.js');


    if (files.exists(controlFilePath)) {
      const code = files.readFile(controlFilePath, 'utf8');

      try {
        Console.debug('Running the mobile control file');
        files.runJavaScript(code, {
          filename: 'mobile-config.js',
          symbols: { App: App(this) }
        });
      } catch (error) {
        throw new Error('Error reading mobile-config.js:' + error.stack);
      }<commit_msg>Add a buildmessage instead of throwing an exception when processing mobile-config.js<commit_after>import _ from 'underscore';
import util from 'util';
import { Console } from '../console/console.js';
import buildmessage from '../utils/buildmessage.js';
import files from '../fs/files.js';
import bundler from '../isobuild/bundler.js';
import archinfo from '../utils/archinfo.js';
import release from '../packaging/release.js';
import isopackets from '../tool-env/isopackets.js';
import utils from '../utils/utils.js';

import { CORDOVA_ARCH } from './index.js';

// Hard-coded size constants

const iconsIosSizes = {
  'iphone': '60x60',
  'iphone_2x': '120x120',
  'iphone_3x': '180x180',
  'ipad': '76x76',
  'ipad_2x': '152x152'
};

const iconsAndroidSizes = {
  'android_ldpi': '36x36',
  'android_mdpi': '42x42',
  'android_hdpi': '72x72',
  'android_xhdpi': '96x96'
};

const launchIosSizes = {
  'iphone': '320x480',
  'iphone_2x': '640x960',
  'iphone5': '640x1136',
  'iphone6': '750x1334',
  'iphone6p_portrait': '1242x2208',
  'iphone6p_landscape': '2208x1242',
  'ipad_portrait': '768x1004',
  'ipad_portrait_2x': '1536x2008',
  'ipad_landscape': '1024x748',
  'ipad_landscape_2x': '2048x1496'
};

const launchAndroidSizes = {
  'android_ldpi_portrait': '320x426',
  'android_ldpi_landscape': '426x320',
  'android_mdpi_portrait': '320x470',
  'android_mdpi_landscape': '470x320',
  'android_hdpi_portrait': '480x640',
  'android_hdpi_landscape': '640x480',
  'android_xhdpi_portrait': '720x960',
  'android_xhdpi_landscape': '960x720'
};

export class CordovaBuilder {
  constructor(cordovaProject, bundlePath, plugins, options) {
    this.cordovaProject = cordovaProject;

    this.bundlePath = bundlePath;
    this.plugins = plugins;
    this.options = options;

    this.resourcesPath = files.pathJoin(
      this.cordovaProject.projectRoot,
      'resources');
  }

  get projectContext() {
    return this.cordovaProject.projectContext;
  }

  start() {
    buildmessage.assertInCapture();

    buildmessage.enterJob({ title: `preparing Cordova project` }, () => {
      this.initalizeDefaults();

      this.processControlFile();

      if (buildmessage.jobHasMessages()) return;

      this.writeConfigXmlAndCopyResources();
      this.copyWWW();
      this.copyBuildOverride();

      this.cordovaProject.ensurePlatformsAreSynchronized();
      this.cordovaProject.ensurePluginsAreSynchronized(this.plugins,
        this.pluginsConfiguration);
    });
  }

  initalizeDefaults() {
    this.metadata = {
      id: 'com.id' + this.projectContext.appIdentifier,
      version: '0.0.1',
      buildNumber: undefined,
      name: this.cordovaProject.appName,
      description: 'New Meteor Mobile App',
      author: 'A Meteor Developer',
      email: 'n/a',
      website: 'n/a'
    };

    // set some defaults different from the Phonegap/Cordova defaults
    this.additionalConfiguration = {
      'webviewbounce': false,
      'DisallowOverscroll': true,
      'deployment-target': '7.0'
    };

    if (this.projectContext.packageMap.getInfo('launch-screen')) {
      this.additionalConfiguration.AutoHideSplashScreen = false;
      this.additionalConfiguration.SplashScreen = 'screen';
      this.additionalConfiguration.SplashScreenDelay = 10000;
    }

    // Default access rules for plain Meteor-Cordova apps.
    // Rules can be extended with mobile-config API.
    // The value is `true` if the protocol or domain should be allowed,
    // 'external' if should handled externally.
    this.accessRules = {
      // Allow external calls to things like email client or maps app or a
      // phonebook app.
      'tel:*': 'external',
      'geo:*': 'external',
      'mailto:*': 'external',
      'sms:*': 'external',
      'market:*': 'external',

      // phonegap/cordova related protocols
      // "file:" protocol is used to access first files from disk
      'file:*': true,
      'cdv:*': true,
      'gap:*': true,

      // allow Meteor's local emulated server url - this is the url from which the
      // application loads its assets
      'http://meteor.local/*': true
    };

    const mobileServerUrl = this.options.mobileServerUrl;
    const serverDomain = mobileServerUrl ?
      utils.parseUrl(mobileServerUrl).host : null;

    // If the remote server domain is known, allow access to it for xhr and DDP
    // connections.
    if (serverDomain) {
      this.accessRules['*://' + serverDomain + '/*'] = true;
      // Android talks to localhost over 10.0.2.2. This config file is used for
      // multiple platforms, so any time that we say the server is on localhost we
      // should also say it is on 10.0.2.2.
      if (serverDomain === 'localhost') {
        this.accessRules['*://10.0.2.2/*'] = true;
      }
    }

    this.imagePaths = {
      icon: {},
      splash: {}
    };

    // Defaults are Meteor meatball images located in tools/cordova/assets directory
    const assetsPath = files.pathJoin(__dirname, 'assets');
    const iconsPath = files.pathJoin(assetsPath, 'icons');
    const launchScreensPath = files.pathJoin(assetsPath, 'launchscreens');

    const setIcon = (size, name) => {
      this.imagePaths.icon[name] = files.pathJoin(iconsPath, size + '.png');
    };

    const setLaunchscreen = (size, name) => {
      this.imagePaths.splash[name] = files.pathJoin(launchScreensPath, size + '.png');
    };

    _.each(iconsIosSizes, setIcon);
    _.each(iconsAndroidSizes, setIcon);
    _.each(launchIosSizes, setLaunchscreen);
    _.each(launchAndroidSizes, setLaunchscreen);

    this.pluginsConfiguration = {};
  }

  processControlFile() {
    const controlFilePath =
      files.pathJoin(this.projectContext.projectDir, 'mobile-config.js');


    if (files.exists(controlFilePath)) {
      Console.debug('Processing mobile-config.js');
      
      buildmessage.enterJob({ title: `processing mobile-config.js` }, () => {
        const code = files.readFile(controlFilePath, 'utf8');

        try {
          files.runJavaScript(code, {
            filename: 'mobile-config.js',
            symbols: { App: App(this) }
          });
        } catch (error) {
          buildmessage.exception(error);
        }
      });
{'fraction_non_alphanumeric': 0.13630771754285245, 'fraction_numerical': 0.03247765111129337, 'mean_word_length': 3.1788896504455106, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 6, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7358156', 'n_tokens_mistral': 4156, 'n_tokens_neox': 3821, 'n_words': 879}