From cd7926a7d70d4decfe83f02836bfbb0903cbdfbb Mon Sep 17 00:00:00 2001 From: Marko Schulz Date: Fri, 31 Jul 2020 08:47:46 +0200 Subject: [PATCH 1/3] Remove unused export --- src/main/fileUtil.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/fileUtil.js b/src/main/fileUtil.js index fa113dcff..6184a2c28 100644 --- a/src/main/fileUtil.js +++ b/src/main/fileUtil.js @@ -288,7 +288,6 @@ function createJsonFileIfNotExists(filePath, jsonData) { } module.exports = { - readFile, readJsonFile, listDirectories, listFiles, From 128b2f95c1409b294f06bfeebc819d4aa680d5d4 Mon Sep 17 00:00:00 2001 From: Marko Schulz Date: Fri, 31 Jul 2020 08:49:21 +0200 Subject: [PATCH 2/3] Fix race condition when upgrading all apps When upgrading all apps we got errors because while one app was finished upgrading another was still in progress, which exposed a temporary state with an app folder being partially cleared or partially installed. So these two operations are now atomic: - When removing an app, that app folder is first moved to a temporary place, so that this happens instantly, and then the folder is cleared there. - When installing an app, the app folder is first created and filled in a temporary place and then at the end moved to the final location, so that this also happens instantly. --- src/main/apps.js | 10 +++++++--- src/main/fileUtil.js | 25 +++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/main/apps.js b/src/main/apps.js index 2962c5dcd..b3686ed8b 100644 --- a/src/main/apps.js +++ b/src/main/apps.js @@ -239,7 +239,7 @@ function installLocalAppArchive(tgzFilePath) { .then(isInstalled => { if (!isInstalled) { return fileUtil.mkdir(appPath) - .then(() => fileUtil.extractNpmPackage(tgzFilePath, appPath)) + .then(() => fileUtil.extractNpmPackage(appName, tgzFilePath, appPath)) .then(() => fileUtil.deleteFile(tgzFilePath)); } return Promise.resolve(); @@ -490,7 +490,11 @@ function removeOfficialApp(name, source) { + `to remove app directory ${appPath}. The directory does not ` + 'have node_modules in its path.')); } - return fs.remove(appPath); + + const tmpDir = fileUtil.getTmpFilename(name); + + return fs.move(appPath, tmpDir) + .then(() => fs.remove(tmpDir)); } /** @@ -513,7 +517,7 @@ function installOfficialApp(name, version, source) { } return Promise.resolve(); }) - .then(() => fileUtil.extractNpmPackage(tgzFilePath, appPath)) + .then(() => fileUtil.extractNpmPackage(name, tgzFilePath, appPath)) .then(() => fileUtil.deleteFile(tgzFilePath)); }); } diff --git a/src/main/fileUtil.js b/src/main/fileUtil.js index 6184a2c28..c724d25db 100644 --- a/src/main/fileUtil.js +++ b/src/main/fileUtil.js @@ -44,7 +44,9 @@ const fse = require('fs-extra'); const path = require('path'); const targz = require('targz'); const chmodr = require('chmodr'); +const { v4 } = require('uuid'); const { mkdir, mkdirIfNotExists } = require('./mkdir'); +const config = require('./config'); /** * Open the given file path and return its string contents. @@ -228,15 +230,33 @@ function chmodDir(src, mode) { }); } +/** + * Create a unique name for a temporary file or folder. The file is not + * created, this just generates an absolute name for it in the directory + * for temporary files. + * + * @param {string} basename a basename to include in the name to make it easier + * to recognise + * @returns {string} the unique file name + */ +function getTmpFilename(basename) { + return path.join(config.getTmpDir(), `${basename}-${v4()}`); +} + /** * Extract the given npm package (tgz file) to the given destination directory. * + * @param {string} appName the name of the app to extract * @param {string} tgzFile the tgz file path to extract. * @param {string} destinationDir the destination directory. * @returns {Promise} promise that resolves if successful. */ -function extractNpmPackage(tgzFile, destinationDir) { - return untar(tgzFile, destinationDir, 1); +function extractNpmPackage(appName, tgzFile, destinationDir) { + const tmpDir = getTmpFilename(appName); + const moveToDestinationDir = () => fse.move(tmpDir, destinationDir, { overwrite: true }); + + return untar(tgzFile, tmpDir, 1) + .then(moveToDestinationDir); } /** @@ -296,6 +316,7 @@ module.exports = { copy, untar, chmodDir, + getTmpFilename, extractNpmPackage, getNameFromNpmPackage, mkdir, From c29c456fead5e1155062920cee421da7faba115a Mon Sep 17 00:00:00 2001 From: Marko Schulz Date: Fri, 31 Jul 2020 15:03:51 +0200 Subject: [PATCH 3/3] Describe fix and bump version --- Changelog.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index f48f044bc..efb9c8c75 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,8 @@ +## Version 3.4.2 +### Fixes +- “Update all apps” sometimes showed an error message (even though it worked + correctly). #451 + ## Version 3.4.1 ### Updates - Updated to pc-nrfjprog-js v1.7.3, including bundled nrfjprog v10.9.0 and JLink 6.80a diff --git a/package.json b/package.json index 890c49672..dfd491867 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nrfconnect", - "version": "3.4.1", + "version": "3.4.2", "description": "nRF Connect for PC", "repository": { "type": "git",