From 535815e98a348ac3e1305c45d9c97afbe5618e56 Mon Sep 17 00:00:00 2001 From: 5saviahv <49443574+5saviahv@users.noreply.github.com> Date: Sun, 4 Aug 2024 23:43:10 +0300 Subject: [PATCH] deleteFile is too eager (#525) Co-authored-by: 5saviahv <5saviahv@users.noreply.github.com> --- adm-zip.js | 4 +- test/methods/methods.test.js | 81 ++++++++++++++++++++++++++++++++++++ zipFile.js | 52 +++++++++++------------ 3 files changed, 108 insertions(+), 29 deletions(-) diff --git a/adm-zip.js b/adm-zip.js index 4c5b9c8..31dddf2 100644 --- a/adm-zip.js +++ b/adm-zip.js @@ -203,11 +203,11 @@ module.exports = function (/**String*/ input, /** object */ options) { * @param {ZipEntry|string} entry * @returns {void} */ - deleteFile: function (entry) { + deleteFile: function (entry, withsubfolders = true) { // @TODO: test deleteFile var item = getEntry(entry); if (item) { - _zip.deleteFile(item.entryName); + _zip.deleteFile(item.entryName, withsubfolders); } }, diff --git a/test/methods/methods.test.js b/test/methods/methods.test.js index e02c588..4cf8777 100644 --- a/test/methods/methods.test.js +++ b/test/methods/methods.test.js @@ -28,6 +28,87 @@ describe("adm-zip.js - methods handling local files", () => { // clean up folder content afterEach((done) => rimraf(destination, done)); + describe(".deleteFile()", () => { + const ultrazip = [ + "./attributes_test/asd/New Text Document.txt", + "./attributes_test/blank file.txt", + "./attributes_test/New folder/hidden.txt", + "./attributes_test/New folder/hidden_readonly.txt", + "./attributes_test/New folder/readonly.txt", + "./utes_test/New folder/somefile.txt" + ].map(wrapList); + + // Issue 523 - deletes additional files + it("zip.deleteFile() - delete folder with subfolders", () => { + const content = "test"; + const comment = "comment"; + const zip1 = new Zip({ noSort: true }); + zip1.addFile("test/"); + zip1.addFile("test/path1/"); + zip1.addFile("test/path1/file1.txt", content, comment); + zip1.addFile("test/path1/folder1/"); + zip1.addFile("test/path1/folder1/file2.txt", content, comment); + zip1.addFile("test/path2/"); + zip1.addFile("test/path2/file1.txt", content, comment); + zip1.addFile("test/path2/folder1/"); + zip1.addFile("test/path2/folder1/file2.txt", content, comment); + + zip1.deleteFile("test/path1/"); + + const zipEntries = zip1.getEntries().map((child) => child.entryName); + + expect(zipEntries).to.deep.equal(["test/", "test/path2/", "test/path2/file1.txt", "test/path2/folder1/", "test/path2/folder1/file2.txt"]); + }); + + it("zip.deleteFile() - delete folder", () => { + const content = "test"; + const comment = "comment"; + const zip1 = new Zip({ noSort: true }); + zip1.addFile("test/"); + zip1.addFile("test/path1/"); + zip1.addFile("test/path1/file1.txt", content, comment); + zip1.addFile("test/path1/folder1/"); + zip1.addFile("test/path1/folder1/file2.txt", content, comment); + zip1.addFile("test/path2/"); + zip1.addFile("test/path2/file1.txt", content, comment); + zip1.addFile("test/path2/folder1/"); + zip1.addFile("test/path2/folder1/file2.txt", content, comment); + + zip1.deleteFile("test/path1/", false); + + const zipEntries = zip1.getEntries().map((child) => child.entryName); + + expect(zipEntries).to.deep.equal([ + "test/", + "test/path1/file1.txt", + "test/path1/folder1/", + "test/path1/folder1/file2.txt", + "test/path2/", + "test/path2/file1.txt", + "test/path2/folder1/", + "test/path2/folder1/file2.txt" + ]); + }); + + it("zip.deleteFile() - delete files", () => { + const content = "test"; + const comment = "comment"; + const zip1 = new Zip({ noSort: true }); + zip1.addFile("test/"); + zip1.addFile("test/path1/"); + zip1.addFile("test/path1/file1.txt", content, comment); + zip1.addFile("test/path1/folder1/"); + zip1.addFile("test/path1/folder1/file2.txt", content, comment); + + zip1.deleteFile("test/path1/file1.txt", false); + zip1.deleteFile("test/path1/folder1/file2.txt", false); + + const zipEntries = zip1.getEntries().map((child) => child.entryName); + + expect(zipEntries).to.deep.equal(["test/", "test/path1/", "test/path1/folder1/"]); + }); + }); + describe(".extractAllTo() - sync", () => { const ultrazip = [ "./attributes_test/asd/New Text Document.txt", diff --git a/zipFile.js b/zipFile.js index 6b277bc..234f6cd 100644 --- a/zipFile.js +++ b/zipFile.js @@ -205,22 +205,14 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { * @param entryName * @returns {void} */ - deleteFile: function (/*String*/ entryName) { + deleteFile: function (/*String*/ entryName, withsubfolders = true) { if (!loadedEntries) { readEntries(); } - var entry = entryTable[entryName]; - if (entry && entry.isDirectory) { - var _self = this; - this.getEntryChildren(entry).forEach(function (child) { - if (child.entryName !== entryName) { - _self.deleteFile(child.entryName); - } - }); - } - entryList.splice(entryList.indexOf(entry), 1); - delete entryTable[entryName]; - mainHeader.totalEntries = entryList.length; + const entry = entryTable[entryName]; + const list = this.getEntryChildren(entry, withsubfolders).map((child) => child.entryName); + + list.forEach(this.deleteEntry); }, /** @@ -234,9 +226,12 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { readEntries(); } const entry = entryTable[entryName]; - entryList.splice(entryList.indexOf(entry), 1); - delete entryTable[entryName]; - mainHeader.totalEntries = entryList.length; + const index = entryList.indexOf(entry); + if (index >= 0) { + entryList.splice(index, 1); + delete entryTable[entryName]; + mainHeader.totalEntries = entryList.length; + } }, /** @@ -245,21 +240,24 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { * @param entry * @return Array */ - getEntryChildren: function (/*ZipEntry*/ entry) { + getEntryChildren: function (/*ZipEntry*/ entry, subfolders = true) { if (!loadedEntries) { readEntries(); } - if (entry && entry.isDirectory) { - const list = []; - const name = entry.entryName; - const len = name.length; - - entryList.forEach(function (zipEntry) { - if (zipEntry.entryName.startsWith(name)) { - list.push(zipEntry); + if (typeof entry === "object") { + if (entry.isDirectory && subfolders) { + const list = []; + const name = entry.entryName; + + for (const zipEntry of entryList) { + if (zipEntry.entryName.startsWith(name)) { + list.push(zipEntry); + } } - }); - return list; + return list; + } else { + return [entry]; + } } return []; },