123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- 'use strict'
- const util = require('util')
- const fs = require('graceful-fs')
- // bind need only for mock unit tests
- const readFile = util.promisify(fs.readFile.bind(fs))
- const tryToRead = function (path, log) {
- const maxRetries = 3
- let promise = readFile(path)
- for (let retryCount = 1; retryCount <= maxRetries; retryCount++) {
- promise = promise.catch((err) => {
- log.warn(err)
- log.warn('retrying ' + retryCount)
- return readFile(path)
- })
- }
- return promise.catch((err) => {
- log.warn(err)
- return Promise.reject(err)
- })
- }
- const mm = require('minimatch')
- const { isBinaryFile } = require('isbinaryfile')
- const _ = require('lodash')
- const CryptoUtils = require('./utils/crypto-utils')
- const log = require('./logger').create('preprocess')
- function executeProcessor (process, file, content) {
- let done = null
- const donePromise = new Promise((resolve, reject) => {
- done = function (error, content) {
- // normalize B-C
- if (arguments.length === 1 && typeof error === 'string') {
- content = error
- error = null
- }
- if (error) {
- reject(error)
- } else {
- resolve(content)
- }
- }
- })
- return (process(content, file, done) || Promise.resolve()).then((content) => {
- if (content) {
- // async process correctly returned content
- return content
- }
- // process called done() (Either old sync api or an async function that did not return content)
- return donePromise
- })
- }
- async function runProcessors (preprocessors, file, content) {
- try {
- for (const process of preprocessors) {
- content = await executeProcessor(process, file, content)
- }
- } catch (error) {
- file.contentPath = null
- file.content = null
- throw error
- }
- file.contentPath = null
- file.content = content
- file.sha = CryptoUtils.sha1(content)
- }
- function createPriorityPreprocessor (config = {}, preprocessorPriority, basePath, instantiatePlugin) {
- _.union.apply(_, Object.values(config)).forEach((name) => instantiatePlugin('preprocessor', name))
- return async function preprocess (file) {
- const buffer = await tryToRead(file.originalPath, log)
- let isBinary = file.isBinary
- if (isBinary == null) {
- // Pattern did not specify, probe for it.
- isBinary = await isBinaryFile(buffer, buffer.length)
- }
- const preprocessorNames = Object.keys(config).reduce((ppNames, pattern) => {
- if (mm(file.originalPath, pattern, { dot: true })) {
- ppNames = _.union(ppNames, config[pattern])
- }
- return ppNames
- }, [])
- // Apply preprocessor priority.
- const preprocessors = preprocessorNames
- .map((name) => [name, preprocessorPriority[name] || 0])
- .sort((a, b) => b[1] - a[1])
- .map((duo) => duo[0])
- .reduce((preProcs, name) => {
- const p = instantiatePlugin('preprocessor', name)
- if (!isBinary || (p && p.handleBinaryFiles)) {
- preProcs.push(p)
- } else {
- log.warn(`Ignored preprocessing ${file.originalPath} because ${name} has handleBinaryFiles=false.`)
- }
- return preProcs
- }, [])
- await runProcessors(preprocessors, file, isBinary ? buffer : buffer.toString())
- }
- }
- createPriorityPreprocessor.$inject = ['config.preprocessors', 'config.preprocessor_priority', 'config.basePath', 'instantiatePlugin']
- exports.createPriorityPreprocessor = createPriorityPreprocessor
|