From f1807ff41e60ee7f89981b084270c8c4258ac4da Mon Sep 17 00:00:00 2001 From: "Keimling, Rene" Date: Sun, 1 May 2022 13:31:56 +0200 Subject: [PATCH 1/4] fix https://github.com/vercel/pkg/issues/1589 --- prelude/bootstrap.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prelude/bootstrap.js b/prelude/bootstrap.js index 9c2ad55ac..f65438a1c 100644 --- a/prelude/bootstrap.js +++ b/prelude/bootstrap.js @@ -197,10 +197,10 @@ function copyFolderRecursiveSync(source, target) { if (fs.lstatSync(curSource).isDirectory()) { copyFolderRecursiveSync(curSource, targetFolder); } else { - fs.copyFileSync( - curSource, - path.join(targetFolder, path.basename(curSource)) - ); + const curTarget = path.join(targetFolder, path.basename(curSource)); + if (!fs.existsSync(curTarget)) { + fs.copyFileSync(curSource, curTarget); + } } }); } From bd93639b2fbdcfd09088a4990e3d0a115368f085 Mon Sep 17 00:00:00 2001 From: "Keimling, Rene" Date: Mon, 2 May 2022 16:17:10 +0200 Subject: [PATCH 2/4] comment added --- prelude/bootstrap.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prelude/bootstrap.js b/prelude/bootstrap.js index f65438a1c..73e20d304 100644 --- a/prelude/bootstrap.js +++ b/prelude/bootstrap.js @@ -198,6 +198,12 @@ function copyFolderRecursiveSync(source, target) { copyFolderRecursiveSync(curSource, targetFolder); } else { const curTarget = path.join(targetFolder, path.basename(curSource)); + // Check if the target file already exists and skip the copy in such a case to + // 1. avoid an exception that the file cannot be written if it is already opened + // by a running instance of the pkg-packaged app + // 2. speed up the second, third, etc. app start if (in best case) all files + // are already existing + // See https://github.com/vercel/pkg/issues/1589 for more details. if (!fs.existsSync(curTarget)) { fs.copyFileSync(curSource, curTarget); } From 696a7702e6c280c56f9d9ea280798a57cdabb09f Mon Sep 17 00:00:00 2001 From: "Keimling, Rene" Date: Sun, 8 May 2022 13:07:02 +0200 Subject: [PATCH 3/4] do the copy even if file exists but is outdated --- prelude/bootstrap.js | 65 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/prelude/bootstrap.js b/prelude/bootstrap.js index 73e20d304..b8d8c973f 100644 --- a/prelude/bootstrap.js +++ b/prelude/bootstrap.js @@ -181,34 +181,71 @@ function copyInChunks( // TODO: replace this with fs.cpSync when we drop Node < 16 function copyFolderRecursiveSync(source, target) { - let files = []; - - // Check if folder needs to be created or integrated + // Build target folder const targetFolder = path.join(target, path.basename(source)); + + // Check if target folder needs to be created or integrated if (!fs.existsSync(targetFolder)) { fs.mkdirSync(targetFolder); } // Copy if (fs.lstatSync(source).isDirectory()) { - files = fs.readdirSync(source); - files.forEach((file) => { + const files = fs.readdirSync(source); + + for (const file of files) { + // Build source name const curSource = path.join(source, file); + + // Call this function recursively as long as source is a directory if (fs.lstatSync(curSource).isDirectory()) { copyFolderRecursiveSync(curSource, targetFolder); } else { - const curTarget = path.join(targetFolder, path.basename(curSource)); - // Check if the target file already exists and skip the copy in such a case to - // 1. avoid an exception that the file cannot be written if it is already opened - // by a running instance of the pkg-packaged app - // 2. speed up the second, third, etc. app start if (in best case) all files - // are already existing + // Current source is a file, it must be available on the real filesystem + // instead of the virtual snapshot file system to load it by process.dlopen. + // + // Before we try to copy we do some checks. // See https://github.com/vercel/pkg/issues/1589 for more details. - if (!fs.existsSync(curTarget)) { - fs.copyFileSync(curSource, curTarget); + + // Build target file name + const curTarget = path.join(targetFolder, path.basename(curSource)); + + if (fs.existsSync(curTarget)) { + // Target file already exists, read source and target file... + const curSourceContent = fs.readFileSync(curSource, { + encoding: 'binary', + }); + const curTargetContent = fs.readFileSync(curTarget, { + encoding: 'binary', + }); + + // ...and calculate checksum from source and target file + const curSourceHash = createHash('sha256') + .update(curSourceContent) + .digest('hex'); + const curTargetHash = createHash('sha256') + .update(curTargetContent) + .digest('hex'); + + // If checksums are equal then there is nothing to do here + // ==> target already exists and is up-to-date + if (curSourceHash === curTargetHash) { + return; + } } + + // Target must be copied because it either does not exist or is outdated. + // Due to the possibility that mutliple instances of this app start simultaneously, + // the copy action might fail. Only one starting instance gets write access. + // + // We don't catch any error here because it does not make sense to go ahead and to + // try to load the file while another instance has not yet finished the copy action. + // If the app start fails then the user should try to start the app later again. + // Unfortunately, we cannot implement delayed retries ourselves because process.dlopen + // is a synchronous function, promises are not supported. + fs.copyFileSync(curSource, curTarget); } - }); + } } } From af60d4cc57b99ded4955d08c9e933d413c0576d3 Mon Sep 17 00:00:00 2001 From: "Keimling, Rene" Date: Sun, 8 May 2022 13:17:46 +0200 Subject: [PATCH 4/4] skip only the file that is up-to-date, not all files --- prelude/bootstrap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prelude/bootstrap.js b/prelude/bootstrap.js index b8d8c973f..8627ea5eb 100644 --- a/prelude/bootstrap.js +++ b/prelude/bootstrap.js @@ -230,7 +230,7 @@ function copyFolderRecursiveSync(source, target) { // If checksums are equal then there is nothing to do here // ==> target already exists and is up-to-date if (curSourceHash === curTargetHash) { - return; + continue; } }