private void deleteRepoFileRecursively(
      final LocalRepoTransaction transaction, final RepoFile repoFile) {
    final RepoFileDao repoFileDao = transaction.getDao(RepoFileDao.class);
    for (final RepoFile childRepoFile : repoFileDao.getChildRepoFiles(repoFile))
      deleteRepoFileRecursively(transaction, childRepoFile);

    repoFileDao.deletePersistent(repoFile);
  }
  protected void createAndPersistPreliminaryCollision(
      final LocalRepoManager localRepoManager,
      final File file,
      String localPath,
      Uid cryptoRepoFileId) {
    assertNotNull("localRepoManager", localRepoManager);
    if (localPath == null) assertNotNull("localPath/file", file);

    logger.debug(
        "createAndPersistPreliminaryCollision: localRoot='{}' localRepositoryId={} file='{}' localPath='{}' cryptoRepoFileId={}",
        localRepoManager.getLocalRoot(),
        getRepositoryId(),
        (file == null ? "" : file.getAbsolutePath()),
        (localPath == null ? "" : localPath),
        cryptoRepoFileId);

    try (final LocalRepoTransaction tx = localRepoManager.beginWriteTransaction(); ) {
      if (localPath == null)
        localPath =
            '/'
                + localRepoManager
                    .getLocalRoot()
                    .relativize(file)
                    .replace(FILE_SEPARATOR_CHAR, '/');

      final PreliminaryCollisionDao pcDao = tx.getDao(PreliminaryCollisionDao.class);

      PreliminaryCollision preliminaryCollision = pcDao.getPreliminaryCollision(localPath);
      if (preliminaryCollision == null) {
        preliminaryCollision = new PreliminaryCollision();
        preliminaryCollision.setPath(localPath);
        preliminaryCollision = pcDao.makePersistent(preliminaryCollision);
      }

      final CryptoRepoFileDao crfDao = tx.getDao(CryptoRepoFileDao.class);
      if (cryptoRepoFileId != null) {
        CryptoRepoFile cryptoRepoFile = crfDao.getCryptoRepoFileOrFail(cryptoRepoFileId);
        preliminaryCollision.setCryptoRepoFile(cryptoRepoFile);
      } else if (file != null) {
        final RepoFileDao rfDao = tx.getDao(RepoFileDao.class);
        final RepoFile repoFile = rfDao.getRepoFile(localRepoManager.getLocalRoot(), file);
        if (repoFile != null) {
          final CryptoRepoFile cryptoRepoFile = crfDao.getCryptoRepoFileOrFail(repoFile);
          preliminaryCollision.setCryptoRepoFile(cryptoRepoFile);
        }
      }

      tx.commit();
    } catch (IOException x) {
      throw new RuntimeException(x);
    }
  }
  @Override
  protected RepoFile syncRepoFile(final LocalRepoTransaction transaction, final File file) {
    assertNotNull("transaction", transaction);
    assertNotNull("file", file);

    final File localRoot = getLocalRepoManager().getLocalRoot();
    final RepoFileDao rfDao = transaction.getDao(RepoFileDao.class);
    RepoFile repoFile = rfDao.getRepoFile(localRoot, file);
    // If the type changed, we must delete the RepoFile here before invoking the super-method,
    // because this would otherwise cause an invocation of Cryptree.preDelete(...) causing
    // the actual file to be deleted.

    if (repoFile != null
        && !LocalRepoSync.create(transaction).isRepoFileTypeCorrect(repoFile, file)) {
      rfDao.deletePersistent(repoFile);
      repoFile = null;
      transaction.flush();
    }
    repoFile = super.syncRepoFile(transaction, file);
    return repoFile;
  }
  @Override
  public void delete(String path) {
    if (isMetaOnly()) {
      path = prefixPath(path);
      final File localRoot = getLocalRepoManager().getLocalRoot();
      try (final LocalRepoTransaction transaction =
          getLocalRepoManager().beginWriteTransaction(); ) {
        final RepoFileDao repoFileDao = transaction.getDao(RepoFileDao.class);
        final File file = getFile(path);
        final RepoFile repoFile = repoFileDao.getRepoFile(localRoot, file);
        if (repoFile != null) deleteRepoFileRecursively(transaction, repoFile);

        transaction.commit();
      }
    } else {
      try {
        super.delete(path);
      } catch (CollisionException x) {
        clearCryptoRepoFileDeleted(path);
        throw x;
      }
    }
  }