Skip to content

Commit

Permalink
fix: error when writing tarball (missing folder) (#4594)
Browse files Browse the repository at this point in the history
* fix: error when writing tarball (missing folder)

* changeset
  • Loading branch information
mbtools committed Apr 25, 2024
1 parent 4ac3aea commit 1bae121
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/unlucky-cycles-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@verdaccio/local-storage': patch
---

fix: error when writing tarball (missing folder)
27 changes: 21 additions & 6 deletions packages/plugins/local-storage/src/local-fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ export default class LocalFS implements ILocalFSPackageManager {
public async writeTarball(fileName: string, { signal }): Promise<Writable> {
debug('write a tarball %o', fileName);
const pathName: string = this._getStorage(fileName);
await this.checkCreateFolder(pathName);
// create a temporary file to avoid conflicts or prev corruption files
const temporalName = path.join(
this.path,
Expand Down Expand Up @@ -352,8 +353,8 @@ export default class LocalFS implements ILocalFSPackageManager {
private async writeTempFileAndRename(dest: string, fileContent: string): Promise<any> {
const tempFilePath = tempFile(dest);
try {
// write file on temp locatio
// TODO: we need to handle when directory does not exist
// write file on temp location
await this.checkCreateFolder(tempFilePath);
await writeFilePromise(tempFilePath, fileContent);
debug('creating a new file:: %o', dest);
// rename tmp file to original
Expand All @@ -370,10 +371,7 @@ export default class LocalFS implements ILocalFSPackageManager {
debug('write file success %s', destiny);
} catch (err: any) {
if (err && err.code === noSuchFile) {
const dir = path.dirname(destiny);
// if fails, we create the folder for the package
debug('write file has failed, creating folder %s', dir);
await mkdirPromise(dir, { recursive: true });
await this.checkCreateFolder(destiny);
// we try again create the temp file
debug('writing a temp file %s', destiny);
await this.writeTempFileAndRename(destiny, fileContent);
Expand All @@ -385,6 +383,23 @@ export default class LocalFS implements ILocalFSPackageManager {
}
}

private async checkCreateFolder(pathName: string): Promise<void> {
// Check if folder exists and create it if not
const dir = path.dirname(pathName);
try {
await accessPromise(dir);
} catch (err: any) {
if (err.code === noSuchFile) {
debug('folder does not exist %o', dir);
await mkdirPromise(dir, { recursive: true });
debug('folder %o created', dir);
} else {
debug('error on check folder %o', dir);
throw err;
}
}
}

private async _lockAndReadJSON(name: string): Promise<Manifest> {
const fileName: string = this._getStorage(name);
debug('lock and read a file %o', fileName);
Expand Down
15 changes: 15 additions & 0 deletions packages/plugins/local-storage/tests/local-fs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,21 @@ describe('Local FS test', () => {
});
});

describe('writeTarballNextNoFolder', () => {
test('should write a tarball even if folder does not exist', (done) => {
const abort = new AbortController();
const tmp = path.join(localTempStorage, 'local-fs-write-tarball-new-folder');
const localFs = new LocalDriver(tmp, logger);
const readableStream = Readable.from('foooo');
localFs.writeTarball('juan-1.0.0.tgz', { signal: abort.signal }).then((stream) => {
stream.on('finish', () => {
done();
});
readableStream.pipe(stream);
});
});
});

describe('readTarballNext', () => {
test('should read a tarball', (done) => {
const abort = new AbortController();
Expand Down

0 comments on commit 1bae121

Please sign in to comment.