UNPKG

2.48 kBJavaScriptView Raw
1'use strict';
2const {promisify} = require('util');
3const fs = require('fs');
4const path = require('path');
5const replaceExt = require('replace-ext');
6const PluginError = require('plugin-error');
7const through = require('through2');
8
9const readFile = promisify(fs.readFile);
10const stat = promisify(fs.stat);
11
12// Ignore missing file error
13function fsOperationFailed(stream, sourceFile, error) {
14 if (error.code !== 'ENOENT') {
15 stream.emit('error', new PluginError('gulp-changed', error, {
16 fileName: sourceFile.path
17 }));
18 }
19
20 stream.push(sourceFile);
21}
22
23// Only push through files changed more recently than the destination files
24async function compareLastModifiedTime(stream, sourceFile, targetPath) {
25 // TODO: Use the `stat` `bigint` option when targeting Node.js 10 and Gulp supports it
26 const targetStat = await stat(targetPath);
27
28 if (sourceFile.stat && Math.floor(sourceFile.stat.mtimeMs) > Math.floor(targetStat.mtimeMs)) {
29 stream.push(sourceFile);
30 }
31}
32
33// Only push through files with different contents than the destination files
34async function compareContents(stream, sourceFile, targetPath) {
35 const targetData = await readFile(targetPath);
36
37 if (sourceFile.isNull() || !sourceFile.contents.equals(targetData)) {
38 stream.push(sourceFile);
39 }
40}
41
42module.exports = (destination, options) => {
43 options = {
44 cwd: process.cwd(),
45 hasChanged: compareLastModifiedTime,
46 ...options
47 };
48
49 if (!destination) {
50 throw new PluginError('gulp-changed', '`dest` required');
51 }
52
53 if (options.transformPath !== undefined && typeof options.transformPath !== 'function') {
54 throw new PluginError('gulp-changed', '`options.transformPath` needs to be a function');
55 }
56
57 return through.obj(function (file, encoding, callback) {
58 const dest2 = typeof destination === 'function' ? destination(file) : destination;
59 let newPath = path.resolve(options.cwd, dest2, file.relative);
60
61 if (options.extension) {
62 newPath = replaceExt(newPath, options.extension);
63 }
64
65 if (options.transformPath) {
66 newPath = options.transformPath(newPath);
67
68 if (typeof newPath !== 'string') {
69 throw new PluginError('gulp-changed', '`options.transformPath` needs to return a string');
70 }
71 }
72
73 (async () => {
74 try {
75 await options.hasChanged(this, file, newPath);
76 } catch (error) {
77 fsOperationFailed(this, file, error);
78 }
79
80 callback();
81 })();
82 });
83};
84
85module.exports.compareLastModifiedTime = compareLastModifiedTime;
86module.exports.compareContents = compareContents;
87