diff --git a/src/backupformat/tgz.js b/src/backupformat/tgz.js index 734a735a2..62ce51714 100644 --- a/src/backupformat/tgz.js +++ b/src/backupformat/tgz.js @@ -85,6 +85,8 @@ async function addPathToPack(pack, localPath, dataLayout) { assert(dataLayout instanceof DataLayout, 'dataLayout must be a DataLayout'); assert.strictEqual(typeof localPath, 'string'); + const stats = { fileCount: 0, linkCount: 0, dirCount: 0 }; + const queue = [ localPath ]; while (queue.length) { // if (pack.destroyed || outStream.destroyed) break; @@ -108,15 +110,18 @@ async function addPathToPack(pack, localPath, dataLayout) { if (stat.size > 8589934590 || entry.name.length > 99) header.pax = { size: stat.size }; const input = handle.createReadStream({ autoClose: true }); await addEntryToPack(pack, header, { input }); + ++stats.fileCount; } else if (entry.isDirectory()) { const header = { name: headerName, type: 'directory', uid: process.getuid(), gid: process.getgid() }; subdirs.push(abspath); await addEntryToPack(pack, header, { /* options */ }); + ++stats.dirCount; } else if (entry.isSymbolicLink()) { const [readlinkError, target] = await safe(fs.promises.readlink(abspath)); if (!target) { debug(`tarPack: skipping link, could not readlink ${abspath}: ${readlinkError.message}`); continue; } const header = { name: headerName, type: 'symlink', linkname: target, uid: process.getuid(), gid: process.getgid() }; await addEntryToPack(pack, header, { /* options */ }); + ++stats.linkCount; } else { debug(`tarPack: ignoring unknown type ${entry.name} ${entry.type}`); } @@ -124,6 +129,8 @@ async function addPathToPack(pack, localPath, dataLayout) { queue.unshift(...subdirs); // add to front of queue and in order of readdir listing } + + return stats; } async function tarPack(dataLayout, encryption, uploader, progressCallback) { @@ -152,9 +159,11 @@ async function tarPack(dataLayout, encryption, uploader, progressCallback) { pipeline = safe(stream.pipeline(pack, gzip, ps, hash, uploader.stream)); } + let fileCount = 0; for (const localPath of dataLayout.localPaths()) { - const [error] = await safe(addPathToPack(pack, localPath, dataLayout), { debug }); + const [error, stats] = await safe(addPathToPack(pack, localPath, dataLayout), { debug }); if (error) break; // the pipeline will error and we will retry the whole packing all over + fileCount += stats.fileCount; } pack.finalize(); // harmless to call if already in error state @@ -165,7 +174,7 @@ async function tarPack(dataLayout, encryption, uploader, progressCallback) { await uploader.finish(); return { - stats: ps.stats(), + stats: { fileCount, ...ps.stats() }, integrity: { size: ps.stats().transferred, sha256: hash.digest('hex') } }; }