Skip to content

Commit

Permalink
Merge pull request #777 from cozy-labs/create-missing-remote-folders
Browse files Browse the repository at this point in the history
Create missing remote folders
  • Loading branch information
sebn authored Jul 31, 2017
2 parents 8ca98b7 + a1b2a24 commit 4e32035
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 5 deletions.
18 changes: 18 additions & 0 deletions cli/src/remote/cozy.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { composeAsync } from '../utils/func'

import type { RemoteDoc, RemoteDeletion } from './document'

const { posix } = path

const log = logger({
component: 'RemoteCozy'
})
Expand Down Expand Up @@ -136,6 +138,22 @@ export default class RemoteCozy {
return {...results[0], _type: FILES_DOCTYPE}
}

// FIXME: created_at is returned by some methods, but not all of them

async findOrCreateDirectoryByPath (path: string): Promise<RemoteDoc> {
try {
return await this.findDirectoryByPath(path)
} catch (err) {
if (!(err instanceof DirectoryNotFound)) throw err

const name = posix.basename(path)
const parentPath = posix.dirname(path)
const parentDir: RemoteDoc = await this.findOrCreateDirectoryByPath(parentPath)
const dirID = parentDir._id
return this.createDirectory({name, dirID})
}
}

async downloadBinary (id: string): Promise<Readable> {
const resp = await this.client.files.downloadById(id)
return resp.body
Expand Down
4 changes: 2 additions & 2 deletions cli/src/remote/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export default class Remote implements Side {
log.info({path}, 'Creating folder...')

const [parentPath, name] = conversion.extractDirAndName(doc.path)
const parent: RemoteDoc = await this.remoteCozy.findDirectoryByPath(parentPath)
const parent: RemoteDoc = await this.remoteCozy.findOrCreateDirectoryByPath(parentPath)
let dir: RemoteDoc

try {
Expand Down Expand Up @@ -91,7 +91,7 @@ export default class Remote implements Side {
log.info({path}, 'Uploading new file...')
const stream = await this.other.createReadStreamAsync(doc)
const [dirPath, name] = conversion.extractDirAndName(path)
const dir = await this.remoteCozy.findDirectoryByPath(dirPath)
const dir = await this.remoteCozy.findOrCreateDirectoryByPath(dirPath)

// Emit events to track the upload progress
let info = clone(doc)
Expand Down
2 changes: 1 addition & 1 deletion cli/test/builders/metadata/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default class BaseMetadataBuilder {
sides: MetadataSidesInfo
}

constructor (pouch?: Pouch) {
constructor (pouch: ?Pouch) {
this.pouch = pouch
this.opts = {
path: 'foo',
Expand Down
4 changes: 2 additions & 2 deletions cli/test/builders/metadata/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import DirMetadataBuilder from './dir'
import FileMetadataBuilder from './file'

export default class MetadataBuilders {
pouch: Pouch
pouch: ?Pouch

constructor (pouch: Pouch) {
constructor (pouch: ?Pouch) {
this.pouch = pouch
}

Expand Down
49 changes: 49 additions & 0 deletions cli/test/unit/remote/cozy.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,55 @@ describe('RemoteCozy', function () {
})
})

describe('findOrCreateDirectoryByPath', () => {
it('resolves with the exisisting directory if any', async function () {
const root = await remoteCozy.findDirectoryByPath('/')
const dir = await builders.remoteDir().create()
const subdir = await builders.remoteDir().inDir(dir).create()

let result = await remoteCozy.findOrCreateDirectoryByPath(root.path)
should(result).have.properties(root)
result = await remoteCozy.findOrCreateDirectoryByPath(dir.path)
should(result).have.properties(dir)
result = await remoteCozy.findOrCreateDirectoryByPath(subdir.path)
should(result).have.properties(subdir)
})

it('creates any missing parent directory', async function () {
const dir = await builders.remoteDir().named('dir').create()
await builders.remoteDir().named('subdir').inDir(dir).create()

let result = await remoteCozy.findOrCreateDirectoryByPath('/dir/subdir/foo')
should(result).have.properties({
type: 'directory',
path: '/dir/subdir/foo'
})
result = await remoteCozy.findOrCreateDirectoryByPath('/dir/bar/baz')
should(result).have.properties({
type: 'directory',
path: '/dir/bar/baz'
})
result = await remoteCozy.findOrCreateDirectoryByPath('/foo/bar/qux')
should(result).have.properties({
type: 'directory',
path: '/foo/bar/qux'
})
})

it('does not swallow errors', async function () {
this.config.cozyUrl = cozyStackDouble.url()
const remoteCozy = new RemoteCozy(this.config)

cozyStackDouble.stub((req, res) => {
res.writeHead(500, {'Content-Type': 'text/plain'})
res.end('Whatever')
})

await should(remoteCozy.findOrCreateDirectoryByPath('/whatever'))
.be.rejected()
})
})

describe('downloadBinary', function () {
it('resolves with a Readable stream of the file content', async function () {
const remoteFile = await builders.remoteFile().data('foo').create()
Expand Down
15 changes: 15 additions & 0 deletions cli/test/unit/remote/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ import timestamp from '../../../src/timestamp'
import type { Metadata } from '../../../src/metadata'
import type { RemoteDoc, JsonApiDoc } from '../../../src/remote/document'

import MetadataBuilders from '../../builders/metadata'
import configHelpers from '../../helpers/config'
import pouchHelpers from '../../helpers/pouch'
import {
cozy, builders, deleteAll, createTheCouchdbFolder
} from '../../helpers/cozy'

const metadataBuilders = new MetadataBuilders()

describe('Remote', function () {
if (process.env.APPVEYOR) {
it('is unstable on AppVeyor')
Expand Down Expand Up @@ -423,6 +426,12 @@ describe('Remote', function () {
size: '36901'
})
})

it('creates the parent folder when missing', async function () {
const metadata: Metadata = metadataBuilders.fileMetadata().path('foo/bar/qux').build()
await this.remote.addFileAsync(metadata)
await should(cozy.files.statByPath('/foo/bar')).be.fulfilled()
})
})

describe('addFolderAsync', () => {
Expand Down Expand Up @@ -460,6 +469,12 @@ describe('Remote', function () {
_rev: remoteDir._rev
})
})

it('creates the parent folder when missing', async function () {
const metadata: Metadata = metadataBuilders.dirMetadata().path('foo/bar/qux').build()
await this.remote.addFolderAsync(metadata)
await should(cozy.files.statByPath('/foo/bar')).be.fulfilled()
})
})

describe('overwriteFileAsync', function () {
Expand Down

0 comments on commit 4e32035

Please sign in to comment.