/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.ant.jgit; import java.io.File; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryCache; import org.eclipse.jgit.lib.RepositoryCache.FileKey; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.filter.MaxCountRevFilter; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.AndTreeFilter; import org.eclipse.jgit.treewalk.filter.PathFilter; import org.eclipse.jgit.treewalk.filter.TreeFilter; import org.eclipse.jgit.util.FS; /** * @author Shuyang Zhou */ public class GitHeadHashTask extends Task { @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 void setGitDir(File gitDir) { _gitDir = gitDir; } public void setIgnoreFileName(String ignoreFileName) { _ignoreFileName = ignoreFileName; } public void setPath(String path) { _path = path; } public void setProperty(String property) { _property = property; } public void setUseCache(boolean useCache) { _useCache = useCache; } protected boolean hasIgnoreFile( Repository repository, RevCommit revCommit, String relativePath) throws Exception { if (_ignoreFileName == null) { return false; } try (TreeWalk treeWalk = new TreeWalk(repository)) { treeWalk.addTree(revCommit.getTree()); if (revCommit.getParentCount() > 0) { RevCommit parentRevCommit = revCommit.getParent(0); treeWalk.addTree(parentRevCommit.getTree()); } treeWalk.setRecursive(true); treeWalk.setFilter( AndTreeFilter.create( PathFilter.create(relativePath + "/" + _ignoreFileName), TreeFilter.ANY_DIFF)); return treeWalk.next(); } } private static final Map<String, String> _hashes = new ConcurrentHashMap<>(); private File _gitDir; private String _ignoreFileName; private String _path; private String _property; private boolean _useCache = true; }