From b8981136b0621a6d3eb709accfad0335f37a2e14 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder <231804+danez@users.noreply.github.com> Date: Mon, 30 May 2022 17:49:42 +0100 Subject: [PATCH] fix: Fix storing same named files from different pkgs in memory plugin (#3200) The memory plugin was not correctly writing tarballs that have the same name but are from different packages and have different content. --- .changeset/chilled-ways-fetch.md | 5 ++ packages/plugins/memory/src/memory-handler.ts | 60 ++++++++++--------- packages/plugins/memory/test/memory.spec.ts | 40 +++++++++++++ 3 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 .changeset/chilled-ways-fetch.md diff --git a/.changeset/chilled-ways-fetch.md b/.changeset/chilled-ways-fetch.md new file mode 100644 index 000000000..4671d6d86 --- /dev/null +++ b/.changeset/chilled-ways-fetch.md @@ -0,0 +1,5 @@ +--- +'verdaccio-memory': patch +--- + +Fix storing tarballs with identical names from different packages in memory plugin diff --git a/packages/plugins/memory/src/memory-handler.ts b/packages/plugins/memory/src/memory-handler.ts index 01f29ad12..2fe990dde 100644 --- a/packages/plugins/memory/src/memory-handler.ts +++ b/packages/plugins/memory/src/memory-handler.ts @@ -1,5 +1,6 @@ import buildDebug from 'debug'; import { fs } from 'memfs'; +import path from 'path'; import { VerdaccioError, errorUtils } from '@verdaccio/core'; import { ReadTarball, UploadTarball } from '@verdaccio/streams'; @@ -35,7 +36,7 @@ class MemoryHandler implements IPackageStorageManager { this.data = data; this.name = packageName; this.logger = logger; - this.path = '/'; + this.path = `/${packageName}`; debug('initialized'); } @@ -113,40 +114,45 @@ class MemoryHandler implements IPackageStorageManager { } public writeTarball(name: string): IUploadTarball { - debug('write tarball %o', name); const uploadStream: IUploadTarball = new UploadTarball({}); - const temporalName = `/${name}`; + const temporalName = `${this.path}/${name}`; + debug('write tarball %o', temporalName); process.nextTick(function () { - fs.stat(temporalName, function (fileError, stats) { - if (!fileError && stats) { - return uploadStream.emit('error', errorUtils.getConflict()); + fs.mkdirp(path.dirname(temporalName), (mkdirpError) => { + if (mkdirpError) { + return uploadStream.emit('error', mkdirpError); } + fs.stat(temporalName, function (fileError, stats) { + if (!fileError && stats) { + return uploadStream.emit('error', errorUtils.getConflict()); + } - try { - const file = fs.createWriteStream(temporalName); + try { + const file = fs.createWriteStream(temporalName); - uploadStream.pipe(file); + uploadStream.pipe(file); - uploadStream.done = function (): void { - const onEnd = function (): void { - uploadStream.emit('success'); + uploadStream.done = function (): void { + const onEnd = function (): void { + uploadStream.emit('success'); + }; + + uploadStream.on('end', onEnd); }; - uploadStream.on('end', onEnd); - }; + uploadStream.abort = function (): void { + uploadStream.emit('error', errorUtils.getBadRequest('transmision aborted')); + file.end(); + }; - uploadStream.abort = function (): void { - uploadStream.emit('error', errorUtils.getBadRequest('transmision aborted')); - file.end(); - }; - - uploadStream.emit('open'); - return; - } catch (err: any) { - uploadStream.emit('error', err); - return; - } + uploadStream.emit('open'); + return; + } catch (err: any) { + uploadStream.emit('error', err); + return; + } + }); }); }); @@ -154,8 +160,8 @@ class MemoryHandler implements IPackageStorageManager { } public readTarball(name: string): IReadTarball { - const pathName = `/${name}`; - debug('read tarball %o', name); + const pathName = `${this.path}/${name}`; + debug('read tarball %o', pathName); const readTarballStream: IReadTarball = new ReadTarball({}); diff --git a/packages/plugins/memory/test/memory.spec.ts b/packages/plugins/memory/test/memory.spec.ts index 5fb9a5a2c..37489ed2c 100644 --- a/packages/plugins/memory/test/memory.spec.ts +++ b/packages/plugins/memory/test/memory.spec.ts @@ -299,6 +299,46 @@ describe('writing files', () => { }); } }); + + test('should support writting identical tarball filenames from different packages', (done) => { + const localMemory: IPluginStorage = new LocalMemory(config, defaultConfig); + const pkgName1 = 'package1'; + const pkgName2 = 'package2'; + const filename = 'tarball-3.0.0.tgz'; + const dataTarball1 = '12345'; + const dataTarball2 = '12345678'; + const handler = localMemory.getPackageStorage(pkgName1); + if (handler) { + const stream = handler.writeTarball(filename); + stream.on('data', (data) => { + expect(data.toString()).toBe(dataTarball1); + }); + stream.on('open', () => { + stream.done(); + stream.end(); + }); + stream.on('success', () => { + const handler = localMemory.getPackageStorage(pkgName2); + if (handler) { + const stream = handler.writeTarball(filename); + stream.on('data', (data) => { + expect(data.toString()).toBe(dataTarball2); + }); + stream.on('open', () => { + stream.done(); + stream.end(); + }); + stream.on('success', () => { + done(); + }); + + stream.write(dataTarball2); + } + }); + + stream.write(dataTarball1); + } + }); }); describe('reading files', () => {