From 0fd4d51898eec239104bf0495a2c75fad0ee60de Mon Sep 17 00:00:00 2001 From: silentrald Date: Sun, 10 Nov 2024 15:34:50 +0800 Subject: [PATCH] [bugfix] fixed logic with folder extraction events --- assets/tests/special.zip | Bin 1310 -> 0 bytes src/__tests__/unit/zip.test.ts | 28 +++--- src/main/helpers/zip.helpers.ts | 91 ++++++++++++++---- .../maps/local-maps-manager.service.ts | 5 +- 4 files changed, 88 insertions(+), 36 deletions(-) delete mode 100644 assets/tests/special.zip diff --git a/assets/tests/special.zip b/assets/tests/special.zip deleted file mode 100644 index 5e8a0fbad1d46a558f6915035059dc623f441d48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1310 zcma))Jr2Sk6vwN!4n{lm0L~5?y@0`02Uka9G@5j5jBCAsvwKhB>^YoW*gSwd;1y_~ z@P?Lz{|EfScHN7!2<9GNc6=c}UG|^Pw$A;S@9#Cmp^-3@iqj=OPK#UN&Ps$*4?8!) zMkw*8^`%sgD;jZWt?}mpiG_C0CMh7XnCWdc5}@#R0STtm!)zqD#GeKvK&r>tNC=I} z>vWer_p4x`d?LtJz+q(oeYFJY75ajdX;Z%_M&n kPP43?{1Yu9Z6^7*w3>D8 { // Uses '\\' it("Extract map zips using forward slashes", async () => { - await extractZip(WINDOWS_LEGACY_MAP_ZIP, DESTINATION_FOLDER); + const beforeExtractedFolders: string[] = []; + const afterExtractedFolders: string[] = []; + await extractZip(WINDOWS_LEGACY_MAP_ZIP, DESTINATION_FOLDER, { + beforeFolderExtracted: (folder) => beforeExtractedFolders.push(folder), + afterFolderExtracted: (folder) => afterExtractedFolders.push(folder), + }); // Expect all the files to exists for (const file of [ @@ -67,22 +71,14 @@ describe("Zip Server Service Test", () => { expect(pathExistsSync(path.join(SUBFOLDER_PATH, file))) .toBe(true); } - }); - it("Extract special zip file", async () => { - const beforeExtracted: string[] = []; - const afterExtracted: string[] = []; - await extractZip(SPECIAL_ZIP, DESTINATION_FOLDER, { - beforeFolderExtracted: (folder) => beforeExtracted.push(folder), - afterFolderExtracted: (folder) => afterExtracted.push(folder), - }); + expect(beforeExtractedFolders).toContain("."); + expect(beforeExtractedFolders).toContain("pfp"); + expect(beforeExtractedFolders.length).toBe(2); - const expected = [ - "1/a", "1/aa", "1/aaa", - "2/a", "2/aa", "2/aaa", - ] - expect(beforeExtracted).toEqual(expected); - expect(afterExtracted).toEqual(expected); + expect(afterExtractedFolders).toContain("."); + expect(afterExtractedFolders).toContain("pfp"); + expect(afterExtractedFolders.length).toBe(2); }); it("Extract manifest.json from zip file", async () => { diff --git a/src/main/helpers/zip.helpers.ts b/src/main/helpers/zip.helpers.ts index e2644978..0e09bcf8 100644 --- a/src/main/helpers/zip.helpers.ts +++ b/src/main/helpers/zip.helpers.ts @@ -67,7 +67,37 @@ function handleExtractZip( name: "", directory: false, }; - let currentDirname = ""; + let indexes: number[] = []; + let dirname = ""; + + options?.beforeFolderExtracted?.("."); + const folderExtractEvents = options?.beforeFolderExtracted + || options?.afterFolderExtracted + ? (filename: string) => { + let newDirname = path.dirname(filename); + if (newDirname === ".") newDirname = ""; + + const comparison = compareStringIndex(dirname, newDirname); + if (comparison === -1) { return; } + + // Push after extraction + if (options?.afterFolderExtracted) { + for (let i = indexes.length - 1; i > -1 && indexes[i] > comparison; --i) { + options.afterFolderExtracted(dirname.substring(0, indexes[i])); + } + } + + // Push before extraction + indexes = getSlashIndexes(newDirname); + if (options?.beforeFolderExtracted) { + for (let i = 0; i < indexes.length; ++i) { + if (indexes[i] <= comparison) { continue; } + options.beforeFolderExtracted(newDirname.substring(0, indexes[i])); + } + } + + dirname = newDirname; + } : () => {}; zip.readEntry(); @@ -86,21 +116,7 @@ function handleExtractZip( zip.openReadStream(entry, (readError, readStream) => { if (readError) return reject(readError); - const dirname = path.dirname(entry.fileName); - if (dirname !== currentDirname) { - if (path.dirname(dirname) === path.dirname(currentDirname)) { - options?.afterFolderExtracted?.(currentDirname); - options?.beforeFolderExtracted?.(dirname); - } else if (currentDirname.startsWith(dirname)) { - options?.afterFolderExtracted?.(currentDirname); - } else if (dirname.startsWith(currentDirname)) { - options?.beforeFolderExtracted?.(dirname); - } else { - options?.afterFolderExtracted?.(currentDirname); - options?.beforeFolderExtracted?.(dirname); - } - currentDirname = dirname; - } + folderExtractEvents(entry.fileName); zipEntry.name = entry.fileName; zipEntry.directory = false; @@ -134,7 +150,14 @@ function handleExtractZip( }); zip.once("end", () => { - options?.afterFolderExtracted?.(currentDirname); + if (options?.afterFolderExtracted) { + // Push after extraction + for (let i = indexes.length - 1; i > -1; --i) { + options.afterFolderExtracted(dirname.substring(0, indexes[i])); + } + options.afterFolderExtracted("."); + } + zip.close(); resolve(files); }); @@ -272,3 +295,37 @@ function handleProcessZip( }); } +/** + * @returns(number) + * -1 = string are the same + * > 0 = index where they don't equal the same + */ +function compareStringIndex(str1: string, str2: string) { + const N = Math.min(str1.length, str2.length); + let i = 0; + for (; i < N; ++i) { + if (str1[i] !== str2[i]) { break; } + } + + return i === str1.length && i === str2.length + ? -1 : i; +} + +/** + * @returns(number[]) - int array of the positions of the slashes + */ +function getSlashIndexes(str: string) { + if (str === "") { + return []; + } + + const indexes: number[] = []; + for (let i = 0; i < str.length; ++i) { + if (str[i] === "/") { + indexes.push(i); + } + } + indexes.push(str.length); + return indexes; +} + diff --git a/src/main/services/additional-content/maps/local-maps-manager.service.ts b/src/main/services/additional-content/maps/local-maps-manager.service.ts index a737e82b..8ff0d164 100644 --- a/src/main/services/additional-content/maps/local-maps-manager.service.ts +++ b/src/main/services/additional-content/maps/local-maps-manager.service.ts @@ -329,7 +329,6 @@ export class LocalMapsManagerService { let nbImportedMaps = 0; (async () => { - // BUG: UI bug where the map is not showing even if it was extracted properly const terminate = () => unsubscribed; let completeNewFolder: () => void; const newFolderTap = tap((folder: string) => { @@ -402,11 +401,11 @@ export class LocalMapsManagerService { condition: !isRoot && ((entry) => mapsFolders.has(path.dirname(entry.name))), beforeFolderExtracted: (folder) => { if (!mapsFolders.has(folder)) return; - log.info("*", `"${folder}"`); + log.info("*", `"${folder}"`, "before"); }, afterFolderExtracted: (folder) => { if (!mapsFolders.has(folder)) return; - newFolder.next(path.join(destination, folder)); + newFolder.next(path.resolve(destination, folder)); } });