/** {@inheritDoc} */
 @Override
 protected SCMRevision retrieve(String unparsedRevision, TaskListener listener)
     throws IOException, InterruptedException {
   try {
     listener.getLogger().println("Opening connection to " + remoteBase);
     SVNURL repoURL = SVNURL.parseURIEncoded(remoteBase);
     SVNRepositoryView repository = openSession(repoURL);
     String repoPath =
         SubversionSCM.DescriptorImpl.getRelativePath(repoURL, repository.getRepository());
     String base;
     long revision;
     Matcher pathAtRev = Pattern.compile("(.+)@(\\d+)").matcher(unparsedRevision);
     if (pathAtRev.matches()) {
       base = pathAtRev.group(1);
       revision = Long.parseLong(pathAtRev.group(2));
     } else {
       base = unparsedRevision;
       revision = -1;
     }
     String path = SVNPathUtil.append(repoPath, base);
     long resolvedRevision = repository.getNode(path, -1).getRevision();
     if (resolvedRevision == -1) {
       listener.getLogger().println("Could not find " + path);
       return null;
     }
     return new SCMRevisionImpl(new SCMHead(base), revision == -1 ? resolvedRevision : revision);
   } catch (SVNException e) {
     throw new IOException(e);
   }
 }
  /** {@inheritDoc} */
  @NonNull
  @Override
  protected void retrieve(@NonNull final SCMHeadObserver observer, @NonNull TaskListener listener)
      throws IOException {
    SVNRepositoryView repository = null;
    try {
      listener.getLogger().println("Opening conection to " + remoteBase);
      SVNURL repoURL = SVNURL.parseURIEncoded(remoteBase);
      repository = openSession(repoURL);

      String repoPath =
          SubversionSCM.DescriptorImpl.getRelativePath(repoURL, repository.getRepository());
      List<String> prefix = Collections.emptyList();
      fetch(
          listener,
          repository,
          -1,
          repoPath,
          toPaths(splitCludes(includes)),
          prefix,
          prefix,
          toPaths(splitCludes(excludes)),
          getCriteria(),
          observer);
    } catch (SVNException e) {
      e.printStackTrace(listener.error("Could not communicate with Subversion server"));
      throw new IOException(e);
    } finally {
      closeSession(repository);
    }
  }
 public synchronized String getUuid() {
   if (uuid == null) {
     SVNRepositoryView repository = null;
     try {
       SVNURL repoURL = SVNURL.parseURIEncoded(remoteBase);
       repository = openSession(repoURL);
       uuid = repository.getUuid();
     } catch (SVNException e) {
       LOGGER.log(
           Level.WARNING,
           "Could not connect to remote repository " + remoteBase + " to determine UUID",
           e);
     } finally {
       closeSession(repository);
     }
   }
   return uuid;
 }
 /** {@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);
            }
          }
        }
      }
    }
  }
 private static void closeSession(@CheckForNull SVNRepositoryView repository) {
   if (repository != null) {
     repository.close();
   }
 }