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) 2008, 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.IOException; 27 import java.io.InputStream; 28 import java.io.InputStreamReader; 29 import java.util.logging.Level; 30 import java.util.logging.Logger; 31 import java.util.regex.Matcher; 32 import java.util.regex.Pattern; 33 import org.opengrok.indexer.logger.LoggerFactory; 34 import org.opengrok.indexer.util.Executor; 35 36 /** 37 * handles parsing the output of the {@code cvs annotate} command 38 * into an annotation object. 39 */ 40 public class CVSAnnotationParser implements Executor.StreamHandler { 41 private static final Logger LOGGER = LoggerFactory.getLogger(CVSAnnotationParser.class); 42 43 /** 44 * Pattern used to extract author/revision from {@code cvs annotate}. 45 */ 46 private static final Pattern ANNOTATE_PATTERN 47 = Pattern.compile("([\\.\\d]+)\\W+\\((\\w+)"); 48 49 /** 50 * Store annotation created by processStream. 51 */ 52 private final Annotation annotation; 53 54 /** 55 * @param fileName the name of the file being annotated 56 */ CVSAnnotationParser(String fileName)57 public CVSAnnotationParser(String fileName) { 58 annotation = new Annotation(fileName); 59 } 60 61 /** 62 * Returns the annotation that has been created. 63 * 64 * @return annotation an annotation object 65 */ getAnnotation()66 public Annotation getAnnotation() { 67 return annotation; 68 } 69 70 @Override processStream(InputStream input)71 public void processStream(InputStream input) throws IOException { 72 BufferedReader in = new BufferedReader(new InputStreamReader(input)); 73 String line = ""; 74 int lineno = 0; 75 boolean hasStarted = false; 76 Matcher matcher = ANNOTATE_PATTERN.matcher(line); 77 while ((line = in.readLine()) != null) { 78 // Skip header 79 if (!hasStarted && (line.length() == 0 80 || !Character.isDigit(line.charAt(0)))) { 81 continue; 82 } 83 hasStarted = true; 84 85 // Start parsing 86 ++lineno; 87 matcher.reset(line); 88 if (matcher.find()) { 89 String rev = matcher.group(1); 90 String author = matcher.group(2).trim(); 91 annotation.addLine(rev, author, true); 92 } else { 93 LOGGER.log(Level.SEVERE, 94 "Error: did not find annotation in line {0}: [{1}]", 95 new Object[]{String.valueOf(lineno), line}); 96 } 97 } 98 } 99 } 100