async function forkDrive (srcDriveUrl, opts = {}) {
  srcDriveUrl = fromKeyToURL(srcDriveUrl)

  // get the source drive
  var srcDrive
  var downloadRes = await Promise.race([
    (async function () {
      srcDrive = await getOrLoadDrive(srcDriveUrl)
      if (!srcDrive) {
        throw new Error('Invalid drive key')
      }
      // return srcDrive.session.drive.download('/') TODO needed?
    })(),
    new Promise(r => setTimeout(() => r('timeout'), 60e3))
  ])
  if (downloadRes === 'timeout') {
    throw new TimeoutError('Timed out while downloading source drive')
  }

  // fetch source drive meta
  var srcManifest = await srcDrive.pda.readManifest().catch(_ => {})
  srcManifest = srcManifest || {}

  // override any opts data
  var dstManifest = {
    title: (opts.title) ? opts.title : srcManifest.title,
    description: (opts.description) ? opts.description : srcManifest.description,
    forkOf: opts.detached ? undefined : fromKeyToURL(srcDriveUrl)
    // author: manifest.author
  }
  for (let k in srcManifest) {
    if (k === 'author') continue
    if (!dstManifest[k]) {
      dstManifest[k] = srcManifest[k]
    }
  }

  // create the new drive
  var dstDrive = await createNewDrive(dstManifest)

  // copy files
  var ignore = ['/.dat', '/.git', '/index.json']
  await pda.exportArchiveToArchive({
    srcArchive: srcDrive.session.drive,
    dstArchive: dstDrive.session.drive,
    skipUndownloadedFiles: false,
    ignore
  })

  return dstDrive
}
@param {string} srcDriveUrl
@param {Object} [opts]
@returns {Promise<DaemonHyperdrive>}