Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING: Use bigint everywhere #895

Merged
merged 1 commit into from
Apr 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions lib/util/__tests__/stat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@ const fs = require(process.cwd())
const os = require('os')
const path = require('path')
const assert = require('assert')
const atLeastNode = require('at-least-node')
const stat = require('../stat.js')

const NODE_VERSION_WITH_BIGINT = '10.5.0'

/* global beforeEach, afterEach, describe, it */

describe('util/stat', () => {
Expand All @@ -21,20 +18,15 @@ describe('util/stat', () => {

afterEach(done => fs.remove(TEST_DIR, done))

describe('should use stats with bigint type for node versions >= 10.5.0 and number type for older versions', () => {
describe('should use stats with bigint type', () => {
it('stat.checkPaths()', () => {
const src = path.join(TEST_DIR, 'src')
const dest = path.join(TEST_DIR, 'dest')
fs.ensureFileSync(src)
fs.ensureFileSync(dest)
stat.checkPaths(src, dest, 'copy', {}, (err, stats) => {
assert.ifError(err)
const { srcStat } = stats
if (atLeastNode(NODE_VERSION_WITH_BIGINT)) {
assert.strictEqual(typeof srcStat.ino, 'bigint')
} else {
assert.strictEqual(typeof srcStat.ino, 'number')
}
assert.strictEqual(typeof stats.srcStat.ino, 'bigint')
})
})

Expand All @@ -44,11 +36,7 @@ describe('util/stat', () => {
fs.ensureFileSync(src)
fs.ensureFileSync(dest)
const { srcStat } = stat.checkPathsSync(src, dest, 'copy', {})
if (atLeastNode(NODE_VERSION_WITH_BIGINT)) {
assert.strictEqual(typeof srcStat.ino, 'bigint')
} else {
assert.strictEqual(typeof srcStat.ino, 'number')
}
assert.strictEqual(typeof srcStat.ino, 'bigint')
})
})

Expand Down
44 changes: 10 additions & 34 deletions lib/util/stat.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,11 @@
const fs = require('../fs')
const path = require('path')
const util = require('util')
const atLeastNode = require('at-least-node')

const nodeSupportsBigInt = atLeastNode('10.5.0')
const stat = (file) => nodeSupportsBigInt ? fs.stat(file, { bigint: true }) : fs.stat(file)
const lstat = (file) => nodeSupportsBigInt ? fs.lstat(file, { bigint: true }) : fs.lstat(file)
const statSync = (file) => nodeSupportsBigInt ? fs.statSync(file, { bigint: true }) : fs.statSync(file)
const lstatSync = (file) => nodeSupportsBigInt ? fs.lstatSync(file, { bigint: true }) : fs.lstatSync(file)

function getStats (src, dest, opts) {
const statFunc = opts.dereference ? stat : lstat
const statFunc = opts.dereference
? (file) => fs.stat(file, { bigint: true })
: (file) => fs.lstat(file, { bigint: true })
return Promise.all([
statFunc(src),
statFunc(dest).catch(err => {
Expand All @@ -24,7 +19,9 @@ function getStats (src, dest, opts) {

function getStatsSync (src, dest, opts) {
let destStat
const statFunc = opts.dereference ? statSync : lstatSync
const statFunc = opts.dereference
? (file) => fs.statSync(file, { bigint: true })
: (file) => fs.lstatSync(file, { bigint: true })
const srcStat = statFunc(src)
try {
destStat = statFunc(dest)
Expand Down Expand Up @@ -102,7 +99,7 @@ function checkParentPaths (src, srcStat, dest, funcName, cb) {
const srcParent = path.resolve(path.dirname(src))
const destParent = path.resolve(path.dirname(dest))
if (destParent === srcParent || destParent === path.parse(destParent).root) return cb()
const callback = (err, destStat) => {
fs.stat(destParent, { bigint: true }, (err, destStat) => {
if (err) {
if (err.code === 'ENOENT') return cb()
return cb(err)
Expand All @@ -111,9 +108,7 @@ function checkParentPaths (src, srcStat, dest, funcName, cb) {
return cb(new Error(errMsg(src, dest, funcName)))
}
return checkParentPaths(src, srcStat, destParent, funcName, cb)
}
if (nodeSupportsBigInt) fs.stat(destParent, { bigint: true }, callback)
else fs.stat(destParent, callback)
})
}

function checkParentPathsSync (src, srcStat, dest, funcName) {
Expand All @@ -122,7 +117,7 @@ function checkParentPathsSync (src, srcStat, dest, funcName) {
if (destParent === srcParent || destParent === path.parse(destParent).root) return
let destStat
try {
destStat = statSync(destParent)
destStat = fs.statSync(destParent, { bigint: true })
} catch (err) {
if (err.code === 'ENOENT') return
throw err
Expand All @@ -134,26 +129,7 @@ function checkParentPathsSync (src, srcStat, dest, funcName) {
}

function areIdentical (srcStat, destStat) {
if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
if (nodeSupportsBigInt || destStat.ino < Number.MAX_SAFE_INTEGER) {
// definitive answer
return true
}
// Use additional heuristics if we can't use 'bigint'.
// Different 'ino' could be represented the same if they are >= Number.MAX_SAFE_INTEGER
// See issue 657
if (destStat.size === srcStat.size &&
destStat.mode === srcStat.mode &&
destStat.nlink === srcStat.nlink &&
destStat.atimeMs === srcStat.atimeMs &&
destStat.mtimeMs === srcStat.mtimeMs &&
destStat.ctimeMs === srcStat.ctimeMs &&
destStat.birthtimeMs === srcStat.birthtimeMs) {
// heuristic answer
return true
}
}
return false
return destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev
}

// return true if dest is a subdir of src, otherwise false.
Expand Down