Contents of /trunk/pkgtools/svn2cl-0.14/svn2cl.xsl
Parent Directory | Revision Log
Revision 3106 -
(show annotations)
(download)
(as text)
Fri Mar 15 10:20:17 2019 UTC (5 years, 1 month ago) by niro
File MIME type: application/xml
File size: 16115 byte(s)
Fri Mar 15 10:20:17 2019 UTC (5 years, 1 month ago) by niro
File MIME type: application/xml
File size: 16115 byte(s)
-added working svn2cl version
1 | <?xml version="1.0" encoding="utf-8"?> |
2 | |
3 | <!-- |
4 | |
5 | svn2cl.xsl - xslt stylesheet for converting svn log to a normal |
6 | changelog |
7 | |
8 | version 0.14 |
9 | |
10 | Usage (replace ++ with two minus signs which aren't allowed |
11 | inside xml comments): |
12 | svn ++verbose ++xml log | \ |
13 | xsltproc ++stringparam strip-prefix `basename $(pwd)` \ |
14 | ++stringparam linelen 75 \ |
15 | ++stringparam groupbyday yes \ |
16 | ++stringparam separate-daylogs yes \ |
17 | ++stringparam include-rev yes \ |
18 | ++stringparam include-actions yes \ |
19 | ++stringparam breakbeforemsg yes/2 \ |
20 | ++stringparam reparagraph yes \ |
21 | ++stringparam authorsfile FILE \ |
22 | ++stringparam ignore-message-starting \ |
23 | svn2cl.xsl - > ChangeLog |
24 | |
25 | This file is based on several implementations of this conversion |
26 | that I was not completely happy with and some other common |
27 | xslt constructs found on the web. |
28 | |
29 | Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Arthur de Jong. |
30 | |
31 | Redistribution and use in source and binary forms, with or without |
32 | modification, are permitted provided that the following conditions |
33 | are met: |
34 | 1. Redistributions of source code must retain the above copyright |
35 | notice, this list of conditions and the following disclaimer. |
36 | 2. Redistributions in binary form must reproduce the above copyright |
37 | notice, this list of conditions and the following disclaimer in |
38 | the documentation and/or other materials provided with the |
39 | distribution. |
40 | 3. The name of the author may not be used to endorse or promote |
41 | products derived from this software without specific prior |
42 | written permission. |
43 | |
44 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
45 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
46 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
47 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
48 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
49 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
50 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
51 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
52 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
53 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
54 | IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
55 | |
56 | --> |
57 | |
58 | <xsl:stylesheet |
59 | version="1.0" |
60 | xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
61 | |
62 | <xsl:output |
63 | method="text" |
64 | encoding="utf-8" |
65 | media-type="text/plain" |
66 | omit-xml-declaration="yes" |
67 | standalone="yes" |
68 | indent="no" /> |
69 | |
70 | <xsl:strip-space elements="*" /> |
71 | |
72 | <!-- the prefix of pathnames to strip --> |
73 | <xsl:param name="strip-prefix" select="'/'" /> |
74 | |
75 | <!-- the length of a line to wrap messages at --> |
76 | <xsl:param name="linelen" select="75" /> |
77 | |
78 | <!-- whether entries should be grouped by day --> |
79 | <xsl:param name="groupbyday" select="'no'" /> |
80 | |
81 | <!-- whether to seperate log messages by empty lines --> |
82 | <xsl:param name="separate-daylogs" select="'no'" /> |
83 | |
84 | <!-- whether a revision number should be included --> |
85 | <xsl:param name="include-rev" select="'no'" /> |
86 | |
87 | <!-- whether aaction labels should be added to files --> |
88 | <xsl:param name="include-actions" select="'no'" /> |
89 | |
90 | <!-- whether the log message should start on a new line --> |
91 | <xsl:param name="breakbeforemsg" select="'no'" /> |
92 | |
93 | <!-- whether the message should be rewrapped within one paragraph --> |
94 | <xsl:param name="reparagraph" select="'no'" /> |
95 | |
96 | <!-- whether certain messages should be ignored --> |
97 | <xsl:param name="ignore-message-starting" select="''" /> |
98 | |
99 | <!-- location of authors file if any --> |
100 | <xsl:param name="authorsfile" select="''" /> |
101 | <xsl:key name="author-lookup" match="author" use="@uid" /> |
102 | <xsl:variable name="authors-top" select="document($authorsfile)/authors" /> |
103 | |
104 | <!-- determin the path part to strip --> |
105 | <xsl:variable name="strip-path"> |
106 | <!-- if strip-prefix does not start with a slash, prepend it --> |
107 | <xsl:if test="not(starts-with($strip-prefix,'/'))"> |
108 | <xsl:text>/</xsl:text> |
109 | </xsl:if> |
110 | <!-- the prefix itself --> |
111 | <xsl:value-of select="$strip-prefix" /> |
112 | <!-- if strip-prefix does not end with a slash, append it --> |
113 | <xsl:if test="substring($strip-prefix,string-length($strip-prefix),1)!='/'"> |
114 | <xsl:text>/</xsl:text> |
115 | </xsl:if> |
116 | </xsl:variable> |
117 | |
118 | <!-- match the topmost log entry --> |
119 | <xsl:template match="log"> |
120 | <xsl:choose> |
121 | <xsl:when test="$ignore-message-starting != ''"> |
122 | <!-- only handle logentries with don't contain the string --> |
123 | <xsl:apply-templates select="logentry[not(starts-with(msg,$ignore-message-starting))]" /> |
124 | </xsl:when> |
125 | <xsl:otherwise> |
126 | <xsl:apply-templates select="logentry" /> |
127 | </xsl:otherwise> |
128 | </xsl:choose> |
129 | <!-- add newlines at the end of the changelog --> |
130 | <xsl:text> </xsl:text> |
131 | </xsl:template> |
132 | |
133 | <!-- format one entry from the log --> |
134 | <xsl:template match="logentry"> |
135 | <xsl:choose> |
136 | <!-- if we're grouping we should omit some headers --> |
137 | <xsl:when test="$groupbyday='yes'"> |
138 | <!-- fetch previous entry's date --> |
139 | <xsl:variable name="prevdate"> |
140 | <xsl:apply-templates select="preceding-sibling::logentry[position()=1]/date" /> |
141 | </xsl:variable> |
142 | <!-- fetch previous entry's author --> |
143 | <xsl:variable name="prevauthor"> |
144 | <xsl:value-of select="normalize-space(preceding-sibling::logentry[position()=1]/author)" /> |
145 | </xsl:variable> |
146 | <!-- fetch this entry's date --> |
147 | <xsl:variable name="date"> |
148 | <xsl:apply-templates select="date" /> |
149 | </xsl:variable> |
150 | <!-- fetch this entry's author --> |
151 | <xsl:variable name="author"> |
152 | <xsl:value-of select="normalize-space(author)" /> |
153 | </xsl:variable> |
154 | <!-- check if header is changed --> |
155 | <xsl:if test="($prevdate!=$date) or ($prevauthor!=$author)"> |
156 | <!-- add newline --> |
157 | <xsl:if test="not(position()=1)"> |
158 | <xsl:text> </xsl:text> |
159 | </xsl:if> |
160 | <!-- date --> |
161 | <xsl:value-of select="$date" /> |
162 | <!-- two spaces --> |
163 | <xsl:text>  </xsl:text> |
164 | <!-- author's name --> |
165 | <xsl:apply-templates select="author" /> |
166 | <!-- two newlines --> |
167 | <xsl:text> </xsl:text> |
168 | <xsl:if test="$separate-daylogs!='yes'"><xsl:text> </xsl:text></xsl:if> |
169 | </xsl:if> |
170 | </xsl:when> |
171 | <!-- write the log header --> |
172 | <xsl:otherwise> |
173 | <!-- add newline --> |
174 | <xsl:if test="not(position()=1)"> |
175 | <xsl:text> </xsl:text> |
176 | </xsl:if> |
177 | <!-- date --> |
178 | <xsl:apply-templates select="date" /> |
179 | <!-- two spaces --> |
180 | <xsl:text>  </xsl:text> |
181 | <!-- author's name --> |
182 | <xsl:apply-templates select="author" /> |
183 | <!-- two newlines --> |
184 | <xsl:text> </xsl:text> |
185 | </xsl:otherwise> |
186 | </xsl:choose> |
187 | <!-- get paths string --> |
188 | <xsl:variable name="paths"> |
189 | <xsl:apply-templates select="paths" /> |
190 | </xsl:variable> |
191 | <!-- get revision number --> |
192 | <xsl:variable name="rev"> |
193 | <xsl:if test="$include-rev='yes'"> |
194 | <xsl:text>[r</xsl:text> |
195 | <xsl:value-of select="@revision" /> |
196 | <xsl:text>] </xsl:text> |
197 | </xsl:if> |
198 | </xsl:variable> |
199 | <!-- trim trailing newlines --> |
200 | <xsl:variable name="msg"> |
201 | <!-- add a line break before the log message --> |
202 | <xsl:choose> |
203 | <xsl:when test="$breakbeforemsg='yes'"> |
204 | <xsl:text> </xsl:text> |
205 | </xsl:when> |
206 | <xsl:when test="number($breakbeforemsg)>0"> |
207 | <xsl:call-template name="newlines"> |
208 | <xsl:with-param name="count" select="number($breakbeforemsg)" /> |
209 | </xsl:call-template> |
210 | </xsl:when> |
211 | </xsl:choose> |
212 | <xsl:call-template name="trim-newln"> |
213 | <xsl:with-param name="txt" select="msg" /> |
214 | </xsl:call-template> |
215 | </xsl:variable> |
216 | <!-- add newline here if separate-daylogs is in effect --> |
217 | <xsl:if test="$groupbyday='yes' and $separate-daylogs='yes'"><xsl:text> </xsl:text></xsl:if> |
218 | <!-- first line is indented (other indents are done in wrap template) --> |
219 | <xsl:text>	* </xsl:text> |
220 | <!-- set up the text to wrap --> |
221 | <xsl:variable name="txt"> |
222 | <xsl:value-of select="$rev" /> |
223 | <xsl:if test="$paths!=''"> |
224 | <xsl:value-of select="concat($paths,': ')" /> |
225 | </xsl:if> |
226 | <xsl:value-of select="$msg" /> |
227 | </xsl:variable> |
228 | <!-- print the paths and message nicely wrapped --> |
229 | <xsl:call-template name="wrap"> |
230 | <xsl:with-param name="txt" select="$txt" /> |
231 | </xsl:call-template> |
232 | </xsl:template> |
233 | |
234 | <!-- format date --> |
235 | <xsl:template match="date"> |
236 | <xsl:variable name="date" select="normalize-space(.)" /> |
237 | <!-- output date part --> |
238 | <xsl:value-of select="substring($date,1,10)" /> |
239 | <!-- output time part --> |
240 | <xsl:if test="$groupbyday!='yes'"> |
241 | <xsl:text> </xsl:text> |
242 | <xsl:value-of select="substring($date,12,5)" /> |
243 | </xsl:if> |
244 | </xsl:template> |
245 | |
246 | <!-- format author --> |
247 | <xsl:template match="author"> |
248 | <xsl:variable name="uid" select="normalize-space(.)" /> |
249 | <!-- try to lookup author in authorsfile --> |
250 | <xsl:choose> |
251 | <xsl:when test="$authorsfile!=''"> |
252 | <xsl:for-each select="$authors-top"> |
253 | <xsl:variable name="author" select="key('author-lookup',$uid)" /> |
254 | <!-- present result --> |
255 | <xsl:choose> |
256 | <xsl:when test="string($author/.)"> |
257 | <xsl:apply-templates select="$author/node()" mode="copy" /> |
258 | </xsl:when> |
259 | <xsl:otherwise> |
260 | <xsl:value-of select="$uid" /> |
261 | </xsl:otherwise> |
262 | </xsl:choose> |
263 | </xsl:for-each> |
264 | </xsl:when> |
265 | <xsl:otherwise> |
266 | <xsl:value-of select="$uid" /> |
267 | </xsl:otherwise> |
268 | </xsl:choose> |
269 | </xsl:template> |
270 | |
271 | <!-- copy but normalize text --> |
272 | <xsl:template match="text()" mode="copy"> |
273 | <xsl:value-of select="normalize-space(.)" /> |
274 | </xsl:template> |
275 | |
276 | <!-- simple copy template --> |
277 | <xsl:template match="@*|node()" mode="copy"> |
278 | <xsl:copy> |
279 | <xsl:apply-templates select="@*|node()" mode="copy" /> |
280 | </xsl:copy> |
281 | </xsl:template> |
282 | |
283 | <!-- present a list of paths names --> |
284 | <xsl:template match="paths"> |
285 | <xsl:choose> |
286 | <!-- only handle paths that begin with the path and strip the path --> |
287 | <xsl:when test="$strip-prefix != ''"> |
288 | <!-- filter on all entries within directory --> |
289 | <xsl:for-each select="path[starts-with(concat(normalize-space(.),'/'),$strip-path)]"> |
290 | <xsl:sort select="normalize-space(.)" data-type="text" /> |
291 | <!-- unless we are the first entry, add a comma --> |
292 | <xsl:if test="not(position()=1)"> |
293 | <xsl:text>, </xsl:text> |
294 | </xsl:if> |
295 | <!-- get path part --> |
296 | <xsl:variable name="path" select="substring(normalize-space(.),string-length($strip-path)+1)" /> |
297 | <!-- translate empty string to dot and print result --> |
298 | <xsl:if test="$path = ''"> |
299 | <xsl:text>.</xsl:text> |
300 | </xsl:if> |
301 | <xsl:value-of select="$path" /> |
302 | <!-- add the action flag --> |
303 | <xsl:if test="$include-actions='yes'"> |
304 | <xsl:apply-templates select="." mode="action"/> |
305 | </xsl:if> |
306 | </xsl:for-each> |
307 | </xsl:when> |
308 | <!-- print a simple list of all paths --> |
309 | <xsl:otherwise> |
310 | <xsl:for-each select="path"> |
311 | <xsl:sort select="normalize-space(.)" data-type="text" /> |
312 | <!-- unless we are the first entry, add a comma --> |
313 | <xsl:if test="not(position()=1)"> |
314 | <xsl:text>, </xsl:text> |
315 | </xsl:if> |
316 | <!-- print the path name --> |
317 | <xsl:value-of select="normalize-space(.)" /> |
318 | <!-- add the action flag --> |
319 | <xsl:if test="$include-actions='yes'"> |
320 | <xsl:apply-templates select="." mode="action"/> |
321 | </xsl:if> |
322 | </xsl:for-each> |
323 | </xsl:otherwise> |
324 | </xsl:choose> |
325 | </xsl:template> |
326 | |
327 | <xsl:template match="path" mode="action"> |
328 | <xsl:choose> |
329 | <xsl:when test="@action='D'"> |
330 | <xsl:text>[DEL]</xsl:text> |
331 | </xsl:when> |
332 | <xsl:when test="@copyfrom-path"> |
333 | <xsl:text>[CPY]</xsl:text> |
334 | </xsl:when> |
335 | <xsl:when test="@action='A'"> |
336 | <xsl:text>[ADD]</xsl:text> |
337 | </xsl:when> |
338 | </xsl:choose> |
339 | </xsl:template> |
340 | |
341 | <!-- string-wrapping template --> |
342 | <xsl:template name="wrap"> |
343 | <xsl:param name="txt" /> |
344 | <xsl:variable name="normtxt" select="normalize-space($txt)" /> |
345 | <xsl:choose> |
346 | <xsl:when test="contains($txt,' ')"> |
347 | <!-- text contains newlines, do the first line --> |
348 | <xsl:call-template name="wrap"> |
349 | <xsl:with-param name="txt" select="substring-before($txt,' ')" /> |
350 | </xsl:call-template> |
351 | <!-- print tab --> |
352 | <xsl:text>	  </xsl:text> |
353 | <!-- wrap the rest of the text --> |
354 | <xsl:call-template name="wrap"> |
355 | <xsl:with-param name="txt" select="substring-after($txt,' ')" /> |
356 | </xsl:call-template> |
357 | </xsl:when> |
358 | <xsl:when test="(string-length($normtxt) < (($linelen)-9)) or not(contains($normtxt,' '))"> |
359 | <!-- this is easy, nothing to do --> |
360 | <xsl:value-of select="$normtxt" /> |
361 | <!-- add newline --> |
362 | <xsl:text> </xsl:text> |
363 | </xsl:when> |
364 | <xsl:otherwise> |
365 | <!-- find the first line --> |
366 | <xsl:variable name="tmp" select="substring($normtxt,1,(($linelen)-9))" /> |
367 | <xsl:variable name="line"> |
368 | <xsl:choose> |
369 | <!-- if our attempt contains spaces wrap on that --> |
370 | <xsl:when test="contains($tmp,' ')"> |
371 | <xsl:call-template name="find-line"> |
372 | <xsl:with-param name="txt" select="$tmp" /> |
373 | </xsl:call-template> |
374 | </xsl:when> |
375 | <!-- otherwise use the first non-space characters from the text --> |
376 | <xsl:otherwise> |
377 | <xsl:value-of select="substring-before($normtxt,' ')" /> |
378 | </xsl:otherwise> |
379 | </xsl:choose> |
380 | </xsl:variable> |
381 | <!-- print line --> |
382 | <xsl:value-of select="$line" /> |
383 | <!-- print newline and tab --> |
384 | <xsl:text> 	  </xsl:text> |
385 | <!-- wrap the rest of the text --> |
386 | <xsl:call-template name="wrap"> |
387 | <xsl:with-param name="txt" select="normalize-space(substring($normtxt,string-length($line)+1))" /> |
388 | </xsl:call-template> |
389 | </xsl:otherwise> |
390 | </xsl:choose> |
391 | </xsl:template> |
392 | |
393 | <!-- template to trim line to contain space as last char --> |
394 | <xsl:template name="find-line"> |
395 | <xsl:param name="txt" /> |
396 | <xsl:choose> |
397 | <xsl:when test="substring($txt,string-length($txt),1)=' '"> |
398 | <xsl:value-of select="substring($txt,1,string-length($txt)-1)" /> |
399 | </xsl:when> |
400 | <xsl:otherwise> |
401 | <xsl:call-template name="find-line"> |
402 | <xsl:with-param name="txt" select="substring($txt,1,string-length($txt)-1)" /> |
403 | </xsl:call-template> |
404 | </xsl:otherwise> |
405 | </xsl:choose> |
406 | </xsl:template> |
407 | |
408 | <!-- template to trim trailing and starting newlines --> |
409 | <xsl:template name="trim-newln"> |
410 | <xsl:param name="txt" /> |
411 | <xsl:choose> |
412 | <!-- find starting newlines --> |
413 | <xsl:when test="substring($txt,1,1) = ' '"> |
414 | <xsl:call-template name="trim-newln"> |
415 | <xsl:with-param name="txt" select="substring($txt,2)" /> |
416 | </xsl:call-template> |
417 | </xsl:when> |
418 | <!-- find trailing newlines --> |
419 | <xsl:when test="substring($txt,string-length($txt),1) = ' '"> |
420 | <xsl:call-template name="trim-newln"> |
421 | <xsl:with-param name="txt" select="substring($txt,1,string-length($txt)-1)" /> |
422 | </xsl:call-template> |
423 | </xsl:when> |
424 | <!-- if the message has paragraphs, find the first one --> |
425 | <xsl:when test="$reparagraph='yes' and contains($txt,' ')"> |
426 | <!-- remove newlines from first paragraph --> |
427 | <xsl:value-of select="normalize-space(substring-before($txt,' '))" /> |
428 | <!-- paragraph separator --> |
429 | <xsl:text> </xsl:text> |
430 | <!-- do the rest of the text --> |
431 | <xsl:call-template name="trim-newln"> |
432 | <xsl:with-param name="txt" select="substring-after($txt,' ')" /> |
433 | </xsl:call-template> |
434 | </xsl:when> |
435 | <!-- remove more single newlines --> |
436 | <xsl:when test="$reparagraph='yes'"> |
437 | <xsl:value-of select="normalize-space($txt)" /> |
438 | </xsl:when> |
439 | <!-- no newlines found, we're done --> |
440 | <xsl:otherwise> |
441 | <xsl:value-of select="$txt" /> |
442 | </xsl:otherwise> |
443 | </xsl:choose> |
444 | </xsl:template> |
445 | |
446 | <!-- insert a number of newlines --> |
447 | <xsl:template name="newlines"> |
448 | <xsl:param name="count" /> |
449 | <xsl:text> </xsl:text> |
450 | <xsl:if test="$count>1"> |
451 | <xsl:call-template name="newlines"> |
452 | <xsl:with-param name="count" select="($count)-1" /> |
453 | </xsl:call-template> |
454 | </xsl:if> |
455 | </xsl:template> |
456 | |
457 | </xsl:stylesheet> |