@Override
  protected void putFolder(ArtifactContext context, File folder) throws RepositoryException {
    Node parent = getOrCreateParent(context);
    log.debug("Adding folder " + context + " to cache " + cache.getDisplayString());
    log.debug(" -> " + NodeUtils.getFullPath(parent));

    // fast-path for Herd
    if (!canHandleFolders()) {
      uploadZipped(parent, context, folder);
      return;
    }

    final String[] names = cache.getArtifactNames(context);
    if (names.length != 1) {
      throw new RepositoryException("ArtifactContext should have a single suffix");
    }
    final String label = names[0];
    if (parent instanceof OpenNode) {
      final OpenNode on = (OpenNode) parent;
      final OpenNode curent = on.createNode(label);
      try {
        for (File f : folder.listFiles()) // ignore folder, it should match new root
        putFiles(curent, f, context);
      } catch (RepositoryException e) {
        throw e;
      } catch (Exception e) {
        removeArtifact(context);
        throw new RepositoryException(e);
      }
    } else {
      throw new RepositoryException(
          "Cannot put folder [" + folder + "] to non-open node: " + context);
    }
    log.debug(" -> [done]");
  }
  protected void putFiles(OpenNode current, File file, ArtifactContext context) throws IOException {
    if (current == null)
      throw new IOException(
          "Null current, could probably not create new node for file: " + file.getParent());

    if (file.isDirectory()) {
      current = current.createNode(file.getName());
      for (File f : file.listFiles()) putFiles(current, f, context);
    } else {
      log.debug(" Adding file " + file.getPath() + " at " + NodeUtils.getFullPath(current));
      // Not the same file so we can add it
      try (InputStream in = new FileInputStream(file)) {
        current.addContent(file.getName(), in, context);
      }
      log.debug("  -> [done]");
    }
  }