1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 22 */ 23 package org.opengrok.indexer.history; 24 25 import java.io.BufferedReader; 26 import java.io.File; 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.io.InputStreamReader; 30 import java.util.HashMap; 31 import java.util.logging.Level; 32 import java.util.logging.Logger; 33 import java.util.regex.Matcher; 34 import java.util.regex.Pattern; 35 import org.opengrok.indexer.logger.LoggerFactory; 36 import org.opengrok.indexer.util.Executor; 37 import org.opengrok.indexer.web.Util; 38 39 /** 40 * handles parsing the output of the {@code hg annotate} command 41 * into an annotation object. 42 */ 43 class MercurialAnnotationParser implements Executor.StreamHandler { 44 private static final Logger LOGGER = LoggerFactory.getLogger(MercurialAnnotationParser.class); 45 46 private Annotation annotation = null; 47 HashMap<String, HistoryEntry> revs; 48 File file; 49 50 /** 51 * Pattern used to extract author/revision from {@code hg annotate}. 52 */ 53 private static final Pattern ANNOTATION_PATTERN 54 = Pattern.compile("^\\s*(\\d+):"); 55 MercurialAnnotationParser(File file, HashMap<String, HistoryEntry> revs)56 MercurialAnnotationParser(File file, HashMap<String, HistoryEntry> revs) { 57 this.file = file; 58 this.revs = revs; 59 } 60 61 @Override processStream(InputStream input)62 public void processStream(InputStream input) throws IOException { 63 annotation = new Annotation(file.getName()); 64 String line; 65 int lineno = 0; 66 Matcher matcher = ANNOTATION_PATTERN.matcher(""); 67 68 try (BufferedReader in = new BufferedReader(new InputStreamReader(input))) { 69 while ((line = in.readLine()) != null) { 70 ++lineno; 71 matcher.reset(line); 72 if (matcher.find()) { 73 String rev = matcher.group(1); 74 String author = "N/A"; 75 // Use the history index hash map to get the author. 76 if (revs.get(rev) != null) { 77 author = revs.get(rev).getAuthor(); 78 } 79 annotation.addLine(rev, Util.getEmail(author.trim()), true); 80 } else { 81 LOGGER.log(Level.SEVERE, 82 "Error: did not find annotation in line {0}: [{1}]", 83 new Object[]{lineno, line}); 84 } 85 } 86 } 87 } 88 getAnnotation()89 Annotation getAnnotation() { 90 return this.annotation; 91 } 92 } 93