mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-03-11 02:15:57 -05:00
fix: error when writing tarball (missing folder) (#4594)
* fix: error when writing tarball (missing folder) * changeset
This commit is contained in:
parent
4ac3aead4f
commit
1bae121dc2
3 changed files with 41 additions and 6 deletions
5
.changeset/unlucky-cycles-sparkle.md
Normal file
5
.changeset/unlucky-cycles-sparkle.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@verdaccio/local-storage': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: error when writing tarball (missing folder)
|
|
@ -237,6 +237,7 @@ export default class LocalFS implements ILocalFSPackageManager {
|
||||||
public async writeTarball(fileName: string, { signal }): Promise<Writable> {
|
public async writeTarball(fileName: string, { signal }): Promise<Writable> {
|
||||||
debug('write a tarball %o', fileName);
|
debug('write a tarball %o', fileName);
|
||||||
const pathName: string = this._getStorage(fileName);
|
const pathName: string = this._getStorage(fileName);
|
||||||
|
await this.checkCreateFolder(pathName);
|
||||||
// create a temporary file to avoid conflicts or prev corruption files
|
// create a temporary file to avoid conflicts or prev corruption files
|
||||||
const temporalName = path.join(
|
const temporalName = path.join(
|
||||||
this.path,
|
this.path,
|
||||||
|
@ -352,8 +353,8 @@ export default class LocalFS implements ILocalFSPackageManager {
|
||||||
private async writeTempFileAndRename(dest: string, fileContent: string): Promise<any> {
|
private async writeTempFileAndRename(dest: string, fileContent: string): Promise<any> {
|
||||||
const tempFilePath = tempFile(dest);
|
const tempFilePath = tempFile(dest);
|
||||||
try {
|
try {
|
||||||
// write file on temp locatio
|
// write file on temp location
|
||||||
// TODO: we need to handle when directory does not exist
|
await this.checkCreateFolder(tempFilePath);
|
||||||
await writeFilePromise(tempFilePath, fileContent);
|
await writeFilePromise(tempFilePath, fileContent);
|
||||||
debug('creating a new file:: %o', dest);
|
debug('creating a new file:: %o', dest);
|
||||||
// rename tmp file to original
|
// rename tmp file to original
|
||||||
|
@ -370,10 +371,7 @@ export default class LocalFS implements ILocalFSPackageManager {
|
||||||
debug('write file success %s', destiny);
|
debug('write file success %s', destiny);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err && err.code === noSuchFile) {
|
if (err && err.code === noSuchFile) {
|
||||||
const dir = path.dirname(destiny);
|
await this.checkCreateFolder(destiny);
|
||||||
// if fails, we create the folder for the package
|
|
||||||
debug('write file has failed, creating folder %s', dir);
|
|
||||||
await mkdirPromise(dir, { recursive: true });
|
|
||||||
// we try again create the temp file
|
// we try again create the temp file
|
||||||
debug('writing a temp file %s', destiny);
|
debug('writing a temp file %s', destiny);
|
||||||
await this.writeTempFileAndRename(destiny, fileContent);
|
await this.writeTempFileAndRename(destiny, fileContent);
|
||||||
|
@ -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> {
|
private async _lockAndReadJSON(name: string): Promise<Manifest> {
|
||||||
const fileName: string = this._getStorage(name);
|
const fileName: string = this._getStorage(name);
|
||||||
debug('lock and read a file %o', fileName);
|
debug('lock and read a file %o', fileName);
|
||||||
|
|
|
@ -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', () => {
|
describe('readTarballNext', () => {
|
||||||
test('should read a tarball', (done) => {
|
test('should read a tarball', (done) => {
|
||||||
const abort = new AbortController();
|
const abort = new AbortController();
|
||||||
|
|
Loading…
Add table
Reference in a new issue