<commit_before>/*
 * grunt-audit
 * https://github.com/azakus/grunt-audit
 *
 * Copyright (c) 2013 <NAME>
 * Licensed under the BSD license.
 */

'use strict';

module.exports = function(grunt) {
  var crypto = require('crypto');
  var path = require('path');

  grunt.registerMultiTask('audit', 'Generate audit trail with sha1 hashes', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      separator: grunt.util.linefeed,
      repos: []
    });

    function fileHash(filepath) {
      var blob = grunt.file.read(filepath);
      var sha1sum = crypto.createHash('sha1');
      sha1sum.update(blob);
      var hex = sha1sum.digest('hex');
      return filepath + ': ' + hex;
    }

    function findRev(repoPath, callback) {
      grunt.util.spawn({
        cmd: 'git',
        args: ['--git-dir', path.resolve(repoPath, '.git'), 'rev-parse', 'HEAD']
      }, function(error, result, code) {
        if (error) {
          callback(error);
        } else {
          callback(null, path.basename(path.resolve(repoPath)) + ': ' + result);
        }
      });
    }

    function repoRevs(repos, callback) {
      repos = repos || [];
      grunt.util.async.map(repos, findRev, function(err, results) {
        if (err) {
          callback(err);
        } else {
          callback(null, results);
        }
      });
    }

    function moduleVersions(callback) {
      grunt.util.spawn({
        cmd: 'npm',
        args: ['list', '--depth=0']
      }, function(error, result, code) {
        var tree = result.stdout;
        var treeArray = tree.split(options.separator);
        treeArray.shift();
        treeArray = treeArray.map(function(s){ return s.replace('@',': ').slice(4); });
        tree = treeArray.join(options.separator);
        callback(null, tree);
      });
    }

    function out(revs, hashes, modules, dest) {
      // build audit log
      var log = [
        'BUILD LOG',
        '---------',
        'Build Time: ' + grunt.template.today('isoDateTime'),
        '',
        'NODEJS INFORMATION',
        '==================',
        'nodejs: ' + process.version,
        modules,
        '',
        'REPO REVISIONS',
        '==============',
        revs.join(options.separator),
        '',
        'BUILD HASHES',
        '============',
        hashes
      ].join(options.separator);

      if (dest) {
        grunt.file.write(dest, log);
        grunt.log.writeln('Wrote audit log:', dest, 'successfully');
      } else {
        grunt.log.writeln(log);
      }
    }

    var done = this.async();
    // Iterate over all specified file groups.
    this.files.forEach(function(f) {
      // Concat specified files.
      var src = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files (if nonull was set).
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).map(fileHash).join(options.separator);
      grunt.util.async.parallel([
        function(callback) {
          repoRevs(options.repos, callback);
        },
        function(callback) {
          moduleVersions(callback)
        }
      ], function(err, results) {
        if (!err) {
          out(results[0], src, results[1], f.dest);
        }
        done(err);
      });
    });
  });
};<commit_msg>Collapse findRev into one line, clean up parallel async<commit_after>/*
 * grunt-audit
 * https://github.com/azakus/grunt-audit
 *
 * Copyright (c) 2013 <NAME>
 * Licensed under the BSD license.
 */

'use strict';

module.exports = function(grunt) {
  var crypto = require('crypto');
  var path = require('path');

  grunt.registerMultiTask('audit', 'Generate audit trail with sha1 hashes', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      separator: grunt.util.linefeed,
      repos: []
    });

    function fileHash(filepath) {
      var blob = grunt.file.read(filepath);
      var sha1sum = crypto.createHash('sha1');
      sha1sum.update(blob);
      var hex = sha1sum.digest('hex');
      return filepath + ': ' + hex;
    }

    function findRev(repoPath, callback) {
      grunt.util.spawn({
        cmd: 'git',
        args: ['--git-dir', path.resolve(repoPath, '.git'), 'rev-parse', 'HEAD']
      }, function(error, result, code) {
        if (error) {
          callback(error);
        } else {
          // assume repo directory name is repo "name"
          callback(null, path.basename(path.resolve(repoPath)) + ': ' + result);
        }
      });
    }

    function moduleVersions(callback) {
      grunt.util.spawn({
        cmd: 'npm',
        args: ['list', '--depth=0']
      }, function(error, result, code) {
        var tree = result.stdout;
        var treeArray = tree.split(options.separator);
        // only show dependencies, not top level
        treeArray.shift();
        // remove leading utf8 line chars, module@version -> module: version
        treeArray = treeArray.map(function(s){ return s.slice(4).replace('@',': '); });
        tree = treeArray.join(options.separator);
        callback(null, tree);
      });
    }

    function out(revs, modules, hashes, dest) {
      // build audit log
      var log = [
        'BUILD LOG',
        '---------',
        'Build Time: ' + grunt.template.today('isoDateTime'),
        '',
        'NODEJS INFORMATION',
        '==================',
        'nodejs: ' + process.version,
        modules,
        '',
        'REPO REVISIONS',
        '==============',
        revs.join(options.separator),
        '',
        'BUILD HASHES',
        '============',
        hashes
      ].join(options.separator);

      if (dest) {
        grunt.file.write(dest, log);
        grunt.log.writeln('Wrote audit log:', dest, 'successfully');
      } else {
        grunt.log.writeln(log);
      }
    }

    var done = this.async();
    // Iterate over all specified file groups.
    this.files.forEach(function(f) {
      // Concat specified files.
      var src = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files (if nonull was set).
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).map(fileHash).join(options.separator);

      grunt.util.async.parallel({
        repos: function(callback) {
          // find commit hash for each repo
          grunt.util.async.map(options.repos || [], findRev, callback);
        },
        versions: function(callback) {
          moduleVersions(callback)
        },
      }, function(err, results) {
        if (!err) {
          out(results.repos, results.versions, src, f.dest);
        }
        done(err);
      });
    });
  });
};
{'fraction_non_alphanumeric': 0.16305750752904058, 'fraction_numerical': 0.0035852574214828626, 'mean_word_length': 2.0334928229665072, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 6, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3547709', 'n_tokens_mistral': 2133, 'n_tokens_neox': 2075, 'n_words': 454}