Comparing version 0.1.0 to 0.1.1
63
index.js
@@ -108,2 +108,6 @@ var tar = require('tar-stream'); | ||
var head = function(list) { | ||
return list.length ? list[list.length-1] : null | ||
}; | ||
exports.extract = function(cwd, opts) { | ||
@@ -114,4 +118,38 @@ if (!cwd) cwd = '.'; | ||
var ignore = opts.ignore || noop; | ||
var own = opts.chown !== false && !win32 && process.getuid() === 0; | ||
var extract = tar.extract(); | ||
var stack = []; | ||
var now = new Date(); | ||
var utimesParent = function(name, cb) { // we just set the mtime on the parent dir again everytime we write an entry | ||
var top; | ||
while ((top = head(stack)) && name.slice(0, top[0].length) !== top[0]) stack.pop(); | ||
if (!top) return cb(); | ||
fs.utimes(top[0], now, top[1], cb); | ||
}; | ||
var utimes = function(name, header, cb) { | ||
if (opts.utimes === false) return cb(); | ||
if (header.type === 'directory') return fs.utimes(name, now, header.mtime, cb); | ||
if (header.type === 'symlink') return utimesParent(name, cb); // TODO: how to set mtime on link? | ||
fs.utimes(name, now, header.mtime, function(err) { | ||
if (err) return cb(err); | ||
utimesParent(name, cb); | ||
}); | ||
}; | ||
var chperm = function(name, header, cb) { | ||
var link = header.name === 'symlink'; | ||
var chmod = link ? fs.lchmod : fs.chmod; | ||
var chown = link ? fs.lchown : fs.chown; | ||
chmod(name, header.mode, function(err) { | ||
if (err) return cb(err); | ||
if (!own) return cb(); | ||
chown(name, header.uid, header.gid, cb); | ||
}); | ||
}; | ||
extract.on('entry', function(header, stream, next) { | ||
@@ -122,11 +160,11 @@ var name = path.join(cwd, path.join('/', header.name)); | ||
stream.resume(); | ||
stream.on('end', next); | ||
return; | ||
return next(); | ||
} | ||
var onstat = function(err) { | ||
var stat = function(err) { | ||
if (err) return next(err); | ||
fs.utimes(name, new Date(), header.mtime, function(err) { | ||
if (win32) return next(); | ||
utimes(name, header, function(err) { | ||
if (err) return next(err); | ||
fs.chmod(name, header.mode, next); | ||
chperm(name, header, next); | ||
}); | ||
@@ -136,3 +174,6 @@ }; | ||
var onlink = function() { | ||
fs.symlink(header.linkname, name, next); // how do you set mtime on a link? | ||
if (win32) return next(); // skip symlinks on win for now before it can be tested | ||
fs.unlink(name, function() { | ||
fs.symlink(header.linkname, name, stat); | ||
}); | ||
}; | ||
@@ -145,12 +186,16 @@ | ||
if (err) return next(err); | ||
ws.on('close', onstat); | ||
ws.on('close', stat); | ||
}); | ||
}; | ||
if (header.type === 'directory') return mkdirp(name, onstat); | ||
if (header.type === 'directory') { | ||
stack.push([name, header.mtime]); | ||
return mkdirp(name, stat); | ||
} | ||
mkdirp(path.dirname(name), function(err) { | ||
if (err) return next(err); | ||
if (header.type === 'symlink') return fs.unlink(name, onlink); | ||
if (header.type === 'symlink') return onlink(); | ||
if (header.type !== 'file') return next(new Error('unsupported type for '+name+' ('+header.type+')')); | ||
onfile(); | ||
@@ -157,0 +202,0 @@ }); |
{ | ||
"name": "tar-fs", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "filesystem bindings for tar-stream", | ||
@@ -5,0 +5,0 @@ "repository": "git://github.com:mafintosh/tar-fs.git", |
@@ -6,4 +6,7 @@ var test = require('tap').test; | ||
var fs = require('fs'); | ||
var os = require('os'); | ||
test('copy a -> b', function(t) { | ||
var win32 = os.platform() === 'win32'; | ||
test('copy a -> copy/a', function(t) { | ||
t.plan(5); | ||
@@ -27,2 +30,61 @@ | ||
}); | ||
}); | ||
test('copy b -> copy/b', function(t) { | ||
t.plan(8); | ||
var a = path.join(__dirname, 'fixtures', 'b'); | ||
var b = path.join(__dirname, 'fixtures', 'copy', 'b'); | ||
rimraf.sync(b); | ||
tar.pack(a) | ||
.pipe(tar.extract(b)) | ||
.on('finish', function() { | ||
var files = fs.readdirSync(b); | ||
t.same(files.length, 1); | ||
t.same(files[0], 'a'); | ||
var dirB = path.join(b, files[0]); | ||
var dirA = path.join(a, files[0]); | ||
t.same(fs.statSync(dirB).mode, fs.statSync(dirA).mode); | ||
t.same(fs.statSync(dirB).mtime.getTime(), fs.statSync(dirA).mtime.getTime()); | ||
t.ok(fs.statSync(dirB).isDirectory()); | ||
var fileB = path.join(dirB, 'test.js'); | ||
var fileA = path.join(dirA, 'test.js'); | ||
t.same(fs.readFileSync(fileB, 'utf-8'), fs.readFileSync(fileA, 'utf-8')); | ||
t.same(fs.statSync(fileB).mode, fs.statSync(fileA).mode); | ||
t.same(fs.statSync(fileB).mtime.getTime(), fs.statSync(fileA).mtime.getTime()); | ||
}); | ||
}); | ||
test('symlink', function(t) { | ||
if (win32) { // no symlink support on win32 currently. TODO: test if this can be enabled somehow | ||
t.plan(1); | ||
t.ok(true); | ||
return; | ||
} | ||
t.plan(5); | ||
var a = path.join(__dirname, 'fixtures', 'c'); | ||
rimraf.sync(path.join(a, 'link')); | ||
fs.symlinkSync('.gitignore', path.join(a, 'link')); | ||
var b = path.join(__dirname, 'fixtures', 'copy', 'c'); | ||
rimraf.sync(b); | ||
tar.pack(a) | ||
.pipe(tar.extract(b)) | ||
.on('finish', function() { | ||
var files = fs.readdirSync(b).sort(); | ||
t.same(files.length, 2); | ||
t.same(files[0], '.gitignore'); | ||
t.same(files[1], 'link'); | ||
var linkA = path.join(a, 'link'); | ||
var linkB = path.join(b, 'link'); | ||
t.same(fs.lstatSync(linkB).mtime.getTime(), fs.lstatSync(linkA).mtime.getTime()); | ||
t.same(fs.readlinkSync(linkB), fs.readlinkSync(linkA)); | ||
}); | ||
}); |
9167
9
229