/** * 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.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.condition.Condition; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryCache; import org.eclipse.jgit.lib.RepositoryCache.FileKey; import org.eclipse.jgit.util.FS; /** * @author Shuyang Zhou */ public class GitUpToDateTask extends Task implements Condition { @Override public boolean eval() throws BuildException { if (_path == null) { throw new BuildException( "Path attribute is required", getLocation()); } if (_since == null) { throw new BuildException( "Since attribute is required", getLocation()); } try { Map<String, Boolean> upToDateMap = loadUpToDateCache(); File gitDir = PathUtil.getGitDir( _gitDir, getProject(), getLocation()); String relativePath = PathUtil.toRelativePath(gitDir, _path); if (upToDateMap == null) { log( "Unable to load cache file, fallback to up to date " + "checking", Project.MSG_VERBOSE); } else { Boolean upToDate = upToDateMap.get(relativePath); if (upToDate == null) { log( "Cache missed for " + relativePath + ", fallback to up to date checking", Project.MSG_VERBOSE); } else { return upToDate; } } try (Repository repository = RepositoryCache.open( FileKey.exact(gitDir, FS.DETECTED))) { if (UpToDateUtil.isClean(new Git(repository), relativePath) && !UpToDateUtil.hasChangedSince( repository, relativePath, _since, _ignoredMessagePattern)) { return true; } return false; } catch (Exception e) { throw new BuildException( "Unable to check cleanness for path " + _path, e); } } catch (IOException ioe) { throw new BuildException(ioe); } } @Override public void execute() throws BuildException { if (_property == null) { throw new BuildException( "Property attribute is required", getLocation()); } if (eval()) { Project currentProject = getProject(); if (_value == null) { currentProject.setNewProperty(_property, "true"); } else { currentProject.setNewProperty(_property, _value); } } } public void setCacheFileName(String cacheFileName) { _cacheFileName = cacheFileName; } public void setGitDir(File gitDir) { _gitDir = gitDir; } public void setIgnoredMessagePattern(String ignoredMessagePattern) { _ignoredMessagePattern = ignoredMessagePattern; } public void setPath(String path) { _path = path; } public void setProperty(String property) { _property = property; } public void setSince(String since) { _since = since; } protected Path getCacheFilePath() { Project currentProject = getProject(); File baseDir = currentProject.getBaseDir(); Path path = baseDir.toPath(); while (path != null) { Path cacheFilePath = path.resolve(_cacheFileName); if (Files.exists(cacheFilePath)) { return cacheFilePath; } path = path.getParent(); } return null; } protected Map<String, Boolean> loadUpToDateCache() throws IOException { Map<String, Boolean> upToDateMap = _upToDateMap; if (upToDateMap != null) { return upToDateMap; } Path cacheFilePath = getCacheFilePath(); if (cacheFilePath == null) { return null; } Properties properties = new Properties(); try (InputStream inputStream = Files.newInputStream(cacheFilePath)) { properties.load(inputStream); } Object pname = properties.remove("pname"); if (pname == null) { Files.delete(cacheFilePath); log( "Deleted corrupted cache file (missing process name info)" + _cacheFileName, Project.MSG_ERR); return null; } if (!pname.equals(UpToDateUtil.getProcessName())) { Files.delete(cacheFilePath); log( "Deleted left over cache file from previous Ant process" + _cacheFileName, Project.MSG_WARN); return null; } upToDateMap = new HashMap<>(); for (Entry<Object, Object> entry : properties.entrySet()) { upToDateMap.put( String.valueOf(entry.getKey()), Boolean.parseBoolean(String.valueOf(entry.getValue()))); } _upToDateMap = upToDateMap; return upToDateMap; } private static volatile Map<String, Boolean> _upToDateMap; private String _cacheFileName = "uptodate.properties"; private File _gitDir; private String _ignoredMessagePattern; private String _path; private String _property; private String _since; private String _value; }