// the RevWalk must be reset by the caller upon return! private ArrayList<RevCommit> findCommits( RevWalk walk, ArrayList<RevCommit> included, ArrayList<RevCommit> excluded, boolean getBody, long after) throws MissingObjectException, IncorrectObjectTypeException, IOException { ArrayList<RevCommit> commits = new ArrayList<RevCommit>(); commits.ensureCapacity(allBranches.size()); // heuristic workaround walk.sort(RevSort.COMMIT_TIME_DESC, true); walk.sort(RevSort.TOPO, true); walk.setRetainBody(getBody); if (after > 0) walk.setRevFilter(CommitTimeRevFilter.after(after)); else walk.setRevFilter(null); walk.markStart(included); RevCommit c; Iterator<RevCommit> it = excluded.iterator(); while (it.hasNext()) { walk.markUninteresting(it.next()); } it = walk.iterator(); while (it.hasNext()) { c = it.next(); if (getBody) walk.parseBody(c); // addUnique(commits, c); // commits are naturally ordered by SHA-1 commits.add(c); } return commits.size() > 0 ? commits : null; }
private void initRevPool(boolean reverse) { if (queue != null) throw new IllegalStateException(); if (revPool != null) revPool.release(); if (reverse) revPool = new ReverseWalk(getRepository()); else revPool = new RevWalk(getRepository()); revPool.setRetainBody(true); SEEN = revPool.newFlag("SEEN"); // $NON-NLS-1$ reader = revPool.getObjectReader(); treeWalk = new TreeWalk(reader); treeWalk.setRecursive(true); }
protected static RevCommit resolveCommitIdByTagName(Repository repository, String tagName) throws IOException, GitAPIException { if (tagName == null || tagName.isEmpty()) return null; RevCommit revCommit = null; Map<String, Ref> tagMap = repository.getTags(); Ref ref = tagMap.get(tagName); if (ref != null) { RevWalk walk = new RevWalk(repository); // some reduce memory effors as described in jgit user guide walk.setRetainBody(false); ObjectId from; from = repository.resolve("refs/heads/master"); if (from == null) { Git git = new Git(repository); String lastTagName = git.describe().call(); from = repository.resolve("refs/tags/" + lastTagName); } ObjectId to = repository.resolve("refs/remotes/origin/master"); if (from == null) { throw new IllegalStateException("cannot determinate start commit"); } walk.markStart(walk.parseCommit(from)); walk.markUninteresting(walk.parseCommit(to)); try { RevObject revObject = walk.parseAny(ref.getObjectId()); if (revObject != null) { revCommit = walk.parseCommit(revObject.getId()); } } finally { walk.close(); } } return revCommit; }
@Override public void execute() throws BuildException { if (_property == null) { throw new BuildException("Property attribute is required", getLocation()); } if (_path == null) { throw new BuildException("Path attribute is required", getLocation()); } File gitDir = PathUtil.getGitDir(_gitDir, getProject(), getLocation()); String relativePath = PathUtil.toRelativePath(gitDir, _path); if (_useCache) { String hash = _hashes.get(relativePath); if (hash != null) { Project currentProject = getProject(); currentProject.setNewProperty(_property, hash); return; } } try (Repository repository = RepositoryCache.open(FileKey.exact(gitDir, FS.DETECTED))) { RevWalk revWalk = new RevWalk(repository); revWalk.setRetainBody(false); revWalk.markStart(revWalk.parseCommit(repository.resolve(Constants.HEAD))); if (_ignoreFileName == null) { revWalk.setRevFilter(MaxCountRevFilter.create(1)); } else { revWalk.setRevFilter(MaxCountRevFilter.create(2)); } revWalk.setTreeFilter( AndTreeFilter.create(PathFilter.create(relativePath), TreeFilter.ANY_DIFF)); RevCommit revCommit = revWalk.next(); if (revCommit == null) { throw new IllegalStateException("Unable to find any commit under " + _path); } if (hasIgnoreFile(repository, revCommit, relativePath)) { RevCommit secondRevCommit = revWalk.next(); if (secondRevCommit != null) { revCommit = secondRevCommit; } } Project currentProject = getProject(); String hash = revCommit.name(); currentProject.setNewProperty(_property, hash); if (_useCache) { _hashes.put(relativePath, hash); } revWalk.dispose(); } catch (Exception e) { throw new BuildException("Unable to get head hash for path " + _path, e); } }
public String getProjectVersion(File repoDir) throws IOException, GitAPIException { Git git = Git.open(repoDir); Repository repo = git.getRepository(); // Find base commit between current branch and "master": String branch = repo.getBranch(); RevCommit base = CommitUtils.getBase(repo, "master", branch); CommitCountFilter count = new CommitCountFilter(); CommitFinder finder = new CommitFinder(repo).setFilter(count); finder.findBetween(branch, base); long commitsSinceBase = count.getCount(); // Find tags in "master" before base commit: RevWalk rw = new RevWalk(repo); rw.markStart(base); rw.setRetainBody(false); Ref master = repo.getRef("master"); List<Ref> masterAsList = Arrays.asList(master); List<Ref> tags = git.tagList().call(); Map<RevCommit, Ref> masterTags = new HashMap<RevCommit, Ref>(); for (Ref tag : tags) { tag = repo.peel(tag); ObjectId commitID = tag.getPeeledObjectId(); if (commitID == null) continue; RevCommit commit = rw.parseCommit(commitID); // Only remember tags reachable from "master": if (!RevWalkUtils.findBranchesReachableFrom(commit, rw, masterAsList).isEmpty()) { masterTags.put(commit, tag); } } // Find the shortest distance in commits between base tag in "master": long commitsBetweenBaseAndTag = Long.MAX_VALUE; String tagName = ""; for (RevCommit tagCommit : masterTags.keySet()) { count.reset(); finder.findBetween(base, tagCommit); if (count.getCount() < commitsBetweenBaseAndTag) { commitsBetweenBaseAndTag = count.getCount(); tagName = masterTags.get(tagCommit).getName(); } } if (commitsBetweenBaseAndTag == Long.MAX_VALUE) { // If no tag, get total number of commits: commitsBetweenBaseAndTag = repo.getRefDatabase().getRefs("").size(); } long commitsSinceLastMasterTag = commitsSinceBase + commitsBetweenBaseAndTag; // Construct version string: String version = branch.equals("master") ? "" : (branch + "-"); if (tagName.startsWith("refs/tags/")) { tagName = tagName.substring("refs/tags/".length()); } // v1.1 -> 1.1 if (tagName.matches("v\\d+.*")) { tagName = tagName.substring(1); } if (tagName.isEmpty()) { version = "0"; } version += tagName + ((!tagonly) ? "." + commitsSinceLastMasterTag : ""); return version; }
@Override public Document execute( Repository repository, Git git, CallSpecification spec, DocumentWriter writer, Values values) throws GitAPIException, IOException { if (spec.parameterCount() == 0) { // This is the top-level "/branches" node writer.setPrimaryType(GitLexicon.TREES); // Generate the child references to the branches and tags. Branches are likely used more // often, so list them first... addBranchesAsChildren(git, spec, writer); addTagsAsChildren(git, spec, writer); addCommitsAsChildren(git, spec, writer, pageSize); } else if (spec.parameterCount() == 1) { // This is a particular branch/tag/commit node ... String branchOrTagOrObjectId = spec.parameter(0); ObjectId objId = resolveBranchOrTagOrCommitId(repository, branchOrTagOrObjectId); RevWalk walker = new RevWalk(repository); walker.setRetainBody(true); // we need to parse the commit for the top-level try { RevCommit commit = walker.parseCommit(objId); // Add the properties for this node ... String committer = commit.getCommitterIdent().getName(); String author = commit.getAuthorIdent().getName(); DateTime committed = values.dateFrom(commit.getCommitTime()); writer.setPrimaryType(GitLexicon.FOLDER); writer.addProperty(JcrLexicon.CREATED, committed); writer.addProperty(JcrLexicon.CREATED_BY, committer); writer.addProperty(GitLexicon.OBJECT_ID, objId.name()); writer.addProperty(GitLexicon.AUTHOR, author); writer.addProperty(GitLexicon.COMMITTER, committer); writer.addProperty(GitLexicon.COMMITTED, committed); writer.addProperty(GitLexicon.TITLE, commit.getShortMessage()); writer.addProperty( GitLexicon.HISTORY, GitHistory.referenceToHistory(objId, branchOrTagOrObjectId, values)); writer.addProperty(GitLexicon.DETAIL, GitCommitDetails.referenceToCommit(objId, values)); // Add the top-level children of the directory ... addInformationForPath(repository, git, writer, commit, "", spec, values); } finally { walker.dispose(); } } else { // This is a folder or file within the directory structure ... String branchOrTagOrObjectId = spec.parameter(0); String path = spec.parametersAsPath(1); ObjectId objId = resolveBranchOrTagOrCommitId(repository, branchOrTagOrObjectId); RevWalk walker = new RevWalk(repository); walker.setRetainBody(false); // we don't need top-level commit information try { // Get the commit information ... RevCommit commit = walker.parseCommit(objId); // Add the top-level children of the directory ... addInformationForPath(repository, git, writer, commit, path, spec, values); } finally { walker.dispose(); } } return writer.document(); }
@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(); } }