/** {@inheritDoc} */
 @Override
 protected SCMRevision retrieve(@NonNull SCMHead head, @NonNull TaskListener listener)
     throws IOException {
   SVNRepositoryView repository = null;
   try {
     listener.getLogger().println("Opening connection to " + remoteBase);
     SVNURL repoURL = SVNURL.parseURIEncoded(remoteBase);
     repository = openSession(repoURL);
     String repoPath =
         SubversionSCM.DescriptorImpl.getRelativePath(repoURL, repository.getRepository());
     String path = SVNPathUtil.append(repoPath, head.getName());
     SVNRepositoryView.NodeEntry svnEntry = repository.getNode(path, -1);
     return new SCMRevisionImpl(head, svnEntry.getRevision());
   } catch (SVNException e) {
     throw new IOException(e);
   } finally {
     closeSession(repository);
   }
 }
  void fetch(
      @NonNull TaskListener listener,
      @NonNull final SVNRepositoryView repository,
      long rev,
      @NonNull final String repoPath,
      @NonNull SortedSet<List<String>> paths,
      @NonNull List<String> prefix,
      @NonNull List<String> realPath,
      @NonNull SortedSet<List<String>> excludedPaths,
      @CheckForNull SCMSourceCriteria branchCriteria,
      @NonNull SCMHeadObserver observer)
      throws IOException, SVNException {
    String svnPath = SVNPathUtil.append(repoPath, StringUtils.join(realPath, '/'));
    assert prefix.size() == realPath.size();
    assert wildcardStartsWith(realPath, prefix);
    SortedMap<List<String>, SortedSet<List<String>>> includePaths = groupPaths(paths, prefix);
    listener
        .getLogger()
        .println("Checking directory " + svnPath + (rev > -1 ? "@" + rev : "@HEAD"));
    SVNRepositoryView.NodeEntry node = repository.getNode(svnPath, rev);
    if (!SVNNodeKind.DIR.equals(node.getType()) || node.getChildren() == null) {
      return;
    }
    for (Map.Entry<List<String>, SortedSet<List<String>>> entry : includePaths.entrySet()) {
      for (List<String> path : entry.getValue()) {
        String name = path.get(prefix.size());
        SVNRepositoryView.ChildEntry[] children = node.getChildren().clone();
        Arrays.sort(
            children,
            new Comparator<SVNRepositoryView.ChildEntry>() {
              public int compare(SVNRepositoryView.ChildEntry o1, SVNRepositoryView.ChildEntry o2) {
                long diff = o2.getRevision() - o1.getRevision();
                return diff < 0 ? -1 : diff > 0 ? 1 : 0;
              }
            });
        for (final SVNRepositoryView.ChildEntry svnEntry : children) {
          if (svnEntry.getType() == SVNNodeKind.DIR && isMatch(svnEntry.getName(), name)) {
            List<String> childPrefix = copyAndAppend(prefix, name);
            List<String> childRealPath = copyAndAppend(realPath, svnEntry.getName());
            if (wildcardStartsWith(childRealPath, excludedPaths)) {
              continue;
            }
            if (path.equals(childPrefix)) {
              final String childPath = StringUtils.join(childRealPath, '/');
              final String candidateRootPath = SVNPathUtil.append(repoPath, childPath);
              final long candidateRevision = svnEntry.getRevision();
              final long lastModified = svnEntry.getLastModified();
              listener
                  .getLogger()
                  .println(
                      "Checking candidate branch " + candidateRootPath + "@" + candidateRevision);
              if (branchCriteria == null
                  || branchCriteria.isHead(
                      new SCMSourceCriteria.Probe() {
                        @Override
                        public String name() {
                          return childPath;
                        }

                        @Override
                        public long lastModified() {
                          return lastModified;
                        }

                        @Override
                        public boolean exists(@NonNull String path) throws IOException {
                          try {
                            return repository.checkPath(
                                    SVNPathUtil.append(candidateRootPath, path), candidateRevision)
                                != SVNNodeKind.NONE;
                          } catch (SVNException e) {
                            throw new IOException(e);
                          }
                        }
                      },
                      listener)) {
                listener.getLogger().println("Met criteria");
                SCMHead head = new SCMHead(childPath);
                observer.observe(head, new SCMRevisionImpl(head, svnEntry.getRevision()));
                if (!observer.isObserving()) {
                  return;
                }
              } else {
                listener.getLogger().println("Does not meet criteria");
              }
            } else {
              fetch(
                  listener,
                  repository,
                  svnEntry.getRevision(),
                  repoPath,
                  paths,
                  childPrefix,
                  childRealPath,
                  excludedPaths,
                  branchCriteria,
                  observer);
            }
          }
        }
      }
    }
  }