<commit_before>var path = require('path');
var packageJson = require('./package.json');

module.exports = function(grunt) {
  'use strict';

  var bower = grunt.file.readJSON('bower.json');
  var components = [];
  for (var i in bower.concat.app) {
    components.push('components/' + bower.concat.app[i] + '/**/*.js');
  }
  components.push('components/' + 'webaudiorecorder/lib/WebAudioRecorder.js');

  var libtextsecurecomponents = [];
  for (i in bower.concat.libtextsecure) {
    libtextsecurecomponents.push(
      'components/' + bower.concat.libtextsecure[i] + '/**/*.js'
    );
  }

  var importOnce = require('node-sass-import-once');
  grunt.loadNpmTasks('grunt-sass');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      components: {
        src: components,
        dest: 'js/components.js',
      },
      libtextsecurecomponents: {
        src: libtextsecurecomponents,
        dest: 'libtextsecure/components.js',
      },
      test: {
        src: [
          'components/mocha/mocha.js',
          'components/chai/chai.js',
          'test/_test.js',
        ],
        dest: 'test/test.js',
      },
      //TODO: Move errors back down?
      libtextsecure: {
        options: {
          banner: ';(function() {\n',
          footer: '})();\n',
        },
        src: [
          'libtextsecure/errors.js',
          'libtextsecure/libsignal-protocol.js',
          'libtextsecure/protocol_wrapper.js',

          'libtextsecure/crypto.js',
          'libtextsecure/storage.js',
          'libtextsecure/storage/user.js',
          'libtextsecure/storage/groups.js',
          'libtextsecure/storage/unprocessed.js',
          'libtextsecure/protobufs.js',
          'libtextsecure/helpers.js',
          'libtextsecure/stringview.js',
          'libtextsecure/event_target.js',
          'libtextsecure/api.js',
          'libtextsecure/account_manager.js',
          'libtextsecure/websocket-resources.js',
          'libtextsecure/message_receiver.js',
          'libtextsecure/outgoing_message.js',
          'libtextsecure/sendmessage.js',
          'libtextsecure/sync_request.js',
          'libtextsecure/contacts_parser.js',
          'libtextsecure/ProvisioningCipher.js',
          'libtextsecure/task_with_timeout.js',
        ],
        dest: 'js/libtextsecure.js',
      },
      libtextsecuretest: {
        src: [
          'components/jquery/dist/jquery.js',
          'components/mock-socket/dist/mock-socket.js',
          'components/mocha/mocha.js',
          'components/chai/chai.js',
          'libtextsecure/test/_test.js',
        ],
        dest: 'libtextsecure/test/test.js',
      },
    },
    sass: {
      options: {
        sourceMap: true,
        importer: importOnce,
      },
      dev: {
        files: {
          'stylesheets/manifest.css': 'stylesheets/manifest.scss',
        },
      },
    },
    jshint: {
      files: [
        'Gruntfile.js',
        'js/**/*.js',
        '!js/background.js',
        '!js/backup.js',
        '!js/components.js',
        '!js/database.js',
        '!js/jquery.js',
        '!js/libsignal-protocol-worker.js',
        '!js/libtextsecure.js',
        '!js/logging.js',
        '!js/modules/**/*.js',
        '!js/Mp3LameEncoder.min.js',
        '!js/signal_protocol_store.js',
        '!js/views/conversation_search_view.js',
        '!js/views/conversation_view.js',
        '!js/views/debug_log_view.js',
        '!js/views/file_input_view.js',
        '!js/views/message_view.js',
        '!js/models/conversations.js',
        '!js/models/messages.js',
        '!js/WebAudioRecorderMp3.js',
        '!libtextsecure/message_receiver.js',
        '_locales/**/*',
      ],
      options: { jshintrc: '.jshintrc' },
    },
    dist: {
      src: [
        'background.html',
        'index.html',
        'options.html',
        '_locales/**',
        'protos/*',
        'js/**',
        'stylesheets/*.css',
        '!js/register.js',
      ],
      res: ['images/**/*', 'fonts/*'],
    },
    copy: {
      deps: {
        files: [
          {
            src: 'components/mp3lameencoder/lib/Mp3LameEncoder.js',
            dest: 'js/Mp3LameEncoder.min.js',
          },
          {
            src: 'components/webaudiorecorder/lib/WebAudioRecorderMp3.js',
            dest: 'js/WebAudioRecorderMp3.js',
          },
          {
            src: 'components/jquery/dist/jquery.js',
            dest: 'js/jquery.js',
          },
        ],
      },
      res: {
        files: [{ expand: true, dest: 'dist/', src: ['<%= dist.res %>'] }],
      },
      src: {
        files: [{ expand: true, dest: 'dist/', src: ['<%= dist.src %>'] }],
      },
    },
    jscs: {
      all: {
        src: [
          'Gruntfile',
          'js/**/*.js',
          '!js/components.js',
          '!js/libsignal-protocol-worker.js',
          '!js/libtextsecure.js',
          '!js/modules/**/*.js',
          '!js/models/conversations.js',
          '!js/models/messages.js',
          '!js/views/conversation_search_view.js',
          '!js/views/conversation_view.js',
          '!js/views/debug_log_view.js',
          '!js/views/file_input_view.js',
          '!js/views/message_view.js',
          '!js/Mp3LameEncoder.min.js',
          '!js/WebAudioRecorderMp3.js',
          'test/**/*.js',
          '!test/blanket_mocha.js',
          '!test/modules/**/*.js',
          '!test/test.js',
        ],
      },
    },
    watch: {
      dist: {
        files: ['<%= dist.src %>', '<%= dist.res %>'],
        tasks: ['copy_dist'],
      },
      libtextsecure: {
        files: ['./libtextsecure/*.js', './libtextsecure/storage/*.js'],
        tasks: ['concat:libtextsecure'],
      },
      protobuf: {
        files: ['./protos/SignalService.proto'],
        tasks: ['exec:build-protobuf'],
      },
      sass: {
        files: ['./stylesheets/*.scss'],
        tasks: ['sass'],
      },
      scripts: {
        files: ['<%= jshint.files %>'],
        tasks: ['jshint'],
      },
      style: {
        files: ['<%= jscs.all.src %>'],
        tasks: ['jscs'],
      },
      transpile: {
        files: ['./ts/**/*.ts'],
        tasks: ['exec:transpile'],
      },
    },
    exec: {
      'tx-pull': {
        cmd: 'tx pull',
      },
      transpile: {
        cmd: 'yarn transpile',
      },
      'build-protobuf': {
        cmd: 'yarn build-protobuf',
      },
    },
    'test-release': {
      osx: {
        archive:
          'mac/' + packageJson.productName + '.app/Contents/Resources/app.asar',
        appUpdateYML:
          'mac/' +
          packageJson.productName +
          '.app/Contents/Resources/app-update.yml',
        exe:
          'mac/' +
          packageJson.productName +
          '.app/Contents/MacOS/' +
          packageJson.productName,
      },
      mas: {
        archive: 'mas/Signal.app/Contents/Resources/app.asar',
        appUpdateYML: 'mac/Signal.app/Contents/Resources/app-update.yml',
        exe:
          'mas/' +
          packageJson.productName +
          '.app/Contents/MacOS/' +
          packageJson.productName,
      },
      linux: {
        archive: 'linux-unpacked/resources/app.asar',
        exe: 'linux-unpacked/' + packageJson.name,
      },
      win: {
        archive: 'win-unpacked/resources/app.asar',
        appUpdateYML: 'win-unpacked/resources/app-update.yml',
        exe: 'win-unpacked/' + packageJson.productName + '.exe',
      },
    },
    gitinfo: {}, // to be populated by grunt gitinfo
  });

  Object.keys(grunt.config.get('pkg').devDependencies).forEach(function(key) {
    if (/^grunt(?!(-cli)?$)/.test(key)) {
      // ignore grunt and grunt-cli
      grunt.loadNpmTasks(key);
    }
  });

  // Transifex does not understand placeholders, so this task patches all non-en
  // locales with missing placeholders
  grunt.registerTask('locale-patch', function() {
    var en = grunt.file.readJSON('_locales/en/messages.json');
    grunt.file.recurse('_locales', function(
      abspath,
      rootdir,
      subdir,
      filename
    ) {
      if (subdir === 'en' || filename !== 'messages.json') {
        return;
      }
      var messages = grunt.file.readJSON(abspath);

      for (var key in messages) {
        if (en[key] !== undefined && messages[key] !== undefined) {
          if (
            en[key].placeholders !== undefined &&
            messages[key].placeholders === undefined
          ) {
            messages[key].placeholders = en[key].placeholders;
          }
        }
      }

      grunt.file.write(abspath, JSON.stringify(messages, null, 4) + '\n');
    });
  });

  grunt.registerTask('getExpireTime', function() {
    grunt.task.requires('gitinfo');
    var gitinfo = grunt.config.get('gitinfo');
    var commited = gitinfo.local.branch.current.lastCommitTime;
    var time = Date.parse(commited) + 1000 * 60 * 60 * 24 * 90;
    grunt.file.write(
      'config/local-production.json',
      JSON.stringify({ buildExpiration: time }) + '\n'
    );
  });

  grunt.registerTask('clean-release', function() {
    require('rimraf').sync('release');
    require('mkdirp').sync('release');
  });

  function runTests(environment, cb) {
    var failure;
    var Application = require('spectron').Application;
    var electronBinary =
      process.platform === 'win32' ? 'electron.cmd' : 'electron';
    var app = new Application({
      path: path.join(__dirname, 'node_modules', '.bin', electronBinary),
      args: [path.join(__dirname, 'main.js')],
      env: {
        NODE_ENV: environment,
      },
    });

    function getMochaResults() {
      return window.mochaResults;
    }

    app
      .start()
      .then(function() {
        return app.client.waitUntil(
          function() {
            return app.client.execute(getMochaResults).then(function(data) {
              return Boolean(data.value);
            });
          },
          10000,
          'Expected to find window.mochaResults set!'
        );
      })
      .then(function() {
        return app.client.execute(getMochaResults);
      })
      .then(function(data) {
        var results = data.value;
        if (results.failures > 0) {
          console.error(results.reports);
          failure = function() {
            grunt.fail.fatal(
              'Found ' + results.failures + ' failing unit tests.'
            );
          };
          return app.client.log('browser');
        } else {
          grunt.log.ok(results.passes + ' tests passed.');
        }
      })
      .then(function(logs) {
        if (logs) {
          console.error();
          console.error('Because tests failed, printing browser logs:');
          console.error(logs);
        }
      })
      .catch(function(error) {
        failure = function() {
          grunt.fail.fatal(
            'Something went wrong: ' + error.message + ' ' + error.stack
          );
        };
      })
      .then(function() {
        // We need to use the failure variable and this early stop to clean up before
        // shutting down. Grunt's fail methods are the only way to set the return value,
        // but they shut the process down immediately!
        return app.stop();
      })
      .then(function() {
        if (failure) {
          failure();
        }
        cb();
      })
      .catch(function(error) {
        console.error('Second-level error:', error.message, error.stack);
        if (failure) {
          failure();
        }
        cb();
      });
  }

  grunt.registerTask('unit-tests', 'Run unit tests w/Electron', function() {
    var environment = grunt.option('env') || 'test';
    var done = this.async();

    runTests(environment, done);
  });

  grunt.registerTask(
    'lib-unit-tests',
    'Run libtextsecure unit tests w/Electron',
    function() {
      var environment = grunt.option('env') || 'test-lib';
      var done = this.async();

      runTests(environment, done);
    }
  );

  grunt.registerMultiTask('test-release', 'Test packaged releases', function() {
    var dir = grunt.option('dir') || 'dist';
    var environment = grunt.option('env') || 'production';
    var asar = require('asar');
    var config = this.data;
    var archive = [dir, config.archive].join('/');
    var files = [
      'config/default.json',
      'config/' + environment + '.json',
      'config/local-' + environment + '.json',
    ];

    console.log(this.target, archive);
    var releaseFiles = files.concat(config.files || []);
    releaseFiles.forEach(function(fileName) {
      console.log(fileName);
      try {
        asar.statFile(archive, fileName);
        return true;
      } catch (e) {
        console.log(e);
        throw new Error('Missing file ' + fileName);
      }
    });

    if (config.appUpdateYML) {
      var appUpdateYML = [dir, config.appUpdateYML].join('/');
      if (require('fs').existsSync(appUpdateYML)) {
        console.log('auto update ok');
      } else {
        throw new Error('Missing auto update config ' + appUpdateYML);
      }
    }

    var done = this.async();
    // A simple test to verify a visible window is opened with a title
    var Application = require('spectron').Application;
    var assert = require('assert');

    var app = new Application({
      path: [dir, config.exe].join('/'),
    });

    app
      .start()
      .then(function() {
        return app.client.getWindowCount();
      })
      .then(function(count) {
        assert.equal(count, 1);
        console.log('window opened');
      })
      .then(function() {
        // Get the window's title
        return app.client.getTitle();
      })
      .then(function(title) {
        // Verify the window's title
        assert.equal(title, packageJson.productName);
        console.log('title ok');
      })
      .then(function() {
        assert(
          app.chromeDriver.logLines.indexOf('NODE_ENV ' + environment) > -1
        );
        console.log('environment ok');
      })
      .then(
        function() {
          // Successfully completed test
          return app.stop();
        },
        function(error) {
          // Test failed!
          return app.stop().then(function() {
            grunt.fail.fatal(
              'Test failed: ' + error.message + ' ' + error.stack
            );
          });
        }
      )
      .then(done);
  });

  grunt.registerTask('tx', ['exec:tx-pull', 'locale-patch']);
  grunt.registerTask('dev', ['default', 'watch']);
  grunt.registerTask('lint', ['jshint', 'jscs']);
  grunt.registerTask('test', ['unit-tests', 'lib-unit-tests']);
  grunt.registerTask('copy_dist', ['gitinfo', 'copy:res', 'copy:src']);
  grunt.registerTask('date', ['gitinfo', 'getExpireTime']);
  grunt.registerTask('default', [
    'concat',
    'copy:deps',
    'sass',
    'date',
    'exec:build-protobuf',
    'exec:transpile',
  ]);
};
<commit_msg>Compile protocol buffers first<commit_after>var path = require('path');
var packageJson = require('./package.json');

