blob: 4b35a402d94c51a86a0a4602bf6255f5f747cdca [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.nbbuild;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
/**
* Creates summary of .hgmail coverage.
*/
public class SummarizeHgmail extends Task {
private File output;
/** Output file. */
public void setOutput(File output) {
this.output = output;
}
// DirSet of repo roots might be more natural, but . will not match at root
private FileSet hgmails;
/** Hgmail files to summarize. */
public void addConfiguredHgmails(FileSet hgmails) {
this.hgmails = hgmails;
}
public @Override void execute() throws BuildException {
try {
try (PrintWriter w = new PrintWriter(output)) {
DirectoryScanner scanner = hgmails.getDirectoryScanner(getProject());
scanner.scan();
for (String hgmailS : new TreeSet<String>(Arrays.asList(scanner.getIncludedFiles()))) {
w.println("SUMMARY OF " + hgmailS);
File hgmail = new File(scanner.getBasedir(), hgmailS);
File dir = hgmail.getParentFile();
File[] kids = dir.listFiles(new FileFilter() {
public boolean accept(File f) {
return /* contrib/contrib is a self-link */f.exists() && !f.getName().equals(".hg") && !new File(f, ".hg").isDirectory();
}
});
if (kids == null) {
throw new BuildException(dir.getPath(), getLocation());
}
// module dir such as java.source or contrib/autosave or file such as .hgtags, to list of addressees such as core-commits@platform.netbeans.org
Map<String,List<String>> notifications = new TreeMap<>();
try (Reader r = new FileReader(hgmail)) {
BufferedReader br = new BufferedReader(r);
String line;
while ((line = br.readLine()) != null) {
if (line.matches("^[\\[#].+|\\s*")) {
continue;
}
String[] split = line.split("=", 2);
if (split.length < 2) {
throw new BuildException(line, getLocation());
}
for (String patt : split[1].trim().split(",")) {
boolean isdir = false;
if (patt.endsWith("/*")) {
patt = patt.substring(0, patt.length() - 2);
isdir = true;
}
if (patt.contains("/")) {
throw new BuildException("Notifications of subdirs not yet supported: " + line, getLocation());
}
List<String> modules = new ArrayList<>();
if (patt.contains("*")) {
// Pattern, have to search for matches.
Pattern wild = Pattern.compile("\\Q" + patt.replace("*", "\\E.*\\Q") + "\\E");
for (File kid : kids) {
String name = kid.getName();
if (wild.matcher(name).matches()) {
if (kid.isDirectory() ^ isdir) {
throw new BuildException("Dir pattern matched non-dir or vice-versa: " + kid + " vs. " + line, getLocation());
}
modules.add(name);
}
}
}
if (modules.isEmpty()) {
// Single file (may or may not exist), or unmatched pattern; so record it.
modules.add(patt);
}
String addr = split[0].trim();
for (String module : modules) {
List<String> addressees = notifications.get(module);
if (addressees == null) {
addressees = new ArrayList<>();
notifications.put(module, addressees);
}
addressees.add(addr);
}
}
}
}
// Now find unmentioned modules:
for (File kid : kids) {
String name = kid.getName();
if (!notifications.containsKey(name)) {
notifications.put(name, new ArrayList<>());
}
}
// Report:
for (Map.Entry<String,List<String>> entry : notifications.entrySet()) {
String path = entry.getKey();
w.println("PATH " + path);
if (!new File(dir, path).exists()) {
w.println(" NONEXISTENT");
}
List<String> addressees = entry.getValue();
if (addressees.isEmpty()) {
w.println(" UNNOTIFIED");
} else {
if (new HashSet<>(addressees).size() < addressees.size()) {
w.println(" DUPLICATES");
}
Collections.sort(addressees);
for (String addressee : addressees) {
w.println(" NOTIFIES " + addressee);
}
}
}
w.println();
}
w.flush();
}
log(output + ": hgmail summary written");
} catch (IOException x) {
throw new BuildException(x, getLocation());
}
}
}