xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/history/AccuRevHistoryParser.java (revision 0e4c55544f8ea0a68e8bae37b0e502097e008ec1)
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, 2021, 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.text.ParseException;
31 import java.util.ArrayList;
32 import java.util.Date;
33 import java.util.List;
34 import org.opengrok.indexer.util.Executor;
35 
36 /**
37  * Parse source history for a AccuRev Repository.
38  *
39  * @author Steven Haehn
40  */
41 public class AccuRevHistoryParser implements Executor.StreamHandler {
42 
43     private AccuRevRepository repository;
44     private History history;
45 
46     /**
47      * Parse the history for the specified file.
48      *
49      * @param file the file to parse history for
50      * @param repos Pointer to the {@code AccuRevRepository}
51      * @return object representing the file's history
52      * @throws HistoryException if a problem occurs while executing p4 command
53      */
parse(File file, Repository repos)54     History parse(File file, Repository repos) throws HistoryException {
55 
56         repository = (AccuRevRepository) repos;
57 
58         history = null;
59 
60         String relPath = repository.getDepotRelativePath(file);
61 
62         /*
63          * When the path given is really just the root to the source
64          * workarea, no history is available, create fake.
65          */
66 
67         String rootRelativePath = File.separator + "." + File.separator;
68 
69         if (relPath.equals(rootRelativePath)) {
70 
71             List<HistoryEntry> entries = new ArrayList<>();
72 
73             entries.add(new HistoryEntry(
74                     "", new Date(), "OpenGrok", "Workspace Root", true));
75 
76             history = new History(entries);
77 
78         } else {
79             try {
80                 /*
81                  * Errors will be logged, so not bothering to add to the output.
82                  */
83                 Executor executor = repository.getHistoryLogExecutor(file);
84                 executor.exec(true, this);
85 
86             } catch (IOException e) {
87                 throw new HistoryException(
88                         "Failed to get history for: \""
89                         + file.getAbsolutePath() + "\"" + e);
90             }
91         }
92 
93         return history;
94     }
95 
96     @Override
processStream(InputStream input)97     public void processStream(InputStream input) throws IOException {
98 
99         BufferedReader in = new BufferedReader(new InputStreamReader(input));
100         List<HistoryEntry> entries = new ArrayList<>();
101         String line;
102         String user;
103         Date date;
104         HistoryEntry entry = null;
105 
106         history = new History();
107 
108         /*
109          * Accurev history of an element (directory or file) looks like:
110          *
111          * element: /./path/to/element eid: 238865 transaction 1486194; purge;
112          * 2012/02/28 12:46:55 ; user: tluksha version 2541/1 (2539/1)
113          *
114          * transaction 1476285; purge; 2012/02/03 12:16:25 ; user: shaehn
115          * version 4241/1 (4241/1)
116          *
117          * transaction 1317224; promote; 2011/05/03 11:37:56 ; user: mtrinh #
118          * changes to ngb to compile on windows version 13/93 (1000/2)
119          *
120          * ...
121          *
122          * What is of interest then is: user (author), version (revision), date,
123          * comment (message)
124          *
125          * Any lines not recognized are ignored.
126          */
127         while ((line = in.readLine()) != null) {
128 
129             if (line.startsWith("e")) {
130                 continue;
131             } // ignore element, eid
132 
133             if (line.startsWith("t")) {             // found transaction
134 
135                 String[] data = line.split("; ");
136                 entry = new HistoryEntry();
137 
138                 user = data[3].replaceFirst("user: ", "");
139 
140                 entry.setMessage("");
141                 entry.setAuthor(user);
142 
143                 try {
144                     date = repository.parse(data[2]);
145                     entry.setDate(date);
146                 } catch (ParseException pe) {
147                     //
148                     // Overriding processStream() thus need to comply with the
149                     // set of exceptions it can throw.
150                     //
151                     throw new IOException("Could not parse date: " + line, pe);
152                 }
153 
154             } else if (line.startsWith("  #")) {  // found comment
155 
156                 entry.appendMessage(line.substring(3));
157 
158             } else if (line.startsWith("  v")) {  // found version
159 
160                 String[] data = line.split("\\s+");
161                 entry.setRevision(data[2]);
162                 entry.setActive(true);
163                 entries.add(entry);
164             }
165         }
166 
167         history.setHistoryEntries(entries);
168     }
169 }
170