Browse Source

Merge pull request #141 from Narigo/preserve-timestamps

Add option to preserve timestamps
ci/travis-osximage
JP Richardson 9 years ago
parent
commit
37f78cac0d
  1. 4
      README.md
  2. 45
      lib/copy/__tests__/copy.test.js
  3. 1
      lib/copy/__tests__/fixtures/a-file
  4. 1
      lib/copy/__tests__/fixtures/a-folder/another-file
  5. 1
      lib/copy/__tests__/fixtures/a-folder/another-folder/file3
  6. 44
      lib/copy/__tests__/sync/copy-sync.test.js
  7. 9
      lib/copy/copy-file-sync.js
  8. 7
      lib/copy/copy-sync.js
  9. 11
      lib/copy/ncp.js

4
README.md

@ -94,6 +94,10 @@ Methods
Copy a file or directory. The directory can have contents. Like `cp -r`.
Options:
clobber (boolean): overwrite existing file or directory
preserveTimestamps (boolean): will set last modification and access times to the ones of the original source files, default is `false`.
Sync: `copySync()`

45
lib/copy/__tests__/copy.test.js

@ -184,6 +184,51 @@ describe('fs-extra', function () {
})
})
describe('> modification option', function () {
var SRC_FIXTURES_DIR = path.join(__dirname, '/fixtures')
var FILES = ['a-file', path.join('a-folder', 'another-file'), path.join('a-folder', 'another-folder', 'file3')]
describe('> when modified option is turned off', function () {
it('should have different timestamps on copy', function (done) {
var from = path.join(SRC_FIXTURES_DIR)
var to = path.join(TEST_DIR)
fse.copy(from, to, {preserveTimestamps: false}, function () {
FILES.forEach(testFile({preserveTimestamps: false}))
done()
})
})
})
describe('> when modified option is turned on', function () {
it('should have the same timestamps on copy', function (done) {
var from = path.join(SRC_FIXTURES_DIR)
var to = path.join(TEST_DIR)
fse.copy(from, to, {preserveTimestamps: true}, function () {
FILES.forEach(testFile({preserveTimestamps: true}))
done()
})
})
})
function testFile (options) {
return function (file) {
var a = path.join(SRC_FIXTURES_DIR, file)
var b = path.join(TEST_DIR, file)
var fromStat = fs.statSync(a)
var toStat = fs.statSync(b)
if (options.preserveTimestamps) {
assert.strictEqual(toStat.mtime.getTime(), fromStat.mtime.getTime())
assert.strictEqual(toStat.atime.getTime(), fromStat.atime.getTime())
} else {
assert.notEqual(toStat.mtime.getTime(), fromStat.mtime.getTime())
// the access time might actually be the same, so check only modification time
}
}
}
})
describe.skip('> REGRESSIONS', function () {
// pretty UNIX specific, may not pass on windows... only test on Mac OS X 10.9
it('should maintain file permissions and ownership', function (done) {

1
lib/copy/__tests__/fixtures/a-file

@ -0,0 +1 @@
sonic the hedgehog

1
lib/copy/__tests__/fixtures/a-folder/another-file

@ -0,0 +1 @@
tails

1
lib/copy/__tests__/fixtures/a-folder/another-folder/file3

@ -0,0 +1 @@
knuckles

44
lib/copy/__tests__/sync/copy-sync.test.js

@ -301,4 +301,48 @@ describe('+ copySync()', function () {
})
})
})
describe('> modification option', function () {
var SRC_FIXTURES_DIR = path.join(__dirname, '/../fixtures')
var FILES = ['a-file', path.join('a-folder', 'another-file'), path.join('a-folder', 'another-folder', 'file3')]
describe('> when modified option is turned off', function () {
it('should have different timestamps on copy', function (done) {
var from = path.join(SRC_FIXTURES_DIR)
fs.copySync(from, TEST_DIR, {preserveTimestamps: false})
FILES.forEach(testFile({preserveTimestamps: false}))
done()
})
})
describe('> when modified option is turned on', function () {
it('should have the same timestamps on copy', function (done) {
var from = path.join(SRC_FIXTURES_DIR)
fs.copySync(from, TEST_DIR, {preserveTimestamps: true})
FILES.forEach(testFile({preserveTimestamps: true}))
done()
})
})
function testFile (options) {
return function (file) {
var a = path.join(SRC_FIXTURES_DIR, file)
var b = path.join(TEST_DIR, file)
var fromStat = fs.statSync(a)
var toStat = fs.statSync(b)
if (options.preserveTimestamps) {
assert.strictEqual(toStat.mtime.getTime(), fromStat.mtime.getTime())
assert.strictEqual(toStat.atime.getTime(), fromStat.atime.getTime())
} else {
assert.notEqual(toStat.mtime.getTime(), fromStat.mtime.getTime())
// the access time might actually be the same, so check only modification time
}
}
}
})
})

9
lib/copy/copy-file-sync.js

@ -3,7 +3,10 @@ var fs = require('graceful-fs')
var BUF_LENGTH = 64 * 1024
var _buff = new Buffer(BUF_LENGTH)
function copyFileSync (srcFile, destFile, clobber) {
function copyFileSync (srcFile, destFile, options) {
var clobber = options.clobber
var preserveTimestamps = options.preserveTimestamps
if (fs.existsSync(destFile) && !clobber) {
throw Error('EEXIST')
}
@ -20,6 +23,10 @@ function copyFileSync (srcFile, destFile, clobber) {
pos += bytesRead
}
if (preserveTimestamps) {
fs.futimesSync(fdw, stat.atime, stat.mtime)
}
fs.closeSync(fdr)
fs.closeSync(fdw)
}

7
lib/copy/copy-sync.js

@ -13,6 +13,7 @@ function copySync (src, dest, options) {
// default to true for now
options.clobber = 'clobber' in options ? !!options.clobber : true
options.preserveTimestamps = 'preserveTimestamps' in options ? !!options.preserveTimestamps : true
options.filter = options.filter || function () { return true }
@ -27,13 +28,15 @@ function copySync (src, dest, options) {
if (performCopy) {
if (!destFolderExists) mkdir.mkdirsSync(destFolder)
copyFileSync(src, dest, options.clobber)
copyFileSync(src, dest, {clobber: options.clobber, preserveTimestamps: options.preserveTimestamps})
}
} else if (stats.isDirectory()) {
if (!fs.existsSync(dest)) mkdir.mkdirsSync(dest)
var contents = fs.readdirSync(src)
contents.forEach(function (content) {
copySync(path.join(src, content), path.join(dest, content), {filter: options.filter, recursive: true})
var opts = options
opts.recursive = true
copySync(path.join(src, content), path.join(dest, content), opts)
})
} else if (options.recursive && stats.isSymbolicLink()) {
var srcPath = fs.readlinkSync(src)

11
lib/copy/ncp.js

@ -2,6 +2,7 @@
var fs = require('graceful-fs')
var path = require('path')
var utimes = require('../util/utimes')
function ncp (source, dest, options, callback) {
if (!callback) {
@ -17,6 +18,7 @@ function ncp (source, dest, options, callback) {
var transform = options.transform
var clobber = options.clobber !== false
var dereference = options.dereference
var preserveTimestamps = options.preserveTimestamps === true
var errs = null
@ -106,7 +108,14 @@ function ncp (source, dest, options, callback) {
}
writeStream.once('finish', function () {
doneOne()
if (preserveTimestamps) {
utimes.utimesMillis(target, file.atime, file.mtime, function (err) {
if (err) return onError(err)
return doneOne()
})
} else {
doneOne()
}
})
}

Loading…
Cancel
Save