module.exports = function(grunt) {
  'use strict';

  var bower = grunt.file.readJSON('bower.json');
  var components = [];
  for (var i in bower.concat.app) {
    components.push('components/' + bower.concat.app[i] + '/**/*.js');
  }
  components.push('components/' + 'webaudiorecorder/lib/WebAudioRecorder.js');

  var libtextsecurecomponents = [];
  for (i in bower.concat.libtextsecure) {
    libtextsecurecomponents.push(
      'components/' + bower.concat.libtextsecure[i] + '/**/*.js'
    );
  }

  var importOnce = require('node-sass-import-once');
  grunt.loadNpmTasks('grunt-sass');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      components: {
        src: components,
        dest: 'js/components.js',
      },
      libtextsecurecomponents: {
        src: libtextsecurecomponents,
        dest: 'libtextsecure/components.js',
      },
      test: {
        src: [
          'components/mocha/mocha.js',
          'components/chai/chai.js',
          'test/_test.js',
        ],
        dest: 'test/test.js',
      },
      //TODO: Move errors back down?
      libtextsecure: {
        options: {
          banner: ';(function() {\n',
          footer: '})();\n',
        },
        src: [
          'libtextsecure/errors.js',
          'libtextsecure/libsignal-protocol.js',
          'libtextsecure/protocol_wrapper.js',

          'libtextsecure/crypto.js',
          'libtextsecure/storage.js',
          'libtextsecure/storage/user.js',
          'libtextsecure/storage/groups.js',
          'libtextsecure/storage/unprocessed.js',
          'libtextsecure/protobufs.js',
          'libtextsecure/helpers.js',
          'libtextsecure/stringview.js',
          'libtextsecure/event_target.js',
          'libtextsecure/api.js',
          'libtextsecure/account_manager.js',
          'libtextsecure/websocket-resources.js',
          'libtextsecure/message_receiver.js',
          'libtextsecure/outgoing_message.js',
          'libtextsecure/sendmessage.js',
          'libtextsecure/sync_request.js',
          'libtextsecure/contacts_parser.js',
          'libtextsecure/ProvisioningCipher.js',
          'libtextsecure/task_with_timeout.js',
        ],
        dest: 'js/libtextsecure.js',
      },
      libtextsecuretest: {
        src: [
          'components/jquery/dist/jquery.js',
          'components/mock-socket/dist/mock-socket.js',
          'components/mocha/mocha.js',
          'components/chai/chai.js',
          'libtextsecure/test/_test.js',
        ],
        dest: 'libtextsecure/test/test.js',
      },
    },
    sass: {
      options: {
        sourceMap: true,
        importer: importOnce,
      },
      dev: {
        files: {
          'stylesheets/manifest.css': 'stylesheets/manifest.scss',
        },
      },
    },
    jshint: {
      files: [
        'Gruntfile.js',
        'js/**/*.js',
        '!js/background.js',
        '!js/backup.js',
        '!js/components.js',
        '!js/database.js',
        '!js/jquery.js',
        '!js/libsignal-protocol-worker.js',
        '!js/libtextsecure.js',
        '!js/logging.js',
        '!js/modules/**/*.js',
        '!js/Mp3LameEncoder.min.js',
        '!js/signal_protocol_store.js',
        '!js/views/conversation_search_view.js',
        '!js/views/conversation_view.js',
        '!js/views/debug_log_view.js',
        '!js/views/file_input_view.js',
        '!js/views/message_view.js',
        '!js/models/conversations.js',
        '!js/models/messages.js',
        '!js/WebAudioRecorderMp3.js',
        '!libtextsecure/message_receiver.js',
        '_locales/**/*',
      ],
      options: { jshintrc: '.jshintrc' },
    },
    dist: {
      src: [
        'background.html',
        'index.html',
        'options.html',
        '_locales/**',
        'protos/*',
        'js/**',
        'stylesheets/*.css',
        '!js/register.js',
      ],
      res: ['images/**/*', 'fonts/*'],
    },
    copy: {
      deps: {
        files: [
          {
            src: 'components/mp3lameencoder/lib/Mp3LameEncoder.js',
            dest: 'js/Mp3LameEncoder.min.js',
          },
          {
            src: 'components/webaudiorecorder/lib/WebAudioRecorderMp3.js',
            dest: 'js/WebAudioRecorderMp3.js',
          },
          {
            src: 'components/jquery/dist/jquery.js',
            dest: 'js/jquery.js',
          },
        ],
      },
      res: {
        files: [{ expand: true, dest: 'dist/', src: ['<%= dist.res %>'] }],
      },
      src: {
        files: [{ expand: true, dest: 'dist/', src: ['<%= dist.src %>'] }],
      },
    },
    jscs: {
      all: {
        src: [
          'Gruntfile',
          'js/**/*.js',
          '!js/components.js',
          '!js/libsignal-protocol-worker.js',
          '!js/libtextsecure.js',
          '!js/modules/**/*.js',
          '!js/models/conversations.js',
          '!js/models/messages.js',
          '!js/views/conversation_search_view.js',
          '!js/views/conversation_view.js',
          '!js/views/debug_log_view.js',
          '!js/views/file_input_view.js',
          '!js/views/message_view.js',
          '!js/Mp3LameEncoder.min.js',
          '!js/WebAudioRecorderMp3.js',
          'test/**/*.js',
          '!test/blanket_mocha.js',
          '!test/modules/**/*.js',
          '!test/test.js',
        ],
      },
    },
    watch: {
      dist: {
        files: ['<%= dist.src %>', '<%= dist.res %>'],
        tasks: ['copy_dist'],
      },
      libtextsecure: {
        files: ['./libtextsecure/*.js', './libtextsecure/storage/*.js'],
        tasks: ['concat:libtextsecure'],
      },
      protobuf: {
        files: ['./protos/SignalService.proto'],
        tasks: ['exec:build-protobuf'],
      },
      sass: {
        files: ['./stylesheets/*.scss'],
        tasks: ['sass'],
      },
      scripts: {
        files: ['<%= jshint.files %>'],
        tasks: ['jshint'],
      },
      style: {
        files: ['<%= jscs.all.src %>'],
        tasks: ['jscs'],
      },
      transpile: {
        files: ['./ts/**/*.ts'],
        tasks: ['exec:transpile'],
      },
    },
    exec: {
      'tx-pull': {
        cmd: 'tx pull',
      },
      transpile: {
        cmd: 'yarn transpile',
      },
      'build-protobuf': {
        cmd: 'yarn build-protobuf',
      },
    },
    'test-release': {
      osx: {
        archive:
          'mac/' + packageJson.productName + '.app/Contents/Resources/app.asar',
        appUpdateYML:
          'mac/' +
          packageJson.productName +
          '.app/Contents/Resources/app-update.yml',
        exe:
          'mac/' +
          packageJson.productName +
          '.app/Contents/MacOS/' +
          packageJson.productName,
      },
      mas: {
        archive: 'mas/Signal.app/Contents/Resources/app.asar',
        appUpdateYML: 'mac/Signal.app/Contents/Resources/app-update.yml',
        exe:
          'mas/' +
          packageJson.productName +
          '.app/Contents/MacOS/' +
          packageJson.productName,
      },
      linux: {
        archive: 'linux-unpacked/resources/app.asar',
        exe: 'linux-unpacked/' + packageJson.name,
      },
      win: {
        archive: 'win-unpacked/resources/app.asar',
        appUpdateYML: 'win-unpacked/resources/app-update.yml',
        exe: 'win-unpacked/' + packageJson.productName + '.exe',
      },
    },
    gitinfo: {}, // to be populated by grunt gitinfo
  });

  Object.keys(grunt.config.get('pkg').devDependencies).forEach(function(key) {
    if (/^grunt(?!(-cli)?$)/.test(key)) {
      // ignore grunt and grunt-cli
      grunt.loadNpmTasks(key);
    }
  });

  // Transifex does not understand placeholders, so this task patches all non-en
  // locales with missing placeholders
  grunt.registerTask('locale-patch', function() {
    var en = grunt.file.readJSON('_locales/en/messages.json');
    grunt.file.recurse('_locales', function(
      abspath,
      rootdir,
      subdir,
      filename
    ) {
      if (subdir === 'en' || filename !== 'messages.json') {
        return;
      }
      var messages = grunt.file.readJSON(abspath);

      for (var key in messages) {
        if (en[key] !== undefined && messages[key] !== undefined) {
          if (
            en[key].placeholders !== undefined &&
            messages[key].placeholders === undefined
          ) {
            messages[key].placeholders = en[key].placeholders;
          }
        }
      }

      grunt.file.write(abspath, JSON.stringify(messages, null, 4) + '\n');
    });
  });

  grunt.registerTask('getExpireTime', function() {
    grunt.task.requires('gitinfo');
    var gitinfo = grunt.config.get('gitinfo');
    var commited = gitinfo.local.branch.current.lastCommitTime;
    var time = Date.parse(commited) + 1000 * 60 * 60 * 24 * 90;
    grunt.file.write(
      'config/local-production.json',
      JSON.stringify({ buildExpiration: time }) + '\n'
    );
  });

  grunt.registerTask('clean-release', function() {
    require('rimraf').sync('release');
    require('mkdirp').sync('release');
  });

  function runTests(environment, cb) {
    var failure;
    var Application = require('spectron').Application;
    var electronBinary =
      process.platform === 'win32' ? 'electron.cmd' : 'electron';
    var app = new Application({
      path: path.join(__dirname, 'node_modules', '.bin', electronBinary),
      args: [path.join(__dirname, 'main.js')],
      env: {
        NODE_ENV: environment,
      },
    });

    function getMochaResults() {
      return window.mochaResults;
    }

    app
      .start()
      .then(function() {
        return app.client.waitUntil(
          function() {
            return app.client.execute(getMochaResults).then(function(data) {
              return Boolean(data.value);
            });
          },
          10000,
          'Expected to find window.mochaResults set!'
        );
      })
      .then(function() {
        return app.client.execute(getMochaResults);
      })
      .then(function(data) {
        var results = data.value;
        if (results.failures > 0) {
          console.error(results.reports);
          failure = function() {
            grunt.fail.fatal(
              'Found ' + results.failures + ' failing unit tests.'
            );
          };
          return app.client.log('browser');
        } else {
          grunt.log.ok(results.passes + ' tests passed.');
        }
      })
      .then(function(logs) {
        if (logs) {
          console.error();
          console.error('Because tests failed, printing browser logs:');
          console.error(logs);
        }
      })
      .catch(function(error) {
        failure = function() {
          grunt.fail.fatal(
            'Something went wrong: ' + error.message + ' ' + error.stack
          );
        };
      })
      .then(function() {
        // We need to use the failure variable and this early stop to clean up before
        // shutting down. Grunt's fail methods are the only way to set the return value,
        // but they shut the process down immediately!
        return app.stop();
      })
      .then(function() {
        if (failure) {
          failure();
        }
        cb();
      })
      .catch(function(error) {
        console.error('Second-level error:', error.message, error.stack);
        if (failure) {
          failure();
        }
        cb();
      });
  }

  grunt.registerTask('unit-tests', 'Run unit tests w/Electron', function() {
    var environment = grunt.option('env') || 'test';
    var done = this.async();

    runTests(environment, done);
  });

  grunt.registerTask(
    'lib-unit-tests',
    'Run libtextsecure unit tests w/Electron',
    function() {
      var environment = grunt.option('env') || 'test-lib';
      var done = this.async();

      runTests(environment, done);
    }
  );

  grunt.registerMultiTask('test-release', 'Test packaged releases', function() {
    var dir = grunt.option('dir') || 'dist';
    var environment = grunt.option('env') || 'production';
    var asar = require('asar');
    var config = this.data;
    var archive = [dir, config.archive].join('/');
    var files = [
      'config/default.json',
      'config/' + environment + '.json',
      'config/local-' + environment + '.json',
    ];

    console.log(this.target, archive);
    var releaseFiles = files.concat(config.files || []);
    releaseFiles.forEach(function(fileName) {
      console.log(fileName);
      try {
        asar.statFile(archive, fileName);
        return true;
      } catch (e) {
        console.log(e);
        throw new Error('Missing file ' + fileName);
      }
    });

    if (config.appUpdateYML) {
      var appUpdateYML = [dir, config.appUpdateYML].join('/');
      if (require('fs').existsSync(appUpdateYML)) {
        console.log('auto update ok');
      } else {
        throw new Error('Missing auto update config ' + appUpdateYML);
      }
    }

    var done = this.async();
    // A simple test to verify a visible window is opened with a title
    var Application = require('spectron').Application;
    var assert = require('assert');

    var app = new Application({
      path: [dir, config.exe].join('/'),
    });

    app
      .start()
      .then(function() {
        return app.client.getWindowCount();
      })
      .then(function(count) {
        assert.equal(count, 1);
        console.log('window opened');
      })
      .then(function() {
        // Get the window's title
        return app.client.getTitle();
      })
      .then(function(title) {
        // Verify the window's title
        assert.equal(title, packageJson.productName);
        console.log('title ok');
      })
      .then(function() {
        assert(
          app.chromeDriver.logLines.indexOf('NODE_ENV ' + environment) > -1
        );
        console.log('environment ok');
      })
      .then(
        function() {
          // Successfully completed test
          return app.stop();
        },
        function(error) {
          // Test failed!
          return app.stop().then(function() {
            grunt.fail.fatal(
              'Test failed: ' + error.message + ' ' + error.stack
            );
          });
        }
      )
      .then(done);
  });

  grunt.registerTask('tx', ['exec:tx-pull', 'locale-patch']);
  grunt.registerTask('dev', ['default', 'watch']);
  grunt.registerTask('lint', ['jshint', 'jscs']);
  grunt.registerTask('test', ['unit-tests', 'lib-unit-tests']);
  grunt.registerTask('copy_dist', ['gitinfo', 'copy:res', 'copy:src']);
  grunt.registerTask('date', ['gitinfo', 'getExpireTime']);
  grunt.registerTask('default', [
    'exec:build-protobuf',
    'exec:transpile',
    'concat',
    'copy:deps',
    'sass',
    'date',
  ]);
};
<|endoftext|>


