package hudson.scm; import hudson.Util; import hudson.model.TaskListener; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.SVNLogEntryPath; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.SVNProperties; /** * Determines whether a log entry contains changes within the included paths for a project. */ public class DefaultSVNLogFilter implements SVNLogFilter { private TaskListener listener; private Pattern[] excludedPatterns; private Pattern[] includedPatterns; private Set<String> excludedUsers; private String excludedRevprop; private Pattern[] excludedCommitMessages; private boolean ignoreDirPropChanges; public DefaultSVNLogFilter(Pattern[] excludedPatterns, Pattern[] includedPatterns, Set<String> excludedUsers, String excludedRevProp, Pattern[] excludedCommitMessages, boolean ignoreDirPropChanges) { this.excludedPatterns = excludedPatterns; this.includedPatterns = includedPatterns; this.excludedUsers = excludedUsers; this.excludedRevprop = excludedRevProp; this.excludedCommitMessages = excludedCommitMessages; this.ignoreDirPropChanges = ignoreDirPropChanges; } public void setTaskListener(TaskListener listener) { this.listener = listener; } private PrintStream getLog() { return this.listener != null ? this.listener.getLogger() : null; } /* (non-Javadoc) * @see hudson.scm.SVNLogFilter#hasExclusionRule() */ public boolean hasExclusionRule() { return excludedPatterns.length > 0 || !excludedUsers.isEmpty() || excludedRevprop != null || excludedCommitMessages.length > 0 || includedPatterns.length > 0 || ignoreDirPropChanges; } /* (non-Javadoc) * @see hudson.scm.SVNLogFilter#isIncluded(org.tmatesoft.svn.core.SVNLogEntry) */ public boolean isIncluded(SVNLogEntry logEntry) { if (excludedRevprop != null) { // If the entry includes the exclusion revprop, don't count it as a change SVNProperties revprops = logEntry.getRevisionProperties(); if (revprops != null && revprops.containsName(excludedRevprop)) { if (getLog() != null) { getLog().println(hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision( logEntry.getRevision(), hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision_revprop(excludedRevprop))); } return false; } } String author = logEntry.getAuthor(); if (excludedUsers.contains(author)) { // If the author is an excluded user, don't count this entry as a change if (getLog() != null) { getLog().println(hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision( logEntry.getRevision(), hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision_author(author))); } return false; } if (excludedCommitMessages != null) { // If the commit message contains one of the excluded messages, don't count it as a change String commitMessage = logEntry.getMessage(); for (Pattern pattern : excludedCommitMessages) { if (pattern.matcher(commitMessage).find()) { return false; } } } // If there were no changes, don't count this entry as a change Map<String, SVNLogEntryPath> changedPaths = logEntry.getChangedPaths(); if (changedPaths.isEmpty()) { return false; } // dirPropChanges are changes that modifiy ('M') a directory, i.e. only // exclude if there are NO changes on files or Adds/Removals if (ignoreDirPropChanges) { boolean contentChanged = false; for (SVNLogEntryPath path : changedPaths.values()) { if (path.getType() != 'M' || path.getKind() != SVNNodeKind.DIR) { contentChanged = true; break; } } if (!contentChanged) { if (getLog() != null) { getLog().println(hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision( logEntry.getRevision(), hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision_onlydirprops())); } return false; } } // If there are included patterns, see which paths are included List<String> includedPaths = new ArrayList<String>(); if (includedPatterns.length > 0) { for (String path : changedPaths.keySet()) { for (Pattern pattern : includedPatterns) { if (pattern.matcher(path).matches()) { includedPaths.add(path); break; } } } } else { includedPaths = new ArrayList<String>(changedPaths.keySet()); } // If no paths are included don't count this entry as a change if (includedPaths.isEmpty()) { if (getLog() != null) { getLog().println(hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision( logEntry.getRevision(), hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision_noincpath())); } return false; } // Else, check each changed path List<String> excludedPaths = new ArrayList<String>(); if (excludedPatterns.length > 0) { for (String path : includedPaths) { for (Pattern pattern : excludedPatterns) { if (pattern.matcher(path).matches()) { excludedPaths.add(path); break; } } } } // If all included paths are in an excluded region, don't count this entry as a change if (includedPaths.size() == excludedPaths.size()) { if (getLog() != null) { getLog().println(hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision( logEntry.getRevision(), hudson.scm.subversion.Messages.SubversionSCM_pollChanges_ignoredRevision_path(Util.join(excludedPaths, ", ")))); } return false; } // Otherwise, a change is a change return true; } private static final long serialVersionUID = 1L; }