1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
|
23 | |
package net.sf.statsvn; |
24 | |
|
25 | |
import java.io.FileInputStream; |
26 | |
import java.io.IOException; |
27 | |
import java.io.InputStream; |
28 | |
import java.io.PrintWriter; |
29 | |
import java.io.StringWriter; |
30 | |
import java.util.ArrayList; |
31 | |
import java.util.List; |
32 | |
import java.util.Locale; |
33 | |
import java.util.logging.LogManager; |
34 | |
|
35 | |
import net.sf.statcvs.Messages; |
36 | |
import net.sf.statcvs.input.LogSyntaxException; |
37 | |
import net.sf.statcvs.model.Repository; |
38 | |
import net.sf.statcvs.output.ConfigurationException; |
39 | |
import net.sf.statcvs.output.ConfigurationOptions; |
40 | |
import net.sf.statcvs.output.ReportConfig; |
41 | |
import net.sf.statcvs.pages.ReportSuiteMaker; |
42 | |
import net.sf.statsvn.input.Builder; |
43 | |
import net.sf.statsvn.input.RepositoryFileManager; |
44 | |
import net.sf.statsvn.input.SvnLogfileParser; |
45 | |
import net.sf.statsvn.output.SvnCommandLineParser; |
46 | |
import net.sf.statsvn.output.SvnConfigurationOptions; |
47 | |
import net.sf.statsvn.util.SvnVersionMismatchException; |
48 | |
|
49 | |
|
50 | |
|
51 | |
|
52 | |
|
53 | |
|
54 | |
|
55 | |
|
56 | |
|
57 | |
public final class Main { |
58 | |
private static final int KB_IN_ONE_MB = 1024; |
59 | |
|
60 | |
private static final int NUMBER_OF_MS_IN_ONE_SEC = 1000; |
61 | |
|
62 | 1 | private static final LogManager LM = LogManager.getLogManager(); |
63 | 29 | |
64 | |
|
65 | |
|
66 | |
|
67 | |
|
68 | 0 | private Main() { |
69 | 0 | } |
70 | 0 | |
71 | |
|
72 | |
|
73 | |
|
74 | |
|
75 | |
|
76 | |
|
77 | |
public static void main(final String[] args) { |
78 | 0 | init(); |
79 | 0 | verifyArguments(args); |
80 | 0 | generate(); |
81 | 0 | System.exit(0); |
82 | 0 | } |
83 | 0 | |
84 | |
private static void verifyArguments(final String[] args) { |
85 | 0 | if (args.length == 0) { |
86 | 0 | printProperUsageAndExit(); |
87 | 0 | } |
88 | 0 | if (args.length == 1) { |
89 | 0 | final String arg = args[0].toLowerCase(Locale.getDefault()); |
90 | 0 | if (arg.equals("-h") || arg.equals("-help")) { |
91 | 0 | printProperUsageAndExit(); |
92 | 0 | } else if (arg.equals("-version")) { |
93 | 0 | printVersionAndExit(); |
94 | 0 | } |
95 | |
} |
96 | |
|
97 | |
try { |
98 | 0 | new SvnCommandLineParser(args).parse(); |
99 | 0 | } catch (final ConfigurationException cex) { |
100 | 0 | SvnConfigurationOptions.getTaskLogger().error(cex.getMessage()); |
101 | 0 | System.exit(1); |
102 | 0 | } |
103 | 0 | } |
104 | 0 | |
105 | |
public static void generate() { |
106 | |
try { |
107 | 0 | RepositoryFileManager manager = createRepoManager(); |
108 | 0 | String version = manager.getProcessor().getVersionProcessor().checkSvnVersionSufficient(); |
109 | 0 | final boolean isNewerDiffPossible = manager.getProcessor().getVersionProcessor().checkDiffPerRevPossible(version); |
110 | 0 | |
111 | 0 | if (!isNewerDiffPossible) { |
112 | 0 | SvnConfigurationOptions.setLegacyDiff(true); |
113 | |
} |
114 | 0 | |
115 | 0 | manager.getProcessor().getInfoProcessor().checkRepoRootAvailable(); |
116 | 0 | generateDefaultHTMLSuite(manager); |
117 | 0 | } catch (final ConfigurationException cex) { |
118 | 0 | SvnConfigurationOptions.getTaskLogger().error(cex.getMessage()); |
119 | 0 | System.exit(1); |
120 | 0 | } catch (final LogSyntaxException lex) { |
121 | 0 | printLogErrorMessageAndExit(lex.getMessage()); |
122 | 0 | } catch (final IOException ioex) { |
123 | 0 | printIoErrorMessageAndExit(ioex.getMessage()); |
124 | 0 | } catch (final OutOfMemoryError oome) { |
125 | 0 | printOutOfMemMessageAndExit(); |
126 | 0 | } catch (final SvnVersionMismatchException ever) { |
127 | 0 | printErrorMessageAndExit(ever.getMessage()); |
128 | 0 | } |
129 | 0 | } |
130 | |
|
131 | 0 | public static void init() { |
132 | 0 | Messages.setPrimaryResource("net.sf.statsvn.statcvs"); |
133 | |
|
134 | 0 | |
135 | 0 | SvnConfigurationOptions.getTaskLogger().info(Messages.getString("PROJECT_NAME") + Messages.NL); |
136 | 0 | } |
137 | |
|
138 | 29 | private static void initLogManager(final String loggingProperties) { |
139 | 1 | InputStream stream = null; |
140 | 58 | try { |
141 | 31 | stream = Main.class.getResourceAsStream(loggingProperties); |
142 | 4 | LM.readConfiguration(stream); |
143 | 0 | } catch (final IOException e) { |
144 | 0 | SvnConfigurationOptions.getTaskLogger().error("ERROR: Logging could not be initialized!"); |
145 | 26 | } finally { |
146 | 1 | if (stream != null) { |
147 | 29 | try { |
148 | 1 | stream.close(); |
149 | 0 | } catch (final IOException e) { |
150 | 32 | SvnConfigurationOptions.getTaskLogger().error("ERROR: could not close stream!"); |
151 | 1 | } |
152 | 3 | } |
153 | 29 | } |
154 | 1 | } |
155 | |
|
156 | 0 | private static void printProperUsageAndExit() { |
157 | 0 | final String cr = System.getProperty("line.separator"); |
158 | 0 | SvnConfigurationOptions.getTaskLogger().error( |
159 | |
|
160 | |
|
161 | |
"Usage: java -jar statsvn.jar [options] <logfile> <directory>" + cr + cr + "Required parameters:" + cr |
162 | |
+ " <logfile> path to the svn logfile of the module" + cr |
163 | |
+ " <directory> path to the directory of the checked out module" + cr + cr + "Some options:" + cr |
164 | |
+ " -version print the version information and exit" + cr + " -output-dir <dir> directory where HTML suite will be saved" |
165 | |
+ cr + " -include <pattern> include only files matching pattern, e.g. **/*.c;**/*.h" + cr |
166 | |
+ " -exclude <pattern> exclude matching files, e.g. tests/**;docs/**" + cr |
167 | |
+ " -tags <regexp> show matching tags in lines of code chart, e.g. version-.*" + cr |
168 | |
+ " -title <title> Project title to be used in reports" + cr + " -viewvc <url> integrate with ViewVC installation at <url>" |
169 | |
+ cr + " -trac <url> integrate with Trac at <url>" + cr + " -bugzilla <url> integrate with Bugzilla installation at <url>" |
170 | |
+ cr + " -username <svnusername> username to pass to svn" + cr + " -password <svnpassword> password to pass to svn" + cr |
171 | |
+ " -verbose print extra progress information" + cr + " -xdoc optional switch output to xdoc" + cr |
172 | |
+ " -xml optional switch output to xml" + cr + " -threads <int> how many threads for svn diff (default: 25)" |
173 | |
+ cr + " -concurrency-threshold <millisec> switch to concurrent svn diff if 1st call>threshold (default: 4000)" + cr |
174 | |
+ " -dump dump the Repository content on console" + cr |
175 | |
+ " -charset <charset> specify the charset to use for html/xdoc\n" |
176 | |
+ " -tags-dir <directory> optional, specifies the director for tags (default '/tags/')" + cr + cr |
177 | 0 | + "Full options list: http://www.statsvn.org"); |
178 | 0 | System.exit(1); |
179 | 0 | } |
180 | |
|
181 | 0 | private static void printVersionAndExit() { |
182 | 0 | SvnConfigurationOptions.getTaskLogger().error("Version " + Messages.getString("PROJECT_VERSION")); |
183 | 0 | System.exit(1); |
184 | 0 | } |
185 | 0 | |
186 | 0 | private static void printOutOfMemMessageAndExit() { |
187 | 0 | SvnConfigurationOptions.getTaskLogger().error("OutOfMemoryError."); |
188 | 0 | SvnConfigurationOptions.getTaskLogger().error("Try running java with the -mx option (e.g. -mx128m for 128Mb)."); |
189 | 0 | System.exit(1); |
190 | 0 | } |
191 | |
|
192 | 0 | private static void printLogErrorMessageAndExit(final String message) { |
193 | 0 | SvnConfigurationOptions.getTaskLogger().error("Logfile parsing failed."); |
194 | 0 | SvnConfigurationOptions.getTaskLogger().error(message); |
195 | 0 | System.exit(1); |
196 | 0 | } |
197 | |
|
198 | 0 | private static void printIoErrorMessageAndExit(final String message) { |
199 | 0 | SvnConfigurationOptions.getTaskLogger().error(message); |
200 | 0 | System.exit(1); |
201 | 0 | } |
202 | 0 | |
203 | |
public static String printStackTrace(final Exception e) { |
204 | 0 | try { |
205 | 0 | final StringWriter sw = new StringWriter(); |
206 | 0 | final PrintWriter pw = new PrintWriter(sw); |
207 | 0 | e.printStackTrace(pw); |
208 | 0 | return sw.toString(); |
209 | 0 | } catch (final Exception e2) { |
210 | 0 | if (e != null) { |
211 | 0 | return e.getMessage(); |
212 | 0 | } else { |
213 | 0 | return ""; |
214 | 0 | } |
215 | 0 | } |
216 | 0 | } |
217 | 0 | |
218 | 0 | private static void printErrorMessageAndExit(final String message) { |
219 | 0 | SvnConfigurationOptions.getTaskLogger().error(message); |
220 | 0 | System.exit(1); |
221 | 0 | } |
222 | |
|
223 | |
|
224 | 0 | |
225 | 0 | |
226 | 0 | |
227 | 0 | |
228 | |
|
229 | |
|
230 | |
|
231 | |
|
232 | |
|
233 | |
|
234 | 0 | public static void generateDefaultHTMLSuite() throws LogSyntaxException, IOException, ConfigurationException { |
235 | 0 | generateDefaultHTMLSuite(createRepoManager()); |
236 | 0 | } |
237 | |
|
238 | |
private static RepositoryFileManager createRepoManager() { |
239 | 0 | return new RepositoryFileManager(ConfigurationOptions.getCheckedOutDirectory()); |
240 | 0 | } |
241 | 0 | |
242 | 0 | |
243 | |
|
244 | |
|
245 | |
|
246 | |
|
247 | |
|
248 | |
|
249 | |
|
250 | |
|
251 | |
|
252 | |
|
253 | |
|
254 | 4 | |
255 | 0 | |
256 | |
|
257 | 4 | public static void generateDefaultHTMLSuite(final RepositoryFileManager repFileMan) throws LogSyntaxException, IOException, ConfigurationException { |
258 | 0 | |
259 | 1 | if (ConfigurationOptions.getLogFileName() == null) { |
260 | 0 | throw new ConfigurationException("Missing logfile name"); |
261 | 29 | } |
262 | 5 | if (ConfigurationOptions.getCheckedOutDirectory() == null) { |
263 | 0 | throw new ConfigurationException("Missing checked out directory"); |
264 | 29 | } |
265 | 0 | |
266 | 5 | final long memoryUsedOnStart = Runtime.getRuntime().totalMemory(); |
267 | 1 | final long startTime = System.currentTimeMillis(); |
268 | 25 | |
269 | 29 | initLogManager(ConfigurationOptions.getLoggingProperties()); |
270 | 3 | |
271 | 26 | SvnConfigurationOptions.getTaskLogger().info( |
272 | 3 | "Parsing SVN log '" |
273 | 29 | + ConfigurationOptions.getLogFileName() |
274 | 1 | + "'" |
275 | 3 | + (ConfigurationOptions.getExcludePattern() != null ? " exclude pattern '" + ConfigurationOptions.getExcludePattern() + "'" |
276 | 26 | : "No exclude pattern")); |
277 | 26 | |
278 | 4 | FileInputStream logFile = null; |
279 | 27 | Builder builder = null; |
280 | 25 | try { |
281 | 2 | logFile = new FileInputStream(ConfigurationOptions.getLogFileName()); |
282 | 30 | builder = new Builder(repFileMan, ConfigurationOptions.getIncludePattern(), ConfigurationOptions.getExcludePattern(), ConfigurationOptions |
283 | 0 | .getSymbolicNamesPattern()); |
284 | 4 | new SvnLogfileParser(repFileMan, logFile, builder).parse(); |
285 | 28 | } finally { |
286 | 2 | if (logFile != null) { |
287 | 1 | logFile.close(); |
288 | 3 | } |
289 | 26 | } |
290 | 3 | |
291 | 26 | if (ConfigurationOptions.getProjectName() == null) { |
292 | 28 | ConfigurationOptions.setProjectName(builder.getProjectName()); |
293 | 4 | } |
294 | 4 | if (ConfigurationOptions.getWebRepository() != null) { |
295 | 26 | ConfigurationOptions.getWebRepository().setAtticFileNames(builder.getAtticFileNames()); |
296 | 4 | } |
297 | 25 | |
298 | 5 | SvnConfigurationOptions.getTaskLogger().info( |
299 | 26 | "Generating report for " + ConfigurationOptions.getProjectName() + " into " + ConfigurationOptions.getOutputDir()); |
300 | 26 | SvnConfigurationOptions.getTaskLogger().info("Using " + ConfigurationOptions.getCssHandler()); |
301 | 27 | final Repository content = builder.createRepository(); |
302 | 4 | |
303 | 26 | long memoryUsedOnEnd = Runtime.getRuntime().totalMemory(); |
304 | 4 | SvnConfigurationOptions.getTaskLogger().info("memory usage After Build: " + (((double) memoryUsedOnEnd - memoryUsedOnStart) / KB_IN_ONE_MB) + " kb"); |
305 | 26 | |
306 | 1 | builder.clean(); |
307 | 2 | builder = null; |
308 | 0 | |
309 | 29 | |
310 | 2 | System.setProperty("java.awt.headless", "true"); |
311 | 26 | |
312 | 2 | final ReportConfig config = new ReportConfig(content, ConfigurationOptions.getProjectName(), ConfigurationOptions.getOutputDir(), ConfigurationOptions |
313 | 2 | .getMarkupSyntax(), ConfigurationOptions.getCssHandler(), ConfigurationOptions.getCharSet()); |
314 | 5 | config.setWebRepository(ConfigurationOptions.getWebRepository()); |
315 | 3 | config.setWebBugtracker(ConfigurationOptions.getWebBugtracker()); |
316 | 23 | config.setNonDeveloperLogins(ConfigurationOptions.getNonDeveloperLogins()); |
317 | 5 | |
318 | 5 | validate(config); |
319 | 22 | |
320 | 29 | if (SvnConfigurationOptions.isDumpContent()) { |
321 | 5 | new RepoDump(content).dump(); |
322 | 25 | } else { |
323 | 21 | |
324 | 26 | final List extraReports = new ArrayList(); |
325 | 4 | |
326 | 1 | if ("xml".equalsIgnoreCase(ConfigurationOptions.getOutputFormat())) { |
327 | 22 | new ReportSuiteMaker(config, ConfigurationOptions.getNotes(), extraReports).toXml(); |
328 | 1 | } else { |
329 | 5 | new ReportSuiteMaker(config, ConfigurationOptions.getNotes(), extraReports).toFile().write(); |
330 | 1 | } |
331 | 22 | } |
332 | 2 | final long endTime = System.currentTimeMillis(); |
333 | 1 | memoryUsedOnEnd = Runtime.getRuntime().totalMemory(); |
334 | |
|
335 | 2 | SvnConfigurationOptions.getTaskLogger().info("runtime: " + (((double) endTime - startTime) / NUMBER_OF_MS_IN_ONE_SEC) + " seconds"); |
336 | 1 | SvnConfigurationOptions.getTaskLogger().info("memory usage: " + (((double) memoryUsedOnEnd - memoryUsedOnStart) / KB_IN_ONE_MB) + " kb"); |
337 | 1 | } |
338 | |
|
339 | |
private static void validate(final ReportConfig config) { |
340 | 1 | if (config.getRepository() == null || config.getRepository().getRoot() == null || config.getRepository().getDirectories() == null) { |
341 | 1 | String cr = System.getProperty("line.separator"); |
342 | 0 | printErrorMessageAndExit("The repository object is not valid. Please check your settings." + cr + "Possible reasons:" + cr |
343 | |
+ "1/ Did you use the option -v to create the SVN log" + cr + "2/ Is the log file empty?" + cr |
344 | |
+ "3/ Do you run from a checked out directory (you should)?" + cr + "4/ Do you have non-committed items?"); |
345 | |
} |
346 | 1 | } |
347 | |
} |