32
32
import java .util .Calendar ;
33
33
import java .util .Date ;
34
34
import java .util .List ;
35
+ import java .util .logging .Level ;
36
+ import java .util .logging .Logger ;
35
37
import java .util .regex .Matcher ;
36
38
import java .util .regex .Pattern ;
37
39
40
+ import org .opengrok .indexer .logger .LoggerFactory ;
38
41
import org .opengrok .indexer .util .Executor ;
39
42
import static org .opengrok .indexer .history .PerforceRepository .protectPerforceFilename ;
40
43
44
47
* @author Emilio Monti - [email protected]
45
48
*/
46
49
public class PerforceHistoryParser {
50
+ private static final Logger LOGGER = LoggerFactory .getLogger (PerforceHistoryParser .class );
51
+
52
+ History parse (File file , Repository repos ) throws HistoryException {
53
+ return this .parse (file , null , repos );
54
+ }
47
55
48
56
/**
49
57
* Parse the history for the specified file.
50
58
*
51
59
* @param file the file to parse history for
60
+ * @param sinceRevision the revision before the start of desired history
52
61
* @param repos Pointer to the {@code PerforceRepository}
53
62
* @return object representing the file's history
54
63
* @throws HistoryException if a problem occurs while executing p4 command
55
64
*/
56
- History parse (File file , Repository repos ) throws HistoryException {
65
+ History parse (File file , String sinceRevision , Repository repos ) throws HistoryException {
57
66
History history ;
58
67
59
68
if (!PerforceRepository .isInP4Depot (file , false )) {
@@ -62,9 +71,16 @@ History parse(File file, Repository repos) throws HistoryException {
62
71
63
72
try {
64
73
if (file .isDirectory ()) {
74
+ /* TODO: Do I need to think about revisions here? */
65
75
history = parseDirectory (file );
66
76
} else {
67
- history = getRevisions (file , null );
77
+ if (sinceRevision == null || "" .equals (sinceRevision )) {
78
+ /* Get all revisions */
79
+ history = getRevisions (file , null );
80
+ } else {
81
+ /* Get revisions between specified and head */
82
+ history = getRevisionsSince (file , sinceRevision );
83
+ }
68
84
}
69
85
} catch (IOException ioe ) {
70
86
throw new HistoryException (ioe );
@@ -84,6 +100,13 @@ private History parseDirectory(File file) throws IOException {
84
100
return parseChanges (executor .getOutputReader ());
85
101
}
86
102
103
+ /**
104
+ * Retrieve the history of a given file.
105
+ *
106
+ * @param file the file to parse history for
107
+ * @param rev the revision at which to end history
108
+ * @return object representing the file's history
109
+ */
87
110
public static History getRevisions (File file , String rev ) throws IOException {
88
111
ArrayList <String > cmd = new ArrayList <String >();
89
112
cmd .add ("p4" );
@@ -96,6 +119,41 @@ public static History getRevisions(File file, String rev) throws IOException {
96
119
return parseFileLog (executor .getOutputReader ());
97
120
}
98
121
122
+ /**
123
+ * Retrieve the history of a given file, beginning after the specified
124
+ * revision.
125
+ *
126
+ * @param file the file to parse history for
127
+ * @param rev the revision before the start of desired history
128
+ * @return object representing the file's history
129
+ */
130
+ public static History getRevisionsSince (File file , String rev ) throws IOException {
131
+ ArrayList <String > cmd = new ArrayList <String >();
132
+ cmd .add ("p4" );
133
+ cmd .add ("filelog" );
134
+ cmd .add ("-lti" );
135
+ /* Okay. This is a little cheeky. getRevisionCmd(String,String) gives
136
+ * a range spec that _includes_ the first revision. But, we don't want
137
+ * that in this case here. So, presume that "rev" is always an integer
138
+ * for perforce, add one to it, then convert back into a string to
139
+ * pass into getRevisionCmd as a starting revision. */
140
+ try {
141
+ Integer irev = Integer .parseInt (rev );
142
+ irev += 1 ;
143
+ rev = irev .toString ();
144
+ } catch (NumberFormatException e ) {
145
+ LOGGER .log (Level .WARNING ,
146
+ "Unable to increment revision {}, NumberFormatException" ,
147
+ new Object []{rev });
148
+ /* Move along with rev unchanged... */
149
+ }
150
+ cmd .add (file .getName () + PerforceRepository .getRevisionCmd (rev , "now" ));
151
+ Executor executor = new Executor (cmd , file .getCanonicalFile ().getParentFile ());
152
+ executor .exec ();
153
+
154
+ return parseFileLog (executor .getOutputReader ());
155
+ }
156
+
99
157
private static final Pattern REVISION_PATTERN = Pattern .compile ("#\\ d+ change (\\ d+) \\ S+ on (\\ d{4})/(\\ d{2})/(\\ d{2}) (\\ d{2}):(\\ d{2}):(\\ d{2}) by ([^@]+)" );
100
158
private static final Pattern CHANGE_PATTERN = Pattern .compile ("Change (\\ d+) on (\\ d{4})/(\\ d{2})/(\\ d{2}) (\\ d{2}):(\\ d{2}):(\\ d{2}) by ([^@]+)@\\ S* '([^']*)'" );
101
159
0 commit comments