<commit_before>// Generated on 2016-03-08 using generator-angular 0.15.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required Grunt tasks
  require('jit-grunt')(grunt, {
    useminPrepare: 'grunt-usemin',
    ngtemplates: 'grunt-angular-templates',
    cdnify: 'grunt-google-cdn'
  });

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all', 'newer:jscs:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
      },
      styles: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'postcss']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Make sure code styles are up to par
    jscs: {
      options: {
        config: '.jscsrc',
        verbose: true
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    postcss: {
      options: {
        processors: [
          require('autoprefixer-core')({browsers: ['last 1 version']})
        ]
      },
      server: {
        options: {
          map: true
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles'
        ],
        patterns: {
          js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    ngtemplates: {
      dist: {
        options: {
          module: 'helmeditor2App',
          htmlmin: '<%= htmlmin.dist.options %>',
          usemin: 'scripts/scripts.js'
        },
        cwd: '<%= yeoman.app %>',
        src: ['views/{,*/}*.html', 'templates/{,*/}*.html'],
        dest: '.tmp/templateCache.js'
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '*.html',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: 'bower_components/bootstrap/dist',
          src: 'fonts/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'copy:styles'
      ],
      test: [
        'copy:styles'
      ],
      dist: [
        'copy:styles',
        'imagemin',
        'svgmin'
      ],
      protractorTest: [
        'protractor:chrome',
        'protractor:firefox'
      ]
    },

    // Test settings
    karma: {
      // discrete unit tests
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      },

      // continuous unit tests
      continuous: {
        configFile: 'test/karma.conf.js',
        singleRun: false
      }
    },

    protractor: {
      options: {
        configFile: 'test/e2e/protractor.conf.js', // protractor config file
        keepAlive: false, // if false, the grunt process stops when the test fails.
        noColor: false, // if true, protractor will not use colors in its output.
        args: {
          // Arguments passed to the command
        }
      },
      chrome: {
        options: {
          args: {
            browser: 'chrome'
          }
        }
      },
      firefox: {
        options: {
          args: {
            browser: 'firefox'
          }
        }
      }
    }
  });

  // load the protractor task
  grunt.loadNpmTasks('grunt-protractor-runner');

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'postcss:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'karma:unit'
  ]);

  // task for running continous unit tests in devlopment
  grunt.registerTask('test-continuous', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'karma:continuous'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'postcss',
    'ngtemplates',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('protractor-chrome', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'protractor:chrome'
  ]);
  grunt.registerTask('protractor-firefox', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'protractor:firefox'
  ]);
  grunt.registerTask('protractor-all', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'concurrent:protractorTest']);

  grunt.registerTask('default', [
    'newer:jshint',
    'newer:jscs',
    'test',
    'build'
  ]);
};
<commit_msg>update grunt build target to include XML files<commit_after>// Generated on 2016-03-08 using generator-angular 0.15.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required Grunt tasks
  require('jit-grunt')(grunt, {
    useminPrepare: 'grunt-usemin',
    ngtemplates: 'grunt-angular-templates',
    cdnify: 'grunt-google-cdn'
  });

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all', 'newer:jscs:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
      },
      styles: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'postcss']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Make sure code styles are up to par
    jscs: {
      options: {
        config: '.jscsrc',
        verbose: true
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    postcss: {
      options: {
        processors: [
          require('autoprefixer-core')({browsers: ['last 1 version']})
        ]
      },
      server: {
        options: {
          map: true
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles'
        ],
        patterns: {
          js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    ngtemplates: {
      dist: {
        options: {
          module: 'helmeditor2App',
          htmlmin: '<%= htmlmin.dist.options %>',
          usemin: 'scripts/scripts.js'
        },
        cwd: '<%= yeoman.app %>',
        src: ['views/{,*/}*.html', 'templates/{,*/}*.html'],
        dest: '.tmp/templateCache.js'
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '*.html',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*',
            '*.xml'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: 'bower_components/bootstrap/dist',
          src: 'fonts/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'copy:styles'
      ],
      test: [
        'copy:styles'
      ],
      dist: [
        'copy:styles',
        'imagemin',
        'svgmin'
      ],
      protractorTest: [
        'protractor:chrome',
        'protractor:firefox'
      ]
    },

    // Test settings
    karma: {
      // discrete unit tests
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      },

      // continuous unit tests
      continuous: {
        configFile: 'test/karma.conf.js',
        singleRun: false
      }
    },

    protractor: {
      options: {
        configFile: 'test/e2e/protractor.conf.js', // protractor config file
        keepAlive: false, // if false, the grunt process stops when the test fails.
        noColor: false, // if true, protractor will not use colors in its output.
        args: {
          // Arguments passed to the command
        }
      },
      chrome: {
        options: {
          args: {
            browser: 'chrome'
          }
        }
      },
      firefox: {
        options: {
          args: {
            browser: 'firefox'
          }
        }
      }
    }
  });

  // load the protractor task
  grunt.loadNpmTasks('grunt-protractor-runner');

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'postcss:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'karma:unit'
  ]);

  // task for running continous unit tests in devlopment
  grunt.registerTask('test-continuous', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'karma:continuous'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'postcss',
    'ngtemplates',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('protractor-chrome', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'protractor:chrome'
  ]);
  grunt.registerTask('protractor-firefox', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'protractor:firefox'
  ]);
  grunt.registerTask('protractor-all', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'concurrent:protractorTest']);

  grunt.registerTask('default', [
    'newer:jshint',
    'newer:jscs',
    'test',
    'build'
  ]);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {

  // deploy path is a symlink to my local wp instance
  // themes folder > bones
  var dirs = {
        deploy: 'output'
    };

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    dirs: dirs,

    less: {
      development: {
        options: {
          paths: ["library/less"]
        },
        files: {
          "library/css/style.full.css": "library/less/style.less"
        }
      }
    },

    cssmin: {
      style: {
        files: [{
          "library/css/style.css": "library/css/style.full.css"
        }]
      }
    },

    copy: {
      css: {
        files: [{
          expand: true,
          cwd: 'library/css/',
          src: '**',
          dest: '<%=dirs.deploy%>/library/css/'
        }]
      }
    },

    watch: {
      files: ['library/less/*.less'],
      tasks: ['less', 'cssmin', 'copy']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('default', ['less']);

};

<commit_msg>better cssmin<commit_after>module.exports = function(grunt) {

  // deploy path is a symlink to my local wp instance
  // themes folder > bones
  var dirs = {
        deploy: 'output'
    };

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    dirs: dirs,

    less: {
      // use this without cssmin in development
      // and you'll be able to make more sense of the CSS
      style: {
        options: {
          paths: ["library/less"]
        },
        files: {
          "library/css/style.css": "library/less/style.less"
        }
      }
    },

    cssmin: {
      style: {
        files: [{
          "library/css/style.css": "library/css/style.css"
        }]
      }
    },

    copy: {
      css: {
        files: [{
          expand: true,
          cwd: 'library/css/',
          src: '**',
          dest: '<%=dirs.deploy%>/library/css/'
        }]
      }
    },

    watch: {
      files: ['library/less/*.less'],
      tasks: ['less', 'copy']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('default', ['less', 'cssmin']);

};

<|endoftext|>


<commit_before>module.exports = function (grunt) {
    require('load-grunt-tasks')(grunt);

    var jsFiles = ['src/app/**/*.js'];
    var otherWatchFiles = ['src/app/**/*.css', 'src/index.html'];
    var eslintFiles = jsFiles.concat([jsFiles, 'package.json', 'Gruntfile.js', 'profiles/*.js']);
    var deployFiles = [
        '**',
        '!**/*.uncompressed.js',
        '!**/*consoleStripped.js',
        '!**/bootstrap/less/**',
        '!**/bootstrap/test-infra/**',
        '!**/tests/**',
        '!build-report.txt',
        '!components-jasmine/**',
        '!favico.js/**',
        '!jasmine-favicon-reporter/**',
        '!jasmine-jsreporter/**',
        '!stubmodule/**',
        '!util/**'
    ];
    var bumpFiles = [
        'package.json',
        'bower.json',
        'src/app/package.json',
        'src/app/App.js'
    ];
    var deployDir = 'wwwroot/wvc/mobile';
    var secrets;
    try {
        secrets = grunt.file.readJSON('secrets.json');
    } catch (e) {
        // swallow for build server
        secrets = {
            stageHost: '',
            prodHost: '',
            username: '',
            password: ''
        };
    }

    grunt.initConfig({
        bump: {
            options: {
                files: bumpFiles,
                commitFiles: bumpFiles.concat('src/index.html'),
                push: false
            }
        },
        clean: {
            build: ['dist'],
            deploy: ['deploy']
        },
        connect: {
            uses_defaults: {}
        },
        compress: {
            main: {
                options: {
                    archive: 'deploy/deploy.zip'
                },
                files: [{
                    src: deployFiles,
                    cwd: 'dist/',
                    expand: true
                }]
            }
        },
        dojo: {
            prod: {
                options: {
                    profiles: ['profiles/prod.build.profile.js', 'profiles/build.profile.js'] // Profile for build
                }
            },
            stage: {
                options: {
                    profiles: ['profiles/stage.build.profile.js', 'profiles/build.profile.js'] // Profile for build
                }
            },
            options: {
                dojo: 'src/dojo/dojo.js', // Path to dojo.js file in dojo source
                load: 'build', // Optional: Utility to bootstrap (Default: 'build')
                releaseDir: '../dist',
                requires: ['src/app/packages.js', 'src/app/run.js'], // Optional: Module to require for the build (Default: nothing)
                basePath: './src'
            }
        },
        imagemin: {
            main: {
                options: {
                    optimizationLevel: 3
                },
                files: [{
                    expand: true,
                    cwd: 'src/',
                    // exclude tests because some images in dojox throw errors
                    src: ['**/*.{png,jpg,gif}', '!**/tests/**/*.*'],
                    dest: 'src/'
                }]
            }
        },
        eslint: {
            options: {
                configFile: '.eslintrc'
            },
            main: {
                src: jsFiles
            }
        },
        pkg: grunt.file.readJSON('package.json'),
        processhtml: {
            options: {},
            main: {
                files: {'dist/index.html': ['src/index.html']}
            }
        },
        replace: {
            main: {
                options: {
                    patterns: [{
                        match: 'version',
                        replacement: function () {
                            return new Date().getTime();
                        }
                    }]
                },
                files: {'dist/serviceworker.js': ['src/serviceworker.js']}
            }
        },
        secrets: secrets,
        sftp: {
            stage: {
                files: {
                    './': 'deploy/deploy.zip'
                },
                options: {
                    host: '<%= secrets.stageHost %>'
                }
            },
            prod: {
                files: {
                    './': 'deploy/deploy.zip'
                },
                options: {
                    host: '<%= secrets.prodHost %>'
                }
            },
            options: {
                path: './' + deployDir + '/',
                srcBasePath: 'deploy/',
                username: '<%= secrets.username %>',
                password: '<%= secrets.password %>',
                showProgress: true
            }
        },
        sshexec: {
            options: {
                username: '<%= secrets.username %>',
                password: '<%= secrets.password %>'
            },
            stage: {
                command: ['cd ' + deployDir, 'unzip -oq deploy.zip', 'rm deploy.zip'].join(';'),
                options: {
                    host: '<%= secrets.stageHost %>'
                }
            },
            prod: {
                command: ['cd ' + deployDir, 'unzip -oq deploy.zip', 'rm deploy.zip'].join(';'),
                options: {
                    host: '<%= secrets.prodHost %>'
                }
            }
        },
        watch: {
            eslint: {
                files: eslintFiles,
                tasks: ['newer:eslint:main']
            },
            src: {
                files: eslintFiles.concat(otherWatchFiles),
                options: {
                    livereload: true
                }
            }
        }
    });

    grunt.registerTask('default', ['eslint', 'connect', 'watch']);

    grunt.registerTask('build-prod', [
        'clean:build',
        'newer:imagemin:main',
        'dojo:prod',
        'processhtml:main',
        'replace:main'
    ]);
    grunt.registerTask('build-stage', [
        'clean:build',
        'newer:imagemin:main',
        'dojo:stage',
        'processhtml:main',
        'replace:main'
    ]);
    grunt.registerTask('deploy-prod', [
        'clean:deploy',
        'compress:main',
        'sftp:prod',
        'sshexec:prod'
    ]);
    grunt.registerTask('deploy-stage', [
        'clean:deploy',
        'compress:main',
        'sftp:stage',
        'sshexec:stage'
    ]);
    grunt.registerTask('travis', [
        'eslint',
        'build-prod'
    ]);
}
<commit_msg>chore: use shell instead of replace to generate service worker<commit_after>module.exports = function (grunt) {
    require('load-grunt-tasks')(grunt);

    var jsFiles = ['src/app/**/*.js'];
    var otherWatchFiles = ['src/app/**/*.css', 'src/index.html'];
    var eslintFiles = jsFiles.concat([jsFiles, 'package.json', 'Gruntfile.js', 'profiles/*.js']);
    var deployFiles = [
        '**',
        '!**/*.uncompressed.js',
        '!**/*consoleStripped.js',
        '!**/bootstrap/less/**',
        '!**/bootstrap/test-infra/**',
        '!**/tests/**',
        '!build-report.txt',
        '!components-jasmine/**',
        '!favico.js/**',
        '!jasmine-favicon-reporter/**',
        '!jasmine-jsreporter/**',
        '!stubmodule/**',
        '!util/**'
    ];
    var bumpFiles = [
        'package.json',
        'bower.json',
        'src/app/package.json',
        'src/app/App.js'
    ];
    var deployDir = 'wwwroot/wvc/mobile';
    var secrets;
    try {
        secrets = grunt.file.readJSON('secrets.json');
    } catch (e) {
        // swallow for build server
        secrets = {
            stageHost: '',
            prodHost: '',
            username: '',
            password: ''
        };
    }

    grunt.initConfig({
        bump: {
            options: {
                files: bumpFiles,
                commitFiles: bumpFiles.concat('src/index.html'),
                push: false
            }
        },
        clean: {
            build: ['dist'],
            deploy: ['deploy']
        },
        connect: {
            uses_defaults: {}
        },
        compress: {
            main: {
                options: {
                    archive: 'deploy/deploy.zip'
                },
                files: [{
                    src: deployFiles,
                    cwd: 'dist/',
                    expand: true
                }]
            }
        },
        dojo: {
            prod: {
                options: {
                    profiles: ['profiles/prod.build.profile.js', 'profiles/build.profile.js'] // Profile for build
                }
            },
            stage: {
                options: {
                    profiles: ['profiles/stage.build.profile.js', 'profiles/build.profile.js'] // Profile for build
                }
            },
            options: {
                dojo: 'src/dojo/dojo.js', // Path to dojo.js file in dojo source
                load: 'build', // Optional: Utility to bootstrap (Default: 'build')
                releaseDir: '../dist',
                requires: ['src/app/packages.js', 'src/app/run.js'], // Optional: Module to require for the build (Default: nothing)
                basePath: './src'
            }
        },
        imagemin: {
            main: {
                options: {
                    optimizationLevel: 3
                },
                files: [{
                    expand: true,
                    cwd: 'src/',
                    // exclude tests because some images in dojox throw errors
                    src: ['**/*.{png,jpg,gif}', '!**/tests/**/*.*'],
                    dest: 'src/'
                }]
            }
        },
        eslint: {
            options: {
                configFile: '.eslintrc'
            },
            main: {
                src: jsFiles
            }
        },
        pkg: grunt.file.readJSON('package.json'),
        processhtml: {
            options: {},
            main: {
                files: {'dist/index.html': ['src/index.html']}
            }
        },
        secrets: secrets,
        shell: {
            main: {
                command: 'npm run workbox'
            }
        },
        sftp: {
            stage: {
                files: {
                    './': 'deploy/deploy.zip'
                },
                options: {
                    host: '<%= secrets.stageHost %>'
                }
            },
            prod: {
                files: {
                    './': 'deploy/deploy.zip'
                },
                options: {
                    host: '<%= secrets.prodHost %>'
                }
            },
            options: {
                path: './' + deployDir + '/',
                srcBasePath: 'deploy/',
                username: '<%= secrets.username %>',
                password: '<%= secrets.password %>',
                showProgress: true
            }
        },
        sshexec: {
            options: {
                username: '<%= secrets.username %>',
                password: '<%= secrets.password %>'
            },
            stage: {
                command: ['cd ' + deployDir, 'unzip -oq deploy.zip', 'rm deploy.zip'].join(';'),
                options: {
                    host: '<%= secrets.stageHost %>'
                }
            },
            prod: {
                command: ['cd ' + deployDir, 'unzip -oq deploy.zip', 'rm deploy.zip'].join(';'),
                options: {
                    host: '<%= secrets.prodHost %>'
                }
            }
        },
        watch: {
            eslint: {
                files: eslintFiles,
                tasks: ['newer:eslint:main']
            },
            src: {
                files: eslintFiles.concat(otherWatchFiles),
                options: {
                    livereload: true
                }
            }
        }
    });

    grunt.registerTask('default', ['eslint', 'connect', 'watch']);

    grunt.registerTask('build-prod', [
        'clean:build',
        'newer:imagemin:main',
        'dojo:prod',
        'processhtml:main',
        'shell:main'
    ]);
    grunt.registerTask('build-stage', [
        'clean:build',
        'newer:imagemin:main',
        'dojo:stage',
        'processhtml:main',
        'shell:main'
    ]);
    grunt.registerTask('deploy-prod', [
        'clean:deploy',
        'compress:main',
        'sftp:prod',
        'sshexec:prod'
    ]);
    grunt.registerTask('deploy-stage', [
        'clean:deploy',
        'compress:main',
        'sftp:stage',
        'sshexec:stage'
    ]);
    grunt.registerTask('travis', [
        'eslint',
        'build-prod'
    ]);
}
<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {

	"use strict";

	// The concatenated file won't pass onevar but our modules can
	var readOptionalJSON = function( filepath ) {
			var data = {};
			try {
				data = grunt.file.readJSON( filepath );
			} catch(e) {}
			return data;
		},
		srcHintOptions = readOptionalJSON("src/.jshintrc");
	delete srcHintOptions.onevar;

	// Project configuration.
	grunt.initConfig({
		pkg: grunt.file.readJSON("package.json"),
		files: [
			"src/intro.js",
			"src/migrate.js",
			"src/attributes.js",
			"src/core.js",
			"src/ajax.js",
			"src/data.js",
			"src/manipulation.js",
			"src/event.js",
			"src/outro.js"
		],
		tests: [
			"dev+git",
			"dev+git2",
			"min+git",
			"min+git2",
			"dev+2.0.3",
			"dev+1.10.2",
			"dev+1.9.1",
			"dev+1.8.3",
			"dev+1.7.2",
			"dev+1.6.4"
		],
		banners: {
			tiny: "/*! <%= pkg.name %> <%= pkg.version %> - <%= pkg.homepage %> */"
		},
		concat: {
			options: {
				banner: "/*!\n * <%= pkg.title || pkg.name %> - v<%= pkg.version %> - " +
					"<%= grunt.template.today('yyyy-mm-dd') %>\n" +
					" * <%= pkg.homepage %>\n" +
					" * Copyright 2005, <%= grunt.template.today('yyyy') %> <%= pkg.author.name %>;" +
					" Licensed <%= _.pluck(pkg.licenses, 'type').join(', ') %>\n */\n"
			},
			dist: {
				src: "<%= files %>",
				dest: "dist/<%= pkg.name %>.js"
			}
		},
		qunit: {
			files: [ "test/**/*.html" ]
		},
		jshint: {
			dist: {
				src: [ "dist/jquery-migrate.js" ],
				options: srcHintOptions
			},
			tests: {
				src: [ "test/*.js" ],
				options: {
					jshintrc: "test/.jshintrc"
				}
			},
			grunt: {
				src: [ "Gruntfile.js" ],
				options: {
					jshintrc: ".jshintrc"
				}
			}
		},
		uglify: {
			all: {
				files: {
					"dist/jquery-migrate.min.js": [ "src/migratemute.js", "dist/jquery-migrate.js" ]
				}
			},
			options: {
				banner: "/*! jQuery Migrate v<%= pkg.version %> | (c) 2005, <%= grunt.template.today('yyyy') %> <%= pkg.author.name %> | jquery.org/license */\n",
				beautify: {
					ascii_only: true
				}
			}

		}
	});

	// Load grunt tasks from NPM packages
	grunt.loadNpmTasks("grunt-git-authors");
	grunt.loadNpmTasks("grunt-contrib-concat");
	grunt.loadNpmTasks("grunt-contrib-watch");
	grunt.loadNpmTasks("grunt-contrib-jshint");
	grunt.loadNpmTasks("grunt-contrib-uglify");
	grunt.loadNpmTasks("grunt-contrib-qunit");

	// Default task.
	grunt.registerTask( "default", [ "concat", "uglify", "jshint", "qunit" ] );

	// Skip unit tests, used by testswarm
	grunt.registerTask( "buildnounit", [ "concat", "uglify", "jshint" ] );

	// Testswarm
	grunt.registerTask( "testswarm", function( commit, configFile ) {
		var jobName,
			testswarm = require( "testswarm" ),
			runs = {},
			done = this.async(),
			pull = /PR-(\d+)/.exec( commit ),
			config = grunt.file.readJSON( configFile ).jquerymigrate,
			tests = grunt.config("tests");

		if ( pull ) {
			jobName = "Pull #" + pull[ 1 ] + "";
		} else {
			jobName = "Commit " + commit.substr( 0, 10 ) + "";
		}

		tests.forEach(function( test ) {
			var plugin_jquery = test.split("+");
			runs[test] = config.testUrl + commit + "/test/index.html?plugin=" +
				plugin_jquery[0] + "&jquery=" + plugin_jquery[1];
		});

		// TODO: create separate job for git/git2 so we can do different browsersets
		testswarm.createClient( {
			url: config.swarmUrl,
			pollInterval: 10000,
			timeout: 1000 * 60 * 30
		} )
		.addReporter( testswarm.reporters.cli )
		.auth( {
			id: config.authUsername,
			token: config.authToken
		})
		.addjob(
			{
				name: jobName,
				runs: runs,
				runMax: config.runMax,
				browserSets: "popular-no-old-ie"
			}, function( err, passed ) {
				if ( err ) {
					grunt.log.error( err );
				}
				done( passed );
			}
		);
	});

	// Update manifest for jQuery plugin registry
	grunt.registerTask( "manifest", function() {
		var pkg = grunt.config( "pkg" );
		grunt.file.write( "migrate.jquery.json", JSON.stringify({
			name: "migrate",
			title: pkg.title,
			description: pkg.description,
			keywords: pkg.keywords,
			version: pkg.version,
			author: {
				name: pkg.author.name,
				url: pkg.author.url.replace( "master", pkg.version )
			},
			maintainers: pkg.maintainers,
			licenses: pkg.licenses.map(function( license ) {
				license.url = license.url.replace( "master", pkg.version );
				return license;
			}),
			bugs: pkg.bugs,
			homepage: pkg.homepage,
			docs: pkg.homepage,
			download: "https://github.com/jquery/jquery-migrate/blob/" + pkg.version + "/README.md#download",
			dependencies: {
				jquery: ">=1.6.4"
			}
		}, null, "\t" ) );
	});
};
<commit_msg>Build: Fix testswarm task, use API correctly<commit_after>/*global module:false*/
module.exports = function(grunt) {

	"use strict";

	// The concatenated file won't pass onevar but our modules can
	var readOptionalJSON = function( filepath ) {
			var data = {};
			try {
				data = grunt.file.readJSON( filepath );
			} catch(e) {}
			return data;
		},
		srcHintOptions = readOptionalJSON("src/.jshintrc");
	delete srcHintOptions.onevar;

	// Project configuration.
	grunt.initConfig({
		pkg: grunt.file.readJSON("package.json"),
		files: [
			"src/intro.js",
			"src/migrate.js",
			"src/attributes.js",
			"src/core.js",
			"src/ajax.js",
			"src/data.js",
			"src/manipulation.js",
			"src/event.js",
			"src/outro.js"
		],
		tests: [
			"dev+git",
			"dev+git2",
			"min+git",
			"min+git2",
			"dev+2.0.3",
			"dev+1.10.2",
			"dev+1.9.1",
			"dev+1.8.3",
			"dev+1.7.2",
			"dev+1.6.4"
		],
		banners: {
			tiny: "/*! <%= pkg.name %> <%= pkg.version %> - <%= pkg.homepage %> */"
		},
		concat: {
			options: {
				banner: "/*!\n * <%= pkg.title || pkg.name %> - v<%= pkg.version %> - " +
					"<%= grunt.template.today('yyyy-mm-dd') %>\n" +
					" * <%= pkg.homepage %>\n" +
					" * Copyright 2005, <%= grunt.template.today('yyyy') %> <%= pkg.author.name %>;" +
					" Licensed <%= _.pluck(pkg.licenses, 'type').join(', ') %>\n */\n"
			},
			dist: {
				src: "<%= files %>",
				dest: "dist/<%= pkg.name %>.js"
			}
		},
		qunit: {
			files: [ "test/**/*.html" ]
		},
		jshint: {
			dist: {
				src: [ "dist/jquery-migrate.js" ],
				options: srcHintOptions
			},
			tests: {
				src: [ "test/*.js" ],
				options: {
					jshintrc: "test/.jshintrc"
				}
			},
			grunt: {
				src: [ "Gruntfile.js" ],
				options: {
					jshintrc: ".jshintrc"
				}
			}
		},
		uglify: {
			all: {
				files: {
					"dist/jquery-migrate.min.js": [ "src/migratemute.js", "dist/jquery-migrate.js" ]
				}
			},
			options: {
				banner: "/*! jQuery Migrate v<%= pkg.version %> | (c) 2005, <%= grunt.template.today('yyyy') %> <%= pkg.author.name %> | jquery.org/license */\n",
				beautify: {
					ascii_only: true
				}
			}

		}
	});

	// Load grunt tasks from NPM packages
	grunt.loadNpmTasks("grunt-git-authors");
	grunt.loadNpmTasks("grunt-contrib-concat");
	grunt.loadNpmTasks("grunt-contrib-watch");
	grunt.loadNpmTasks("grunt-contrib-jshint");
	grunt.loadNpmTasks("grunt-contrib-uglify");
	grunt.loadNpmTasks("grunt-contrib-qunit");

	// Default task.
	grunt.registerTask( "default", [ "concat", "uglify", "jshint", "qunit" ] );

	// Skip unit tests, used by testswarm
	grunt.registerTask( "buildnounit", [ "concat", "uglify", "jshint" ] );

	// Testswarm
	grunt.registerTask( "testswarm", function( commit, configFile ) {
		var jobName,
			testswarm = require( "testswarm" ),
			runs = {},
			done = this.async(),
			pull = /PR-(\d+)/.exec( commit ),
			config = grunt.file.readJSON( configFile ).jquerymigrate,
			tests = grunt.config("tests");

		if ( pull ) {
			jobName = "Pull #" + pull[ 1 ] + "";
		} else {
			jobName = "Commit " + commit.substr( 0, 10 ) + "";
		}

		tests.forEach(function( test ) {
			var plugin_jquery = test.split("+");
			runs[test] = config.testUrl + commit + "/test/index.html?plugin=" +
				plugin_jquery[0] + "&jquery=" + plugin_jquery[1];
		});

		// TODO: create separate job for git/git2 so we can do different browsersets
		testswarm.createClient( {
			url: config.swarmUrl
		} )
		.addReporter( testswarm.reporters.cli )
		.auth( {
			id: config.authUsername,
			token: config.authToken
		})
		.addjob(
			{
				name: jobName,
				runs: runs,
				runMax: config.runMax,
				browserSets: "popular-no-old-ie",
				timeout: 1000 * 60 * 30
			}, function( err, passed ) {
				if ( err ) {
					grunt.log.error( err );
				}
				done( passed );
			}
		);
	});

	// Update manifest for jQuery plugin registry
	grunt.registerTask( "manifest", function() {
		var pkg = grunt.config( "pkg" );
		grunt.file.write( "migrate.jquery.json", JSON.stringify({
			name: "migrate",
			title: pkg.title,
			description: pkg.description,
			keywords: pkg.keywords,
			version: pkg.version,
			author: {
				name: pkg.author.name,
				url: pkg.author.url.replace( "master", pkg.version )
			},
			maintainers: pkg.maintainers,
			licenses: pkg.licenses.map(function( license ) {
				license.url = license.url.replace( "master", pkg.version );
				return license;
			}),
			bugs: pkg.bugs,
			homepage: pkg.homepage,
			docs: pkg.homepage,
			download: "https://github.com/jquery/jquery-migrate/blob/" + pkg.version + "/README.md#download",
			dependencies: {
				jquery: ">=1.6.4"
			}
		}, null, "\t" ) );
	});
};
<|endoftext|>


<commit_before>'use strict';

module.exports = function (grunt) {

    require('time-grunt')(grunt);
    require('load-grunt-tasks')(grunt);

    grunt.initConfig({

        pkg: grunt.file.readJSON('package.json'),

        jshint: {
            all: [
                'Gruntfile.js',
                'src/**/*.js',
                'node_modules/app/**/*.js',
                'test/**/*.js'
            ],
            options: {
                jshintrc: '.jshintrc'
            }
        },

        mochaTest: {
            all: {
                options: {reporter: 'spec'},
                src: ['test/test.js']
            }
        }

    });

    grunt.registerTask('test', ['jshint', 'mochaTest']);
    grunt.registerTask('default', ['test']);
};
<commit_msg>Solve unexpected require<commit_after>'use strict';

var time = require('time-grunt');
var load = require('load-grunt-tasks');

module.exports = function (grunt) {

    time(grunt);
    load(grunt);

    grunt.initConfig({

        pkg: grunt.file.readJSON('package.json'),

        jshint: {
            all: [
                'Gruntfile.js',
                'src/**/*.js',
                'node_modules/app/**/*.js',
                'test/**/*.js'
            ],
            options: {
                jshintrc: '.jshintrc'
            }
        },

        mochaTest: {
            all: {
                options: {reporter: 'spec'},
                src: ['test/test.js']
            }
        }

    });

    grunt.registerTask('test', ['jshint', 'mochaTest']);
    grunt.registerTask('default', ['test']);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {

    require('load-grunt-tasks')(grunt);
    //grunt.loadNpmTasks('grunt-contrib-requirejs');
    grunt.loadNpmTasks('grunt-angular-templates');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-ng-annotate');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-run');

    //grunt.registerTask('build', ['requirejs', 'ngtemplates', 'concat:dist']);
    grunt.registerTask('build', [
      'clean:jsbuild', 'run',
      'ngAnnotate:clientApp', //'uglify:clientApp',
      'ngAnnotate:adminApp', //'uglify:adminApp'
    ]);

    grunt.registerTask('production', ['build']);

    var commonLibs = ['module/main-app'];

    grunt.initConfig({
        bower: {
            requirejs: {
                rjsConfig: 'public/config.js',
                options: {
                    baseUrl: './public'
                }
            }
        },
        karma: {
            unit: {
                configFile: 'test/karma.conf.js'
            }
        },
        run: {
          options: {
            // Task-specific options go here.
          },
          requirebuilder: {
            cmd: './requirebuilder.js'
          }
        },
        ngtemplates: {
          MyApp:        {
            cwd:      'public',
            src:      ['template/**.html', 'template/**/*.html'],
            dest:     'public/build/js/template.js',
            options:  {
              prefix:   '/'
            }
          }
        },
        concat: {
          dist: {
            src: ['public/build/js/*.js'],
            dest: 'public/build/all.js',
            sourceMap: true
          }
        },
        ngAnnotate: {
          options: {
            singleQuotes: true
          },
          clientApp: {
            files: {
              'public/build/js/client-app.js': ['public/build/js/client-app.js']
            }
          },
          adminApp: {
            files: {
              'public/build/js/admin-app.js': ['public/build/js/admin-app.js']
            }
          }
        },
        clean: {
          jsbuild: {
            src: ["public/build/js/*", 'public/file_thumbnail/*']
          }
        },
        uglify: {
          clientApp: {
            files: {
              'public/build/js/client-app.js': ['public/build/js/client-app.js']
            }
          },
          adminApp: {
            files: {
              'public/build/js/admin-app.js': ['public/build/js/admin-app.js']
            }
          }
        }
    });

};
<commit_msg>gruntfile uglify<commit_after>module.exports = function(grunt) {

    require('load-grunt-tasks')(grunt);
    //grunt.loadNpmTasks('grunt-contrib-requirejs');
    grunt.loadNpmTasks('grunt-angular-templates');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-ng-annotate');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-run');

    //grunt.registerTask('build', ['requirejs', 'ngtemplates', 'concat:dist']);
    grunt.registerTask('build', [
      'clean:jsbuild', 'run',
      'ngAnnotate:clientApp', 'uglify:clientApp',
      'ngAnnotate:adminApp', 'uglify:adminApp'
    ]);

    grunt.registerTask('production', ['build']);

    var commonLibs = ['module/main-app'];

    grunt.initConfig({
        bower: {
            requirejs: {
                rjsConfig: 'public/config.js',
                options: {
                    baseUrl: './public'
                }
            }
        },
        karma: {
            unit: {
                configFile: 'test/karma.conf.js'
            }
        },
        run: {
          options: {
            // Task-specific options go here.
          },
          requirebuilder: {
            cmd: './requirebuilder.js'
          }
        },
        ngtemplates: {
          MyApp:        {
            cwd:      'public',
            src:      ['template/**.html', 'template/**/*.html'],
            dest:     'public/build/js/template.js',
            options:  {
              prefix:   '/'
            }
          }
        },
        concat: {
          dist: {
            src: ['public/build/js/*.js'],
            dest: 'public/build/all.js',
            sourceMap: true
          }
        },
        ngAnnotate: {
          options: {
            singleQuotes: true
          },
          clientApp: {
            files: {
              'public/build/js/client-app.js': ['public/build/js/client-app.js']
            }
          },
          adminApp: {
            files: {
              'public/build/js/admin-app.js': ['public/build/js/admin-app.js']
            }
          }
        },
        clean: {
          jsbuild: {
            src: ["public/build/js/*", 'public/file_thumbnail/*']
          }
        },
        uglify: {
          clientApp: {
            files: {
              'public/build/js/client-app.js': ['public/build/js/client-app.js']
            }
          },
          adminApp: {
            files: {
              'public/build/js/admin-app.js': ['public/build/js/admin-app.js']
            }
          }
        }
    });

};
<|endoftext|>