feat(fs/mk{dir,tree}): new methods to create dirs (#3763)

This commit is contained in:
Julien Fontanet 2018-12-06 18:50:39 +01:00 committed by GitHub
parent 11cff2c065
commit 10d4782ee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 8 deletions

View File

@ -12,7 +12,7 @@ import { type Readable, type Writable } from 'stream'
import { createChecksumStream, validChecksumOfReadStream } from './checksum'
const { resolve } = path.posix
const { dirname, resolve } = path.posix
type Data = Buffer | Readable | string
type FileDescriptor = {| fd: mixed, path: string |}
@ -235,6 +235,24 @@ export default class RemoteHandlerAbstract {
return entries
}
async mkdir(dir: string): Promise<void> {
dir = normalizePath(dir)
try {
await this._mkdir(dir)
} catch (error) {
if (error == null || error.code !== 'EEXIST') {
throw error
}
// this operation will throw if it's not already a directory
await this._list(dir)
}
}
async mktree(dir: string): Promise<void> {
await this._mktree(normalizePath(dir))
}
async openFile(path: string, flags?: string): Promise<FileDescriptor> {
path = normalizePath(path)
@ -382,6 +400,23 @@ export default class RemoteHandlerAbstract {
throw new Error('Not implemented')
}
async _mkdir(dir: string): Promise<void> {
throw new Error('Not implemented')
}
async _mktree(dir: string): Promise<void> {
try {
return await this.mkdir(dir)
} catch (error) {
if (error.code !== 'ENOENT') {
throw error
}
}
await this._mktree(dirname(dir))
return this._mktree(dir)
}
async _openFile(path: string, flags?: string): Promise<mixed> {
throw new Error('Not implemented')
}

View File

@ -57,9 +57,7 @@ handlers.forEach(url => {
beforeEach(async () => {
// ensure test dir exists
// TODO: replace with mkdir
await handler.outputFile('file', '')
await handler.unlink('file')
await handler.mkdir('.')
})
afterEach(async () => {
await handler.rmtree('.')
@ -146,6 +144,49 @@ handlers.forEach(url => {
})
})
describe('#mkdir()', () => {
it('creates a directory', async () => {
await handler.mkdir('dir')
await expect(await handler.list('.')).toEqual(['dir'])
})
it('does not throw on existing directory', async () => {
await handler.mkdir('dir')
await handler.mkdir('dir')
})
it('throws ENOTDIR on existing file', async () => {
await handler.outputFile('file', '')
const error = await rejectionOf(handler.mkdir('file'))
expect(error.code).toBe('ENOTDIR')
})
})
describe('#mktree()', () => {
it('creates a tree of directories', async () => {
await handler.mktree('dir/dir')
await expect(await handler.list('.')).toEqual(['dir'])
await expect(await handler.list('dir')).toEqual(['dir'])
})
it('does not throw on existing directory', async () => {
await handler.mktree('dir/dir')
await handler.mktree('dir/dir')
})
it('throws ENOTDIR on existing file', async () => {
await handler.outputFile('dir/file', '')
const error = await rejectionOf(handler.mktree('dir/file'))
expect(error.code).toBe('ENOTDIR')
})
it('throws ENOTDIR on existing file in path', async () => {
await handler.outputFile('file', '')
const error = await rejectionOf(handler.mktree('file/dir'))
expect(error.code).toBe('ENOTDIR')
})
})
describe('#outputFile()', () => {
it('writes data to a file', async () => {
await handler.outputFile('file', TEST_DATA)
@ -183,10 +224,7 @@ handlers.forEach(url => {
describe('#rmdir()', () => {
it('should remove an empty directory', async () => {
// TODO: replace with mkdir
await handler.outputFile('dir/file', '')
await handler.unlink('dir/file')
await handler.mkdir('dir')
await handler.rmdir('dir')
expect(await handler.list('.')).toEqual([])
})

View File

@ -54,6 +54,10 @@ export default class LocalHandler extends RemoteHandlerAbstract {
return fs.readdir(this._getFilePath(dir))
}
_mkdir(dir) {
return fs.mkdir(this._getFilePath(dir))
}
async _openFile(path, flags) {
return fs.open(this._getFilePath(path), flags)
}

View File

@ -163,6 +163,17 @@ export default class SmbHandler extends RemoteHandlerAbstract {
}
}
async _mkdir(dir) {
const client = this._getClient()
try {
return await client.mkdir(this._getFilePath(dir))
} catch (error) {
throw normalizeError(error, true)
} finally {
client.disconnect()
}
}
// TODO: add flags
async _openFile(path) {
const client = this._getClient()