|
1 |
| -'use strict'; |
2 |
| -const {promisify} = require('util'); |
3 |
| -const fs = require('fs'); |
4 |
| -const path = require('path'); |
5 |
| -const replaceExt = require('replace-ext'); |
6 |
| -const PluginError = require('plugin-error'); |
7 |
| -const through = require('through2'); |
8 |
| - |
9 |
| -const readFile = promisify(fs.readFile); |
10 |
| -const stat = promisify(fs.stat); |
11 |
| - |
12 |
| -// Ignore missing file error |
13 |
| -function 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 |
| -} |
| 1 | +import process from 'node:process'; |
| 2 | +import fs from 'node:fs/promises'; |
| 3 | +import path from 'node:path'; |
| 4 | +import changeFileExtension from 'change-file-extension'; |
| 5 | +import {gulpPlugin} from 'gulp-plugin-extras'; |
22 | 6 |
|
23 | 7 | // Only push through files changed more recently than the destination files
|
24 |
| -async 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); |
| 8 | +export async function compareLastModifiedTime(sourceFile, targetPath) { |
| 9 | + const targetStat = await fs.stat(targetPath, {bigint: true}); |
27 | 10 |
|
28 |
| - /* |
29 |
| - Precision is lost in the `mtime` when Gulp copies the file from source to target so we cannot compare the modified times directly. This has been the case since Gulp 4. Now, due to an issue in libuv affecting Node.js 14.17.0 and above (including 16.x: https://github.com/nodejs/node/issues/38981) when Gulp copies the file to the target, its `mtime` may be behind the source file by up to 1ms. For example, if the source file has a `mtime` like `1623259049896.314`, the target file `mtime` can end up as `1623259049895.999`. So to compare safely we use floor on the source and ceil on the target, which would give us `1623259049896` for both source and target in that example case. |
30 |
| - */ |
31 |
| - if (sourceFile.stat && Math.floor(sourceFile.stat.mtimeMs) > Math.ceil(targetStat.mtimeMs)) { |
32 |
| - stream.push(sourceFile); |
| 11 | + if (sourceFile.stat && sourceFile.stat.mtimeMs > targetStat.mtimeMs) { |
| 12 | + return sourceFile; |
33 | 13 | }
|
34 | 14 | }
|
35 | 15 |
|
36 | 16 | // Only push through files with different contents than the destination files
|
37 |
| -async function compareContents(stream, sourceFile, targetPath) { |
38 |
| - const targetData = await readFile(targetPath); |
| 17 | +export async function compareContents(sourceFile, targetPath) { |
| 18 | + const targetData = await fs.readFile(targetPath); |
39 | 19 |
|
40 |
| - if (sourceFile.isNull() || !sourceFile.contents.equals(targetData)) { |
41 |
| - stream.push(sourceFile); |
| 20 | + if (!sourceFile.contents.equals(targetData)) { |
| 21 | + return sourceFile; |
42 | 22 | }
|
43 | 23 | }
|
44 | 24 |
|
45 |
| -module.exports = (destination, options) => { |
| 25 | +export default function gulpChanged(destination, options) { |
46 | 26 | options = {
|
47 | 27 | cwd: process.cwd(),
|
48 | 28 | hasChanged: compareLastModifiedTime,
|
49 |
| - ...options |
| 29 | + ...options, |
50 | 30 | };
|
51 | 31 |
|
52 | 32 | if (!destination) {
|
53 |
| - throw new PluginError('gulp-changed', '`dest` required'); |
| 33 | + throw new Error('gulp-changed: `dest` required'); |
54 | 34 | }
|
55 | 35 |
|
56 | 36 | if (options.transformPath !== undefined && typeof options.transformPath !== 'function') {
|
57 |
| - throw new PluginError('gulp-changed', '`options.transformPath` needs to be a function'); |
| 37 | + throw new Error('gulp-changed: `options.transformPath` needs to be a function'); |
58 | 38 | }
|
59 | 39 |
|
60 |
| - return through.obj(function (file, encoding, callback) { |
61 |
| - const dest2 = typeof destination === 'function' ? destination(file) : destination; |
62 |
| - let newPath = path.resolve(options.cwd, dest2, file.relative); |
| 40 | + return gulpPlugin('gulp-changed', async file => { |
| 41 | + const destination2 = typeof destination === 'function' ? destination(file) : destination; |
| 42 | + let newPath = path.resolve(options.cwd, destination2, file.relative); |
63 | 43 |
|
64 | 44 | if (options.extension) {
|
65 |
| - newPath = replaceExt(newPath, options.extension); |
| 45 | + newPath = changeFileExtension(newPath, options.extension); |
66 | 46 | }
|
67 | 47 |
|
68 | 48 | if (options.transformPath) {
|
69 | 49 | newPath = options.transformPath(newPath);
|
70 | 50 |
|
71 | 51 | if (typeof newPath !== 'string') {
|
72 |
| - throw new PluginError('gulp-changed', '`options.transformPath` needs to return a string'); |
| 52 | + throw new TypeError('`options.transformPath` needs to return a string'); |
73 | 53 | }
|
74 | 54 | }
|
75 | 55 |
|
76 |
| - (async () => { |
77 |
| - try { |
78 |
| - await options.hasChanged(this, file, newPath); |
79 |
| - } catch (error) { |
80 |
| - fsOperationFailed(this, file, error); |
| 56 | + try { |
| 57 | + return await options.hasChanged(file, newPath); |
| 58 | + } catch (error) { |
| 59 | + if (error.code !== 'ENOENT') { |
| 60 | + throw error; |
81 | 61 | }
|
82 | 62 |
|
83 |
| - callback(); |
84 |
| - })(); |
| 63 | + return file; |
| 64 | + } |
85 | 65 | });
|
86 |
| -}; |
87 |
| - |
88 |
| -module.exports.compareLastModifiedTime = compareLastModifiedTime; |
89 |
| -module.exports.compareContents = compareContents; |
90 |
| - |
| 66 | +} |
0 commit comments