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); } } } } } }
@NonNull @Override protected void retrieve(@NonNull final SCMHeadObserver observer, @NonNull TaskListener listener) throws IOException, InterruptedException { String cacheEntry = getCacheEntry(); Lock cacheLock = getCacheLock(cacheEntry); cacheLock.lock(); try { File cacheDir = getCacheDir(cacheEntry); Git git = Git.with(listener, new EnvVars(System.getenv())) .in(cacheDir) .using(GitTool.getDefaultInstallation().getGitExe()); GitClient client = git.getClient(); client.addDefaultCredentials(getCredentials()); if (!client.hasGitRepo()) { listener.getLogger().println("Creating git repository in " + cacheDir); client.init(); } String remoteName = getRemoteName(); listener.getLogger().println("Setting " + remoteName + " to " + getRemote()); client.setRemoteUrl(remoteName, getRemote()); listener.getLogger().println("Fetching " + remoteName + "..."); List<RefSpec> refSpecs = getRefSpecs(); client.fetch(remoteName, refSpecs.toArray(new RefSpec[refSpecs.size()])); listener.getLogger().println("Pruning stale remotes..."); final Repository repository = client.getRepository(); try { client.prune(new RemoteConfig(repository.getConfig(), remoteName)); } catch (UnsupportedOperationException e) { e.printStackTrace(listener.error("Could not prune stale remotes")); } catch (URISyntaxException e) { e.printStackTrace(listener.error("Could not prune stale remotes")); } listener.getLogger().println("Getting remote branches..."); SCMSourceCriteria branchCriteria = getCriteria(); RevWalk walk = new RevWalk(repository); try { walk.setRetainBody(false); for (Branch b : client.getRemoteBranches()) { if (!b.getName().startsWith(remoteName + "/")) { continue; } final String branchName = StringUtils.removeStart(b.getName(), remoteName + "/"); listener.getLogger().println("Checking branch " + branchName); if (isExcluded(branchName)) { continue; } if (branchCriteria != null) { RevCommit commit = walk.parseCommit(b.getSHA1()); final long lastModified = TimeUnit.SECONDS.toMillis(commit.getCommitTime()); final RevTree tree = commit.getTree(); SCMSourceCriteria.Probe probe = new SCMSourceCriteria.Probe() { @Override public String name() { return branchName; } @Override public long lastModified() { return lastModified; } @Override public boolean exists(@NonNull String path) throws IOException { TreeWalk tw = TreeWalk.forPath(repository, path, tree); try { return tw != null; } finally { if (tw != null) { tw.release(); } } } }; if (branchCriteria.isHead(probe, listener)) { listener.getLogger().println("Met criteria"); } else { listener.getLogger().println("Does not meet criteria"); continue; } } SCMHead head = new SCMHead(branchName); SCMRevision hash = new SCMRevisionImpl(head, b.getSHA1String()); observer.observe(head, hash); if (!observer.isObserving()) { return; } } } finally { walk.dispose(); } listener.getLogger().println("Done."); } finally { cacheLock.unlock(); } }